Nonblocking assignments (NBA) — the myth of Verilog parallel assignment

Because of examples like the following, which swaps the value of a and b

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 b and 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;

Because write_idx0 and 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
Advertisements

2 Comments

  1. Thank you, thank you! I have lost count of the times I’ve had to explain this.

    I agree with you that a useful definition of “parallel assignment” is far from obvious. Verilog’s completely unmanaged concurrency allows apparently parallel operations to behave in a sequential but nondeterministic way, providing even more opportunities for confusion – as in this completely broken attempt to swap two variables:

    fork
    a = b;
    b = a;
    join

    Fun, fun, fun.

    Jonathan

    Like

  2. Regarding “Because write_idx0 and 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.,” the LRM says in 4.6:

    a) Statements within a begin-end block shall be executed in the order in which they appear in that
    begin-end block. Execution of statements in a particular begin-end block can be suspended in favor
    of other processes in the model; however, in no case shall the statements in a begin-end block be
    executed in any order other than that in which they appear in the source.
    b) NBAs shall be performed in the order the statements were executed (see 10.4.2).
    Consider the following example:
    module test;
    logic a;
    initial begin
    a <= 0;
    a <= 1;
    end
    endmodule
    When this block is executed, there will be two events added to the NBA region. The previous rule requires
    that they be entered in the event region in execution order, which, in a sequential begin-end block, is source order. This rule requires that they be taken from the NBA region and performed in execution order as well.
    Hence, at the end of simulation time 0, the variablea will be assigned 0 and then 1.

    and in 10.4.2:

    The order of the execution of distinct nonblocking assignments to a given variable shall be preserved. In
    other words, if there is clear ordering of the execution of a set of nonblocking assignments, then the order of the resulting updates of the destination of the nonblocking assignments shall be the same as the ordering of the execution (see 4.6).
    Example 4:
    module multiple;
    logic a;
    initial a = 1;
    // The assigned value of the variable is determinate
    initial begin
    a <= #4 0; // schedules a = 0 at time 4
    a <= #4 1; // schedules a = 1 at time 4
    end // At time 4, a = 1
    endmodule
    If the simulator executes two procedural blocks concurrently and if these procedural blocks contain
    nonblocking assignment operators to the same variable, the final value of that variable is indeterminate.

    ——————

    Another misconception about NBA's is that the sampled value is that before the trigger.
    For example,
    always @(posedge clk)
    a <- b;
    that the value used of b is that before the rising edge of clk.
    This is not so. First clk rises, then b is sampled.

    Like

Tell me (anonymous OK)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s