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'
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
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.
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;