This style has one FSM process, and uses synthesiser-determined state encodings. The two outputs are generated from a second clocked process, which guarantees that the module outputs are registered.
This style is shown as a "two-process" style in the XST documentation, but is normally referred to as a "one-process" style.
This code is essentially identical to Style #3, except that the single clocked process is now split into two clocked processes. One of the two processes handles the FSM itself, while the second derives the SCK and BUSY outputs. In some circumstances, this might add some clarity to the description. However, in this case, it clearly makes the code more verbose, and could only be justified if it produced a better synthesis result. This version is arguably also more error-prone than Style #3, since both processes must duplicate the control flow (the case statement); this introduces a second point where errors might be made.
Output generation process
The first process in the code below is commented "generate the outputs", and drives SCK and BUSY. This process must ensure that all the outputs are defined in every branch of the case statement (see the discussion in the FSM3 code). The FSM3 code uses the second option from that list; in other words, it assigns to the outputs only when they change. The simplest way to code FSM4 is to split out the FSM3 process into two processes with no logic changes; in this case, FSM4 would also use the second option. As it happens, however, the resulting code actually produces exactly the same synthesis results as the more compact FSM3 code (at least for auto encoding).
Given this, there would be little point in reproducing the obvious FSM4 code below. The fsm4b.v and fsm4b.vhd code below instead uses the third option to generate the outputs: in other words, it sets default values, and only assigns to SCK and BUSY when non-default outputs are required.
The output generation process includes one other interesting feature. The default values for SCK and BUSY are set before the clock edge if-else statement, which saves a small amount of typing. This style of register inference is supported by XST, but it is possible that some other synthesisers might reject this as an invalid template. In this case, the code should be modified as follows:
always @(posedge CLK) if(SRST) begin SCK <= 1; BUSY <= 0; end else SCK <= 0; BUSY <= 0; case(STATEREG) ...
Verilog
fsm4b.v
module FSM ( input CLK, SRST, LOAD, TC, output reg SCK, BUSY); parameter [1:0] st0 = 0, st1 = 1, st2 = 2, st3 = 3; reg [1:0] STATEREG; // generate the outputs always @(posedge CLK) begin SCK <= 0; BUSY <= 0; if(SRST) SCK <= 1; else case(STATEREG) st3: BUSY <= 1; st0: BUSY <= LOAD; st1: begin SCK <= 1; BUSY <= 1; end default: BUSY <= ~TC; endcase end // one-process FSM always @(posedge CLK) if(SRST) STATEREG <= st3; else case(STATEREG) st3: STATEREG <= st1; st0: if(LOAD) STATEREG <= st1; st1: STATEREG <= st2; default: if(TC) STATEREG <= st0; else STATEREG <= st1; endcase endmodule
VHDL
fsm4b.vhd
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 STATEREG : FSMTYPE; begin -- generate the outputs process (CLK) is begin if rising_edge(CLK) then SCK <= '0'; BUSY <= '0'; if SRST = '1' then SCK <= '1'; else case STATEREG is when st3 => BUSY <= '1'; when st0 => BUSY <= LOAD; when st1 => SCK <= '1'; BUSY <= '1'; when st2 => BUSY <= not TC; end case; end if; end if; end process; -- one-process FSM process (CLK) is begin if rising_edge(CLK) then if SRST = '1' then STATEREG <= st3; else case STATEREG is when st3 => STATEREG <= st1; when st0 => if LOAD = '1' then STATEREG <= st1; end if; when st1 => STATEREG <= st2; when st2 => if TC = '1' then STATEREG <= st0; else STATEREG <= st1; end if; end case; end if; end if; end process; end architecture RTL;
Synthesis
The synthesis results are substantially different from the Style 3 synthesis results:
Mode | SCK/BUSY | Period | LUT2 | LUT3 | LUT4 | LUT5 | FD | FDR | FDS | FDRS | Total | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
fsm4b.v | Auto | Reg/Reg | 1.103 | 1 | 3 | 1 | 2 | 1 | 2 | 10 | ||
fsm4b.vhd | Auto | Reg/Reg | 1.107 | 2 | 1 | 2 | 2 | 2 | 9 | |||
fsm4b.v | User | Reg/Reg | 1.110 | 1 | 2 | 1 | 1 | 2 | 1 | 8 | ||
fsm4b.vhd | User | Reg/Reg | 1.107 | 1 | 1 | 1 | 2 | 1 | 6 |
The VHDL code with 'user' extraction (7) mode has, surprisingly, produced a three-register solution. SCK was taken directly from a state register bit; the synthesiser added an extra register for the BUSY output.