verilogsystem-verilogwaveform

Confusion about nonblocking assignments to signals for synchronous logic


I have Verilog code like this:

module gen_bits(input clk, input clear, input ld, input in, output reg[7:0] out);

    always @(posedge clk) begin
        if (clear)
            out <= 8'b00000000;
        else if (ld)
            out <= (2 * out + in);
        else
            out <= out;
    end
endmodule

wave

And I get a waveform. I have questions about this waveform.

  1. At time = 25ns, we can see from the wave that clear=1, so I thought that out would be 0 because of if (clear) out <= 8'b00000000;, but why the wave shows that the value of out was still 'XX'?

  2. At time = 125ns, ld = 0. So I thought the value of out should be 78. But it out to be f1.

I know that my questions the waveform diagram are due to my lack of knowledge about nonblocking assignment and sequential circuits.


Solution

  • This is expected simulation behavior with nonblocking assignments (<=).

    Your gen_bits design code follows the recommended Verilog coding style for synchronous logic because it uses nonblocking assignments in an always block with a clock event (such as posedge).

    The clear signal is used as a synchronous reset. Lets' assume you used the recommended coding style to drive the input signal from outside of the module, which is the same as how you drive output signal inside the module, namely:

    For example, let's say you have a testbench to drive clear with the recommended approach:

    module tb;
        bit clear;
        bit clk;
        bit in;
        bit ld;
        wire [7:0] out;
    
    gen_bits dut (
        .clear  (clear),
        .clk    (clk),
        .in     (in),
        .ld     (ld),
        .out    (out)
    );
    
    always #5 clk++;
    
    initial begin
        repeat (3) @(posedge clk);
        clear <= 1;
    
        @(posedge clk);
        clear <= 0;
        in <= 1;
        
        repeat (3) @(posedge clk);
        $finish;
    end
    
    endmodule
    

    In this case clear is synchronous to clk. That means that the simulator will sample clear just before the rising edge of the clock. Since the waves show clk and clear rise at the same time at time=25ns, then the simulator samples clear as 0, not 1. Since clear is 0, the output will not change and remains unknown (x).

    This is how nonblocking assignments are designed to behave according to the IEEE Std 1800-2023.

    At the next rising edge of clk, clear is sampled as 1, and the output will become known.

    By the same reasoning, at time=125ns, ld is sampled as 1, not 0.