在上一篇文章中,我们介绍了Verilog HDL里面的"非阻塞赋值"和"阻塞赋值"。并且通过一个实例,分析了在阻塞赋值中竞争的产生,即如果在一个always块内等式右边的表达式或者变量,是另一个always块内等式左边的表达式或者变量,仿真器在同一个时间(同一个时钟的边沿)内同时执行两个等式,这就会有问题产生,因为在赋值过程中,已经有竞争产生,所以会导致赋值过程变得不可控,我们也不清楚仿真器到底会怎么调度赋值语句的顺序。 今天我们继续来分析在非阻塞赋值中的情况。非阻塞赋值 非阻塞赋值的整个过程可以分为两步:在当前时间节点,开始估计右边表达式的值;在当前时间节点结束时候,将值赋给左边的变量。 非阻塞赋值的特点在于,无论我们在估算右边的表达式的值,还是赋值给左边的变量,在整个过程中,不会影响其他非阻塞赋值语句的执行。 需要说明的是,Verilog HDL语法中规定,"非阻塞赋值"只能出现在always/initial程序块中,在assign的连续赋值语句中,不能使用。 非阻塞赋值实例 为了说明这个问题,我们同样给出一个实例。这个实例和上一篇实例的区别在于,将阻塞赋值替换成了非阻塞赋值。 具体实例,如图所示: 图一 非阻塞赋值 当我们使用非阻塞赋值之后,两个always块里面的语句,就可以任意执行。两个reg变量在rst_n之后,赋不同的初值。复位完成之后,不论两个always块的执行先后顺序如何,在同一个时间点,开始估算右边表达式的值,然后,在时间点结束时,同时将估算得到的值,赋给左边变量,完成整个操作。所以,虽然两个always语句块同时执行,但是却并不会像阻塞赋值一样,产生竞争现象。Verilog编码的建议 通过以上内容,我们可以看出如果我们稍不注意,就会出现Verilog的竞争现象,并且这种现象是很难debug的。所以我列出了几条建议,如果大家能够严格按照下面的建议来进行硬件的RTL建模和仿真,相信可以帮助大家省去很多和Verilog竞争的烦恼。用非阻塞赋值对时序逻辑建模;如果实在always块为组合逻辑建模,请使用阻塞赋值;在一个always块内,只出现一种赋值类型,不能混合使用非阻塞赋值和阻塞赋值;同一个变量的赋值要放在一个always块内部,不能放到两个或两个以上的always块内。 小结 今天的文章,我们讨论了Verilog HDL中的非阻塞赋值。并且举了一个实例来说明非阻塞赋值的赋值过程。为了消除因为使用不当引起的Verilog竞争,我们给出了一些使用非阻塞赋值和阻塞赋值的建议。 另外,我的专栏《15节课教你搞懂Verilog HDL》已经正式上线,主要讲解Verilog HDL语言,以及RTL代码和数字电路的映射关系,欢迎大家订阅。