一般常见的分频器的最小单位为1,并且输出时钟为50%占空比。对于N+0.5倍分频也不难实现,但是却难以实现50%占空比,本文参考网上的思路,给出了一种实现N+0.5分频器的实现方法以及Verilog仿真源码。
对于分频器,k分频说明分频后的时钟周期等于k倍原时钟周期,则 (n-0.5)分频的思路:
1、设输入时钟为clk,首先实现这样的非50%占空比n分频器:
①计数器cnt在输入时钟clk的上升沿从0到n-1循环计数(模n计数)
②在clk上升沿改变输出:当cnt==n-1时,输出为1,其余时刻输出为0。
2、将上述时钟周期减小半个原时钟周期,则可以得到N-0.5分频的时钟,如下:
在cnt==n-1后,立即将clk反相,则紧接着的下降沿将变成上升沿,上升沿将提前0.5个周期到达,cnt的值会在保持半个时钟周期后遇到上升沿而变为0,因而输出时钟周期为n-0.5倍clk时钟周期,因而实现了n-0.5分频。
3、clk0的反相逻辑可以用异或来实现:
令clk0=clk^phase;
当phase==0时,clk0=clk
当phase==1时,clk0=~clk
可见,phase的值决定着clk0的相位,只要在输出时钟的上升沿将phase置反,那么clk0也随之反相。
模块代码如下:
1 `timescale 10ps/1ps 2 //----------------------------------------- 3 //module name :clk_div 4 //function :n-0.5 frequency divider 5 //author :huangqiwei 6 //verision : 7 //----------------------------------------- 8 module clk_div(clk,clkout,clr); 9 parameter n = 5;//division number 10 input clk,clr; 11 output clkout; 12 reg [31:0]cnt; 13 reg phase,clkout; 14 wire clk0; 15 16 assign #1 clk0 = clk^phase;//change clk phase 17 always @(negedge clr or posedge clk0)begin 18 $stop(1); 19 if(!clr) 20 cnt<=32'd0; 21 else if(cnt == n-32'd1) 22 cnt<=32'd0; 23 else 24 #2 cnt<=cnt+32'd1; 25 end 26 27 always @(negedge clr or posedge clk0)begin 28 if(!clr) 29 clkout<=0; 30 else if(cnt == n-1) 31 clkout<=1; 32 else 33 clkout<=0; 34 end 35 36 always @(negedge clr or posedge clkout)begin 37 if(!clr) 38 phase <=0; 39 else 40 #1 phase <= ~phase; 41 end 42 endmodule
验证代码如下:
1 `timescale 10ps/1ps 2 module tst(); 3 reg clk,clr; 4 wire clkout; 5 6 always #50 clk =~clk; 7 initial begin 8 clr = 1; 9 clk = 0; 10 #10 clr =0; 11 #10 clr = 1; 12 end 13 14 15 clk_div div5(.clk(clk),.clkout(clkout),.clr(clr)); 16 defparam div5.n = 7; 17 endmodule
modelsim仿真结果如下: