Implementing a FSM in VHDL
Yes, you will infer latches if you only drive signals intended to be combinatorial in some branches of the process.
However, you can define a 'default' state for the signal simply by assigning a value to it before the case
statement (but within the same process). For example:
process(currentstate, a)
begin
b <= '1';
c <= '1';
case currentstate is
when s1 =>
if (a = '1') then
c <= '0';
end if;
nextstate <= s2;
when s2 =>
-- b doesnt change state from s1 to here, do I need to define what it is here?
if (a /= '1') then
c <= '0';
end if;
nextstate <= s3;
when s3 =>
if (a = '1') then
b <= '0';
c <= '0';
end if;
nextstate <= s1;
end case;
end process;
Three problems with your example code:
The last port in your port list should not have a semicolon:
port (
clk : in std_logic;
a : in std_logic;
b: out std_logic;
c: out std_logic -- no semicolon here!!!
);
In your register process, you should not have an "else" statement. While this will probably be accepted by the tools, it will confuse your fellow-VHDL designers.
process (clk)
begin
if(rising_edge(clk)) then
currentstate <= nextstate;
end if;
end process;
In your combinational logic, the sensitivity list should contain all signals that you read: process(a, currentstate)
. In this particular case (again) things will probably work out fine, but you are bound to infer latches or cause other problems if your sensitivity list is not correct.
As for your question:
- Yes, you need to assign a value (for each state) to each signal in the combinational process.
- As Tomi mentions, you can easily do this by assigning a default value in the beginning of the process.
- But you can also write the entire state machine in one single synchronous process. This way, you do not have to assign a value to every signal in every state.
Just a note to Philippe's response (can't comment on it directly?)..
I do prefer to write state machines in the two process style. It makes it very clear where you expect inferred flipflops and where you don't. It's also a bit more along the lines of describing the hardware - imagine building a state machine with board level logic for example. The registered device matches the state <= next_state process, and the case statement maps to the and/or array in front of the state register..
Having said that, I typically use one process state machines for small simple tasks, and move over to two process machines for bigger ones. I will even sometimes use a third process for organizing state outputs into different "task" groups.. but not often. A really large state machine tends to tell me the architecture needs work..