verilog中阻塞与非阻塞赋值形象理解

一、阻塞赋值

阻塞赋值,顾名思义,即在一个always块中,后面的语句会受到前语句的影响,具体来说,在同一个always中,一条阻塞赋值语句如果没有执行结束,那么该语句后面的语句就不能被执行,即被“阻塞”。

也就是说always块内的语句是一种顺序关系,这里和C语言很类似。比如,在C语言中,b=a;c=b;执行的时候就是先执行第一句b=a,然后执行下一句c=b,最后结果是a=c。同样,在时钟沿触发下,always块内,阻塞赋值也是顺序执行,如下代码:

always@(posedge clk)
    begin 
        b = a;
        c = b;
    end

在时钟上升沿来的时候,a赋给b,执行完成后,b在赋给c,整个代码执行完时,a=c,效果与C语言同。 其过程下图所示 :
在这里插入图片描述

二、非阻塞赋值

在说非阻塞赋值之前,我们要先知道触发器的工作原理。即在时钟到来时,触发器会将输入端的数据打到输出端,这是受时钟节拍控制的。其实,非阻塞赋值更能体现出硬件电路工作时的实际情况。那么非阻塞赋值具体是怎么回事呢? 继续用上面的例子:

always@(posedge clk)
    begin
        b <= a;
        c <= b;
    end 

在时钟上升沿到来时,该always块就不同于阻塞赋值的最终输出结果a=c,而是a传递到c需要间隔两个时钟,怎么理解呢? 直接看图吧 :
在这里插入图片描述
非阻塞赋值是由时钟节拍决定,在时钟上升到来时,执行赋值语句右边,然后将begin-end之间的所有赋值语句同时赋值到赋值语句的左边,注意:是begin-end之间的所有语句,一起执行,且一个时钟只执行一次。

对于上面的例子,在第一个时钟上升沿到来时,a把值赋给b,b把值赋给c,而此时b的值还没有被更新(即a的值还没有被触发器打给b),只是将b0(b前一次的值)打给c,所以第一个时钟结束后,b的当前值是a,c的当前值是b0(图中的c0)。第二个时钟上升沿到来时,才将当前的b赋给c,由触发器输出,所以此时c的值才更新为a,故a和c相差2个时钟。

posted @ 2020-09-21 19:02  耐心的小黑  阅读(149)  评论(0编辑  收藏  举报