【原创】边沿检测中需要注意的细节
0赞
发表于 10/25/2015 9:38:53 PM
阅读(3602)
很多人看到这个标题的时候,都会想边沿检测不是很简单的吗?有什么需要注意的?它是很简单,只要对输入信号进行两级缓存,然后通过判断前后两级的逻辑来决定信号的上升沿或下降沿。但你们有没有想过当系统复位时应该给寄存器赋什么值?估计很多人都没有想过吧,管它三七二十一,一律赋0(或1)。那恭喜你,你已经掉进陷阱了。什么陷阱?误判的陷阱。举个例子,检测一个信号的上升沿,见如程序清单1所示:
程序清单1
/******************************************Copyright******************************************** ** CrazyBird ** http://blog.chinaaet.com/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 ** http://blog.chinaaet.com/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。*^_^*