Search code examples
vhdlstate-machine

Understanding interferring latch in state machine


Please take a look at this example code of a simple state machine:

entity Top is
    Port ( Clock : in STD_LOGIC;
           Reset : in STD_LOGIC;
           TREADY : out STD_LOGIC
           );
end Top;

architecture Behavioral of Top is
    
    type STATE_t is (S0, S1, S2);
    signal CurrentState : STATE_t := S0;
    
    signal TREADY_Int   : STD_LOGIC := '0';
    
begin

    -- Transit network
    process(Clock, Reset, CurrentState)
        variable NextState : STATE_t;
    begin
        if(rising_edge(Clock)) then
            case CurrentState is
                when S0 =>
                    if(Reset = '1') then
                        NextState := S0;
                    else
                        NextState := S1;
                    end if;
                when S1 =>
                     NextState := S2;
                when S2 =>
                    NextState := S1;
            end case;
        end if;
        
        CurrentState <= NextState;
    end process;

    -- Output network
    process(CurrentState)
    begin
        if(CurrentState = S0) then
            TREADY_Int <= '0';
        elsif(CurrentState = S1) then
            TREADY_Int <= '1';
        elsif(CurrentState = S2) then
            TREADY_Int <= '0';
        end if;
    end process;
    
    TREADY <= TREADY_Int;

end Behavioral;

The synthesis shows me the following warning:

[Synth 8-327] inferring latch for variable 'TREADY_Int_reg'

Schematic with latch

The warning disappears when I change the last condition of the output network to

    else
        TREADY_Int <= '0';
    end if;

and also the latch is gone

Schemativ without latch

So why does the last condition of the output state machine in the first version result in a latch? Why is else something other than elsif()? In my opinion, the two expressions are equal, because the state machine has only three states, so else and elsif(<ThirdState>) should be the same when all other states are handled. But it seems that my understanding is wrong here.


Solution

  • It's usually best not to assume that a synthesiser is as clever as you are. Using else is safer as you have discovered.

    Here's another example. This is better:

    process (A, B)
    begin
      if (A < B)
        F <= ...
      else
        F <= ...
      end if;
    end process;
    

    than this:

    process (A, B)
    begin
      if (A < B)
        F <= ...
      end if;
      if (A >= B)
        F <= ...
      end if;
    end process;