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

 

 

版权声明:本文为wt2110原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wt2110/p/14000496.html