Overview

Compared to the conventional simualtion that we see in procedural program execution lilke C/C++, HDL simulators exist to model a real world hardware circuit. This means that the programming language needed constructs which enabled scheduling value assignments and statement execution. Hence the verilog regions and the non blocking assignment constructs were introduced.

One key aspect that must be remembered in case of non blocking assignments is that, the RHS part of the assignment is run and evaluated but never assigned immideately. Instead, this assignment is scheduled to happen in the NBA region. You can assume the RHS is assigned to a temp variable which is the same type as the actual LHS variable. Then, later in the NBA region, this temp variable is assigned to the actual LHS variable.

Conside the following simple NBA assignment.

module top;

    integer a;

    initial
    begin
        a <= 100;    
    end

endmodule

The simulator internally simplifies this in this manner ( we will not see it, but this is something the simulator will do internally )

module top;

    integer a;

    initial
    begin
        a <= 100; // No changes take place in "a"
        /*
            a_temp = 100; // Schedule this to execute in NBA | this is internally done my the simulator    
        */
    end

    /*
        NBA Region Code Execution
        -------------------------

        a = a_temp;
    */

endmodule

LHS <= RHS

Another Example

Consider this slightly more complex example and understand how the verilog regions and NBA scheduling togather work.

module top;

    integer a,b;

    initial
    begin
        a = 1;
        b = 2;
        a <= 3;
        b <= a;
        a = b;
        b <= a + b;
        a = 5;
        b = 6;        
    end

endmodule

This can be simplified in the following manner to better understand.

module top;

    integer a,b;

    initial
    begin
        a = 1; // a updates to 1 in Active Region
        b = 2; // b updates to 2 in Active Region
        a <= 3; // a_temp_1 = 3 updates in Active Region | a = a_temp_1 is scheduled into NBA Region
        b <= a; // b_temp_1 = a ( a is 1 right now in Active Region ) updates in Active Region | b = b_temp_1 is scheduled into NBA Region
        a = b; // a updates to 2 ( since b is 2 right now in Active Region )
        b <= a + b; // b_temp_2 = a + b ( 2 + 2 ) | b = b_temp_2 is scheduled into NBA Region
        a = 5; // a updates to 5 in Active Region
        b = 6; // b updates to 6 in Active Region
    end

    /*
        NBA Region Code Execution ( based on the scheduled order )
        ----------------------------------------------------------

        a = a_temp_1; // a_temp_1 is 3
        b = b_temp_1; // b_temp_1 is 1
        b = b_temp_2; // b_temp_2 is 4

        // The above statements become

        a = 3;
        b = 1;
        b = 4;

        // After executing these in order, by the end of NBA, a is 3 and b is 4 ( you can check this in postponed region using $strobe )
    */

    initial
    begin
        $strobe( "a : %0d, b : %0d", a, b );
    end

endmodule
Theory Questions
    NBA assignment was introduced to mimic the transient behaviour digital circuits before they finally stabilize into a stable value towards the end of the circuit.
    RHS expression is evaluated, but never really assigned to LHS in the active region.
    LHS value is assigned the RHS evalueted value in the NBA region. The evaluated value was calculated in the Active region, but the LHS updation happens in the NBA region.
    When RHS is evaluated, ot is not assigned to the RHS but rather scheduled to be assigned to LHS in NBA.
    module top;
        integer a,b;
    
        initial
        begin
            a = 100;
            b <= 10;
            a = 50;
        end
    endmodule
    
    a is 50 and b is 10.
    module top;
        integer a,b;
    
        initial
        begin
            a = 100;
            b = 200;
            a <= 10;
            b <= 20;
            a <= b;
            b = 50;
        end
    endmodule
    
    a is 200 and b is 20.
    module top;
        integer a,b,c,d;
    
        initial
        begin
            a = 100;
            b = 200;
            c <= 0;
            a <= 10;
            b <= 20;
            a <= b;
            b = 50;
        end
    
        initial
        begin
            #0;
            b <= a;
            a <= b;
            a <= 100;
            a = 20;
            b = 300;
        end
    endmodule
    
    a is 100, b is 100, c is 0 and d is X.
Coding Questions
    module top;
        integer a = 100, b = 200;
    
        initial
        begin
            $display( "Before -> a : %d, b : %d", a, b );
            a <= b;
            b <= a;
            $display( "After  -> a : %d, b : %d", a, b );
        end
    endmodule