verilogsimulation

The simulation results of Vivado are inconsistent with those of HDLBits


I studied Verilog and do my exercises on HDLBits. I came up with a question when trying to solve this problem: https://hdlbits.01xz.net/wiki/Exams/2014_q3fsm

I wrote the following codes according to this State transition diagram.

enter image description here

I submit my code:

module top_module(
    input clk,
    input reset,   // Synchronous reset
    input s,
    input w,
    output reg z
);
    // State encoding
    parameter A = 3'd0, B1 = 3'd1, B2 = 3'd2, B3 = 3'd3, B = 3'd4;

    reg [2:0] state, next_state;
    reg [2:0] count;
    //reg z;
    
    // Next-state logic
    always @(*) begin
        case (state)
            A:  next_state = s ? B : A;
            B1: next_state = B2;
            B2: next_state = B3;
            B3: next_state = B;
            B: next_state = B1;
            default: next_state = A;
        endcase
    end

    // Sequential logic
    always @(posedge clk) begin
        if (reset) begin
            state <= A;
            count <= 0;
            z <= 0;
        end else begin
            state <= next_state;
            z <= 0;
            // Count update
            case (next_state)
                B : count <= 0;
                B1 : count <= w;
                B2: count <= count + w;
                B3: begin 
                    count <= count + w;
                    z <= (count + w == 2);
                end
                default: count <= 0;
            endcase
            
        end
    end
 
endmodule

Then I got those messages:

result from dhlbits

From the result, we can see my z become 1 when t = 120, but the refs become 1 at time = 110.

But when I execute this code in Vivado, the waveform is as below:

waveforms from vivado

The testbench code is:

module fsm1_tb;
    reg s, w, clk, reset;
    wire out, out2;
    top_module dut(clk, reset, s, w, out);

    always
        #5 clk = ~clk;
        
    initial begin
        clk = 1;
        reset = 1;
        s = 0;
        w = 0;
        #20 reset = 0;
        #20 s = 1;
        #10 w = 1;
        #30 w = 0;
        #5 w = 1;
        #10 w = 0;
        #5 w = 1;
        #10 w = 0;
        #5 w = 1;
        #5 w = 0;
        #5 w = 1;
        #5 w = 0;
        #5 w = 1;
        #10 w = 0;
        #25 $finish;
        
    end


    always @(posedge clk) begin
        $strobe("t=%0t: state=%d, next_state=%d, in=%b, count=%d", $time, dut.state, dut.next_state, w, dut.count);
    end
endmodule

The waveforms Vivado show that my z become 1 at 110ns.

I don't know why this happens. Are there any problems with my state transition diagram or codes?


Solution

  • I think there is a problem with the HDLBits question. When I follow your link, I see sample waveforms which show the input signals s and w being synchronous to the clock. The text does not explicitly say they are synchronous, but it is a reasonable assumption for anyone to make.

    However, when you post your code in the site, then run the simulation there, the input waveforms they used show w as an asynchronous signal because it is changing on both edges of the clock. I consider this a problem because they did not give you a complete specification for the design. This HDLBits exercise is faulty, and you should not bother using it.


    That being said, if you assume all inputs should be synchronous to the clock, you should change your testbench to drive the inputs the same as how you drive output signals inside the module, namely:

    For example:

    initial begin
        clk = 1;
        reset = 1;
        s = 0;
        w = 0;
        repeat (2) @(posedge clk);
        reset <= 0;
        repeat (2) @(posedge clk);
        s <= 1;
        // etc.
    

    This avoids the simulation race conditions in your testbench code. Due to the races, simulation results between 2 simulators are not guaranteed to match each other.

    Note: at time=0, it doesn't matter if you use blocking or nonblocking assignments.

    Another issue with HDLBits is that you can't see their testbench code, nor do you have any visibility into internal signals. The site is very useful for trivial designs, but it is not very useful for more complex designs like this example.


    Someone posted a solution to Q3a: FSM that shows a passing result on HDLBits, although it uses poor coding style.