边沿检测
代码
module edge_detection(
input sys_clk,
input sys_rst_n,
input signal_in,
output edge_rise,
output edge_down
);
//存储上一个时钟周期的输入信号
reg signal_in_prev;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
signal_in_prev <= 0;
else begin
signal_in_prev <= signal_in; //两个信号相差一个时钟周期
end
end
//上升沿检测:signal_in_prev为0,signal_in为1
assign edge_rise = signal_in & ~signal_in_prev;
assign edge_down = ~signal_in & signal_in_prev;
endmodule
若为下降沿检测,则为:
assign edge_detected = ~signal_in & signal_in_prev;
TB文件
`timescale 1ns/1ps
module tb_top();
//接口声明
reg sys_clk;
reg sys_rst_n;
reg signal_in;
wire edge_rise;
wire edge_down;
//对被测的设计进行例化
edge_detection u_edge_detection(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.signal_in (signal_in),
.edge_rise (edge_rise),
.edge_down (edge_down)
);
//产生时钟
initial sys_clk = 1;
always #10 sys_clk = ~sys_clk;
//测试激励产生
initial begin
sys_rst_n = 0;
signal_in = 0;
#117;
sys_rst_n = 1;
signal_in = 1;
#217;
signal_in = 0;
#317;
signal_in = 1;
#517;
signal_in = 0;
#317;
signal_in = 1;
#737;
signal_in = 1;
#519;
signal_in = 0;
#817;
signal_in = 1;
#417;
signal_in = 0;
#107;
signal_in = 1;
#300;
end
endmodule
注意,若TB文件中输入信号signal_in的上升\下降沿和sys_clk同步,则检测不出边沿。所以我将输入信号的持续时间都设定为随机数字,来和sys_clk产生区别
仿真波形
改进
若出现不定值x或高阻值z,则检测不准确。
可以改进为:
assign edge_detected = ((a & ~signal_in_prev)===1)?1:0;//上升沿检测
assign edge_detected = ((~a & signal_in_prev)===1)?1:0;//下降沿检测
解释:
==
和!==
称为逻辑等式运算符,其结果由两个操作数的值决定。真值表如下:
== | 0 | 1 | x | z |
---|---|---|---|---|
0 | 1 | 0 | x | x |
1 | 0 | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
===
和!===
常用于case表达式的判别,所以又称为case等式运算符。它是对操作数进行按位比较,两个操作数必须完全一致,结果才为1。若两个操作数对应位都出现不定值x或高阻值z,则也可认为是相同的。真值表如下:
=== | 0 | 1 | x | z |
---|---|---|---|---|
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |