深入理解阻塞和非阻塞的不同
记住:阻塞赋值就是它运行时,别人就不能运行,并且直接赋值到底
非阻塞赋值就是它运行时,不阻碍别人的运行,这里说不清(你懂的就OK)
num<=num+1;//是代表只有在时钟结束的时候右边的数据才赋值给左边的寄存器。
一、设计原则
1、在描述组合逻辑的always块中用阻塞赋值,则综合成组合逻辑的电路结构;
2、在描述时序逻辑的always块中用非阻塞赋值,则综合成时序逻辑的电路结构;
二、语句排列先后的缺点
1、语句的排列有时候是决定了语句的执行顺序。当几个语句在同一时刻执行时,但是由于排列的不同就会造成先后执行,就会出现竞争冒险。
三、什么叫阻塞赋值?
1、阻塞赋值操作符”=“
2、为什么叫阻塞赋值呢?
即阻止其他语句执行的赋值语句。因为在赋值时,先计算等号右边部分的值,此时赋值语句就不允许任何别的语句的执行,直到现在的赋值完成,即左边等于右边的时候,才允许别的语句执行。
3、阻塞赋值缺点举例说明:
1)always@(posedge clk or posedge rst)
if(rst) y1=0;
else y1=y2;
2)always@(posedge clk or posedge rst)
if(rst) y2=1;
else y2=y1;
在同一个时钟沿到来时,我们两者的两个always块在硬件上是不可能同步的,中间会差个几皮秒的相隔时间。
如果1)先执行,那么y1和y2都是1。
如果2)先执行,那么y1和y2都是0。
这说明这个verilog模块是不稳定的,必定会产生冒险和竞争。
四、非阻塞赋值
1、为什么叫非阻塞赋值?
因为在整个右边语句计算和左边语句被赋值的过程中,其他语句依然可以运行。
2、非阻塞赋值操作过程:
1)在赋值开始时刻,计算非阻塞赋值右边表达式。
2)在赋值结束时刻,更新非阻塞赋值左边表达式。
五、verilog模块编程要点
记住以下8点,才能在综合布局布线后的方阵中避免出现冒险竞争现象。
1、时序电路建模时,用非阻塞赋值。
2、锁存器电路建模时,用非阻塞赋值。
3、用always块建立组合逻辑模型时,用阻塞赋值。
4、在同一个always块中,建立时序和组合逻辑电路时,用非阻塞赋值。
5、在同一个always块中不要即使用非阻塞赋值又使用阻塞赋值。
6、严禁在多个always块中对同一个变量赋值。易产生竞争冒险。
7、用$strobe系统任务来显示用非阻塞赋值的变量值。
8、在复制时不要使用#0延迟。
六、verilog的层次化事件队列
这里我没有看懂,就是感觉有一个点:非阻塞赋值LHS变量的更新是安排在非阻塞赋值更新事件队列中,而剩余的其他队列是被安排在另外的一个队列事件中。
七、实例讲解
1、使用阻塞赋值,不能自行触发的振荡器,不建议
initial #10 clk=0;//--------------------------(1)
always@(clk) //-----------------------------(2)
#10 clk=~clk;//------------------------(3)
这里使用的是阻塞赋值,在(1)中,我们的clk变化成0,触发了always块,延迟10ns,clk变成1
注意在由0->1的过度期间,我们是不允许任何其他程序执行的,所以always块没有检测到变化,也就是always块并没有因为第二次的clk变化而被触发。
2、采用非阻塞赋值,自触发振荡器,不建议
initial #10 clk=0;//--------------------------(1)
always@(clk) //-----------------------------(2)
#10 clk<=~clk;//-----------------------(3)
这里always块第一次触发后~clk便被计算出来,并赋值给LHS的事件并被安排在更新事件队列中。在非阻塞赋值更新事件队列被激活之前,又遇到@(clk)语句。当clk发生变化时,always块便被触发。这里看来延迟10ns是有必要的。
3、移位寄存器模型
当阻塞赋值时,在并行的always块中,我们虽说是并行的,当是他们开始的时间是有先后的,这样就可能造成竞争现象,所以我们不建议在用阻塞赋值。但是我们使用非阻塞赋值时,就不会出现竞争现象,因为他不是阻塞的,也不会立即就会变化的。这样很好,你懂的。。。。
摘自:verilog数字系统设计教程(夏宇闻)