What is a one-hot encoded state machine?
A one-hot encoded state machine is a state machine in which there is a bit in the state vector for every state in the state machine. (eg. a state machine with 17 states will have a 17-bit wide state vector). It is sometimes known as bit-per-state encoding.
The one-hot encoding technique was developed as a consequence of the typical FPGA architecture - rich in registers but with limited fan-in to each internal logic macrocell (a CLB in Xilinx-speak). Only one of the state vector registers is active ('hot') at any one time.
Example state machine - The state machine is clocked by a signal 'clk' which is not shown on the flow diagram.
| Back to top |
Why use them?
To detect when the state machine is in a particular state only requires that a single bit is tested instead of the whole state vector as would be the case for a binary-coded state machine. Changing states is simply a case of changing the currently 'hot' register to 'cold' and setting the next state register to 'hot'. (Note that 2 bits in the state vector change for every state transition - so caution must be used if the state vector is decoded asynchronously to generate other outputs.) The logic required to detect the current state to generate outputs and next state logic is minimal, requiring less combinatorial logic - so allowing for higher clock frequencies. This is the main reason for using the one-hot structure. Our example state machinehas 6 states, so 6 registers will be required - the disadvantage of one-hot encoding is the larger quantity of registers that are required.
| Back to top |
Where should they be used?
One-hot state machines require more flip-flops than a binary-coded state machine, so use them in devices that are register-rich but have low fan-in to each logic macrocell (e.g. Xilinx FPGAs). They are generally not useful in CPLDs such as the Xilinx 9500 or CoolRunner families since these have a wide fan-in to each logic macrocell.
| Back to top |
Writing the VHDL code
There are 2 coding styles - "hard encoding" and "soft coding".
Soft encoding
Soft encoding a state machine allows the state encoding to be quickly and easily changed. The basic technique is to declare an enumeration type which has the state names as the set of possible values, then declare the state vector(s) as signals of that type. The default encoding of the enumeration type is modified by the attribute "enum_encoding". The state assignments are made by positional association between the TYPE declaration and the ATTRIBUTE declaration. In our example listing below, idle takes the value"000001", state1 takes the value "000010" and so on. The rest of the state machine is coded as normal using a CASE construct. The following code snippet (Listing 1) shows our example state machine coded as a one-hot state machine using the two-process style:
IMPORTANT!
Not all synthesis tools support the enum_encoding attribute and some may use a different name for the attribute. Check your synthesis tool documentation.
ARCHITECTURE arc_softenc OF softenc IS
-- declare the enumeration type
TYPE states IS (idle,state1,state2,state3,state4,state5);
-- assign the states
ATTRIBUTE enum_encoding : string;
ATTRIBUTE enum_encoding OF states: TYPE IS "000001 000010 000100
001000 010000 100000";
-- the state vectors
SIGNAL present_state : states;
SIGNAL next_state : states;
BEGIN
-- the combinatorial process
comb_proc : PROCESS (present_state,start,branch,hold)
BEGIN
-- state transitions
CASE present_state IS
WHEN idle => -- when in idle ..
IF (start = '0') THEN -- ..wait for start=0
next_state <= state1; -- ..then go to state1
ELSE
next_state <= idle; -- ..else stay in idle
END IF ;
WHEN state1 => -- in state 1..
IF (branch = '1') THEN -- ..if branch=1
next_state <= state4; -- ..then go to state4
ELSE
next_state <= state2; -- ..else pass to state2
END IF ;
WHEN state2 =>
next_state <= state3; -- go to state3
WHEN state3 =>
IF (hold = '0') THEN -- ..if hold=0
next_state <= state4; -- ..then go to state4
ELSE
next_state <= state3; -- ..else stay in state3
END IF ;
WHEN state4 =>
next_state <= state5; -- go to state5
WHEN state5 =>
next_state <= idle; -- go to idle
END CASE;
END PROCESS comb_proc;
-- the synchronous process
sync_proc : PROCESS (clk,reset)
BEGIN
IF (reset = '0') THEN -- async active low reset
present_state <= idle; -- to idle state on reset
ELSIF (clk'EVENT AND clk = '0') THEN -- sync to clk falling edge
present_state <= next_state; -- change state
END IF ;
END PROCESS sync_proc;
END ARCHITECTURE arc_softenc;
Listing 1 : soft encoded one-hot state machine