用Verilog实现流水移位寄存器,请尽量不要使用阻塞赋值
我们用了4篇文章,分别讨论了VerilogHDL里面的非阻塞赋值和阻塞赋值。用实例分析了如果在一个always块内等式右边的表达式或者变量,是另一个always块内等式左边的表达式或者变量,仿真器在同一个时间(同一个时钟的边沿)内同时执行两个等式,这就会导致竞争产生。并且我们详细分析了在同一个always块里面,如果混合使用非阻塞赋值和阻塞赋值,所可能出现的结果,并且给出了建议的编码方式。
同时给大家分享2种流水移位寄存器的建模方式,并通过代码来比较,这2种方式的优劣。今天我们继续来给出另外2种流水移位寄存器的描述方式,并看看这两种描述方式有什么问题。
第三种描述方式,用阻塞赋值描述
下面这种还是使用阻塞赋值进行描述:
regqff,q2ff,q3ff;
always(posedgeclk)qffdatain;
always(posedgeclk)q2ffqff;
always(posedgeclk)q3ffq2ff;
如果采用这种描述方式,3个always块里面的语句会同时执行,所以会出现冒险竞争问题,导致仿真结果不正确。但是让人诧异的是,综合的结果却是正确的。这就出现了综合前的仿真结果和综合后的仿真结果不同的情况发生。我们要避免这种情况。
第四种描述方式,用阻塞赋值描述
在前面的例子中,我们提到过,在阻塞赋值中,可以通过调整赋值语句的顺序,使得RTL满足我们的需求。同样的,在这里我们试着调整描述语句顺序,看是否能够满足。
regqff,q2ff,q3ff;
always(posedgeclk)q2ffqff;
always(posedgeclk)q3ffq2ff;
always(posedgeclk)qffdatain;
经过调整之后,通过仿真发现,这种描述方式依然存在和上面例子同样的问题。即综合前仿真不正确,而综合后仿真结果正确。
所以看出,以上两种方式,都是不好的描述方式,希望大家不要使用。
推荐的描述方式
既然上面的描述方式有问题,我们给出推荐的描述方式:
regqff,q2ff,q3ff;
always(posedgeclk)begin
q3ffq2ff;
q2ffqff;
qffdatain;
end
当我们使用上面的非阻塞赋值进行描述时候,就能保证综合前后的电路仿真结果一致了。小结
今天我们分享了2种不好的verilogHDL描述语句,并给出了一种推荐的描述语句,希望能让大家加深对非阻塞赋值和阻塞赋值的理解。
另外,我的专栏《15节课教你搞懂VerilogHDL》已经正式上线,主要讲解VerilogHDL语言,以及RTL代码和数字电路的映射关系,欢迎大家订阅。