Verilog 脉冲同步电路设计
2026/6/26 7:20:01 网站建设 项目流程

一、题目分析

本题要求实现一个脉冲同步电路,将 A 时钟域中的单周期脉冲 data_in,同步到 B 时钟域中,并在 B 时钟域重新生成一个单周期宽度的脉冲 dataout。

题目中 clk_fast 是 A 时钟域时钟,clk_slow 是 B 时钟域时钟。A 时钟域频率是 B 时钟域的 10 倍,也就是说 clk_fast 比 clk_slow 快很多。如果直接把 data_in 接到慢时钟域中采样,就可能出现慢时钟采不到快时钟单周期脉冲的情况。

因此,本题不能简单地使用两级寄存器直接同步 data_in,而是需要先在快时钟域中把脉冲转换成电平变化,再把这个电平变化同步到慢时钟域中,最后在慢时钟域中通过边沿检测重新产生脉冲。

二、解题思路

由于 data_in 是 clk_fast 时钟域中的单周期脉冲,而 clk_slow 比 clk_fast 慢很多,如果 data_in 只保持一个 clk_fast 周期,那么 clk_slow 很可能刚好错过这个脉冲,导致同步失败。

所以这里使用“脉冲转翻转信号”的方式。具体做法是,在 clk_fast 时钟域中定义一个寄存器 data_in_fast_reg。当检测到 data_in 为 1 时,不是直接传递这个脉冲,而是让 data_in_fast_reg 翻转一次。这样一来,原本很窄的脉冲就变成了一个稳定的电平变化。只要 data_in_fast_reg 发生翻转,就代表快时钟域中出现过一次输入脉冲。

然后在 clk_slow 时钟域中,对 data_in_fast_reg 进行多级寄存器同步。代码中使用了三个寄存器 data_in_slow_reg1、data_in_slow_reg2 和 data_in_slow_reg3。前两级主要用于降低跨时钟域亚稳态的影响,第三级用于和第二级做比较。

最后通过异或运算:dataout = data_in_slow_reg2 ^ data_in_slow_reg3;当同步后的信号发生变化时,第二级和第三级寄存器的值会有一个时钟周期不同,此时异或结果为 1,于是在慢时钟域中产生一个单周期脉冲 dataout。这样就实现了从快时钟域到慢时钟域的脉冲同步。

三、Verilog 代码

`timescale 1ns/1ns module pulse_detect( input clk_fast , input clk_slow , input rst_n , input data_in , output dataout ); reg data_in_fast_reg; always @ (posedge clk_fast or negedge rst_n) begin if(~rst_n) begin data_in_fast_reg <= 1'b0; end else begin if(data_in == 1'b1) data_in_fast_reg <= ~data_in_fast_reg; else data_in_fast_reg <= data_in_fast_reg; end end reg data_in_slow_reg1; reg data_in_slow_reg2; reg data_in_slow_reg3; always @ (posedge clk_slow or negedge rst_n) begin if(~rst_n) begin data_in_slow_reg1 <= 1'b0; data_in_slow_reg2 <= 1'b0; data_in_slow_reg3 <= 1'b0; end else begin data_in_slow_reg1 <= data_in_fast_reg; data_in_slow_reg2 <= data_in_slow_reg1; data_in_slow_reg3 <= data_in_slow_reg2; end end assign dataout = data_in_slow_reg2 ^ data_in_slow_reg3; endmodule

四、波形分析

从代码可以知道,data_in 是快时钟域 clk_fast 下的输入脉冲。当 data_in 为 1 时,data_in_fast_reg 会在 clk_fast 上升沿翻转一次。对应到波形中可以看到,每来一个 data_in 脉冲,data_in_fast_reg 就会翻转一次。这样就说明快时钟域中的窄脉冲已经被转换成了电平变化,避免了被慢时钟漏采的问题。

之后 data_in_fast_reg 进入慢时钟域,在 clk_slow 下依次经过 data_in_slow_reg1、data_in_slow_reg2 和 data_in_slow_reg3。波形中也能看到,这几个寄存器的变化是逐拍传递的,符合代码中的三级打拍逻辑。

最后 dataout 是由 data_in_slow_reg2 和 data_in_slow_reg3 异或得到的。当这两个信号不同的时候,dataout 拉高;当二者相同后,dataout 又恢复为 0。从波形中可以看到,每次 data_in_fast_reg 的变化同步到慢时钟域后,dataout 都会产生一个 clk_slow 周期宽度的脉冲。说明该设计能够把快时钟域的单周期脉冲,正确同步成慢时钟域下的单周期脉冲。

五、总结

本题的重点是跨时钟域脉冲同步。对于单 bit 信号来说,如果是从慢时钟域同步到快时钟域,直接使用两级寄存器同步通常就可以采到。但是如果是从快时钟域同步到慢时钟域,尤其是单周期脉冲,就不能直接同步,因为慢时钟可能采不到这个很窄的脉冲。

为了解决这个问题,常用的方法是先把脉冲转换成翻转信号。每来一个脉冲,就让寄存器状态翻转一次。这样脉冲信息就不会因为宽度太窄而丢失,慢时钟域只要采到这个电平变化,就能知道快时钟域中发生过一次脉冲。代码中的 data_in_fast_reg 就是这个翻转寄存器。当 data_in 为 1 时,data_in_fast_reg 取反。注意这里不是保持高电平,而是每来一次脉冲就翻转一次。

进入慢时钟域后,使用 data_in_slow_reg1、data_in_slow_reg2、data_in_slow_reg3 进行同步和延迟。前两级寄存器主要是为了降低亚稳态风险,这是跨时钟域处理中很常见的做法。第三级寄存器则用于保存上一个慢时钟周期的同步结果。最后通过 data_in_slow_reg2 和 data_in_slow_reg3 异或,就可以检测同步信号是否发生变化。只要发生变化,异或结果就会在一个 clk_slow 周期内为 1,因此 dataout 就是慢时钟域中的单周期脉冲。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询