将100MHz时钟分成16MHz时钟[Verilog]

时间:2017-04-14 20:49:18

标签: verilog clock

正如它在锡上所说,我有一个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。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

听起来你想要用数字电路实现分数时钟分频器。由于时钟分频是一小部分,输出时钟将在两个时钟周期之间抖动(在您的情况下,在100 MHz时钟的6到7个周期之间),但平均值将是100/16 = 6.25个周期。这是一个实现:

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

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