1

A frequently used style for state machines is to change state in a very simple clocked process and either in the same process or another one, a combinatorial section which defines the transition to the next state: (here I use a synchronous reset, because I have a master reset synchronizer)

process( aclk, state, next_state, bob, alice )
begin
  if rising_edge( aclk ) then
    if resetn = '0' then
      state <= IDLE;
    else
      state <= next_state;
    end if;
  end if;

  next_state <= state;
  case state is
    when IDLE =>
      if bob = alice then
        next_state <= ANOTHER_STATE;

...and so on. Some prefer to put the combinatorial section in another process, styles vary. I split the machine and various things such as counters which control state transitions into separate small processes, but I know some dislike this style.

Is there any serious problem with keeping everything in the synchronous block, as in:

process( aclk )
begin
  if rising_edge( aclk ) then
    if resetn = '0' then
      state <= IDLE;
    else
      case state is
        when IDLE =>
          if bob = alice then
            state <= ANOTHER_STATE;
          end if;
        when others =>
          null;
      end case;
    end if;
  end if;
end process;

I ask because when I started programming (very badly, as a software person!) I used to use the second method, and am wondering if I should rewrite the code.

I have a friend who wrote some of the ARM logic, (not Sophie! I think she used a pencil and paper...) who tells me his rule was never to create processes with anything other than the clock in the sensitivity list.

Best regards Geoff

Geoff
  • 13
  • 3
  • 1
    Single process form is greatly to be preferred (despite many textbooks out there) Smaller, simpler, avoids several classes of potential bug. One difference from the 2-process form is that outputs change on the next clock edge along with state changes. 2-process fans regard this as a disadvantage but I see its cleaner timings (with no combinational glitches) as another advantage. –  May 20 '18 at 14:28
  • 1
    Ok so I can leave it alone. It's an accepted form. Many thanks. Some things, like the AXI4-stream protocol, I find difficult when a cycle of delay is inserted, but that's just my inexperience/incompetence, I imagine. – Geoff May 20 '18 at 14:52
  • Cycles of delay are easily handled. For a single cycle, sometimes it's easiest to add another state. Multiple cycle delays, different delays, see https://stackoverflow.com/questions/31138152/vhdl-state-machine-with-several-delays-best-approach/31139055#31139055 –  May 20 '18 at 15:11
  • You could also use a combination of the above. Combinatorial *and* registered. But I would never combine clocked and combinatorial in one process: that might confuse the synthesis software, which could start to infer latches. It's more then just a matter of style. I would advise several processes. – JHBonarius May 20 '18 at 20:34

1 Answers1

0

I don't think you can prescribe what to do. As with many coding styles some people prefer the one others the other. There is definitely not a good or a bad style.

For small simple state-machines I use the first method.

For big, complex state-machines I prefer the second method.

Tricks I like about the second method:

  1. e.g. in state X you need a register R to have the value A. In the first method you have to track down every state transition which goes to X and add: R <= A;. Also if you make changes your state-machines you should not forget that.
    The second method normally has a state and next_state variable. Then you can write:
    if (next_state==X) R <= A;. You can now play around with your code and know that when you get to state X, R will be have been assigned the value A.
  2. Break out: Suppose you need to have an 'emergency stop' or the user negates the 'enable' bit and the whole FSM needs to stop. In method 1 you have to start every state condition with: if (stop_everything) state<=IDLE else...
    In method two you register part becomes:

    if (stop_everything) state <= IDLE; else state <= next_state;

I have worked with IP from a big CPU core vendor (You can guess their name). In their code you see only the second method even for the simplest of code. I assume it is a mandatory coding style if you work for them.

Oldfart
  • 6,104
  • 2
  • 13
  • 15
  • 1
    (1) is true (but not exactly difficult in my experience). (2) is very easily implemented in single process form, using "last assignment wins". `if STOP then state <= idle; end if;` after the main Case statement. –  May 20 '18 at 15:07
  • Just to clarify, Oldfart (from one to another), my first illustrated method, using the next_state signal evaluated purely combinatorially seems to be what you describe as the second method and my second, your first. In my illustration, I have included both the combinatorial and state register sections in the same process (although it has been advised not to do this in practice) – Geoff May 23 '18 at 06:10
  • Sorry, dozed off mid-comment. Do you agree? – Geoff May 23 '18 at 09:03
  • @Geoff Sorry, been away for a while. I think we are in agreement. I read your VHDL slightly wrong, but that is because i am 95% Verilog oriented. – Oldfart May 25 '18 at 17:02