We use two-process FSM style to clearly separate the logic that changes states from the logic that decides what the next state should be. This makes the design easier to understand and debug.
Two-process FSM coding style in VHDL
process(clk, reset) begin if reset = '1' then current_state <= initial_state; elsif rising_edge(clk) then current_state <= next_state; end if; end process; process(current_state, inputs) begin case current_state is when state1 => if condition then next_state <= state2; else next_state <= state1; end if; when state2 => -- other transitions when others => next_state <= initial_state; end case; end process;
The first process is called the state register. It updates the current state on the clock edge or resets it.
The second process is the next state logic. It decides what the next state will be based on the current state and inputs.
process(clk, reset) begin if reset = '1' then current_state <= IDLE; elsif rising_edge(clk) then current_state <= next_state; end if; end process;
process(current_state, start) begin case current_state is when IDLE => if start = '1' then next_state <= RUNNING; else next_state <= IDLE; end if; when RUNNING => next_state <= IDLE; when others => next_state <= IDLE; end case; end process;
This simple FSM has two states: IDLE and RUNNING. When 'start' is high, it moves to RUNNING state for one clock cycle, then returns to IDLE. The output 'done' is high only in RUNNING state.
library ieee; use ieee.std_logic_1164.all; entity simple_fsm is port( clk : in std_logic; reset : in std_logic; start : in std_logic; done : out std_logic ); end entity; architecture behavioral of simple_fsm is type state_type is (IDLE, RUNNING); signal current_state, next_state : state_type; begin -- State register process process(clk, reset) begin if reset = '1' then current_state <= IDLE; elsif rising_edge(clk) then current_state <= next_state; end if; end process; -- Next state logic process process(current_state, start) begin case current_state is when IDLE => if start = '1' then next_state <= RUNNING; else next_state <= IDLE; end if; when RUNNING => next_state <= IDLE; when others => next_state <= IDLE; end case; end process; -- Output logic done <= '1' when current_state = RUNNING else '0'; end behavioral;
Always use a reset signal to set the FSM to a known state at start.
Keep the state register and next state logic in separate processes to avoid mixing sequential and combinational logic.
Use meaningful state names to make your code easier to read.
Two-process FSM style separates state memory and next state logic.
One process updates the current state on clock edges.
The other process decides the next state based on current state and inputs.
Practice
Solution
Step 1: Understand the two-process FSM structure
The first process in a two-process FSM handles synchronous operations like updating the current state on clock edges and reset.Step 2: Identify the role of the first process
This process updates the current state register based on clock and reset signals, ensuring state changes happen synchronously.Final Answer:
To update the current state on clock and reset signals -> Option AQuick Check:
First process updates state [OK]
- Confusing output logic with state update
- Thinking next state logic is in first process
- Assuming initialization happens in first process
Solution
Step 1: Identify what triggers next state and output logic
The second process is combinational and depends on current state and inputs to decide next state and outputs.Step 2: Determine the sensitivity list
It must include all signals that affect next state and outputs, which are current_state and inputs, not clock or reset.Final Answer:
current_state, inputs -> Option DQuick Check:
Second process sensitivity = current_state, inputs [OK]
- Including clock in second process sensitivity
- Using reset in sensitivity list incorrectly
- Leaving sensitivity list empty
current_state after the rising edge of clk if reset is '0' and next_state is S1?
process(clk, reset)
begin
if reset = '1' then
current_state <= S0;
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process;Solution
Step 1: Analyze reset condition
Reset is '0', so the reset block is skipped; no forced reset to S0.Step 2: Analyze clock rising edge behavior
On rising edge of clk, current_state is assigned next_state, which is S1.Final Answer:
S1 -> Option BQuick Check:
Reset '0' + rising edge = current_state = next_state [OK]
- Assuming reset '0' resets state to S0
- Confusing next_state with current_state immediately
- Ignoring rising_edge condition
process(current_state, input_signal)
begin
case current_state is
when S0 =>
if input_signal = '1' then
next_state <= S1;
else
next_state <= S0;
end if;
when S1 =>
next_state <= S0;
end case;
end process;
process(clk, reset)
begin
if reset = '1' then
current_state <= S0;
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process;Solution
Step 1: Check the case statement coverage
The case(current_state is) only specifies when S0 and when S1, but omits a catch-all 'when others' clause.Step 2: Understand the consequence
In a combinational process, incomplete case coverage infers latches on next_state, which is undesirable; it should be fully combinational logic. A default like 'when others => next_state <= current_state;' is needed.Final Answer:
Missing default case in case statement -> Option CQuick Check:
Missing when others => latch inferred [OK]
- Omitting 'when others' in case statement
- Ignoring sensitivity list completeness
- Placing next state logic in clocked process
Solution
Step 1: Check reset and state transitions
The FSM resets to IDLE (handled in clocked process), so next_state logic must handle transitions from IDLE to BUSY on start='1', BUSY to DONE, and DONE to IDLE.Step 2: Analyze next state logic options
The correct code uses a combinational process with sensitivity to current_state and start, employing a case statement that fully covers all states with proper transitions: IDLE stays or goes to BUSY based on start, BUSY to DONE, DONE to IDLE. Other codes fail by using clocked process for next_state, missing inputs in sensitivity, incomplete state handling, or unassigned paths in conditional logic leading to latches.Final Answer:
The case statement with IDLE, BUSY, DONE transitions -> Option AQuick Check:
Case statement with all states and transitions [OK]
- Placing next state logic in clocked process
- Missing transitions for all states
- Ignoring start signal conditions
Ready to prove it?
Pass the test and this pattern moves unknown
