State Management at VHDL FSM

Many of the FSMs that I see in VHDL work by setting the next_state variable in the FSM logic and then assigning it separately to the state variable outside the process.

If something is wrong, simply by writing " state <= state_five ;" set the following state instead? I assume that there is a reason that many people use the separate following state variable instead of directly assigning it to the state as I see it all the time, but as far as I can tell, there is no difference except that it makes the code longer and more complex view.

Did I miss something? Or is it just a matter of style? And if so, why is this style better, it seems unnecessary to me.

+4
source share
3 answers

"Is there something wrong just by writing state <= state_five; ;?"

Nothing done - GRANT of state assignment is executed in time. process.

This leads to a neat, simple, reliable "one-process machine" rather than unreliable (because sensitivity lists are not so easy), the two-step style that WAY has taught too many tutorials and online manuals.

Search for โ€œone-process state machineโ€ and you can find a good example of the material and further discussion.

Historical note: in the previous century, there may have been some synthesis tools that had problems with uniprocessor style; but there is no reason to avoid it now.

+6
source

The reason some people always write two-stage state machines (i.e., one synchronous process and one parallel process) is probably mainly because they learned how to do this at school, as others said.

However, in some cases, this coding style may be better than having one synchronous process. In short, it allows you to mix synchronous and parallel assignments in one context. Consider the following two code snippets, both performing the same thing:

Two-process state machine:

 process (clk) begin if rising_edge(clk) then state <= state_next; end if; end process; process (all) begin state_next <= state; case state is when s_idle => if req_i = '1' then fifo_read <= '1'; -- Concurrent assignment state_next <= s_check_data; -- "Synchronous" assignment end if; when s_check_data => if fifo_out = x"1234" then (...) end if; (...) end case; end process; 

Single-stage state machine:

 process (clk) begin if rising_edge(clk) then case state is when s_idle => if req_i = '1' then fifo_read <= '1'; state <= s_wait_for_data; end if; when s_wait_for_data => state <= s_check_data; when s_check_data => -- Data word from FIFO now available. if fifo_out = x"1234" then (...) end if; (...) end case; end if; end process; 

Note the additional state in the second example. Since there is no way to make simultaneous assignments in synchronous processes in VHDL (I would like to!), A register will be added to the fifo_read signal, delaying it by one cycle. Although this example is simple enough, always sticking to uniprocessor states of a machine can sometimes cause the code to become quite confusing and difficult to follow for this reason. It can also cause your state machine to spend more hardware resources and even make the code longer. No style is always the right choice, but I usually prefer the one-process option.

+3
source

Or even use a variable:

 state := state_five 

Using a variable to store state means that it remains completely local to the process and does not pollute the namespace for the entire architecture .

It also means that if you are used to using printf (sorry report ) to track the progress of state machines during debugging (which is sometimes preferable for the waveform viewer), you can report the expected next state at the end of the final machine process, which may be convenient.

Added: As noted in the comments, variable assignment occurs "instantly" (to be clear - this does not cause the case immediately switch to the next state!)

This effect can be used to advantage (sometimes) if you need to display the cycle earlier - by assigning the specified signal based on the next state at the end of the process. If I need to do this, I have an explicit next_state variable that I use for everything except the case , and state := next_state; (which is at the end of the clock process). It demonstrates to code reviewers that you intended to do it this way!

+2
source

All Articles