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
Karan Shah
  • 1,912
  • 1
  • 29
  • 42
  • 1
    This is the same question that was asked a couple days ago. Greg did a good job answering it. http://stackoverflow.com/a/24918187/922723 – Russell Jul 25 '14 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??? – Karan Shah Jul 25 '14 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 http://stackoverflow.com/a/22825856/1959732 , http://stackoverflow.com/a/21316975/1959732 , and there are plenty of other online resources. – Greg Jul 25 '14 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. – Karan Shah Jul 25 '14 at 18:49

1 Answers1

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);
Community
  • 1
  • 1
Greg
  • 18,111
  • 5
  • 46
  • 68