reg F1,F2; // F2 Previous State, F1 Current State always@(posedge CLK or negedge RSTn) if(!RSTn) begin F1<=1'b0;//(注意复位时F1;F2都是等于0的!) F2<=1'b0; end else begin F1<= A; F2<= F1; end wire Aup = F1 & !F2; wire Adown = F2 & !F1;
这个模块可以用来检测A输入口的“上跳变”以及“下跳变”
现在,开始分析:
1、假设:A的默认值,也就是初始值为0;
第一个时钟来临时,F1=0;F2=0;所以Aup = 0 & 1 = 0;Adown = 0 & 1 =0;的这完全没有问题。
2、假设:A的默认值,也就是初始值为1;
第一个时钟来临时,F1=1;F2=0;所以Aup = 1 & 1 = 1;Adown = 0 & 0 =0;
这个时候就有问题了,本来在第一个时钟A是没有发生变化的,但是Aup却等于1,被认为有一个上跳变。
这就是,检测模块要注意的问题。这种问题会导致,你发现计数时问什么会“无缘无故”多一个。问题就在这里。
这个问题如何预防呢?首先我们必须搞清楚,我们所检测的这个引脚是默认0还是1.如果是1的话我们应该这么写。
reg F1,F2; // F2 Previous State, F1 Current State always@(posedge CLK or negedge RSTn) if(!RSTn) begin F1<=1'b1;(注意复位时F1;F2都是等于1的!) F2<=1'b1; end else begin F1<= A; F2<= F1; end wire Aup = F1 & !F2; wire Adown = F2 & !F1;
第一个时钟来临时,F1=1;F2=1;所以Aup = 1 & 0 = 0;Adown = 1 & 0 =0;的这样就没有问题了。
总结:这个检测模块容易出问题的地方就是在第一个时钟的时候,但是如果搞清楚检测引脚的初始状态,我们根据这个状态来选择这个模块的写法就不会出问题。
当然如果这个检测引脚既不是高电平也不是低电平,也就是高组态。那么两种写法都可以咯。因此,我们反方思维一下,如果我们写测试文件(产生激励信号)时,不清楚应该个输入赋什么值的时候,这样写就是一个不错的选择——A <= 1'bz;(将输入设为不确定状态)。