• 预分频之三


    半分频(N+0.5)

    波形分析(4.5分频)

    分析可知,9 = 4.5 + 4.5 = 4 + 5 = 5 + 4 = (1.5 + 3) * 2。
    先使用两个信号pre9与pre9_inv将9划分为两种实现方式,然后再通过错位的波形运算得到4.5分频。

    参考代码

    verilog code

    module decimalprescaler(
                            output     prescaler,
                            input      clk,
                            input      rstn
                           );
    parameter   N = 9;  //4.5分频
    
    reg [7:0]   cnt;
    reg [7:0]   cnt_next;
    
    reg         pre9;
    reg         pre9_inv;
    reg         pre9_inv_reg;
    
    
    //计数器
    always@(posedge clk,negedge rstn)
    begin
        if(!rstn)
            cnt <= 7'b0;
        else
            cnt <= cnt_next;
    end
    
    always@(*)
    begin
        if(cnt == (N - 1'b1))  //周期设定( 0 - N-1 ) N分频
            cnt_next = 0;
        else
            cnt_next = cnt + 1'b1;
    end
    
    
    //产生pre9
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre9  <= 1'b0;
    end
    else
    begin if(cnt == 7'b1000 || cnt == 7'b0100)   //注意计数到(N - 1)
             pre9 <= 1'b1;
          else if(cnt == 7'b0000 || cnt == 7'b0101)
             pre9 <= 1'b0;
    end
    
    //产生pre9_inv
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre9_inv  <= 1'b0;
    end
    else
    begin if(cnt == 7'b1000 || cnt == 7'b0011)
             pre9_inv <= 1'b1;
          else if(cnt == 7'b0000 || cnt == 7'b0100)
             pre9_inv <= 1'b0;
    end
    
    //使用下降沿处理得到0.5拍
    always @ (negedge clk,negedge rstn) //注意使用下降沿
    begin
      if(!rstn)
         pre9_inv_reg <= 1'b0;
      else
         pre9_inv_reg <= pre9_inv;
    end
    
    assign prescaler = pre9 | pre9_inv_reg;
    endmodule
    

    testbench

    module decimalprescaler_tb;
    
    reg                   clk;
    reg                   rstn;
    wire                  prescaler;
    
    initial
    begin
        clk   = 0;
        rstn  = 0;
        @(posedge clk)   rstn = 1;
     
        repeat(100) @(posedge clk);
        @(posedge clk)   $finish;
    end
    
    always #5  clk = ~clk;
    
    initial begin
      $fsdbDumpfile("test.fsdb");
      $fsdbDumpvars();
    end
    
    decimalprescaler    u_decimalprescaler(
                                    .prescaler(prescaler),
                                    .clk(clk),
                                    .rstn(rstn)
                                    );
    endmodule
    

    仿真结果


    学习更多

    4.5分频的另一种方法(更接近50%占空比)

    波形分析

    分析可知,4.5 = 2 + 2.5,我们可以得到上文中更宽的有效边沿,以接近50%占空比。

    部分参考代码

    verilog code

    //产生pre9
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre9  <= 1'b0;
    end
    else
    begin if(cnt == 7'b0001 || cnt == 7'b0110)
             pre9 <= 1'b1;
          else if(cnt == 7'b0011 || cnt == 7'b1000)
    
             pre9 <= 1'b0;
    end
    
    //产生pre9_inv
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre9_inv  <= 1'b0;
    end
    else
    begin if(cnt == 7'b0001 || cnt == 7'b0101)
             pre9_inv <= 1'b1;
          else if(cnt == 7'b0011 || cnt == 7'b0111)
             pre9_inv <= 1'b0;
    end
    

    testbench 与上文同一个testbench

    仿真结果


    5.5分频

    波形分析

    分析思路,11 = 5.5 + 5.5 = 5 + 6 = 6 + 5 = (1.5 + 4) + (1.5 + 4)

    参考代码

    verilog code

    module decimalprescaler(
                            output     prescaler,
                            input      clk,
                            input      rstn
                           );
    parameter   N = 11;  //5.5分频
    
    reg [7:0]   cnt;
    reg [7:0]   cnt_next;
    
    reg         pre11;
    reg         pre11_inv;
    reg         pre11_inv_reg;
    
    
    //计数器
    always@(posedge clk,negedge rstn)
    begin
        if(!rstn)
            cnt <= 7'b0;
        else
            cnt <= cnt_next;
    end
    
    always@(*)
    begin
        if(cnt == (N - 1'b1))  //周期设定( 0 - N-1 ) N分频
            cnt_next = 0;
        else
            cnt_next = cnt + 1'b1;
    end
    
    
    //产生pre11
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre11  <= 1'b0;
    end
    else
    begin if(cnt == 7'b1010 || cnt == 7'b0101)  //注意计数到(N-1)
             pre11 <= 1'b1;
          else if(cnt == 7'b0000 || cnt == 7'b0110)
             pre11 <= 1'b0;
    end
    
    //产生pre11_inv
    always@(posedge clk,negedge rstn)
    if(!rstn)
    begin
      pre11_inv  <= 1'b0;
    end
    else
    begin if(cnt == 7'b1010 || cnt == 7'b0100)
             pre11_inv <= 1'b1;
          else if(cnt == 7'b0000 || cnt == 7'b0101)
             pre11_inv <= 1'b0;
    end
    
    //使用下降沿处理得到0.5拍
    always @ (negedge clk,negedge rstn) //注意使用下降沿
    begin
      if(!rstn)
         pre11_inv_reg <= 1'b0;
      else
         pre11_inv_reg <= pre11_inv;
    end
    
    assign prescaler = pre11 | pre11_inv_reg;
    endmodule
    

    testbech 同上文

    仿真结果


    问题思考:可以像4.5分频使用两种方法吗?


    参考资料

    [1]. 用Verilog语言实现奇数倍分频电路3分频、5分频、7分频
    [2]. 基于Verilog的奇数偶数小数分频器设计

  • 相关阅读:
    多线程设计的要素—任务线程确定
    https://www.neroxie.com/2019/01/22/深入理解GCD之dispatch-group/
    性能、指标、监控、数据大盘
    iOS PhotoKit 笔记
    多线程的核心问题是控制共享变量的无序访问(读写)
    objective-c arc -对象、变量、变量修饰符、赋值
    大幅降低存储成本,Elasticsearch可搜索快照是如何办到的?
    压测利器:TarsBenchmark正确打开方式
    跨国合作:Serverless Components 在腾讯云的落地和实践
    前端视角谈物联网三部曲:连接智能、交互智能、数据智能
  • 原文地址:https://www.cnblogs.com/OneFri/p/6055606.html
Copyright © 2020-2023  润新知