Verilog双时钟场景下慢时钟上升沿触发的单快周期脉冲实现咨询
实现方案
整数分频场景实现(本题适用:18M为快时钟、6M为慢时钟,刚好为3倍整数分频)
这种场景下用快时钟采样慢时钟边沿的方案最稳定,输出脉冲必然和慢时钟上升沿对齐,且持续1个快时钟周期:
- 第一步:用快时钟对慢时钟打两拍做同步处理,避免亚稳态风险
reg slow_clk_r1, slow_clk_r2; always @(posedge clk_fast) begin slow_clk_r1 <= clk_slow; slow_clk_r2 <= slow_clk_r1; end
- 第二步:通过两个寄存器的差值提取慢时钟上升沿,得到目标脉冲
assign pulse_1t_fast = slow_clk_r1 & (~slow_clk_r2);
生成的pulse_1t_fast信号完全符合需求:每次慢时钟上升沿出现后,第一个快时钟上升沿就会输出1个快时钟周期的高脉冲,和慢时钟上升沿完全对齐。
现有代码修正
你当前代码里用5位计数器最高位生成的clk6M实际是18M的16分频,输出频率为1.125M而非6M,脉冲匹配的是计数器等于10000的时刻,虽然和分频出来的时钟上升沿对齐,但分频系数完全不符合要求。适配6M输出的修改后代码如下:
module clock_check; reg clk18M = 1'b0; always #1 clk18M <= ~clk18M; // 18M快时钟,周期2ns wire clk6M; wire clk_puls; reg [1:0] cnt; // 3分频计数器 always @(posedge clk18M) begin cnt <= (cnt == 2'd2) ? 2'd0 : cnt + 2'd1; end // 生成占空比50%的6M时钟 reg clk6M_r; always @(posedge clk18M) begin if(cnt == 2'd1) clk6M_r <= ~clk6M_r; end assign clk6M = clk6M_r; // 生成对齐6M上升沿的1个18M周期脉冲 assign clk_puls = (cnt == 2'd2); initial begin #200; $finish(); end initial begin $dumpfile("dump.vcd"); $dumpvars(0); end endmodule
非整数分频场景说明
如果慢时钟不是快时钟的整数分频,需要先对慢时钟做异步边沿检测,搭配脉冲同步电路实现,需要额外处理跨时钟域亚稳态问题,逻辑会更复杂。
内容的提问来源于stack exchange,提问作者Amineko Stone
相关产品推荐
相关产品推荐

