推荐答案
测试一下
题目
用VERILOG或VHDL写一段代码,实现消除一个glitch(毛刺)
参考答案与知识点
参考答案
实现glitch(毛刺)消除的常用方法有:两级/三级触发器同步(适用于较窄毛刺)或计数器滤波(适用于任意宽度毛刺)。以下给出两种典型实现。
方法一:两级触发器同步(适用于毛刺宽度小于时钟周期的情况)
```verilog
module glitch_remover (
input clk,
input rst_n,
input data_in,
output data_out
);
reg q1, q2;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
q1 <= 1'b0;
q2 <= 1'b0;
end else begin
q1 <= data_in;
q2 <= q1;
end
end
assign data_out = q2;
endmodule
```
该代码通过两级寄存器打拍,将异步信号同步到本地时钟域。第一级寄存器可能采样到毛刺(若毛刺宽度满足建立保持时间),但第二级寄存器采样第一级的输出,由于第一级输出可能因亚稳态而振荡,但经过一个时钟周期后大概率稳定,因此第二级输出基本消除亚稳态。若毛刺宽度小于时钟周期,第一级可能采样不到毛刺,从而直接滤除。但此方法不能保证完全消除大于一个时钟周期的毛刺。
方法二:计数器滤波(适用于任意宽度毛刺,可设定稳定阈值)
```verilog
module glitch_remover #(parameter CNT_WIDTH=4, STABLE_TH=4) (
input clk,
input rst_n,
input data_in,
output reg data_out
);
reg [CNT_WIDTH-1:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 0;
data_out <= 0;
end else begin
if (data_in != data_out) begin
if (cnt == STABLE_TH-1) begin
data_out <= data_in;
cnt <= 0;
end else begin
cnt <= cnt + 1;
end
end else begin
cnt <= 0;
end
end
end
endmodule
```
该方法在输入与输出不同时启动计数器,仅当输入连续保持STABLE_TH个时钟周期不变时,才更新输出,从而滤除所有宽度小于STABLE_TH-1个时钟周期的毛刺。阈值可根据实际毛刺最大宽度设置。
注意事项:
- 组合逻辑毛刺(如因路径延迟差异产生)可通过在组合逻辑输出后加寄存器消除。
- 跨时钟域的毛刺消除需结合同步器和滤波,单靠触发器同步可能无法滤除宽毛刺。
- 实际应用中需考虑毛刺宽度与时钟频率的关系,选择合适的滤波策略。
涉及知识点
- VERILOG
- 时钟
- verilog
- STA