Verilog HDL作为芯片设计领域的一门语言,在世界范围内的使用者众多。特别是在我们国内,除了一些军工企业使用VHDL之外,包括企业、高校里面都大多使用Verilog HDL作为工作和教学的语言。相信很多电子相关专业的同学和从业者,对这门语言的第一感觉,都觉得很难,而阻塞赋值和非阻塞赋值有时Verilog HDL这门语言里面最难明白的结构之一。

不管是刚毕业的新同事,还是一些比较有经验的老从业者,有很多都不太清楚在仿真器里面“非阻塞赋值”和“阻塞赋值”究竟是怎么设定执行的。那么今天我就想分享一些我的理解(先不考虑延时的影响),来和大家进行讨论,因为自己水平有限,如果理解有误,欢迎大家指正。

verilog hdl语言如何表达数字常量(HDL中的阻塞赋值和非阻塞赋值)(1)

阻塞赋值

阻塞赋值使用“=”作为赋值符号,表示阻止下一句的执行。在具体使用的时候,有两种常用的语法结构:

  1. assign语句中使用。这条大家应该会比较清楚,因为如果使用不正确,编译都没办法通过,在这里就不再讨论。
  2. 在always块中使用阻塞赋值,来产生组合逻辑。这块的问题会比较多,因为如果使用不正确,在仿真阶段可能没有问题,但是也许会导致综合得到的电路和RTL代码的仿真结果不匹配,这就是很大的风险。
非阻塞赋值

非阻塞赋值使用“<=”作为赋值符号,当前过程语句执行完毕,就立刻执行下一条语句。如果一个always块里面都是非阻塞赋值,则整个赋值过程可以分为以下两步:

  1. 仿真器先计算出表达式右端的值,将结果保存下来。
  2. 在时序控制调度下面,在指定时间完成给左边表达式的赋值。

verilog hdl语言如何表达数字常量(HDL中的阻塞赋值和非阻塞赋值)(2)

仿真器对阻塞赋值方式的调度

如果仿真器对两种赋值方式的调度能够更严苛一些的话,问题似乎就能简单清楚一些。但是问题在于IEEE Verilog标准定义的比较松,能够接受在同一个仿真时间,赋值操作中出现竞争现象的出现。这就导致了不同的赋值语句描述,产生完全不同的结果,却又都符合IEEE Verilog的标准,这就使问题变得复杂了。我们再深入阐述一下这个问题。

verilog hdl语言如何表达数字常量(HDL中的阻塞赋值和非阻塞赋值)(3)

阻塞赋值在完成赋值之前,会阻塞其他类型的赋值,所以我们考虑下面一个问题:

如果在一个always块内等式右边的表达式或者变量,是另一个always块内等式左边的表达式或者变量,仿真器在同一个时间(同一个时钟的边沿)内同时执行两个等式,这就会有问题产生,因为在赋值过程中,已经有竞争产生,所以会导致赋值过程变得不可控,我们也不清楚仿真器到底会怎么调度赋值语句的顺序。

让我们举个例子来说明这种情况:

verilog hdl语言如何表达数字常量(HDL中的阻塞赋值和非阻塞赋值)(4)

上面这端RTL就会产生Verilog HDL的竞争。因为按照IEEE Verilog的标准,两个always块的执行顺序是任意的,那就会产生两种情况:

  1. 假如第一个always块先执行,则test_01和test_02都是1;
  2. 假如第二个always块先执行,则test_01和test_02都是0;

这就导致了问题的产生。

小结

今天的文章,我们讨论了Verilog HDL中的阻塞赋值和非阻塞赋值。并且举了一个实例来说明阻塞赋值可能产生竞争,导致RTL功能出现问题。关于非阻塞赋值的详细讨论,欢迎继续关注后面的文章。

另外,我的专栏《15节课教你搞懂Verilog HDL》已经正式上线,主要讲解Verilog HDL语言,以及RTL代码和数字电路的映射关系,欢迎大家订阅。

,