0

I have following codes with blocking (code 1) and nonblocking (code 2) assignment in always block.

But output is different in both cases. Why?

Event queue I know, but probably I am not able to understand where "always @ (clk)" statement will be placed in event queue.

// Code 1
module osc2 (clk, d);
    output clk;
    reg clk;
    input d;
    initial 
        begin
            #10 clk = 0;
            $monitor ("%d %b", $time, clk);
        end
    initial #100 $finish;       
    always @ (clk) #10 clk = ~clk;
endmodule

// Output of Code 1
10 0
20 1

// Code 2
module osc2 (clk, d);
    output clk;
    reg clk;
    input d;
    initial 
        begin
            #10 clk = 0;
            $monitor ("%d %b", $time, clk);
        end
    initial #100 $finish;       
    always @ (clk) #10 clk <= ~clk; 
endmodule

// Output of Code 2
10 0
20 1
30 0 (goes on upto 90)
90 0
4
  • 1
    This is the same question that was asked a couple days ago. Greg did a good job answering it. stackoverflow.com/a/24918187/922723 Commented Jul 25, 2014 at 11:50
  • Thanks russell, I read it, but still having some confusions. When exactly event will be scheduled, on ~clk or when clk= is executed then???? & always @ event is placed in which event queue??? Commented Jul 25, 2014 at 13:58
  • @KaranShah, Everything except clk <= and $monitor are in the active region. Everything within the always block is procedural. <= postpones the update, but the ~clk is evaluated before going back to @. If you are interested in how the scheduler works you can check out stackoverflow.com/a/22825856/1959732 , stackoverflow.com/a/21316975/1959732 , and there are plenty of other online resources. Commented Jul 25, 2014 at 18:07
  • @Greg, Thanks a lot for providing these two threads. It enhanced my concepts of event queue and scheduling, but I request you if you can just give me while loop iterations (event queue statements) of code1, then it will help me a lot for complete understanding. Commented Jul 25, 2014 at 18:49

1 Answer 1

1

For explanatory purposes, I unraveled the content of the first two loops and expanded components for break down. The below code will simulate.

always @ (clk) #10 clk = ~clk;

initial while (1) // to see the loop, functionally equivalent to 'always' 
  begin           // procedural block
    begin : loop0_unraveled
      @(clk);       // suspend continuation of loop until change in clk
      #10;          // suspend continuation of loop 10 time units
      clk = ~clk;   /* eval '~clk' now
                     * update clk now
                     */
    end
    begin : loop1_unraveled
      begin // this block is functionally equivalent to '@(clk)'
        reg smpl_clk;      // local variable
        smpl_clk = clk;    // sample 
        $display("%t::Pre-Suspend  : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
        wait(clk != smpl_clk); // suspend continuation of loop until
             /*  1. no other blocking statements can execute, go to next region
              *  2. All other regions are empty
              *  3. Remaining events are block
              *  4. Nothing left to do, exit simulation
              */
        $display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
      end
      #10;           // unreachable
      clk = ~clk;
    end
end

always @ (clk) #10 clk <= ~clk;

initial while (1) // to see the loop, functionally equivalent to 'always' 
  begin           // procedural block
    begin : loop0_unraveled       
      @(clk);       // suspend continuation of loop until change in clk
      #10;          // suspend continuation of loop 10 time units
      clk <= ~clk;  /* eval '~clk' now,
                     * update clk after all blocking statements are suspended
                     */
    end
    begin : loop1_unraveled
      begin         // this block is functionally equivalent to '@(clk)'
        reg smpl_clk;      // local variable
        smpl_clk = clk;    // sample 
        $display("%t::Pre-Suspend  : smpl_clk=%b clk=%b",$time, smpl_clk, clk);
        wait(clk != smpl_clk); // suspend continuation of loop until true
             /*  1. no other blocking statements can execute, go to next region
              *  2. In NBA region update clk
              *  3. Go back to active region
              *  4. Eval true, continue
              */
        $display("%t::Post-Suspend : smpl_clk=%b clk=%b", $time, smpl_clk, clk);
      end
      #10;           // reached
      clk <= ~clk;
    end
end                  // Go to top of the loop

As I already mentioned here, self triggering blocks are not very common in practice. Clock generator are usually implanted something similar to:

initial begin
  #10 clk = 0;
  forever #10 clk = ~clk;
end

Or

always #10 clk = (clk===1'b0);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.