4.3 阻塞赋值与非阻塞赋值

一.Golden Rule

编码原则很多,就阻塞非阻塞赋值而言,新手最需要牢记的是其中三条:

1)      时序逻辑一定用非阻塞赋值”<=”,一旦看到敏感列表有posedge就用”<=”。

2)      组合逻辑一定用”=”,一旦敏感列表没有posedge就用”=”,一旦看到assign就用”=”。

3)      时序逻辑和组合逻辑分成不同的模块即一个always模块里面只能出现非阻塞赋值”<=”或者”=”。如果发现两种赋值并存,一个字”改”,心存侥幸可能会给后续工作带来更多麻烦。

以上三条,对新手而言不必追求为什么,需要的就是条件反射的照章办事。最后说一句,新手可能记不住哪个符号是阻塞赋值,哪个是非阻塞赋值,大家可以数数,”非阻塞赋值”一共5个字,“阻塞赋值“4个字,所以非阻塞用的符号”<=”比阻塞赋值用的符号”=”长。

 

二.电路行为逻辑

第一节给出了三条最基本的编码原则,有个朋友可能会想,按照这三条编码原则写出来的代码会按怎样的逻辑工作呢?这一节就是回答这个问题。首先解释一下阻塞赋值与非阻塞赋值的含义。

阻塞赋值”=”就是说,在这个语句没有执行完之前,后面的语句是不执行的这里执行的含义是指完成变量值的更新

非阻塞赋值”<=”是指,所有的语句可以并发执行,而前面的值是否执行完毕不会影响后面的语句,换句话说,语句的顺序是无关紧要的。

举个例子,假设一个模块,有2个寄存器,b和c,初值都是1。a为输入信号线。在某个时刻,因为某种原因,模块被触发执行。对于组合逻辑而言,一般是输入信号值变了,对于时序逻辑而言,一般是时钟沿到了。首先看组合逻辑:

//    假设输入 : a = 2; b和c初值 = 1
always@(a)
begin
       b = a;     // after run : b = 2
       c = b;     // after run : c = 2
end

由于是阻塞赋值,所以首先执行完第一句b=a,执行完成之后b=2。接着执行c=b,执行完成后c=2,一次仿真结束后 b=c=2;

对于时序逻辑而言,

//    依然假设:  a =2 ;    b和c初值 = 1
always@(posedge clk)
begin
       b <= a;    //  after run : b = 2 
       c <= b;    //  after run : c = 1
end

由于是非阻塞赋值,首先执行第一句b<=a,这时候a = 2,但是还没有执行完第一句的时候,第二句c<=b也执行了,由于第一句没有执行完,b的值还是1,这时候赋值给c的值也是1。执行完毕的结果就是c=1,b=2.等到模块再次被触发的时候c的值更新为2。有个朋友可能就会问了,凭啥第一句执行到一半就该第二句执行呢?到底是第一句先完成赋值呢还是第二句先完成赋值?答案是,谁先完成赋值都没关系,结果是一样的。(在博文4.3Verilog练习4中有一个程序可参考)

为什么说结果一样呢?因为两种赋值方式分别是按照下面的顺序执行的。阻塞赋值,就跟C语言一样,严格按照代码书写的先后顺序执行,所有值都是立即更新,并且在下面的语句中按照新值执行。而时序电路就不一样了,大家可以这么理解时序逻辑的代码行为,一次执行分为两轮:第一轮是所有的左值都先赋给临时变量,第二轮用输入值以及和右值同名的临时变量值去更新左值。比如上面的例子,第一轮,赋给临时变量:tempc=c;tempb=b。第二轮,临时变量更新左值,b = a;c = tempb;output = tempc。从上面的分析也可以看出,组合逻辑的结果与代码顺序直接相关,而时序逻辑与代码顺序没有关系。这就是所谓的顺序执行(组合逻辑)与并发执行(时序逻辑)。

 

三. 总结

阻塞:在本语句中“右式计算”和“左式更新”完全完成之后,才开始执行下一条语句;

     • 阻塞(blocking) 赋值语句(b = a):    

       - 完成该赋值语句后才能做下一句的操作;    

       - b的值立刻被赋成新值a;    

       - 硬件没有对应的电路,因而综合结果未知。

 

非阻塞:当前语句的执行不会阻塞下一语句的执行。

    • 非阻塞(non-blocking) 赋值语句(b<= a):     

       - 块内的赋值语句同时赋值;    

       - b的值被赋成新值a的操作, 是与块内其他赋值语句同时完成的;    

       - 建议在可综合风格的模块中使用非阻塞赋值。

 

阻塞赋值和非阻塞赋值如果使用不当会存在冒险和竞争现象,必须按照下面两条准则:

     1)在描述组合逻辑的always块中使用阻塞赋值,则综合组合逻辑的电路结构;

     2)在描述时序逻辑的always块中使用非阻塞赋值,则综合时序逻辑的电路结构。

     

在时钟沿触发的always块中,如果用非阻塞赋值语句对reg型变量赋值;或者当reg型变量经过多次循环其值仍保持不变,则会在综合中生成触发器。若不想生成触发器,而希望用reg型变量生成组合逻辑,则应使用电平触发。

在组合逻辑中,阻塞赋值只与电平有关,往往和触发沿没有关系,可以将其看成并行执行的;在时序逻辑中,非阻塞赋值是并行执行的;因此,优秀的HDL设计,其内部语句也是并行执行的。

posted @ 2019-02-19 16:10  Aurora_l  阅读(858)  评论(0编辑  收藏  举报