Style #4

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:

Style 4 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.