查看: 24|回复: 0

Verilog实现小数分频

[复制链接]
  • TA的每日心情

    2024-11-15 16:19
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    292

    主题

    26

    回帖

    2978

    积分

    管理员

    积分
    2978
    发表于 2024-11-15 11:50:12 | 显示全部楼层 |阅读模式
    由于Verilog只能在时钟的上升沿或者下降沿改变电路的状态,因此精确的小数分频是无法通过Verilog实现的,我们只能实现平均意义上的小数分频,即某段时间内,该时钟的周期平均为T(T为小数)。

    我们以8.6分频为例,来阐述小数分频的实现方法。

    T=8.6 对应于M.N(即M=8|N = 6),T也可以表示为 T = M + b/(a+b)

    将M通分至分母(a+b),则T = ( Ma+(M+1)b )/( a+b),这里我们发现组成小数分频使用了a个M分频和b个M+1分频的整数分频电路。

    这个方法被称作”双模前置小数分频“,其最重要的核心是M分频和M+1分频这个相近频率

    因此,对于8.6分频,整数部分为8,我们选用8分频和9分频来进行合成,列出二元方程组如下

    8a+9b=43

    a+b=5

    得出来a和b的解为2和3,也就是说,在五个周期内,有两个8分频和3个9分频时钟,从而在这五个周期内,平均周期为(2x8+3x9)/(3+2)=8.6。

    以下是RTL代码实现:

    module clkdiv(
        input logic clk,
        input logic rst,
        output logic clkout
    );

    //8.6=43/5
    //a*8+b*9=43
    //a+b=5
    //-->a=2,b=3
    //16+27=43
    logic [4:0] cnt8;
    logic [4:0] cnt9;
    logic [4:0] cnt;
    //cnt
    always_ff@(posedge clk,posedge rst)
    if(rst)
        cnt<=0;
    else if(cnt==0||cnt==2)   //9 clkdiv when cnt=0,2,4
    begin
        if(cnt9==9-1)
            cnt<=cnt+1;
        else
            cnt<=cnt;
    end
    else if(cnt==4)
    begin
        if(cnt9==9-1)
            cnt<=0;
        else
            cnt<=cnt;
    end
    else if(cnt==1||cnt==3)   //8 clkdiv when cnt=1,3
    begin
        if(cnt8==8-1)
            cnt<=cnt+1;
        else
            cnt<=cnt;
    end
    //cnt9
    always_ff@(posedge clk,posedge rst)
    if(rst)
        cnt9<=0;
    else if(cnt==0||cnt==2||cnt==4)
        if(cnt9==9-1)
            cnt9<=0;
        else
            cnt9<=cnt9+1;
    else
        cnt9<=0;
    //cnt8
    always_ff@(posedge clk,posedge rst)
    if(rst)
        cnt8<=0;
    else if(cnt==1||cnt==3)
    if(cnt8==8-1)
        cnt8<=0;
    else
        cnt8<=cnt8+1;
    else
        cnt8<=0;
    //clkout
    always_comb
    begin
        case(cnt)
            0,2,4:if(cnt9==9-1)
                     clkout=1;
                  else
                     clkout=0;
            1,3:if(cnt8==8-1)
                     clkout=1;
                else
                     clkout=0;
            default:clkout=0;
        endcase
    end
    endmodule

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    友情链接:

    返回顶部 返回列表