关于veriolg中阻塞与非阻塞赋值问题

Posted flyuea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于veriolg中阻塞与非阻塞赋值问题相关的知识,希望对你有一定的参考价值。

在一开始学到阻塞和非阻塞的时候,所被告知的两者的区别就在于阻塞是串行的,非阻塞是并行的。但是虽然知道这个不同点,有些时候还是很难真正区分用两者电路的区别,在这就通过几个例子来解释一下。

以一个简单的串行流水线寄存器为例:d-q1-q2-q3.

1,采用阻塞赋值

代码:always @ (posedge clk) begin q1=d; q2=q1; q3=q2; end

这样的代码将会导致每一个寄存器输出都是d,即d将无延时的传送给q3(即q3=d)。因为采用的是阻塞赋值,当时钟上升沿到来时,先执行q1=d,再执行q2=q1。以此类推,最后所以寄存器的值都变成了d.反映到电路中的结果就是一个单独的直接从d到q3的寄存器,不符合流水线要求。

2,依然采用阻塞赋值,但是赋值顺序有变化

代码:always @ (posedge clk) begin q3=q2; q2=q1; q1=d; end

当我们改变赋值顺序后,综合的电路是符合要求的。当上升沿到来,先执行q3=q2,则q3的值是上一个时钟沿时q2的值。类似的,当上升沿到来后,每个寄存器的值都往后移动了一位,也就实现了预期的流水线结构。但是这样的缺点就在于我们要仔细的安排赋值的顺序,容易出错,且增加工作量。

3,采用非阻塞赋值

代码:always @ (posedge clk) begin q1<=d; q2<=q1; q3<=q2; end

由于非阻塞赋值是并发执行的,当时钟沿到来时,每个寄存器更新的值都是赋值寄存器在上一个时钟沿所被赋予的值,也就真正实现了流水线的结构。而且采用非阻塞赋值的好处在于,不用想阻塞赋值一样需要考虑赋值顺序问题。

另外一个问题是,为什么在组合逻辑中需要使用阻塞赋值?

在大多数情况下,都应该使用非阻塞赋值,这也比较符合电路并发执行的特点。但是在组合逻辑中并不一定。

例如:

always @ (a or b or c or d) begin

temp1<=a & b;

temp2<=c & d;

y<=temp1 | temp2;

end

在这个组合逻辑中,我们希望实现的是先将ab相与,cd相与,再将产生的temp1,temp2相或。但由于采用的是非阻塞赋值,是并发执行的。当执行y<=temp1 | temp2时,temp1,temp2的值并未更新,也就是说y输出的是上一个触发时temp1 | temp2的值,即延后了一次触发。

而如果此时采用阻塞赋值的话,则能正确实现电路。

不过对于这个问题,我还是觉得并不是说组合逻辑导致要使用阻塞赋值,而是说电路功能决定到底使用哪种。即便上面的例子是时序电路,如果要实现相同的逻辑,则依然要用阻塞赋值。而如果你是使用类似之前提到的移位的功能,则即便用的是组合逻辑,也需要用非阻塞赋值。

至于为什么会有组合电路用阻塞的说法,应该是大部分时候组合逻辑功能需要阻塞赋值,且这是一个规范吧,毕竟规范有时候不是很好解释,但是却在工作中大有裨益。当然,这只是我个人观点,有不同意见者希望不吝指教。

以上是关于关于veriolg中阻塞与非阻塞赋值问题的主要内容,如果未能解决你的问题,请参考以下文章

verilog 关于阻塞与非阻塞赋值同时使用时的问题

真正理解阻塞逻辑赋值与非阻塞逻辑赋值

阻塞赋值和非阻塞赋值有何区别

RTL基本知识:阻塞赋值与非阻塞赋值

07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档

FPGA的阻塞赋值与非阻塞赋值