【问题标题】:Dividing a 100MHz clock into a 16MHz clock [Verilog]将 100MHz 时钟划分为 16MHz 时钟 [Verilog]
【发布时间】:2017-04-14 20:49:18
【问题描述】:

正如锡上所说,我有一个 100MHz 时钟(取自 Nexys 3 Spartan 6 板),我想将它分成 16MHz 时钟。我制作了 1Mhz 和 60Hz 时钟没有问题,但我在获得干净的 16MHz 信号时遇到了一些问题。

这是我目前正在测试的内容:

module clk_gen(
    input clk_100MHz,
      output reg clk_16MHz,
    output reg clk_1MHz,
    output reg clk_1s );

integer count_16MHz;
integer count_1MHz;
integer count_1s;
integer skip_cnt;

initial begin
    count_16MHz = 1;
    count_1MHz = 1;
    count_1s = 1;
    skip_cnt = 1;
    clk_1s = 1'b0;
    clk_1MHz = 1'b0;
    clk_16MHz = 1'b0;
end

//16MHz
always@(posedge clk_100MHz) begin
     //8*(100Mhz/6.25) == 7*(100MHz/6)+((100MHz/8))
     if((skip_cnt == 8) & (count_16MHz == 4)) begin
        clk_16MHz = ~clk_16MHz;
        skip_cnt = 1;
        count_16MHz = 1;
     end
     else if((skip_cnt < 8) & (count_16MHz == 3)) begin
        clk_16MHz = ~clk_16MHz;
        skip_cnt = skip_cnt + 1;
        count_16MHz = 1;
   end
     count_16MHz = count_16MHz + 1;
end
//1MHz
always@(posedge clk_100MHz) begin
     if(count_1MHz == 50) begin
        clk_1MHz = ~clk_1MHz;
        count_1MHz = 1;
     end
     count_1MHz = count_1MHz + 1;
end

我有 1Mhz 和 60Hz(1 秒)的分频器,但 16MHz 很痛苦。有没有更好的方法(留在 Verilog)?

不幸的是,由于在 1MHz 时钟周期之间发生了 16 次移位操作,我确实想要一个非常严格的 16MHz。我唯一的其他攻击方法可能是将 1MHz 降低到更慢且更容易除以 16 的值。

【问题讨论】:

    标签: verilog clock


    【解决方案1】:

    使用 FPGA 上可用的时钟资源。

    由于您使用的是 Spartan-6,因此您可以访问 DCM_CLKGEN 和 DCM_SP 原语。设置这些最简单的方法是使用 Xilinx 时钟向导,但如果您真的想使用 Verilog 进行设置,您可以直接实例化 DCM_CLKGEN。

    从 100 MHz 到 16 MHz 的最简单方法是乘以 4,然后除以 25。DCM 还可以通过将输出除以 16 同时生成 1 MHz 时钟。

    DCM_CLKGEN #(
        .CLKIN_PERIOD("100 MHZ"),
        .CLKFX_MULTIPLY(4),
        .CLKFX_DIVIDE(25),
        .CLKFXDV_DIVIDE(16)
    ) clkgen_100to16and1 (
        .RST     (1'b0),
        .CLKIN   (clk_100MHz),
        .CLKFX   (clk_16MHz),
        .CLKFXDV (clk_1MHz)
    );
    

    请注意,16 MHz 和 1 MHz 输出之间没有保证的相位关系。

    有关 Spartan-6 中可用的 DCM 和其他时钟资源的详细信息,请参阅 Xilinx 文档UG382: Spartan-6 FPGA Clocking Resources

    【讨论】:

      【解决方案2】:

      听起来您想用数字电路实现小数时钟分频器。由于时钟的分频是一小部分,输出时钟将在两个时钟周期之间抖动(在您的情况下,在 100 MHz 时钟的 6 到 7 个周期之间),但平均值将是 100/16=6.25 个周期长。如果分数小于或等于原始频率的一半,如下例所示:

      always@(posedge clk_100MHz) begin
        if(count_16MHz >= 100) begin
          clk_16MHz <= 1;
          count_16MHz <= count_16MHz - 100 + 16;
        end
        else begin
          count_16MHz <= count_16Mhz + 16;
          if(count_16MHz >= 50) begin
            clk_16MHz <= 0
          end
        end
      end
      

      分频器的关键是它不会被重置为 0,它只会在时钟周期发生时减 100。

      如果分数大于二分之一,此电路将不起作用。由于该电路仅在原始时钟的时钟上计时,在这种情况下,没有足够的时钟来生成生成时钟的上升沿和下降沿。

      这是一个实现,它始终在较快时钟的半个时钟周期内保持时钟为高电平,因此可以在大于 1/2 的比率下工作。

      always@(posedge clk_100MHz) begin
        if(count_75MHz >= 100) begin
          pos <= ~neg;
          count_75MHz <= count_75MHz - 100 + 75;
        end
        else begin
          count_75MHz <= count_75Mhz + 75;
        end
      end
      
      always@(negedge clk_100MHz) begin
        neg <= pos;
      end
      
      assign clk_75MHz <= pos ^ neg;
      

      在这种情况下,posege 通过使两个信号不同而使时钟变高,而 negedge 总是使时钟变低。

      【讨论】:

      • 您能为此分享任何文档吗?这是否也适用于任何非整数除法?
      • @KaranShah 是的,这是通用的,可用于生成除以任意分数的时钟。我已经将它与赛普拉斯 PSoC 微控制器一起使用,然后将生成的时钟输入 PLL 以平滑和缩放生成的时钟。这是从相互锁定的 USB 时钟创建音频时钟的一种经济有效的方法。您应该能够轻松搜索有关此技术的参考资料。
      • 这种方法有什么限制吗?如果我想从 100MHz 变成 75MHz。
      • @KaranShah 是的,有一个限制。我已经更新了我的答案,并补充说这仅适用于分数
      • 你知道 > 1/2 * freq (75MHz from 100MHz) 的任何逻辑吗?
      猜你喜欢
      • 2020-09-03
      • 1970-01-01
      • 1970-01-01
      • 2016-02-10
      • 1970-01-01
      • 2021-11-29
      • 2020-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多