将100MHz时钟划分为16MHz时钟[Verilog]
正如锡上所说,我有一个100MHz的时钟(取自Nexys 3 Spartan 6板),我想把它分成16MHz的时钟。我制作了1Mhz和60Hz的时钟,没有问题,但我在获取清晰的16MHz信号时遇到了一些问题 以下是我目前正在测试的内容:将100MHz时钟划分为16MHz时钟[Verilog],verilog,clock,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_
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
模块时钟发电机(
输入时钟100MHz,
输出调节时钟16MHz,
输出调节时钟1MHz,
输出寄存器clk_1s);
整数计数_16MHz;
整数计数_1MHz;
整数计数_1s;
整数跳跃;
初始开始
计数_16MHz=1;
计数_1MHz=1;
计数1s=1;
跳过cnt=1;
时钟1s=1'b0;
时钟频率1MHz=1'b0;
时钟频率16MHz=1'b0;
结束
//16MHz
始终@(posedge时钟100MHz)开始
//8*(100Mhz/6.25)==7*(100Mhz/6)+(100Mhz/8))
如果((跳过cnt==8)和(计数16MHz==4))开始
clk_16MHz=~clk_16MHz;
跳过cnt=1;
计数_16MHz=1;
结束
否则如果((跳过cnt<8)和(计数16MHz==3))开始
clk_16MHz=~clk_16MHz;
skip_cnt=skip_cnt+1;
计数_16MHz=1;
结束
计数_16MHz=计数_16MHz+1;
结束
//1MHz
始终@(posedge时钟100MHz)开始
如果(计数频率=50)开始
clk_1MHz=~clk_1MHz;
计数_1MHz=1;
结束
计数频率=计数频率+1;
结束
我有1Mhz和60Hz(1秒)的分频,但16MHz是一种痛苦。有没有更好的方法(在Verilog中)
不幸的是,我确实想要一个非常严格的16MHz,因为在1MHz时钟周期之间会发生16次移位操作。我唯一的另一种攻击方法可能是将1MHz降低到较慢的速度,更容易除以16。使用FPGA上可用的时钟资源 由于您使用的是Spartan-6,因此可以访问DCM_CLKGEN和DCM_SP原语。设置这些的最简单方法是使用Xilinx时钟向导,但是如果您真的想使用Verilog,可以直接实例化DCM_CLKGEN 从100MHz到16MHz的最简单方法是乘以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文档。听起来您想用数字电路实现分数时钟分频器。由于时钟的划分是一个分数,因此输出时钟将在两个时钟周期之间抖动(在您的情况下,在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
始终@(posedge时钟100MHz)开始
如果(计数16MHz>=100)开始
clk_16MHz您可以共享此文档吗?这也适用于任何非整数除法吗?@KaranShah是的,这是通用的,可以用来产生被任何分数除法的时钟。我已经将其与Cypress PSoC微控制器一起使用,然后将产生的时钟输入PLL,以平滑和缩放产生的时钟。这是一种从相互锁定的USB时钟创建音频时钟的经济高效的方法。您应该能够轻松地搜索有关此技术的参考。此方法有任何限制吗?如果我想从100MHz制作75MHz。@KaranShah是的,有一个限制。我更新了我的答案,补充说这只适用于分数。你知道>1/2*freq(从100MHz到75MHz)的逻辑吗?
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;