1 竞争冒险
竞争:两个输入信号同时向相反方向的逻辑电平跳变的现象(即一个由1- > 0, 另一个从0 -> 1),称为竞争。(指组合逻辑电路中,多个输入信号变化传输到同一个门级电路时,时间上有先有后的现象引起竞争的原因就是时延,竞争会导致冒险)因竞争导致在输出端可能产生尖峰脉冲的现象,称为冒险。分为功能冒险和逻辑冒险.
● 时延:电信号发生电平跳变时,在导线上传输的时间。
功能冒险
● 功能冒险:组合逻辑电路中,多个输入信号同时发生变化,因为时延到达门电路时间各不相同,导致瞬时干扰脉冲的现象。
module test(input [2:0] a, input [2:0] b, output [2:0] y);
assign y = a & b;
endmodule
a和b信号到达与门延迟不同,就是竞争现象。
而这种竞争现象,可能会使Y出现瞬时脉冲,这就是功能冒险现象。
如当a由0变1,b由1变0时。如果由于线长短原因,a比b先到达,即a已经为较高电平了,b还维持较高电平,输出y就可能出现尖峰脉冲。
与门,如果B恒为高,A由0变1,不会出现功能冒险。A和B均由低变高,且时间不同,也不会出现功能冒险。
逻辑冒险
● 逻辑冒险:组合逻辑电路中,某一个信号电平发生变化,到达门电路的时间不相同,导致瞬时干扰脉冲的现象。
注意功能冒险和逻辑冒险的区别在于促使冒险的竞争信号数目不同
下面介绍两个逻辑冒险模板,任何逻辑冒险都可归结为下面两种
● 1型逻辑冒险:Y=AA’
还是与门,但与门的两个输入相关联
当A电平由低拉高时,由于非门的存在会使与门两个输入的电平翻转时刻不同,导致出现高电平脉冲,即1型冒险。
当A由1变0时,1型逻辑冒险不会出现
0型逻辑冒险:Y=A+A’
A和A非用或门连接时,A由高拉低时,Y会出现短暂的低电平脉冲,即0型冒险。
当A由0变1时,0型逻辑冒险也不会出现
2. 测试仿真的 竞争问题
仿真波形图中,posedge clk往往与信号变化对齐,那到底采样的是变化前的值还是变化后的值?
如下图所示,黄线处,分别用clk1和clk2采样,采样的d1的值是多少呢?看是看不出来的
如果clk1驱动clk2和d1,则黄线处:clk1采样d1为01,clk2采样d1为02。
如果clk2驱动clk1和d1,则黄线处:clk1采样d1为02,clk2采样d1为01。
出现不同取值的原因在于,仿真波形会默认在驱动信号和被驱动信号波形之间增加大小为delta cycle的延迟,且delta cycle → 0,只有放大才能看出来时序关系,如下图
实际硬件中,delta cycle其实是时钟产生posedge clk到触发器Q端输出的时间,后文会讲怎么算,非常小而且仿真软件并不知道硬件时间是多少。
综上所述
仿真中竞争问题:波形无法表达时钟和信号间的驱动关系。若是在时钟处采样,也无法判定采样的结果是时钟前的值还是时钟后的值。
下面给出解决办法
放大delta cycle
驱动时钟和被驱动信号在时间上存在着delta cycle的延迟,仿真波形中看不出来,所以为了方便起见解决方法是
放大delta cycle至肉眼可见,体现驱动信号的前后关系
例如clk驱动某个寄存器,就将寄存器输出整体右移即可,如下图
可以清晰看出每个posedge clk采样的是什么值,驱动的是什么值
而Systemverilog中interface子程序中的clocking块就是干这个用的
2. 判断冒险
再回到电路的组合逻辑中来,下面给出组合逻辑冒险的判断方法。
2.1. 判断 功能冒险
实际上功能冒险很容易出现,因为电路中不同信号走线延迟各不相同,功能冒险在所难免。
2.2. 判断 逻辑冒险:代数法
首先要说明,判断逻辑冒险要保证逻辑表达式中同时出现了A和A’
例如下面表达式子,Z有没有逻辑冒险,显然是有的,由A导致的。不能说Z没有或者是功能冒险。
assign X = A;
assign Y = ~A;
assign Z = X && Y; //本质还是Z = A && ~A;
判断逻辑冒险的方法很简单,若组合逻辑表达式中同时出现A和A’,对其他变量赋0或者1,若能化简成Y=AA’则会出现1型冒险,若是Y=A+A’则会出现0型冒险
例如
assign X = ~A && B;
assign Y = A && C;
assign Z = X || Y;
其实还是Z = A'B + AC,令B=C=1,此时称为Z=A’+A,因此会出现0型逻辑冒险。其本质是当B和C为恒定高电平时,A电平拉低会出现逻辑冒险
再如
assign X = ~A && B && C;
assign Y = A && ~B && C;
assign Z = A && B && ~C;
assign res = X || Y || Z;
本质上是res = A'BC + AB'C + ABC',发现无法赋值化简,因此不存在逻辑冒险。
3. 消除冒险
功能冒险也是可以消除的
3.1. 消除 逻辑冒险:引入冗余项
既然在某个情况下能够化简成Y=AA’或Y=A+A’,那么怎么能在那种情况下不能作这样化简呢?那就得改组合逻辑了。
思路是额外加一个使原逻辑式出现逻辑冒险的最小项
例如Z = A'B + AC出现0逻辑冒险的条件是B = C = 1,那么就加一个BC。这样当B = C = 1时就恒为1了,不再出现0逻辑冒险。
再如Z = A'BC+ AB同理
3.2. 锁存器
都说写代码的时候if语句要把else写全,case语句要写default,为啥?为了避免锁存器Latch的产生。
那产生个Latch又咋地了?这里分析下
以下面这个代码为例,en为1时q为1’b1,en为0时q锁存。
always@(*)
if(en)
q = 1'b1;
得到逻辑表达式为q = en + (en)'·q,然后用上面讲的方法分析这个表达式呗。
与q直连的是或门,或门输入一个是en、另一个是与门,因此可能会存在竞争。
那么锁存器会因此存在冒险嘛?看样子是有可能的,下面分析下。
危害:锁存瞬态值
综合出来的电路图如下,并为各导线标注:
首先,稳定时令wa=en=1;wb=(en)'=0;wc=q=1;wd=0;
然后我们让en=1→0;,那么信号传输是有延迟的,所以wa一定先于wb、wc、wd变化,故wa=1→0;,因此对于q来说第一个变化一定是q=1→0;
然后非门才变化完成,即wb=0→1;那么此时wc是多少?是原值1还是新值0?分类讨论
● 电平变化先后为:wa(1→0)、wb(0→1)、wc(1→0)
如果是这样的话,会存在wb=1;wc=1;的中间态,再经过与门wd=0→1,因此会有q=0→1
wb变完之后,wc再变化,最终会有wb=1;wc=0的状态,因此q又有q=1→0;
● 电平变化先后为:wa(1→0)、wc(1→0)、wb(0→1)
如果是这样的话,会存在wb=0;wc=0;的中间态,再经过与门wd=0→1,因此q还是0
wc变完之后,wb再变化,最终会有wb=1;wc=0的状态,因此q保持为0
由此可见最终的输出居然是0,甚至还可能出现个毛刺1。直接看代码无论如何都想不到这个结果。
根本原因在于含有锁存器的电路会有一条导线将输出和某个输入直接相连。
如果出现竞争,那么瞬态的异常电平会被锁存(上面电路中,当wa=1→0而wb仍为0的异常瞬态,就被q捕捉到并通过wc反馈到输入)
如果是时序电路就不会捕获这个异常瞬态。
因此Latch的最大缺陷倒不是毛刺,而是捕获瞬间出现的异常状态并锁存,导致实际输出难以预料
参考