Electrical – FSM implementation using single always block in Verilog

fpgastate-machinessynchronousverilog

So while looking up for material on implementing high level state machines in Verilog I came upon this:enter image description here I am also trying to implement a high level FSM in Verilog that has a number of nested conditional (if) statements and many inputs. Overall the design I am trying to implement is a synchronous design where the inputs and outputs are also available on clock edges. So my question is is there any pitfall in designing an FSM like this? Any help is appreciated.

Best Answer

The approach in the example is a perfectly reasonable way of designing state machines. It's also the approach I tend to stick with for all of my designs, including some pretty darn large state machines in big systems.

The thing to remember about this approach though is that everything happens with a one-cycle latency from the state. To explain what I mean, lets look at the example you gave:

...
S0: begin
    L <= 0;
    D <= 0;
    state <= S1;
end
...

When we are in state S0, the L, D, and state registers all get updated. However because it is a clocked process, the values don't change immediately when we enter S0. Instead they change the clock cycle afterward. This means that taking this example, L and D will go to 0 when we enter state S1. Any logic that uses the state register should be aware of this when doing any calculations. It's also something to bear in mind when analysing simulation output.

Beyond that there are practical upshots to this design.

All of the outputs are registered, which means anything using them down the line doesn't have to contend with a cloud of combinational logic. This is as opposed to state machines in which the outputs are asynchronously dependent on the state machine registers which will result in a large combinational cloud that can cause timing problems in high speed designs. That's where the 1 cycle latency in this approach comes from.

I find it much clearer to follow because you have all of the logic in one place, following in a high level state by state layout. This is unlike ones which split the design into two always blocks - an asynchronous one for logic, and a synchronous one for the next state.

TL;DR Basically you can use this design approach very successfully, as long as you remember and can cope with the 1 cycle latency.