NBA update behavior form scheduler point of view?


module top;
    bit clk, a, a_d1; //!< Variable declaration
   
    //! Clock generator
    initial begin
        clk = 0;
        forever #10 clk = ~clk;
    end

    assign a = #30 1'b1;

    always @(posedge clk) begin
        a_d1 <= a;
    end
endmodule : top

       t0 t1 t2  t3 t4 t5
          +--+   +--+   +--+   +--+
       ___|  |___|  |___|  |___|  |___
 
                 +--------------
 a     xxxxxxxxxx|
                        +--------------
 a_d1  xxxxxxxxxxxxxxxxx|               Actual behavior

                 +--------------
 a_d1  xxxxxxxxxx|               My interpretation


Is my interpretation of the sequence of event correct?

  1. t0: Active Region: Clk initialized, forever block suspended (moved to inactive waiting for #10 to elapse?), assign evaluated &
    moved to inactive (wait for #30 to elapse), always @(posedge) evaluated and suspended waiting on posedge clk event
    t1: Active Region: forever event in inactive (from t0 slot) moved to active, evaluated and clk updated and suspended. Always
    @(posedge) evaluated, variable “a” evaluated and assignment scheduled to NBA region
    NBA Region: “a_d1” assigned the evaluated value of “a”; done once active queue is empty
    t2: Active Region: forever event in inactive (from t1 slot) moved to active, evaluated and clk updated and suspended. Always
    @(posedge) evaluated and suspended waiting on posedge clk event
    t3: Active Region: forever event in inactive (from t2 slot) moved to active, evaluated and clk updated and suspended.
    i. Would update of clk trigger evaluation of “always @(posedge clk)”, or would it wait for all active events to finish?
    ii. If its the latter, assign statement would now update “a” with “1’b1”. If not, I’d guess we wouldn’t know the order of
    evaluation of always block & continuous assignment block, correct?
    iii. Assuming the first part of bullet “ii” to be correct, once the active events are done, always block gets processed and
    the value of “a” is evaluated, in this case “a == 1’b1” and the update of “a_d1” is scheduled in the NBA region
    NBA Region: “a_d1” assigned the evaluated value of “a”, in this case “1’b1”. But, this is not the behavior as the actual update
    of “a_d1” is witnessed in slot “t5”

What is the sequence of processing that causes “a_d1” to reflect the value of “a” in slot “t5”?

In reply to amandepanda:

It would really help if you gave a complete example with the correct syntax. It only needs 3 extra lines:

module top; // complete example
bit clk, a, a_d1; // declarations
 initial begin
           clk = 0;
           forever #10 clk = ~clk; // needs to be in an initial block
         end
 
    assign #30 a = 1'b1; // correct syntax
 
    always @(posedge clk) begin
        a_d1 <= a;
    end
endmodule

In t3 (time =30) there is a race condition with both clk rising and the assignment to a. Since these are all active events, the simulator is free to execute them in any order. It seems your simulator is choosing to execute the @(posedge clk) before updating a. Then it takes another posedge to get the updated value.

In reply to dave_59:

Thanks Dave! Sorry about the syntax. I’ve updated it.

Thanks,
amandepanda