Search code examples
verilogvariable-assignment

The assignment in Verilog


Why does the Verilog simulator handle these cases differently?

1)

always  #1 clk =! clk;
initial
begin
@(posedge clk)
start <= 1;
end
initial
begin
clk <= 1;
start <= 1;
end

The literature says that in 1 case, the clk and start signals will be set simultaneously and clk can capture the start signal only on the next edge. That's how it works.

But why is the second case different from the first? After all, nonblocking assignments should also be set at the same time. But it doesn't work as in the first case. But if you write it like that, then it works like the first case.

2)

initial
begin
clk = 1;
start <= 1;
end

Example 1)

module test();
reg clk=0;
reg start=0;
reg flag=0;

always  #1 clk =! clk;

initial
begin
#5;
@(posedge clk)
start <= 1;
end

always@(posedge clk)
if(start)
  flag<=1;

endmodule
module test();
reg clk=0;
reg start=0;
reg flag=0;


initial
begin
#5;
clk <= 1;
start <= 1;
end

always@(posedge clk)
if(start)
  flag<=1;

endmodule

Simulation results

https://drive.google.com/file/d/1W2eyKEXLEfwpB_iIfGnSzHqfSOw1Vs_M/view?usp=sharing

https://drive.google.com/file/d/17F9NIH41DKhrvJqnQTG7jPkfcNoJjBfh/view?usp=sharing


Solution

  • Your code examples do not follow recommended coding style for synchronous logic. This leads to simulation race conditions.

    You should expect different results with these different code samples.

    You are mixing coding styles. You should generate the clock with the blocking assignment (=) in an always block. Since start and flag are synchronous to clk, they should both use nonblocking assignments (<=) and be aligned with the clock (@(posedge clk)):

    module test();
    reg clk=0;
    reg start=0;
    reg flag=0;
    
    always #1 clk = !clk;
    
    initial
    begin
        repeat (3) @(posedge clk);
        start <= 1;
    end
    
    always @(posedge clk)
        if (start) flag <= 1;
    endmodule