verilog里面always块中的阻塞赋值的问题
请参见IEEE 1364.1标准第5.2.2小节,给临时变量使用的阻塞赋值不会影响综合结果
5.2.2 Modeling edge-sensitive storage devices
An edge-sensitive storage device shall be modeled for a variable that is assigned a value in an always statement that has exactly one edge event in the event list. The edge event specified shall represent the clock edge
condition under which the storage device stores the value.
Nonblocking procedural assignments should be used for variables that model edge-sensitive storage devices. Nonblocking assignments are recommended to avoid Verilog simulation race conditions.
Blocking procedural assignments may be used for variables that are temporarily assigned and used within an always statement.
牛!这个代码是老外一个比较有经验的工程师写的,所以我一直在想是不是有什么道理,但是没查到。我举的第一个例子个人觉得还是改成data <= {aaa[7:4],din[3:0]};比较好,因为aaa是定义在always block之外的全局变量,这样可读性较好;不过我举的第二个例子,变量定义在always block里面,作为一个复杂计算结果的暂存值,或者作为一个判断条件,感觉还是原写法可读更好,你的引用正好解释了这种方法的合理性,不然这个信号只能在block之外用组合逻辑计算再在block内部引用了,可读较差。谢谢!
没听说过这个限制
描述时序逻辑的信号变量,使用非阻塞赋值,这样可以避免仿真时的竞争冒险
作为时序逻辑描述中的临时变量,可以使用阻塞赋值,不会影响综合结果和仿真
嗯,这是一种在时序逻辑描述中使用临时变量的经典写法
不用客气
教科书上已经说了,在时序always里面混用阻塞和非阻塞有可能导致仿真和综合的结果不一致。从本质上讲,在时序always里面使用阻塞复制是无法用真实电路来映射的,综合器必须去猜测设计者的意图,来推断该变量是寄存器还是一段组合逻辑。ieee所谓的规范不过是规定了一种不会产生歧义的场景。
两种赋值混用并非不可替代,而且没有任何优化效果,虽然有无数场景下没有问题,但是只要有一处出错,就不是推荐的代码风格。真实中,由于笔误把<=写成=的情况非常常见,在统一使用非阻塞赋值的代码中,这种低级错误很容易纠正,而混合赋值的代码则很难纠错。
任何正规公司,在RTL标准之外都会有一套更严格的代码规范,这就是工程和学术的区别。
在always里面混用的结果就是其他人很难直观理解设计者的意图。因为用阻塞赋值,最后有可能综合出reg,也有可能综合出wire.专指rtl级。
不要太相信工具能完美体现出标准,要不然我们也不需要做一致性验证了。
第一种情况当然是很容易替代的;但是我提到的第二种,比如原来代码是这样:
always @(posedge clk) begin
reg [31:0] tmp;
..............
case(n)
1: tmp = function1(xxxx);
2: tmp = function2(yyyy);
........
endcase
if (function3(tmp,aaa,bbb)) begin
data <= xyz;
end
end
利用在always块中定义一个tmp变量使得后续的代码可读性较高且符合规范,假如要严格遵守只能使用非阻塞赋值的规定的话,需要在always块外定义wire型的tmp,然后通过复杂的组合逻辑,算出tmp,再组合逻辑得出function3的结果,然后用在always时序块中,当always块中内容非常多的时候,反而使可读性下降了啊
赞成
另外还有一个问题:一旦规范允许这种写法
某些工程师就会将其引申发挥到极致,创造出很多匪夷所思的代码
我只想对lz说,全部用非阻塞赋值一定可以实现你想要的时序,而不必通过这种混用的办法!
嗯,因为是维护别人的代码,改动时序有点麻烦,只能尽量小修改增加可读性了
代码是老板以前写的,现在要移到另外一个项目中,他要review的,改太多不好,老外。。。
只要你遵循IEEE 1364.1标准中所描述的规则来混用,是不会“最后有可能综合出reg,也有可能综合出wire”
你可以举例来说明
这是IEEE标准中的提示——即用阻塞赋值来描述时序逻辑会在仿真中遇到竞争冒险问题
注意不是混用阻塞和非阻塞赋值的问题,而是试图用阻塞赋值来描述时序逻辑器件
使用阻塞赋值来操作临时变量是没有任何问题的
内部临时变量就是寄存器d端前面的一坨组合逻辑么,写在always外面单独描述给人一种"
