Search code examples
verilogsystem-verilogvivado

increment operation in Systemverilog Vivado not working as expected


Sum: The part with the state machine named "WaitS2" is only incrementing the "count" once.

I am trying to control ultrasound sensors HC-SR04 in systemverilog. As I saw in the datasheet, this sensor creates a signal "trigger" which creates the sound and after generating the sound sensor creates logic "echo", I need to count the time, so that I create the state machine you can see in the code, but the problem is count++ is not working as well as expected it is only incrementing count variable once, no matter how long the echo signal is

I used another module called 32-bit adder from internet, which did not changed anything. I changed all of the statements to non-block statements it did not work. I even tried changed count++ to count = count + 1 did not work

module sensorFSM(
    input logic echo , clk ,reset, 
    output logic trig,
    output logic[31:0] distance,
    output logic[1:0] presentState
    );
    /*typedef enum logic[1:0] {BeginS , WaitS , ReturnS } states;
    states presentState , nextState;
    */
    logic[31:0] count , count1; 
    logic[1:0] BeginS , WaitS, WaitS2 , ReturnS  , nextState;
    assign BeginS = 2'b00;
    assign WaitS = 2'b01; 
    assign WaitS2 = 2'b10;
    assign ReturnS = 2'b11; 

    // clk and state change
    always_ff @( posedge clk )
        begin
            if ( reset == 1'b1 )
            presentState <= BeginS;
            else
            presentState <= nextState;
        end

    // real state changes    
    always_comb 
        begin            
            case(presentState)           
            BeginS:
                begin
                    trig = 1'b1;
                    count = 32'b0;
                    nextState = WaitS;
                end
            WaitS:
                begin
                    trig = 1'b0;
                    distance = 32'b0;
                    //#5000;
                    nextState = WaitS2;
                end
            WaitS2:
                begin
                    if( echo  == 1 )
                      begin
                        if ( count < 24'b101100111000000100100000 )
                            begin 
                            // here is the problem count is only incrementing 
                            //once
                                count++;                               
                                nextState = WaitS2; 
                            end 
                         else 
                            begin
                                distance = count;
                                nextState = BeginS;
                            end 
                      end
                    else // echo == 0   
                        begin
                            nextState = ReturnS;
                        end
                   end 
            ReturnS:
                begin
                    //count =  count / 1470;
                    distance = count;
                    nextState = BeginS;
                end
            default:
                nextState = BeginS;
            endcase
         end  
endmodule

I expect the simulation will count like around 1 miliion but it always outputs 1, but I can see that the state named "WaitS2" is present for a long amount of time when echo is active also


Solution

  • You created an asynchronous feedback loop with count++; inside always_comb. You need to make count a register.

    Also trig and distance are currently inferred level-sensitive latches. distance needs to be a flop. trig could be written as pure combinational logic, but since it is an output I highly recommend to make it a flop remove the rise of output glitches.

    always_ff @( posedge clk )
        begin
          if ( reset == 1'b1 ) begin
            presentState <= BeginS;
            trig <= 0; // <-- reset
            distance <= 0; // <-- reset
            count <= 0; // <-- reset
          end else begin
            presentState <= nextState;
            trig <= next_trig; // <-- flop trig
            distance <= next_distance; // <-- flop distance
            count <= next_count; // <-- flop count
          end
        end
    
    // real state changes    
    always_comb 
        begin
          next_trig = trig; // <-- default value is flopped value
          next_distance = distance; // <-- default value is flopped value
          next_count = count; // <-- default value is flopped value
            case(presentState)           
            BeginS:
                begin
                    //trig = 1'b1; // <-- is now a flop assigned in always_ff
                    //count = 32'b0; // <-- is now a flop assigned in always_ff
                    next_trig = 1'b1; // <-- update value
                    next_count = 32'b0; // <-- update value
                    nextState = WaitS;
                end
            WaitS:
                // ... replace trig/distance with next_trig/next_distance in here ...
            WaitS2:
                begin
                  // ...
                  //count++;  // <-- NOPE would be asynchronous feedback
                  next_count = count + 1; // <-- synchronous increment
                  // ...
                end
            ReturnS:
                //  ... replace distance with next_distance in here ...
            default:
                nextState = BeginS;
            endcase
         end