Level sensitive always blocks are executed even when nothing has changed
The Verilator manual says that code such as "always @ (x) y = x & z;" will be executed if x or z has changed, however it appears to get executed even if nothing has changed. This is a problem for system functions such as $display/$fwrite because it will be called on every eval().
A testcase is attached that passes with VCS.
#1 Updated by Wilson Snyder over 3 years ago
- Status changed from New to WillNotFix
I reworded it
always @ (x) y = x & z;
"This will recompute y when there is even a potential for change in x or a change in z, that is when the flops computing x or z evaluate (which is what Design Compiler will synthesize.) A compliant simulator would only calculate y if x changes. Use verilog-mode's /*AS*/ or Verilog 2001's always @* to reduce missing activity items. Avoid putting $displays in combo blocks, as they may print multiple times when not desired, even on compliant simulators as event ordering is not specified."
The (mis-)functionality itself is core to how code scheduling works and won't be changed until there's a fundamental rewrite, probably Verilator 4. That will decrease performance when it does work, though.
#2 Updated by Byron Bradley over 3 years ago
Thanks Wilson. I wasn't expecting a change for Verilator 3 (I'd already looked at how V3Active works), but I thought I'd report the difference since it took me a while to track it down.
Manually adding the code to execute the block only on a change reduced performance by almost 10% compared to just deleting the $display, so it is probably best avoided anyway.