玩转VHDL-003分频

2020-02-02 11:52发布


分频器
我们知道串口常用的波特率为300,600, 1200, 2400, 4800, 9600, 19200, 38400, 43000, 56000, 57600, 115200。在用FPGA实现UART协议时,我们期望最好有上述波特率整数倍的系统时钟,但这样的时钟频率不常见。不过,我们可以通过分数分频的方法实现这一功能。为清晰阐明分数分频,在此先不考虑4300bps的波特率。
假设FPGA系统时钟为80M,如果我们能通过分数分频实现64.512M的时钟,那么除43000外其他所有波特率值均可以整除64.512M。再分别实现各个波特率,接下来就只剩下整数分频的问题了。由于64512 / 80000 = 504 / 625,那么在80M时钟下每625个时钟取504个时钟则等效为64.512M时钟了。
进一步分析,625=125×5504=125×4 + 4。设计两个计数器partsshareshare按照80M时钟节拍模5计数,而partsshare=4为节拍模125计数。那么partsshare的组合625个时钟周期重复一次。每个share5个时钟周期,取4个周期,这样在625个时钟周期中获得了500个周期。再从125parts中选择4个,在这4个选出的partsshare的第5个周期也被选择使能,那么就获得了125×4 + 4 = 504个周期。程序代码如下:
--fraction_div.vhdLibrary ieee;Useieee.std_logic_1164.all,ieee.std_logic_unsigned.all;Library ucxLib; Use ucxLib.ucx_2008pkg.all;
Entity fraction_div is port(         clock                                                        :in std_logic;         q                                                            :out std_logic         );End fraction_div;
Architecture myFavor of fraction_div is         signal parts                                  : std_vector(0to 6);         signal share                                 : std_vector(0to 2);         signalclk32256K,clk_en                  : std_logic :='0';BeginProcess(clock) begin         if rising_edge(clock)then                   RstIncDec(share,share(0), '1');                   RstIncDec(parts,share(0) and parts=124, share(0));                   clk_en <=not share(0) or parts=0 or parts=31 or parts=62 or parts=93;         end if;End process;Process(clock, clk_en) begin         if rising_edge(clock)and clk_en then                   clk32256K<= not clk32256K;         end if;End process;q <= clk32256K;End myFavor; fraction_div.png
fraction_div.vhd实现的功能是输入clock为80MHz,输出q为32.256M。即表明程序中rising_edge(clock) and clk_en实现64.512M时钟功能。不过q的占空比不是固定50%。
代码行18表明parts在parts=124和share >=4时清零,否则在share>=4条件下增1计数。行19中not share(0)表示share=0,1,2,3四个周期,parts=0or parts=31 or parts=62 or parts=93表示均匀选取4个parts。行18中与运算share(0)and parts=124第一个参数share(0)是std_logic型,第二个参数parts=124是boolean。这样书写可以编译通过,因为在ucx_2008pkg.vhd中重载了and运算符。
         Function"and"(bL: std_logic;  bR:boolean) return std_logic is         begin                   return bLand STDZ(bR);         End;         Function"and"(bL: boolean;             bR:std_logic) return boolean is         begin                   return bLand bR='1';         End;运算符and重载后,boolean和std_logic两个不同类型的变量运算后结果同第一个变量。类似地可以重载or,xor,nand,nor和xnor。并加入到自定义库中。


0条回答

一周热门 更多>