收藏 分销(赏)

使用VHDL进行分频器设计.doc

上传人:pc****0 文档编号:7778616 上传时间:2025-01-16 格式:DOC 页数:41 大小:812KB 下载积分:10 金币
下载 相关 举报
使用VHDL进行分频器设计.doc_第1页
第1页 / 共41页
使用VHDL进行分频器设计.doc_第2页
第2页 / 共41页


点击查看更多>>
资源描述
使用 VHDL 进行分频器设计 作者:ChongyangLee 摘要 使用 VHDL 进行分频器设计 作者:ChongyangLee 本文使用实例描述了在 FPGA/CPLD 上使用 VHDL 进行分频器设 计,包括偶数分频、非 50%占空比和 50%占空比的奇数分频、半整数 (N+0.5)分频、小数分频、分数分频以及积分分频。所有实现均可 通过 Synplify Pro 或 FPGA 生产厂商的综合器进行综合,形成可使 用的电路,并在 ModelSim 上进行验证。 目录 概述.......................................................................................................................................1 计数器 ..................................................................................................................................1 普通计数器..................................................................................................................1 约翰逊计数器 .............................................................................................................3 分频器 ..................................................................................................................................4 偶数分频器..................................................................................................................4 奇数分频器..................................................................................................................6 半整数分频器 .............................................................................................................9 小数分频器................................................................................................................11 分数分频器................................................................................................................15 积分分频器................................................................................................................18 概述 分频器是数字电路中最常用的电路之一,在 FPGA 的设计中也是使用效率 非常高的基本设计。基于 FPGA 实现的分频电路一般有两种方法:一是使用 FPGA 芯片内部提供的锁相环电路,如 ALTERA 提供的 PLL (Phase Locked Loop),Xilinx 提供的 DLL(Delay Locked Loop);二是使用硬件描述语言,如 VHDL、Verilog HDL 等。使用锁相环电路有许多优点,如可以实现倍频;相位 偏移;占空比可调等。但 FPGA 提供的锁相环个数极为有限,不能满足使用要 求。因此使用硬件描述语言实现分频电路经常使用在数字电路设计中,消耗不 多的逻辑单元就可以实现对时钟的操作,具有成本低、可编程等优点。 计数器 计数器是实现分频电路的基础,计数器有普通计数器和约翰逊计数器两 种。这两种计数器均可应用在分频电路中。 普通计数器 最普通的计数器是加法(或减法)计数器。下面是加法计数器的VHDL实 现,其Synplify Pro下的RTL View如图 1所示。 --file Name: ripple.vhd --Description: 带复位功能的加法计数器 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ripple is generic (width: integer := 4); port(clk, rst: in std_logic; cnt: out std_logic_vector(width - 1 downto 0)); end ripple; architecture a of ripple is signal cntQ: std_logic_vector(width - 1 downto 0); begin process(clk, rst) begin if (rst = '1') then cntQ <= (others => '0'); elsif (clk'event and clk = '1') then cntQ <= cntQ + 1; 1 end if; end process; cnt <= cntQ; end a;  代码 1 加法计数器 VHDL 代码 图 1 加法计数器 RTL 视图 加法计数器的Test Bench代码如下所示,在ModelSim下进行功能仿真,仿真 波形结果如图 2所示。 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ripple_tb is end ripple_tb; architecture testbench of ripple_tb is component ripple generic(width: integer := 4); port(clk, rst: in std_logic; cnt: out std_logic_vector(width - 1 downto 0)); end component; signal clk_tb: std_logic := '0'; signal rst_tb: std_logic := '0'; signal cnt_tb: std_logic_vector(3 downto 0); begin UUT: ripple generic map(width => 4) port map(clk => clk_tb, rst => rst_tb, cnt => cnt_tb); clk_tb <= not clk_tb after 50 ns; process begin rst_tb <= transport '1'; wait for 200 ns; 2 rst_tb <= transport '0'; wait for 2000 ns; end process; end testbench; 代码 2 加法计数器的 test bench 代码 图 2 加法计数器的仿真结果波形 在同一时刻,加法计数器的输出可能有多位发生变化,因此,当使用组合 逻辑对输出进行译码时,会导致尖峰脉冲信号。使用约翰逊计数器可以避免这 个问题。 约翰逊计数器 约翰逊计数器是一种移位计数器,采用的是把输出的最高位取非,然后反 馈送到最低位触发器的输入端。约翰逊计数器在每个时钟下只有一个输出发生 变化。下面是约翰逊计数器的 VHDL 实现代码。 --file Name: ripple.vhd --Description: 带复位功能的约翰逊计数器 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity johnson is generic (width: integer := 4); port (clk, rst: in std_logic; cnt: out std_logic_vector(width - 1 downto 0)); end johnson; architecture a of johnson is signal cntQ: std_logic_vector(width - 1 downto 0); begin process(clk, rst) begin if(rst = '1') then cntQ <= (others => '0'); elsif (rising_edge(clk)) then cntQ(width - 1 downto 1) <= cntQ(width - 2 downto 0); cntQ(0) <= not cntQ(width - 1); end if; end process; 3 cnt <= cntQ; end a;  代码 3 约翰逊计数器 VHDL 代码 图 3 约翰逊计数器 RTL 视图 显然,约翰逊计数器没有有效利用寄存器的所有状态,假设最初值或复位 状态为 0000,则依次为 0000、0001 、0011、0111、1111、1110、1100 、1000、 0000 如此循环。再者,如果由于干扰噪声引入一个无效状态,如 0010,则无法 恢复到有效到循环中去,需要我们加入错误恢复处理,在此不再赘述。 分频器 如前所述,分频器的基础是计数器,设计分频器的关键在于输出电平翻转 的时机。下面使用加法计数器分别描述各种分频器的实现。 偶数分频器 偶数分频最易于实现,欲实现占空比为 50%的偶数 N 分频,一般来说有两 种方案:一是当计数器计数到 N/2-1 时,将输出电平进行一次翻转,同时给计 数器一个复位信号,如此循环下去;二是当计数器输出为 0 到 N/2-1 时,时钟输 出为 0 或 1,计数器输出为 N/2 到 N-1 时,时钟输出为 1 或 0,当计数器计数到 N-1 时,复位计数器,如此循环下去。需要说明的是,第一种方案仅仅能实现占 空比为 50%的分频器,第二种方案可以有限度的调整占空比,参考非 50%占空 比的奇数分频实现。 在如下所示的以 6 分频为例的 VHDL 代码中, architecture a 使用的是第一种 方案,architecture b 使用的是第二种方案。更改 configuration 可查看不同方案的 综合结果。 --filename clk_div1.vhd 4 --description: 占空比为 50%的 6 分频 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity clk_div1 is port(clk_in: in std_logic; clk_out: out std_logic); end clk_div1; --使用第一种方案 architecture a of clk_div1 is signal clk_outQ: std_logic := '0';--赋初始值仅供仿真使用 signal countQ: std_logic_vector(2 downto 0) := "000"; begin process(clk_in) begin if(clk_in'event and clk_in = '1') then if(countQ /= 2) then CountQ <= CountQ + 1; else clk_outQ <= not clk_outQ; CountQ <= (others =>'0'); end if; end if; end process; clk_out <= clk_outQ; end a; --使用第二种方案 architecture b of clk_div1 is signal countQ: std_logic_vector(2 downto 0); begin process(clk_in) begin if(clk_in'event and clk_in = '1') then if(countQ < 5) then countQ <= countQ + 1; else CountQ <= (others =>'0'); end if; end if; end process; process(countQ) begin if(countQ < 3) then clk_out <= '0'; else clk_out <= '1';  5 end if; end process; end b; configuration cfg of clk_div1 is for a end for; end cfg; 代码 4 偶数分频的 VHDL 代码 图 4图 5所示的分别是使用architecture a和architecture b的仿真结果波形。两者均 正确的实现了 50%占空比的 6 分频。 图 4 architecture a 的仿真结果 图 5 architecture b 的仿真结果 奇数分频器 实 现 非 50% 占 空 比 的 奇 数 分 频 , 如 实 现 占 空 比 为 20% ( 1/5 ) 、 40% (2/5)、60%(3/5)、80%(4/5)的 5 类 种方案;但如果实现占空比为 50%的奇数分频,就不能使用偶数分频中所采用 的方案了。 非 50%占空比的奇数分频 下面就以实现占空比为 40%的 5 分频分频器为例,说明非 50%占空比的奇数 分频器的实现。该分频器的实现对于我们实现 50%占空比的分频器有一定的借 鉴意义。 --filename clk_div2.vhd --description: 占空比为 40%的 5 分频 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity clk_div2 is port(clk_in: in std_logic; clk_out: out std_logic); end clk_div2; 6 architecture a of clk_div2 is signal countQ: std_logic_vector(2 downto 0); begin process(clk_in) begin if(clk_in'event and clk_in = '1') then if(countQ < 4) then countQ <= countQ + 1; else CountQ <= (others =>'0'); end if; end if; end process; process(countQ) begin if(countQ < 3) then clk_out <= '0'; else clk_out <= '1'; end if; end process; end a; 代码 5 占空比为 40%的 5 分频 仿真波形如图 6所示。 图 6 占空比为 40%的 5 分频仿真波形 50%占空比的奇数分频 通过待分频时钟下降沿触发计数,产生一个占空比为 40%(2/5)的 5 分频 的时钟相或,即可得到一个占空比为 50% 器。将产生的时钟与上升沿触发产生 的 5 分频器。 推广为一般方法:欲实现占空比为 50%的 2N+1 分频器,则需要对待分频时 钟上升沿和下降沿分别进行 N/(2N+1)分频,然后将两个分频所得的时钟信号相 或得到占空比为 50%的 2N+1 分频器。 下面的代码就是利用上述思想获得占空比为 50%的 7 分频器。需要我们分别 对上升沿和下降沿进行 3/7 分频,再将分频获得的信号相或。 7 --filename clk_div3.vhd --description: 占空比为 50%的 7 分频 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_ar th.all; use ieee.std_logic_unsigned.all; entity clk_div3 is port(clk_in: in std_logic; clk_out: out std_logic); end clk_div3; architecture a of clk_div3 is signal cnt1, cnt2: integer range 0 to 6; signal clk1, begin clk2: std_logic; process(clk_in)--上升沿 begin if(rising_edge(clk_in)) then if(cnt1 < 6) then cnt1 <= cnt1 + 1; else cnt1 <= 0; end if; if(cnt1 < 3) then clk1 <= '1'; else clk1 <= '0'; end if; end if; end process; process(clk_in)--下降沿 begin if(falling_edge(clk_in)) then if(cnt2 < 6) then cnt2 <= cnt2 + 1; else cnt2 <= 0; end if; if(cnt2 < 3) then clk2 <= '1'; else clk2 <= '0'; end if; end if; end process; clk_out <= clk1 or clk2;  8 end a;  代码 6 占空比为 50%的 7 分频 VHDL 代码 综合得到的RTL视图如图 7所示,仿真结果如图 8所示。 图 7 占空比为 50%的 7 分频 RTL 视图 图 8 占空比为 50%的 7 分频仿真波形 占空比为 50%的奇数分频可以帮助我们实现半整数分频。 半整数分频器 仅仅采用数字分频,不可能获得占空比为 50%的 N+0.5 分频,我们只可以 设计出占空比为(M+0.5)/(N+0.5)或者 M/(N+0.5)的分频器,M 小于 N。这种半整 数分频方法是对输入时钟进行操作,让计数器计数到某一个数值时,将输入时 钟电平进行一次反转,这样,该计数值只保持了半个时钟周期,因此实现半整 数分频。 如上所述,占空比为 50%的奇数分频可以帮助我们实现半整数分频,将占 空比为 50%的奇数分频与待分频时钟异或得到计数脉冲,下面的代码就是依靠 占空比为 50%的 5 分频实现 2.5 分频器的。 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity clk_div4 is 9 port(clk_in: in std_logic; clk_out: out std_logic); end clk_div4; architecture a of clk_div4 is signal cnt1, cnt2: integer range 0 to 4; signal clk1, clk2: std_logic; signal Pclk, signal cnt3: begin Lclk: std_logic; integer range 0 to 2; process(clk_in) begin if(rising_edge(clk_in)) then if(cnt1 < 4) then cnt1 <= cnt1 + 1; else cnt1 <= 0; end if; end if; end process; process(clk_in) begin if(falling_edge(clk_in)) then if(cnt2 < 4) then cnt2 <= cnt2 + 1; else cnt2 <= 0; end if; end if; end process; process(cnt1) begin if (cnt1 < 3) then clk1 <= '0'; else clk1 <= '1'; end if; end process; process(cnt2) begin if (cnt2 < 3) then clk2 <= '0'; else clk2 <= '1'; end if; end process; process(Lclk) begin  10 if(rising_edge(Lclk)) then if(cnt3 < 2) then cnt3 <= cnt3 + 1; else cnt3 <= 0; end if; end if; end process; process(cnt3) begin if(cnt3 < 1) then clk_out <= '0'; else clk_out <= '1'; end if; end process; Pclk <= clk1 or clk2; Lclk <= clk_in xor Pclk;--对输入时钟进行处理 end a; 代码 7 2.5 分频 VHDL 代码 正如仿真波形图 9所示,该分频器的占空比为 1.5/2.5,即 60%。 图 9 2.5 分频仿真波形 小数分频器 小数分频是通过可变分频和多次平均的方法实现的。例如要实现 4.7 分频, 只要在 10 次分频中,做 7 次 5 分频,3 次 4 分频就可以得到。再如要实现 5.67 分 频,只要在 100 次分频中,做 67 次 6 分频,33 次 5 分频即可。考虑到小数分频 器要进行多次两种频率的分频,必须设法将两种分频均匀。表 1以 2.7 分频为 例,小数部分进行累加,如果大于等于 10,则进行 3 分频,如果小于 10,进行 2 分频。 表 1 小数分频系数序列 序号 0  1  2  3  4  5  6  7  8  9  11 累 加 值 分 频 系数  7 2  14 3  11 3  8 2  15 3  12 3  9 2  16 3  13 3  10 3 下面的代码就是基于上述原理实现 2.7 分频。其中,architecture b 是使用累 分频 数选系 择的 机,architectur a 是直接使用已计算好的结果。 加器计算 --file name: clk_div6.vhd --description: 2.7 分频 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity clk_div6 is port(clk_in: in std_logic; clk_out: out std_logic); end clk_div6; architecture b of clk_div6 is signal clkoutQ: std_logic; signal ctrl: std_logic; signal cnt1: integer range 0 to 1; signal cnt2: integer range 0 to 2; begin clk_out <= clkoutQ; process(clkoutQ) variable tmp: integer range 0 to 20; begin if(rising_edge(clkoutQ)) tmp := tmp + 7; if(tmp < 10) then ctrl <= '1'; else ctrl <= '0'; tmp := tmp - 10; end if; end if; end process; process(clk_in) begin then if(clk_in'event and clk_in = '1') then if(ctrl = '1') then if(cnt1 < 1) then cnt1 <= cnt1 + 1; else  12 cnt1 <= 0; end if; if(cnt1 < 1) then clkoutQ <= '1'; else clkoutQ <= '0'; end if; else if(cnt2 < 2) then cnt2 <= cnt2 + 1; else cnt2 <= 0; end if; if(cnt2 < 1) then clkoutQ <= '1'; else clkoutQ <= '0'; end if; end if; end if; end process; end b; architecture a of clk_div6 is signal cnt: integer range 0 to 9; signal clkoutQ: std_logic; signal cnt1: integer range 0 to 1; signal cnt2: integer range 0 to 2; begin clk_out <= clkoutQ; process(clkOutQ) begin if(clkoutQ'event and clkoutQ = '1') then if (cnt < 9) then cnt <= cnt + 1; else cnt <= 0; end if; end if; end process; process(clk_in) begin if(clk_in'event and clk_in = '1') then case cnt is when 0|3|6 => if(cnt1 < 1) then cnt1 <= cnt1 + 1; else cnt1 <= 0;  13 end if; if(cnt1 < 1) then clkoutQ <= '1'; else clkoutQ <= end if; when others => '0'; if(cnt2 < 2) then cnt2 <= cnt2 + 1; else cnt2 <= 0; end if; if(cnt2 < 1) then clkoutQ <= '1'; else clkoutQ <= '0'; end if; end case; end if; end process; end a; configuration cfg of clk_div6 is for a end for; end cfg; 代码 8 2.7 分频 VHDL 代码 仿真波形如图 10所示,在cursor1 和cursor2 之间,我们可以清楚地看到 2.7 分 频的实现。按照占空比的定义,该分频器的占空比应为 10/27。 图 10 2.7 分频仿真波形 14 分数分频器  L 将小数分频的方法进行扩展,可以得到形如 M 的分数分频的方法,例 N 7 如, 2 13 分频,只要在 13 次分频中,进行 7 次 3 分频,6 次 2 分频就可以得到。 同样,为了将两种分频均匀,将分子部分累加,小于分母的,进行M分频,大于 7 等于分母的,进行(M+1)分频。表 2显示了13 2 的分频次序。 序号 0 累加  1  2  3  表 2 分数分频系数序列 4 5 6 7  8  9  10 11 12 值 分频 系数 7 2 14 3 8 2 15 3 7 9 2 16 10 17 11 18 12 19 13 3 2 3 2 3 2 3 3 仿照代码 8,给出 2 分频的代码如下: 13 --file name: clk_div7.vhd --description: (33/13)分频 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity clk_div7 is port(clk_in: in std_logic; clk_out: out std_logic); end clk_div7; archi
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 百科休闲 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服