Because of examples like the following, which swaps the value of
a <= b; b <= a;
a misconception has arisen that Verilog nonblocking assignments (NBA) achieve parallel assignment. Instead, an NBA defers an assignment until late in the time step, but calculates immediately the value that is eventually to be assigned. So in the above example, the values of
a are calculated when the NBAs are encountered, and are saved away until they are used later in the time step.
Consider instead a more realistic example, where the “parallel assignment” intuition breaks down.
memory[write_idx0] <= data0; memory[write_idx1] <= data1;
write_idx1 could be equal, priority logic is required so that the last write will win. And what would a “parallel assignment” mean anyway when these indices are equal? — Nondeterminism, multiple-writers, …? Defining parallel assignment is not an obvious thing, and the Verilog language standard does not attempt it within a sequential block.
Such examples get created when, through outside knowledge, the designer knows that the indices will never be equal, hence parallel assignment would be unproblematic. In SystemVerilog, an immediate assertion could be used to inform the tool of this fact, or with an extra loop, the
unique0 case construct
foreach (memory[idx]) begin:parallel unique0 case(idx) write_idx0: memory[idx] <= data0; write_idx1: memory[idx] <= data1; endcase end