#+title: Interesting edge case in Simulation and Synthesis Mismatch I have always known about situations where the simulation might not match the synthesised result, for example when blocking assignment is used in one always block and is read from another. However, the following mismatch is slightly surprising to me because I feel like simulators should be giving the same result as synthesis tools, as it seems to be quite common. Otherwise, it also seems fair that the synthesis tool should implement what the simulator is showing, as it is strange to get such different results. I tested the following with the Quartus 20.1 and Yosys 0.9+2406 synthesis tool (which both gave the same result) and the icarus verilog, verilator and ModelSim simulators which also agreed with each other. Assuming we want to implement the following design. My expectation would be that it just basically assigns ~a~ to ~x~ whenever ~a~ changes. #+begin_src verilog module top(a, x); reg [3:0] tmp; input [3:0] a; output reg [3:0] x; always @* begin x = tmp; tmp = a; end endmodule // top #+end_src This seems to be correct when looking at the synthesised design printed by Yosys. #+begin_src verilog /* Generated by Yosys 0.9+2406 (git sha1 000fd08198, clang++ 7.1.0 -fPIC -Os) */ module top_synth(a, x); input [3:0] a; wire [3:0] tmp; output [3:0] x; assign tmp = a; assign x = a; endmodule #+end_src However, when simulating it with the following testbench, it instead acts like a shift register. #+begin_src verilog module main; reg [3:0] a; wire [3:0] x, x_synth; top top(a, x); top_synth top_synth(a, x_synth); initial begin a = 0; #10 a = 1; #10 $display("x: %d\nx_synth: %d", x, x_synth); $finish; end endmodule #+end_src The test bench above prints #+begin_src text x: 0 x_synth: 1 #+end_src showing that the synthesised design does not match the simulated design. Is the test bench that I wrote slightly broken? Or is this expected to be this different. In the latter case, how come simulators don't implement the correct behaviour? This could be done by recursing and reevaluating the always block when an element in the sensitivity list changed, even if that was in the same always block. Even in simulation I would expect these two snippets to act the same #+begin_src verilog always @* begin x = tmp; tmp = a; end #+end_src #+begin_src verilog always @* begin tmp = a; x = tmp; end #+end_src Because ~a~ and ~tmp~ are both in the sensitivity list, meaning in the first code snippet, it should reevaluate the always block and update the ~x~ register with the correct value which is ~a~.