Why not a two-process state machine in VHDL?
Asked Answered
V

3

6

When I learnt how to express finite state machines in VHDL, it was with a two-process architecture. One process handles the clock/reset signals, and another handles the combinatorial logic of updating the state and output. An example is below.

I've seen this style criticised (see the comments and answer to this question for example), but never in any detail. I'd like to know whether there are objective(ish) reasons behind this.

Are there technical reasons to avoid this style? Xilinx' synthesiser seems to detect it as a state machine (you can see it in the output, and verify the transitions), but do others struggle with it, or generate poor quality implementations?

Is it just not idiomatic VHDL? Remember to avoid opinion-based answers; if it's not idiomatic, is there a widely used teaching resource or reference that uses a different style? Idiomatic styles can also exist because, eg. there are classes of mistakes that are easy to catch with the right style, or because the code structure can better express the problem domain, or for other reasons.

(Please note that I'm not asking for a definition or demonstration of the different styles, I want to know if there are objective reasons to specifically avoid the two-process implementation.)

Example

Some examples can be found in Free Range VHDL (p89). Here's a super simple example:

library ieee;
use ieee.std_logic_1164.all;

-- Moore state machine that transitions from IDLE to WAITING, WAITING
-- to READY, and then READY back to WAITING each time the input is
-- detected as on.
entity fsm is
    port(
        clk    : in std_logic;
        rst    : in std_logic;
        input  : in std_logic;
        output : out std_logic
    );
end entity fsm;

architecture fsm_arc of fsm is
    type state is (idle, waiting, ready);
    signal prev_state, next_state : state;
begin
    -- Synchronous/reset process: update state on clock edge and handle
    -- reset action.
    sync_proc: process(clk, rst)
    begin
        if (rst = '1') then
            prev_state <= idle;
        elsif (rising_edge(clk)) then
            prev_state <= next_state;
        end if;
    end process sync_proc;

    -- Combinatorial process: compute next state and output.
    comb_proc: process(prev_state, input)
    begin
        case prev_state is
            when idle =>
                output <= '0';
                if input = '1' then
                    next_state <= waiting;
                else
                    next_state <= idle;
                end if; 
            when waiting =>
                output <= '1';
                if input = '1' then
                    next_state <= ready;
                else
                    next_state <= waiting;
                end if;
            when ready =>
                output <= '0';
                if input = '1' then
                    next_state <= waiting;
                else
                    next_state <= ready;
                end if;
        end case;
    end process comb_proc;
end fsm_arc;

(Note that I don't have access to a synthesiser right now, so there might be some errors in it.)

Vallecula answered 15/11, 2015 at 10:26 Comment(8)
Your question misses the 3 process style. I also think one should divide the answers into styles for Moore and Mealy FSMs. Your second process has no default assignments (either before the case or in an others statement). This can cause latches if the FSM is extended and you or an other person misses to assign one output. Your res is asynchronous.Assault
The FSM had no initial state.Assault
The Free Range book is OK as a beginners guide but notoriously bad as a reference. For example, notice the mistake in the sync_proc sensitivity list here (which is not your mistake, it's present in the book). @Assault I withdraw the remainder of of my earlier comment, it wasn't the Q I thought it was.Harville
see maia-eda.net/… for a pretty comprehensive answer. And maia-eda.net/….Terreverte
@Assault - Good points, but: 1. I wasn't so much interested in a comparison of styles as knowing whether there's anything wrong with this one; 2. The latch warning can be useful to catch such an error (plus the synthesiser should also object to the case statement missing a value, although I haven't synthesised this, so I could be wrong). I'll have a look at the referenced question though and see if it answers it.Vallecula
@AndreaTosoni - The referenced question is about defining or demonstrating what 1/2/3 process FSMs are, not about the technical merits of any particular approach. Your answer there doesn't really address that aspect of my question here. It is often possible to discuss the pros and cons of a particular style in an objective way, and that's what I'd like to read about.Vallecula
@BrianDrummond - do you mean the mistake that's been corrected now (the extra signal in the list)? Or is there another one?Vallecula
It has been corrected. Sorry I haven't answered today, maybe tomorrow.Harville
Y
5

I always recommend one-process state machines because it avoids two classes of basic errors that are exceedingly common with beginners:

  1. Missing items in the combinational process's sensitivity list cause the simulation to misbehave. It even works in the lab since most synthesizers don't care about the sensitivity list.
  2. Using one of the combinational results as an input instead of the registered version, causing unclocked loops or just long paths/skipped states.

Less importantly, the combinational process reduces simulation efficiency.

Less objectively, I find them easier to read and maintnain; they require less boiler plate and I don't have to keep the sensitivity list in sync with the logic.

Yuk answered 16/11, 2015 at 21:2 Comment(0)
Z
1

The only two objective reasons I see are about readability and simulation efficiency in the case of Moore state machines (where primary outputs depend only on the current state, not the primary inputs).

Readability: if you merge together in a single process outputs and next state computations it might be more difficult to read / understand / maintain than with separate combinatorial processes for separate concerns.

Simulation efficiency: in the 2-processes solution your combinatorial process will be triggered on every primary input and / or current state change. This makes sense for the part of the process that computes the next state but not for the part that computes the outputs. The latter shall be triggered only on current state changes.

Zaratite answered 16/11, 2015 at 16:18 Comment(0)
K
0

There is a detailed description about this in ref. [1] below. First, FSMs are classified in 3 categories (first time this is done), then each is examined thoroughly, with many complete examples. You can find the exact answer to your question on pages 107-115 for category 1 (regular) finite state machines; on pages 185-190 for category 2 (timed) machines; and on pages 245-248 for category 3 (recursive) state machines. The templates are described in detail for both Moore and Mealy version in each of the three categories.

[1] V. Pedroni, Finite State Machines in Hardware: Theory and Design (with VHDL and SystemVerilog), MIT Press, Dec. 2013.

Kanchenjunga answered 16/11, 2015 at 5:18 Comment(1)
@serenesat It was at the end of the paragraph. I broke it out to make it clearer.Vallecula

© 2022 - 2024 — McMap. All rights reserved.