估计很多人都没有想过吧,管它三七二十一,一律赋0(或1)。那恭喜你,你已经掉进陷阱了。什么陷阱?误判的陷阱。举个例子,检测一个信号的上升沿,见如程序清单1所示:
程序清单1
/******************************************Copyright********************************************
** CrazyBird
**----------------------------------------File Infomation--------------------------------------
** FileName : edge_detection.v
** Author : CrazyBird
** Data : 2015-10-25
** Version : v1.0
** Description : the rising edge detection of signal
**
************************************************************************************************/
// synopsys translate_off
`timescale 1 ns / 1 ps
// synopsys translate_on
module edge_detection
(
input clk,
input rst_n,
input din,
output pos_flag
);
//------------------------------------
// Two levels of cache on the signal
reg din_r1;
reg din_r2;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
din_r1 <= 1'b0;
din_r2 <= 1'b0;
end
else
begin
din_r1 <= din;
din_r2 <= din_r1;
end
end
//------------------------------------
// rising edge detect
assign pos_flag = din_r1 & ~din_r2;
endmodule
//*****************************************End File**********************************************
这是一个超级简单的信号上升沿检测,相信很多人也是这样写。但你这样设计出来的东西是不稳定的。为什么?从理论上分析,当复位后,din_r1和din_r2d的值都为1'b0。如果输入信号din为1'b1,在时钟上升沿到来时,din的值会被锁进din_r1即din_r1=1'b1,而din_r1前一时刻的值被锁进din_r2即din_r2=1'b0。此时,并没有信号的上升沿到来,而pos_flag的值为1'b1,从而导致第一次上升沿是误判的。也可以从仿真波形中体现出来,如图1所示。
图1 导致第一次上升沿误判
为了避免误判情况的出现,我们采取措施:对于信号上升沿检测,复位后寄存器应都赋值为1'b1。修改后的代码如程序清单2所示:
程序清单2
/******************************************Copyright********************************************
** CrazyBird
**----------------------------------------File Infomation--------------------------------------
** FileName : edge_detection.v
** Author : CrazyBird
** Data : 2015-10-25
** Version : v1.0
** Description : the rising edge detection of signal
**
************************************************************************************************/
// synopsys translate_off
`timescale 1 ns / 1 ps
// synopsys translate_on
module edge_detection
(
input clk,
input rst_n,
input din,
output pos_flag
);
//------------------------------------
// Two levels of cache on the signal
reg din_r1;
reg din_r2;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
din_r1 <= 1'b1;
din_r2 <= 1'b1;
end
else
begin
din_r1 <= din;
din_r2 <= din_r1;
end
end
//------------------------------------
// rising edge detect
assign pos_flag = din_r1 & ~din_r2;
endmodule
//*****************************************End File**********************************************
仿真结果如图2所示:
图2 上升沿正确检测
同样,对于下降沿检测,复位时应将寄存器都赋值为1'b0,大家可自行验证。
总结一下,上升沿检测,复位时寄存器应赋值为1'b1;下降沿检测,复位时寄存器应赋值为1'b0。*^_^*