2017-04-14 334 views
1

就像它说的那样,我有一个100MHz时钟(来自Nexus 3 Spartan 6板卡),我想把它分成16MHz时钟。我做了1Mhz和60Hz时钟没有问题,但我有一些问题获得干净的16MHz信号。将100MHz时钟划分为16MHz时钟[Verilog]

这里就是我目前正在测试出:

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 
[email protected](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 
[email protected](posedge clk_100MHz) begin 
    if(count_1MHz == 50) begin 
     clk_1MHz = ~clk_1MHz; 
     count_1MHz = 1; 
    end 
    count_1MHz = count_1MHz + 1; 
end 

我有我的1Mhz为和60赫兹(1秒)分,但16MHz的是正在痛苦。有没有更好的方法(同时留在Verilog中)?

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

回答

0

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

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

最简单的方法从100MHz到16MHz的是由4倍增,然后通过25. 16.

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) 
); 
划分DCM也可以生成在同一时间1 MHz的时钟除以输出得到

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

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

0

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

[email protected](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时,时钟周期发生递减。