news 2026/5/8 5:19:40

多级延迟触发器与边沿检测电路设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多级延迟触发器与边沿检测电路设计

多级延迟触发器与边沿检测电路设计

在现代数字系统中,尤其是在FPGA或ASIC开发场景下,我们常常会遇到这样一个看似简单却极易出错的问题:如何安全地捕获一个外部按键按下、中断请求到来或者状态信号跳变的瞬间?

如果你直接把这个信号拿来驱动某个状态机或计数器,可能第一次仿真没问题,但烧到板子上运行几天后突然死机——原因往往就藏在那根“看起来很干净”的控制线上。根本问题在于:这个信号可能是异步输入的,它与时钟不同步,采样时容易进入亚稳态;更糟的是,机械抖动、噪声干扰会让边沿误触发。

解决这类问题的核心思路非常经典:先同步化,再比较变化。而实现这一目标最可靠且资源开销最小的方法之一,就是使用多级延迟触发器链 + 边沿检测逻辑


我们不妨从一个实际案例切入:某HW公司实习生面试题要求5分钟内手写出上升沿检测代码。这不仅考察Verilog语法熟练度,更考验对时序逻辑本质的理解。真正的难点不在写几行代码,而在于清楚每一拍背后的物理意义。

首先来看最基本的构建模块——延迟链。

多级延迟触发器的设计哲学

延迟链的本质是用时间换稳定。通过将输入信号逐级打拍(delayed by one clock cycle per stage),我们可以获得该信号在过去多个时刻的状态快照。这种结构最常见的用途有两个:

  • 跨时钟域同步:当信号从一个时钟域进入另一个异步时钟域时,至少需要两级D触发器串联来降低亚稳态传播概率。
  • 边沿检测基础:只有知道“刚才什么样”和“现在什么样”,才能判断是否发生了跳变。

下面是一个参数化的N级延迟链模块,适用于各种需要固定延迟的应用场景:

module dff_chain #( parameter N = 3 // 延迟级数,默认3级 )( input clk, input rst_n, // 异步复位,低电平有效 input din, // 输入信号 output dout // 输出:延迟N拍后的信号 ); reg [N-1:0] delay_reg; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin delay_reg <= {N{1'b0}}; end else begin delay_reg[0] <= din; for (integer i=1; i<N; i=i+1) begin delay_reg[i] <= delay_reg[i-1]; end end end assign dout = delay_reg[N-1]; endmodule

这段代码虽然简洁,但有几个关键点值得注意:

  • 使用了for循环进行行为级描述,在综合工具中会被完全展开为独立的寄存器链,不会生成不可综合逻辑。
  • 复位清零采用{N{1'b0}}的拼接方式,确保宽度匹配。
  • 每一级输出都可以单独引出,比如delay_reg[0]delay_reg[1]正好可用于后续边沿检测中的“当前值”与“前一拍值”。

综合后的电路结构如下(以N=3为例):

din ──▶ DFF ──▶ DFF ──▶ DFF ──▶ dout │ │ │ ▼ ▼ ▼ delay[0] delay[1] delay[2]

每一级都工作在同一个时钟域下,形成稳定的移位路径。这样的结构既简单又高效,是CDC处理中最基本也是最重要的单元之一。


有了稳定的延迟采样信号,接下来就可以着手做边沿判断了。

边沿检测:不只是“异或”那么简单

很多人初学时认为边沿检测就是把原信号和延迟信号异或一下就行。但实际上,真正可靠的边沿检测必须建立在同步采样的基础上,并且要考虑毛刺抑制脉冲完整性

常用的检测方法基于两个采样点之间的比较:

检测类型条件表达式说明
上升沿检测!sig_d1 & sig_d0当前为高,前一拍为低
下降沿检测sig_d1 & !sig_d0当前为低,前一拍为高

其中:
-sig_d0sig_in经过一拍采样的结果
-sig_d1sig_d0再延迟一拍的结果(即两拍前的原始信号)

为什么非得用两级延迟?因为单级无法提供足够的历史信息来做稳定比较。如果只有一级延迟,一旦输入信号处于亚稳态,其输出可能在高低之间震荡,导致组合逻辑产生虚假脉冲。

下面是完整的边沿检测模块实现:

module edge_detector ( input clk, input rst_n, input sig_in, output reg pos_pulse, output reg neg_pulse ); reg sig_d0, sig_d1; // 同步采样链 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin sig_d0 <= 1'b0; sig_d1 <= 1'b0; end else begin sig_d0 <= sig_in; sig_d1 <= sig_d0; end end // 边沿脉冲生成 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin pos_pulse <= 1'b0; neg_pulse <= 1'b0; end else begin pos_pulse <= (!sig_d1) & sig_d0; // 上升沿 neg_pulse <= sig_d1 & (!sig_d0); // 下降沿 end end endmodule

注意所有逻辑都在时钟边沿触发,避免出现锁存器;同时支持异步复位,保证系统上电初始化的安全性。

对应的时序图清晰展示了脉冲生成过程:

clk __↑___↑___↑___↑___↑___↑___↑___ din ____↑_______________↓__________ d0 ____↑_______________↓____ d1 ____↑_______________↓ pos_en ↑_________________ neg_en _________↑___

可以看到,无论是上升还是下降,输出都能准确生成一个宽度恰好为一个时钟周期的脉冲信号,非常适合用于触发单次动作,如中断置位、状态切换等。


为了验证设计的正确性,我们需要编写测试激励。

仿真验证:不只是跑通波形

一个好的testbench不仅要覆盖正常情况,还要模拟边界条件和异常行为。以下是一个典型的验证平台:

module tb_edge_detector; reg clk; reg rst_n; reg sig_in; wire pos_pulse; wire neg_pulse; edge_detector uut ( .clk(clk), .rst_n(rst_n), .sig_in(sig_in), .pos_pulse(pos_pulse), .neg_pulse(neg_pulse) ); // 生成50MHz时钟(周期10ns) initial begin clk = 0; forever #5 clk = ~clk; end initial begin rst_n = 1'b0; sig_in = 1'b0; #15; rst_n = 1'b1; #50; sig_in = 1'b1; // 上升沿 #50; sig_in = 1'b0; // 下降沿 #50; sig_in = 1'b1; // 再次上升 #30; sig_in = 1'b0; // 快速抖动 #20; sig_in = 1'b1; #100; $finish(); end endmodule

预期行为包括:

  • T=65ns:第一个上升沿触发pos_pulse=1
  • T=115ns:下降沿触发neg_pulse=1
  • T=165ns:再次上升,正确响应
  • 抖动期间(T≈195~215ns)仅最后一次有效跳变被记录,中间短脉冲被自然滤除

使用ModelSim或VCS仿真后可观察到脉冲宽度严格对齐时钟周期,无毛刺传播,符合设计预期。


当然,在真实项目中还会遇到更多复杂问题。以下是几个常见疑问及其工程实践建议:

常见问题解析

为什么不能只用一级延迟?

一句话总结:没有“过去”,就无法定义“变化”
单级延迟只能得到当前值和一拍前的值,但若这一拍正好落在亚稳态恢复过程中,其逻辑值可能是不确定的,导致边沿误判。使用两级延迟可以显著降低这种风险。

能检测小于一个时钟周期的窄脉冲吗?

不能。这是奈奎斯特采样定理的基本限制:你的采样频率必须高于信号变化频率的两倍以上才能可靠捕获。如果输入脉冲宽度小于系统时钟周期,很可能在某个周期内根本没有被采样到。

应对策略有三种:
1. 提高采样时钟频率(例如使用PLL倍频)
2. 在前端加脉冲展宽电路(monostable multivibrator)
3. 确保源端信号持续时间 ≥ 1.5 × 时钟周期

如何防止按键抖动或EMI干扰引起的误触发?

硬件层面可以在输入端加入RC低通滤波器,软件层面则可通过增加判决深度来提升鲁棒性。例如使用三级延迟并采用“多数表决”机制:

reg sig_d0, sig_d1, sig_d2; ... assign clean_sig = (sig_d0 & sig_d1) | (sig_d1 & sig_d2); // 三取二

然后再对clean_sig进行边沿检测,能有效抑制短暂毛刺。

可否同时输出双边沿脉冲?

完全可以。只需将两个脉冲信号或起来即可:

wire both_edge = pos_pulse | neg_pulse;

这种信号常用于唤醒低功耗模块、作为计数器使能信号等场合。

多比特总线如何检测变化边沿?

本设计针对单比特信号。对于多比特总线(如地址线、数据线),应先通过异或运算判断是否有任意一位发生变化:

wire bus_changed = |(bus ^ bus_d1);

然后对该变化标志进行边沿检测。注意此时仍需同步处理,避免跨时钟域问题。


工程最佳实践

应用场景推荐做法
按键消抖两级同步 + 状态机延时确认(如20ms)
中断捕获上升沿检测 + 标志位锁存 + CPU清零机制
状态切换双沿检测配合有限状态机控制流程
跨时钟域至少两级DFF同步,禁止跨域直连

此外还需注意以下设计原则:

  • 禁止组合逻辑反馈回路:可能导致锁存器或振荡
  • 所有异步输入必须同步化:哪怕来自同一板卡的不同芯片
  • ⚠️避免重复延迟同一信号:多个模块各自打拍会造成资源浪费和相位不一致
  • 🔧关键路径延迟不超过4级:过多级数增加延迟,影响性能

从资源角度看,该设计极为轻量。在Xilinx Artix-7 XC7A35T器件上综合结果显示:

指标数值
LUT 使用量~12 LUTs
触发器数量4个(含两级延迟+两个输出)
最大工作频率>200 MHz
延迟时间固定2个时钟周期

这意味着你可以在一个中等规模的FPGA中集成数十甚至上百个这样的检测单元,而几乎不占用额外资源。


小结:小电路,大智慧

别看这个电路结构简单,它背后体现的是数字设计中最核心的思想:用时间换取稳定性,用冗余换取可靠性。无论是高级的高速接口同步,还是基础的按键扫描,其底层逻辑都离不开这种“打两拍再判断”的范式。

当你下次面对一个“为什么我的中断偶尔没响应?”或“状态机怎么自己跳走了?”的问题时,不妨回头看看是不是少了这两级DFF。

这种高度集成且可复用的设计模式,正是现代数字系统稳健运行的基石之一。


原创内容,转载请注明出处。Verilog示例代码可用于学习与项目参考,请注明来源。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 9:08:56

UTF-8编码与Unicode字符解析

UTF-8编码与Unicode字符解析 你有没有遇到过网页上突然出现一堆“锟斤拷”或“烫烫烫”的尴尬场面&#xff1f;又或者在处理用户提交的昵称时&#xff0c;发现某个 emoji 被替换成了空白方框&#xff1f;这些问题的背后&#xff0c;往往不是程序逻辑出了错&#xff0c;而是字符…

作者头像 李华
网站建设 2026/5/3 6:58:43

为什么创客匠人坚持赋能创始人IP?因为这关乎行业的未来

在知识服务领域&#xff0c;我们正面临一个关键转折点&#xff1a;用户不再满足于单一课程或产品&#xff0c;他们渴望连接背后的“人”——那位有理念、有担当、有持续创造力的创始人。创客匠人之所以将“创始人IP赋能”作为平台战略重点&#xff0c;正是基于一个深刻认知&…

作者头像 李华
网站建设 2026/5/2 23:14:44

PHP木马代码分析:功能与危害揭示

PHP木马代码分析&#xff1a;功能与危害揭示 在一次对某企业Web系统的例行安全检查中&#xff0c;技术人员发现了一个名为 hello.php 的文件。它没有复杂的命名&#xff0c;内容开头甚至写着“无需验证密码&#xff01;”&#xff0c;看起来就像一段被遗忘的测试脚本&#xff1…

作者头像 李华
网站建设 2026/4/30 17:10:44

采煤区光伏电站远程监控运维管理系统方案

国家能源局下发《关于推进煤炭与新能源融合发展的指导意见》文件指出&#xff1a;依托煤炭矿区资源要素大力发展新能源&#xff0c;有序实施矿区清洁能源替代&#xff0c;推动煤炭产业链延伸发展&#xff0c;建立完善煤炭与新能源融合发展机制&#xff0c;促进煤炭行业绿色转型…

作者头像 李华
网站建设 2026/5/1 14:33:12

使用Jsoup爬取网页中的新闻与图片链接

使用 Jsoup 爬取网页中的新闻与图片链接 在信息聚合、内容监控和数据挖掘的日常开发中&#xff0c;如何从结构化的网页中高效提取图文内容&#xff0c;是许多 Java 工程师面临的实际问题。Jsoup 作为一款轻量级且功能强大的 HTML 解析库&#xff0c;凭借其类 jQuery 的选择器语…

作者头像 李华
网站建设 2026/5/3 19:55:37

PPAP流程详解及提交等级解析

VibeVoice-WEB-UI 技术详解及多说话人语音生成能力解析 在播客制作、有声书演绎或AI角色对话开发中&#xff0c;你是否曾遇到这样的困扰&#xff1a;传统语音合成听起来像“念稿”&#xff0c;角色切换生硬&#xff0c;长段落里音色漂移、情绪断裂&#xff1f;更别提三人以上对…

作者头像 李华