Modelsim仿真指南:Verilog毛刺消除的3种方法对比(单边/双边/三拍滤波)
在数字电路设计的日常工作中,我们常常会遇到一个看似微小却足以颠覆整个系统稳定性的问题——信号毛刺。无论是按键输入、传感器采样,还是跨时钟域的信号传递,这些不期而至的短暂脉冲就像电路中的“幽灵”,轻则导致状态机误跳转,重则引发数据锁存错误,让精心设计的逻辑功亏一篑。对于数字IC验证工程师而言,掌握一套行之有效的毛刺消除技术,并能在仿真环境中直观地验证其效果,是一项至关重要的基本功。
今天,我们就以Modelsim为舞台,深入探讨三种经典的Verilog毛刺消除方法:单边毛刺滤除、双边毛刺滤除(输入消抖)以及多周期毛刺滤除(三拍滤波)。我不会仅仅停留在理论公式的罗列,而是会带你一步步搭建仿真环境,编写可修改、可复用的测试激励(Testbench),并通过波形对比,让你清晰地看到不同方法在应对不同宽度、不同类型毛刺时的真实表现。无论你是正在处理一个敏感的按键接口,还是在调试一个跨时钟域的异步FIFO,这篇文章提供的思路和代码模板,都能成为你工具箱里的得力助手。
1. 毛刺的本质:为什么你的电路会“说谎”?
在深入代码之前,我们有必要先搞清楚对手的底细。毛刺(Glitch)并非电路设计错误,而是数字逻辑门固有的延迟特性所导致的必然现象。当两个或更多个输入信号同时(或几乎同时)发生变化,并且它们经过不同长度的路径到达同一个逻辑门时,由于路径延迟的差异,输出端就可能产生一个短暂的非预期脉冲。
想象一下一个简单的与门,两个输入A和B从00变为11。理想情况下,输出应该保持为0,然后跳变为1。但如果A的路径延迟比B长,在某个极短的时间窗口内,信号状态可能是A=0, B=1,此时与门输出就会产生一个短暂的0(毛刺)。这种因信号竞争而产生的冒险,在组合逻辑中尤为常见。
注意:时序逻辑电路(如触发器)对毛刺有一定的免疫力,因为其输出只在时钟边沿采样。但毛刺如果出现在触发器的数据输入端或时钟端,同样可能导致亚稳态或错误的数据锁存。
毛刺的危害不容小觑:
- 状态机误触发:一个毛刺可能被误认为是有效的边沿,导致状态机跳转到错误的状态。
- 计数器错误计数:毛刺可能被计数器误认为是有效的时钟脉冲。
- 数据采样错误:在数据总线稳定前出现的毛刺,可能被锁存为错误的值。
- 功耗增加:频繁的毛刺会导致不必要的电路翻转,增加动态功耗。
在仿真中,我们通常通过构造特定的测试序列来模拟毛刺。例如,在信号稳定为高电平或低电平之前,故意插入几个时钟周期宽度的反向脉冲。下面是一个在Testbench中生成包含毛刺的输入信号的简单例子:
initial begin
din = 1'b0; // 初始为低电平
#100; // 等待100ns
// 模拟一个带有毛刺的上升沿
din = 1'b1; // 正常跳变到高
#5;
din = 1'b0; // 插入一个5ns宽的低电平毛刺
#5;
din = 1'b1; // 恢复高电平
#50;
// 模拟一个带有毛刺的下降沿
din = 1'b0;
#10;
din = 1'b1; // 插入一个10ns宽的高电平毛刺
#10;
din = 1'b0;
#100;
$finish;
end
理解了毛刺的成因和危害,我们就能有的放矢地设计滤波电路。接下来,我们将从最简单、最直接的单边毛刺滤除开始。
2. 单边毛刺滤除:用“与”和“或”逻辑构筑第一道防线
单边毛刺滤除,顾名思义,专门针对信号中出现的单一极性(高电平或低电平)的短暂脉冲进行过滤。其核心思想异常简洁:利用D触发器的延迟特性,对原始信号进行多级采样,然后通过逻辑运算(与/或)来“投票”决定最终输出。
这种方法特别适用于你知道毛刺只可能出现在信号的一种边沿(上升沿或下降沿)之后的情况。它的实现成本极低,通常只需要两个或三个触发器加上一个门电路。
2.1 工作原理与数学模型
我们以消除高电平毛刺为例。假设输入信号din,时钟clk。我们使用两级触发器进行采样:
din_r1=din延迟一个时钟周期din_r2=din_r1延迟一个时钟周期(即din延迟两个时钟周期)
滤除高电平毛刺的输出dout_high由下式给出: dout_high = din_r1 & din_r2
为什么这样能滤除毛刺? 一个有效的高电平信号,其宽度通常远大于一个时钟周期。当一个短暂的高电平毛刺(宽度小于一个时钟周期)出现时,在连续的时钟沿采样下,它极有可能无法被相邻的两个触发器同时捕获。例如,毛刺出现在两个时钟沿之间,那么din_r1可能采样到1,而din_r2采样到0,两者相与的结果为0,毛刺就被过滤掉了。只有当连续两个时钟沿都采样到高电平时,输出才为高,这保证了输出高电平的宽度至少为一个时钟周期。
同理,滤除低电平毛刺的输出为: dout_low = din_r1 | din_r2 其逻辑是,只有当连续两个时钟沿都采样到低电平时,输出才为低,从而过滤掉短暂的低电平毛刺。
2.2 Verilog实现与Modelsim仿真
让我们用代码来实现一个可配置的单边毛刺滤波器。这个模块通过参数FILTER_TYPE来选择是滤除高电平毛刺还是低电平毛刺,并通过参数FILTER_DEPTH来配置采样深度(打拍级数)。
`timescale 1ns / 1ps
module single_edge_glitch_filter #(
parameter FILTER_TYPE = 0, // 0: 滤除高电平毛刺 (AND), 1: 滤除低电平毛刺 (OR)
parameter FILTER_DEPTH = 2 // 采样深度,通常为2或3
)(
input wire clk,
input wire rst_n,
input wire din,
output reg dout
);
// 移位寄存器,用于多级采样
reg [FILTER_DEPTH-1:0] shift_reg;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
shift_reg <= {FILTER_DEPTH{1'b0}};
dout <= 1'b0;
end else begin
// 采样输入信号
shift_reg <= {shift_reg[FILTER_DEPTH-2:0], din};
// 根据滤波类型进行逻辑运算
if (FILTER_TYPE == 0) begin
// 滤除高电平毛刺:所有采样值相与
dout <= &shift_reg;
end else begin
// 滤除低电平毛刺:所有采样值相或
dout <= |shift_reg;
end
end
end
endmodule
为了验证这个模块

708

被折叠的 条评论
为什么被折叠?



