Search code examples
verilogblockingnonblocking

Verilog blocking/nonblocking assignment in clk generator with self triggered


Why the following code is not self-triggered?

module osc1 (clk);
output clk;
reg clk;
initial #10 clk = 0;
always @(clk) #10 clk = ~clk;

always
begin
$monitor("%0d clk=%0d\n",$time,clk);
#100 $finish;
end
endmodule

output:

# 0 clk=x
# 10 clk=0
# 20 clk=1

when used non-blocking assignment it works normally
i.e., always @(clk) #10 clk <= ~clk;

output:

# 0 clk=x 
# 10 clk=0 
# 20 clk=1
# 30 clk=0
# 40 clk=1
# 50 clk=0 
# 60 clk=1 
# 70 clk=0
# 80 clk=1
# 90 clk=0

thanks in advance.


Solution

  • It has to do with the verilog scheduler.

    @ will wait for a new event, it will ignore any past events. Within the same time step, execution order matters.

    clk = ~clk is a blocking assignment, meaning clk will be update before scheduling the next @. The clk event will be missed.

    clk <= ~clk is a non-blocking assignment, meaning clk will be update after scheduling the next @. The clk event will be sensed.


    Self triggering blocks are not very common in practice. always blocks are not required to have a sensitivity list. They should have at least one reachable time blocking delay (e.g. @(_list_), #(_timeunit_)) within the block; else there is a zero time infinite loop and the simulation hangs.

    Clock generator are usually implanted something similar to:

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

    Or

    reg clk;
    always #10 clk = (clk===1'b0);