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