偶数、奇数、小数分频器
1、偶数
通过计数器计数到分频数中值实现,如实现8分频,DIV_PARA=8;
1、复位后,clk_out=0;
2、计数值为0——DIV_PARA-1,
3、计数到3(即DIV_PARA/2 – 1)时, clk_out=1;
4、计数到7(即DIV_PARA-1)时,clk_out=0;
module divider_even ( clk, clk_out, rstn ); input wire clk; input wire rstn; output reg clk_out; parameter RATIO=8; reg [7:0]temp; always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_out<=0; end else if (temp==RATIO/2-1) begin clk_out<=1; end else if (temp==RATIO-1) begin clk_out<=0; end end always @(posedge clk or negedge rstn) begin if(!rstn)begin temp<=0; end else if (temp==RATIO-1) begin temp<=0; end else temp=temp+1; end endmodule
2、奇数
分别利用时钟上升沿下降沿,利用计数器计数到分频中值(向下取整)翻转,得到两组波形相或得到,如实现7分频,DIV_PARA=7;
1、复位后clk_out=0;
2、计数值为0——DIV_PARA-1,
3、clk_cnt1与clk_cnt2分别对应两组分频的计数值,
4、分别利用时钟上升沿和下降沿对clk_cnt1与clk_cnt2计数,
5、分别计数到3((DIV_PARA-1)/2 )时,clk_out1=1,clk_out2=1;
6、分别计数到3(DIV_PARA-1 )时,clk_out1=0,clk_out2=0;
7、assign clk_out=clk_out1|clk_out2;
module divider_odd ( clk, clk_out, rstn ); input wire clk; input wire rstn; output clk_out; parameter RATIO=7; reg [7:0]temp; reg clk_out1; reg clk_out2; assign clk_out=clk_out1|clk_out2; always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_out1<=0; end else if (temp==(RATIO-1)/2) begin clk_out1<=1; end else if (temp==RATIO-1) begin clk_out1<=0; end end always @(negedge clk or negedge rstn) begin if (!rstn) begin clk_out2<=0; end else if (temp==(RATIO-1)/2) begin clk_out2<=1; end else if (temp==RATIO-1) begin clk_out2<=0; end end always @(posedge clk or negedge rstn) begin if (!rstn) begin temp<=0; end else if(temp==RATIO-1) temp<=0; else temp=temp+1; end endmodule //divider_odd
3、小数
将小数化为整数/10的形式(一位小数,两位小数/100,以此类推),即DIV_PARA*10个clk相当于输出的10个clk,如实现10.1分频,DIV_PARA=10.1;
10*DIV_PARA=101,即在101个clk想同的时间内,输出要产生10个clk_out
可将101使用两个相邻的值(N和N+1)进行分解,要保证aN+b(N+1)=101;a+b=10;(使用相邻的值是为了保证输出波形有相近的占空比),解出可令N=10,a=9,b=1
即我们可以利用9次10分频和1次11分频,拼出10.1分频(如果次数不为1的情况,需要将次数少的尽可能平均的插入到次数多的)
1、分别实现N分频和N+1分频,对应计数变量为clk_cnt1和clk_cnt2
2、计数器选择信号en,用于选择输出信号的频率
3、频率计数值fre_cnt,用于计数当前周期(101个clk)中输出波形的个数
4、en控制计数器计数;en=0时,clk_cnt1累加(到N-1清零),clk_cnt2清零;en=1时,clk_cnt2累加(到N-1清零),clk_cnt1清零;
5、en控制分频器输出;en=0时,clk_cnt1累加到N/2 -1,clk_out=1; clk_cnt1累加到N-1,clk_out=0。en=1时,clk_cnt2累加到N /2 ,clk_out=1; clk_cnt1累加到N,clk_out=0
6、en=0时,clk_cnt1变为0,则fre_cnt加一;en=1时,clk_cnt2变为0,则fre_cnt加一;fre_cnt范围为0-9。而fre_cnt=9时意味着要切换频率,en=1;其他情况下en=0;
module fdiv10_1(clk,rstn,clk_out); input clk,rstn; output reg clk_out; reg [3:0] clk_cnt1,clk_cnt2; reg [3:0] fre_cnt; reg en; always @(posedge clk or negedge rstn) begin if(!rstn)begin fre_cnt<=0; end else if (!en) begin if(clk_cnt1==4) clk_out<=1; else if (clk_cnt1==9) begin clk_out<=0; fre_cnt<=fre_cnt+1; end else clk_out<=clk_out; end else begin if(clk_cnt2==5) clk_out<=1; else if (clk_cnt2==10) begin clk_out<=0; fre_cnt<=0; end else clk_out<=clk_out; end end always @(fre_cnt or negedge rstn) begin if (!rstn) begin en<=0; end else if(fre_cnt==9) begin en<=1; end else en<=0; end always @(posedge clk or negedge rstn) begin if (!rstn) begin clk_cnt1<=0; clk_cnt2<=0; end else if(!en) begin if (clk_cnt1==9) begin clk_cnt1<=0; end else begin clk_cnt1<=clk_cnt1+1; clk_cnt2<=0; end end else begin if (clk_cnt2==10) begin clk_cnt2<=0; end else begin clk_cnt2<=clk_cnt2+1; clk_cnt1<=0; end end end endmodule
clk周期为20ns,clk_out第一个上升沿起始位置310ns,第十个对应2330ns,即2020ns时间内10个时钟沿,每个周期202ns,即clk的10.1分频
4、TestBench
module divider_tb ( ); reg clk; reg rstn; wire clk_out_even; wire clk_out_odd; wire clk_out_fra; initial begin clk=0; forever #10 clk=~clk; end initial begin rstn=0; #30 rstn=1; end divider_even u_divider_even ( .clk ( clk ), .rstn ( rstn ), .clk_out ( clk_out_even ) ); divider_odd u_divider_odd ( .clk ( clk ), .rstn ( rstn ), .clk_out ( clk_out_odd ) ); fdiv10_1 u_fdiv10_1( .clk ( clk ), .rstn ( rstn ), .clk_out ( clk_out_fra ) ); initial begin $fsdbDumpfile("tb.fsdb"); $fsdbDumpvars; #10000 $finish; end endmodule