This style has two processes, and uses synthesiser-determined state encodings. A sequential process is used for the state register, and a combinatorial process is used to derive the next state. The two outputs are generated combinatorially by decoding the current state.
This style is shown as a "three-process" style in the XST documentation, but is normally referred to as a "two-process" style. There are two things that should be noted about this style:
- the sequential state register process has a synchronous reset. In principle, the reset could actually be rolled into the combinatorial next state process, and the sequential process would then not need a reset branch. However, XST requires the state register to have a reset in order for an FSM to be recognised and extracted, and removing the reset would probably result in a sub-optimal solution. This may or may not be true of other synthesisers.
the next-state process is combinatorial, and some care must therefore be
taken with it. NEXTSTATE should be given a default value to avoid latch
creation, and the sensitivity list must be correct. The examples below
show explicit sensitivity lists. However, wildcard sensitivity lists are
more convenient (
always @*for Verilog (8), or
module FSM ( input CLK, SRST, LOAD, TC, output SCK, BUSY); parameter[1:0] st0 = 0, st1 = 1, st2 = 2, st3 = 3; reg [1:0] NEXTSTATE, STATEREG; // outputs assign SCK = (STATEREG == st2) | (STATEREG == st3); assign BUSY = (STATEREG == st1) | (STATEREG == st2); // state register always @(posedge CLK) if(SRST) STATEREG <= st3; else STATEREG <= NEXTSTATE; // next state derivation always @(LOAD or TC or STATEREG) begin NEXTSTATE = STATEREG; // default: state unchanged case(STATEREG) st3: NEXTSTATE = st1; st0: if(LOAD) NEXTSTATE = st1; st1: NEXTSTATE = st2; default: if(TC) NEXTSTATE = st0; else NEXTSTATE = st1; endcase end endmodule
library IEEE; use IEEE.std_logic_1164.all; entity FSM is port ( CLK, SRST, LOAD, TC : in std_logic; SCK, BUSY : out std_logic); end entity FSM; architecture RTL of FSM is type FSMTYPE is (st0, st1, st2, st3); signal NEXTSTATE, STATEREG : FSMTYPE; begin -- outputs SCK <= '1' when STATEREG = st2 or STATEREG = st3 else '0'; BUSY <= '1' when STATEREG = st1 or STATEREG = st2 else '0'; -- state register process (CLK) is begin if rising_edge(CLK) then if SRST = '1' then STATEREG <= st3; else STATEREG <= NEXTSTATE; end if; end if; end process; -- next state derivation process (LOAD, TC, STATEREG) is begin NEXTSTATE <= STATEREG; -- default: state unchanged case STATEREG is when st3 => NEXTSTATE <= st1; when st0 => if LOAD = '1' then NEXTSTATE <= st1; end if; when st1 => NEXTSTATE <= st2; when st2 => if TC = '1' then NEXTSTATE <= st0; else NEXTSTATE <= st1; end if; end case; end process; end architecture RTL;
The Verilog code, with 'auto' encoding selected, produced the expected one-hot FSM, with 4 flip-flops, and the SCK and BUSY outputs driven combinatorially from LUTs. The auto-encoded VHDL code, however, produced an optimal solution with only 2 flip-flops, and the SCK and BUSY bits driven directly from the state register bits. This is the same as the Style #2 output.
With 'user' encoding selected, both the Verilog and VHDL sources produced a 2 flip-flop solution, with one of the state register bits directly driving SCK. The BUSY output was combinatorially driven from a LUT2.