Search code examples
verilogsystem-verilogquartus

Cause of inferred latches (not else or default statement) in Verilog


Quartus is telling me that I have inferred latches for input_val, ii, output_val, delayed, and addr_to_rom. I have looked at previous posts and made changes so that all my if statements have an else component and that my case statement has a default option.

What else could be causing all of these inferred latches? (updated code below)

   module   simple_fir(clk, reset_n, output_val); 
    
    parameter               data_width = 8; 
    parameter               size = 1024;    

    
    input   wire                clk;
    input   wire                reset_n;
    //input     reg [(data_width):0]    input_val;
    reg [(data_width):0]    input_val;
    output  reg [data_width:0]      output_val;

    reg     [(data_width):0]    delayed;
    reg     [data_width:0]      to_avg;     
    reg         [9:0]           ii ;
    reg         [9:0]           i ;
    reg     [data_width:0]      val;
    reg     [data_width:0]      output_arr [(size-1):0];

    
    logic [(data_width):0] data_from_rom; //precalculated 1 Hz sine wave
    logic [9:0] addr_to_rom;

    initial delayed = 0;
    initial i = 0;
    initial ii = 0;
    
    
    //port map to ROM
    rom_data input_data(
    .clk(clk),
    .addr(addr_to_rom), //text file?
    .data(data_from_rom)
    );
        
    //Moore FSM
    localparam [3:0]
    s0=0, s1 = 1, s2 = 2, s3 = 3, s4 = 4, s5 = 5, s6 = 6;
    
    reg [3:0] state_reg, state_next;
    initial state_next = 0;
    always @(posedge clk, negedge reset_n) begin //posedge clk, reset_n
        if (reset_n == 'b0) begin //reset is active low
        state_reg <= s0;
        end else begin
        state_reg <= state_next;
        end
    end
            
    always @* begin 
        state_next = state_reg; // default state_next
        case (state_reg)
            s0 : begin //initial state, reset state
                    if (!reset_n) begin
            output_val = 0;
            delayed = 0; 
            to_avg= 0; 
            i = 0;
            ii = 0;
            end else begin
            state_next = s1;
            end
            end
            s1 : begin
                if (ii>(size-2)) begin
                ii = 0;
                end else begin
                addr_to_rom = ii;
                end
                input_val = input_val;
                delayed = delayed; 
                state_next = s2;
            end
            s2 : begin
                input_val = data_from_rom;
                ii = ii+1;
                delayed = delayed; 
                state_next = s3;
            end
            s3 : begin
                delayed = input_val;
                state_next = s4;
            end
            s4 : begin
                addr_to_rom = ii;
                input_val = input_val;
                delayed = delayed; 
                state_next = s5;
            end
            s5 : begin
                input_val = data_from_rom;
                delayed = delayed;
                //i=i+1;
                //ii <= ii+1;
                state_next = s6;
            end
           s6 : begin
                to_avg = input_val + delayed; //summing two values
                val = (to_avg >> 1);    //taking the average
                output_arr[ii-1] = val; //indexing starts on [2]
                output_val = val; 
                state_next = s0;
                input_val = input_val;
            end
            default: begin
                addr_to_rom = addr_to_rom;
                data_from_rom = data_from_rom;
                delayed = delayed;
                input_val = input_val;
                to_avg = to_avg;
                val = val;
                output_val = output_val;
                ii = ii;
                end
        endcase
    end 

endmodule

Solution

  • you have to look at the ways state machines are programmed. Usually states are calculated using flop and the final assignment is a combinatorial. You have it vice versa. Therefore you have issues. Something like the following should work for you. Sorry, i did not test it. The code needs to use non-blocking assignments except in the place where you caculate an intermediate value.

        always @* 
            state_reg = state_next;
    
        always @(posedge clk, negedge reset_n) begin //posedge clk, reset_n
            if (reset_n == 'b0) begin //reset is active low
                state_next <= s0;
            end 
            else begin
              case (state_reg)
                S0: begin
                  output_val <= 0;
                  delayed <= 0; 
                  i <= 0;
                  ii <= 0;
                end
                s1 : begin
                    if (ii>(size-2)) begin
                       ii <= 0;
                    end else begin
                       addr_to_rom <= ii;
                    end
                    input_val <= input_val;
                    delayed <= delayed; 
                    state_next <= s2;
                end
                s2 : begin
                    input_val <= data_from_rom;
                    ii <= ii+1;
                    state_next <= s3;
                end
                s3 : begin
                    delayed <= input_val;
                    state_next <= s4;
                end
                s4 : begin
                    addr_to_rom <= ii;
                    state_next <= s5;
                end
                s5 : begin
                    input_val <= data_from_rom;
                    state_next <= s6;
                end
                s6 : begin
                    // calculating intermediate value, need blocking assignments here
                    to_avg = input_val + delayed; //need blocking here
                    val = (to_avg >> 1);    //need blocking here
    
                    output_arr[ii-1] <= val; //indexing starts on [2]
                    output_val <= val; 
                    state_next <= s0; 
                end
            endcase
          end // else
        end // always