Search code examples
verilogsystem-verilogtest-bench

Testbench error caused by the line order of the always begin and initial begin block


I am trying to write a testbench for systemverilog module and I realized a strange behaviour depending on order of the always begin and initial begin block. Here is my code block which works correctly.

 top test(clk, reset, writedata, dataadr, pc, instr, readdata, memwrite);
        
    always begin
            reset = 0;
            clk = 0;
            #10;
                    
            reset = 0;
            clk = 1;
            #10;
    end
    
    initial begin
        clk = 0;  
        reset = 1; #10; 
    end

If the always begin block written before the initial begin block the code works perfectly fine and outputs thisenter image description here

But if we change the order of the always begin and initial begin blocks

 top test(clk, reset, writedata, dataadr, pc, instr, readdata, memwrite);
   
    initial begin
        clk = 0;  
        reset = 1; #10; 
    end
     
    always begin
            reset = 0;
            clk = 0;
            #10;
                    
            reset = 0;
            clk = 1;
            #10;
    end     

enter image description here

In which the values are set to undetermined. Don't these two blocks work independently? Why does their order of writing cause a problem here?


Solution

  • You have a simulation race condition. The always block and the initial block assign the reset signal to different values at the same simulation time (0ns).

    Your first code sets reset to 1 at time 0, then to 0 at time 10ns. Your design presumably has an active-high reset, and it properly reset the internal design signals to known value at time 0.

    The waveforms for your 2nd code appear to keep the reset signal at 0 for the whole simulation; I assume the signal below the clock is reset. In this case, the internal design signals are not properly reset, and they retain their initial unknown values.

    In the 2nd block, the simulator sets reset=1 in the initial block at time 0, then the value of reset is overwritten by the always block at time 0, setting reset=0.

    In any case, I recommend you simplify the code like this to avoid the race condition:

    always #10 clk = ~clk;
    
    initial begin
        clk = 0;  
        reset = 1;
        #10;
        reset = 0;
    end
    

    Due to nondeterminism, even your 1st code could produce the bad result. There is no guarantee that the simulator will execute the always block before the initial block.