This style has one process, and uses explicit (manually-coded) state encodings. This is the only style that uses manual codings; the remaining styles all allow the synthesiser to select the state codings.
The intent of the code below is that the BUSY and SCK outputs should both be registered, and that this 2-bit register should also be the state register itself; this should give the most compact implementation.
In principle, an explicit state coding allows the designer to manually optimise an FSM, and to guarantee that important bits of the state register are registered at the module outputs, and not delayed by additional combinatorial decoding.
In practice, the synthesiser will probably modify the FSM unless it is instructed not to. XST, for example, will by default ignore the manual state codings in these examples, and will generate a one-hot FSM with a new set of 4-bit state codings. This may, in general, produce an FSM which is either smaller or faster than the designer's original, but it does introduce two potential problems:
- if the testbench relies on specific state codings, then the post-synthesis netlist may not simulate correctly
- if the source code drives a registered state bit directly out of the module, and the synthesiser changes the state encodings, then it will almost certainly need to create a new combinatorial signal to replace the original registered output. It is common to have a methodology requirement to drive only registered outputs from a block, and the synthesiser can break this requirement when it recodes the FSM. If this is an issue, then a second process should be used to generate the required registered outputs.
Style #1 is only used in VHDL when the designer specifically needs the requested state coding, and is sure that the synthesiser will not change the codings. In Verilog, however, the general form of this style is also used when the designer does expect the synthesiser to carry out state recoding. In these cases, the original designer-specified state coding is not required. However, the state codings cannot simply be ignored; the parameters must be set in a way that will allow the RTL code to simulate. The synthesiser will also analyse the FSM before recoding it, and will complain if two states have the same encoding, for example.
Verilog
FSMs are almost always described in Verilog by using parameter constants to
represent state encodings. Historically, a synthesiser directive (/*
synopsys enum */
) was added to the code to allow the synthesiser to
treat the state register as being of an enumerated type. The synthesiser
(but not the simulator) could then report an error if, for example, a
constant value, rather than a declared parameter, was assigned to the state
register. This is similar to the VHDL coding of enumerated FSMs
(Style #2),
but it does require the parameters to be given specific values. In other
words, each state must be manually encoded.
This Verilog code is essentially identical to the VHDL code below it. The two forms synthesise identically in XST.
The precise form of the parameter and state vector declarations in the Verilog code may depend on the synthesiser. Historically, Synopsys required a state vector and parameter declaration in this form:
parameter[1:0] // synopsys enum STATES st0 = 2'b00, st1 = 2'b01, st2 = 2'b11, st3 = 2'b10; reg [1:0] // synopsys enum STATES STATEREG; // synopsys state_vector STATEREG
This is not required in current usage. XST, in particular, doesn't require the [1:0] in the parameter declaration, although it is included in the code below.
fsm1.v
module FSM ( input CLK, SRST, LOAD, TC, output SCK, BUSY); parameter[1:0] st0 = 2'b00, st1 = 2'b01, st2 = 2'b11, st3 = 2'b10; reg[1:0] STATEREG; assign SCK = STATEREG[1]; assign BUSY = STATEREG[0]; always @(posedge CLK) if(SRST) STATEREG <= st3; else begin case(STATEREG) st3: STATEREG <= st1; st0: if(LOAD) STATEREG <= st1; st1: STATEREG <= st2; st2: if(TC) STATEREG <= st0; else STATEREG <= st1; endcase end endmodule
VHDL
The VHDL implementation uses a block to form a new declarative region. This isn't required, but provides greater encapsulation, by allowing the state register and the state encodings to be declared locally to the FSM itself.
fsm1.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 subtype SLV2 is std_logic_vector(1 downto 0); -- put in a global package in normal use begin CONTROL : block signal STATEREG : SLV2; constant S0 : SLV2 := "00"; constant S1 : SLV2 := "01"; constant S2 : SLV2 := "11"; constant S3 : SLV2 := "10"; begin SCK <= STATEREG(1); BUSY <= STATEREG(0); FSM : process (CLK) is begin if rising_edge(CLK) then if SRST = '1' then STATEREG <= S3; else case STATEREG is when S3 => STATEREG <= S1; when S0 => if LOAD = '1' then STATEREG <= S1; end if; when S1 => STATEREG <= S2; when S2 => if TC = '1' then STATEREG <= S0; else STATEREG <= S1; end if; when others => null; end case; end if; end if; end process FSM; end block CONTROL; end architecture RTL;
Synthesis
XST was run with the FSM encoding algorithm set to both automatic, and user-defined. The Verilog and VHDL sources synthesised identically, for both the automatic and user modes.
With the default automatic FSM encoding, XST recoded the 2-bit state register into a 4-bit one-hot state register. The technology schematic showed 4 flip-flops, two of which were driven by 4-input LUTs. The SCK and BUSY outputs were driven by 2-input LUTs, giving a total utilisation of 4 flip-flops and 4 LUTs. Since XST had recoded the state register, the SCK and BUSY outputs were no longer registered outputs, and each was derived from a combination of 2 state bits.
With user-defined FSM encoding, the technology output was exactly as expected. There were 2 state register bits, one driven by a LUT2, and the other by a LUT4. The SCK and BUSY outputs were directly driven from the state register bits. The total utilisation was 2 flip-flops and 2 LUTs:
Mode | SCK/BUSY | Period | LUT2 | LUT4 | FDR | FDS | FDRS | Total | |
---|---|---|---|---|---|---|---|---|---|
fsm1.v | Auto | Comb/Comb | 1.103 | 2 | 2 | 2 | 1 | 1 | 8 |
fsm1.vhd | Auto | Comb/Comb | 1.103 | 2 | 2 | 2 | 1 | 1 | 8 |
fsm1.v | User | Reg/Reg | 0.926 | 1 | 1 | 1 | 1 | 4 | |
fsm1.vhd | User | Reg/Reg | 0.926 | 1 | 1 | 1 | 1 | 4 |