top of page

MicroZed Chronicles: State Machines

Writer: Adam TaylorAdam Taylor

I always remember when I was learning digital electronics at university, the lecturer John Rowe passing comment that a professional would use a state machine where an amateur would use a shift register. I owe John a lot; it was he who, in our microelectronics class back in 1998, introduced our cohort to FPGAs and VHDL, at the time using Cypress FPGAs and the Warp compiler.


Being able to understand, design, and select the most appropriate implementation for a state machine is a skill every FPGA engineer should understand, as state machines form a fundamental part of many FPGA developments.


Moore, Mealy, Who Cares


Let’s start at the beginning: state machines generally fall into one of two categories:


  • Moore – In a Moore state machine, the output is a function of the present state.

  • Mealy – In a Mealy state machine, the output is a function of the present state and the input.


If you are reading this as a student working on your degree, this is a very important concept, and you are going to need to know this difference to pass the class. You might need to mention things like how Moore machines offer better timing performance and Mealy machines offer a faster reaction to input changes.


However, in 25 years of being an FPGA engineer, outside of interviews, no one has ever asked me the question, nor has it ever come up in technical discussion or review. Though now I have said this, it is bound to come up at some point soon.


What does matter professionally, though, is how we develop our state machines, as how we define our FSM can have impacts on the final performance.


One or Two Process


There is always a debate about one-process or two-process state machines. That is, do you separate the sequential element from the combinatorial elements, or combine it all together in a single process?


Most people are taught to develop two-process state machines when they learn their HDL of choice. This equates to how we design FSMs if we are using logic gates and registers, with present-state/next-state tables and K-Maps to generate the logic equations and then, of course, registers to store the state.


I tend to prefer the one-process approach as it removes the possibility of latches being created, is slightly easier to debug, and ensures the outputs are always registered. However, there is no hard and fast rule outside of company coding standards—both methods work well.


When I am developing the state machine, unless it is safety-critical or otherwise required, I try to ensure I follow the ultrafast design methodology rules: I avoid using a reset unless necessary and ensure it is synchronous.


State Encoding


To aid understanding and documentation of the state machine, when using SystemVerilog or VHDL, I do ensure I use enumerated types to define the states. This makes the design and verification much easier.

typedef enum logic [1:0] {
    IDLE,
    READ,
    PROCESS,
    WRITE
} state_t;

state_t current_state, next_state;

When it comes to implementation style—one-hot, sequential, etc.—unless I am designing a safety-critical system or facing specific timing issues, I tend to let the synthesis tool determine the best approach for implementation structure.


If you are developing for a high-reliability environment, you might want to take a look at this blog, which discusses how to use Vivado synthesis to implement safe state machines.


Modularity


If you are designing a complex state machine that may result in a large design, it is better to break it down, if possible, into several smaller modules. Complexity is the root cause of many issues that pop up later in the development lifecycle, often at the wrong time.


Breaking the state machine down into a series of state machines that interact makes the design of the overall behaviour easier. For example, if the machine needs to read and write memory locations as part of its operation, it is better to have a separate memory-interface state machine that can interact with the FSM requiring this functionality.


This approach is not limited to just one memory or communication module; you can do the same for sequence processing or control. Having one main state machine that receives the original command and then several sub-state machines to handle elements of the process while reporting back to the main state machine on completion or error.


These modules are also easier to understand when you come back to them years later to make a modification.


Decoupling Functionality


One aspect that does have an impact on the FPGA performance is how much functionality is coupled within the state machine.


We often have state machines that must wait for a specified period before taking action or moving to the next state. In this case, it is common to use a counter to measure the time. One way this is often implemented—and I am guilty of this too—is to include the counter in the state machine design. For example:

This means the logic for the counter is part of the state machine, which, when synthesized and placed-and-routed, might impact timing performance.


It is better, therefore, to enable only a single bit to enter or leave the state machine to start the timer, or indicate the timer has expired.

Such an approach decouples the counter from the FSM and provides the implementation team more options to help achieve timing.


Visualization


One of the things I am very keen on is visualising the state machine I have written in the RTL before I move on to simulation and synthesis. Ideally, this should match the state chart that I started out to implement. There are a range of tools that can do this, including Blue Pearl’s Visual Verification Suite, and the Teros HDL plug-in for VS Code.



Often these visualisation tools are capable of showing errors within the state machine prior to simulation, such as states with no entry or terminal states.


Of course, the best way to ensure the state machine implemented looks like the state chart designed is to auto-generate it from the state chart itself. There are several tools that will do this, including Stateflow in Simulink, HDL Designer, etc. (though these require a license). There is also FIZZIM, a free tool that generates Verilog, SystemVerilog, and VHDL according to its website.


Verification


Verification of state machines can be complex, as you need to demonstrate you have tested every state, all input and output conditions, and all possible paths through the different states.


One of the best ways to ensure this is to leverage code and functional coverage during your simulation efforts. You may also want to consider constrained random testing during simulation.


Wrap-Up


State machines are critical to the successful implementation of many features in FPGAs. Hopefully, this blog has provided some insight into how you can design them better. If you have any thoughts or tips that I might have missed, then please comment.


Workshops and Webinars


If you enjoyed the blog why not take a look at the free webinars, workshops and training courses we have created over the years. Highlights include



Boards


Get an Adiuvo development board



Embedded System Book   


Do you want to know more about designing embedded systems from scratch? Check out our book on creating embedded systems. This book will walk you through all the stages of requirements, architecture, component selection, schematics, layout, and FPGA / software design. We designed and manufactured the board at the heart of the book! The schematics and layout are available in Altium here   Learn more about the board (see previous blogs on Bring up, DDR validation, USB, Sensors) and view the schematics here.



 
 
bottom of page