Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VHDL state machine differences (for synthesization)

I am taking a class on embedded system design and one of my class mates, that has taken another course, claims that the lecturer of the other course would not let them implement state machines like this:

architecture behavioral of sm is
    type state_t is (s1, s2, s3);
    signal state : state_t;
begin
    oneproc: process(Rst, Clk)
    begin
        if (Rst = '1') then
            -- Reset
        elsif (rising_edge(Clk)) then
            case state is
                when s1 =>
                    if (input = '1') then
                        state <= s2;
                    else
                        state <= s1;
                    end if;
                    ...
                    ...
                    ...

            end case;
        end if;
    end process;
end architecture;

But instead they had to do like this:

architecture behavioral of sm is
    type state_t is (s1, s2, s3);
    signal state, next_state : state_t;
begin
    syncproc: process(Rst, Clk)
    begin
        if (Rst = '1') then
            --Reset
        elsif (rising_edge(Clk)) then
            state   <= next_state;
        end if;
    end process;

    combproc: process(state)
    begin
        case state is
            when s1 =>
                if (input = '1') then
                    next_state <= s2;
                else
                    next_state <= s1;
                end if;
                ...
                ...
                ...

        end case;
    end process;
end architecture;

To me, who is very inexperienced, the first method looks more fool proof since everything is clocked and there is less (no?) risk of introducing latches.

My class mate can't give me any reason for why his lecturer would not let them use the other way of implementing it so I'm trying to find the pros and cons of each. Is any of them prefered in industry? Why would I want to avoid one or the other?

like image 908
evading Avatar asked Dec 12 '22 10:12

evading


1 Answers

The single process form is simpler and shorter. This alone reduces the chance that it contains errors.

However the fact that it also eliminates the "incomplete sensitivity list" problem that plagues the other's combinational process should make it the clear winner regardless of any other considerations.

And yet there are so many texts and tutorials advising the reverse, without properly justifying that advice or (in at least one case I can't find atm) introducing a silly mistake into the single process form and rejecting the entire idea on the grounds of that mistake.

The only thing (AFAIK) the single-process form doesn't do well is un-clocked outputs. These are (IMO) poor practice anyway as they can be races at the best of times, and could be handled by a separate combinational process for that output only if you really had to.

I'm guessing there was originally some practical reason behind it; maybe a mid-1990s synthesis tool that couldn't reliably handle the single process form, and that made it into the original documentation that the lecturers learned from. Like those blasted non-standard std_logic_arith libraries. And so the myth has been perpetuated...

Those same lecturers would probably have a fit if they saw what can pass through a modern synthesis tool : integers, enumerations, record types, loops, functions and procedures updating signals (Xilinx ISE is now fine with these. Some versions of Synplicity have trouble with functions, but accept an identical procedure with an Out parameter).

One other comment : I prefer if Rst = '1' then over if (Rst = '1') then. It looks less like line noise (or C).

like image 136
user_1818839 Avatar answered Dec 21 '22 21:12

user_1818839