Finite State Machine Description - FSM

State diagrams are used to graphically represent state machines. At the dataflow level, where we separate control and data of hardware system, the design and description of state machines for implementing the control unit become important.

The general architecture of an FSM consists of a combinational block of next state logic, state registers, and combinational output logic. There are two types of state machines - Moore machines and Mealy machines. As we have mentioned before "Moore" is less. That is, Moore machine's output depends on state variables only not on inputs. Mealy machine's output depends on both inputs and state variables. We called Moore machine's output funciton "state-based". Output function of the Mealy machine is called input-and-state-based. Graphically a "state-based" FSM looks like:


      inputs
       | | |
       | | |
       | | |     State Regs
     +---------+    +----+        +-------+    
     |         |----| FF |-+------|       |    
     |  State  |    +----+ |      |  O    |    
     |         |    +----+ |      |  U    |------->  Output signals   
     |         |----| FF |---+----|  T F  | 
     | Mapping |    +----+ | |    |  P U  |------->
     |         |    +----+ | |    |  U N  |    
     |         |----| FF |-----+--|  T C  |------->
     |         |    +----+ | | |  |    T  |    
     |         |      ...  | | |  |    I  |------>
     |         |    +----+ | | |  |    O  |    
     |         |----| FF |-------+|    N  |    
     +---------+    +----+ | | | |+-------+    
       | | | |             | | | |
       +-|-|-|-------------+ | | |
         +-|-|---------------+ | |
           +-|-----------------+ |
             +-------------------+


Common "state-based" FSMs are counters. Graphically, Mealy machine appears as:


      inputs
       | | |
       +-|-|----------------------------+
       | +-|--------------------------+ |
       | | +------------------------+ | |
       | | |                        | | |
       | | |     State Regs         | | |
     +---------+    +----+        +-------+    
     |         |----| FF |-+------|       |    
     |  State  |    +----+ |      |  O    |    
     |         |    +----+ |      |  U    |------->  Output signals   
     |         |----| FF |---+----|  T F  | 
     | Mapping |    +----+ | |    |  P U  |------->
     |         |    +----+ | |    |  U N  |    
     |         |----| FF |-----+--|  T C  |------->
     |         |    +----+ | | |  |    T  |    
     |         |      ...  | | |  |    I  |------>
     |         |    +----+ | | |  |    O  |    
     |         |----| FF |-------+|    N  |    
     +---------+    +----+ | | | |+-------+    
       | | | |             | | | |
       +-|-|-|-------------+ | | |
         +-|-|---------------+ | |
           +-|-----------------+ |
             +-------------------+

A Sequence Detector

One can draw a state diagram for a detector that continuously search for the 1011 sequence on its x input.

This diagram is a Mealy machine, which means that the output is a function of the input while the machine is in a stable state.

The states are labeled according to the significant input sequence they detect.

VHDL detector only has one active state at any time.



-- `stat` is of enumeration type;
-- state_vector is an unconstrained array of state';
-- one_of is a resolution function;
-- `current` is a guarded resolved  signal of type `state`; the kind of 
-- it is REGISTER and it uses the resolution function `one_of`.
-- `one_of` chooses one of the driving values of `current` for
-- assigning to this signal. `current` has only one driving value at any
-- time and the function returns justthat one value.

ENTITY detector IS
    PORT (x, clk : IN BIT; z : OUT BIT);
END detector;


-- Architecture. 

-- `clocking` block uses the rising edge of clk for its guard expression;
-- four "state" blocks that correspond to the states are nested in the main
-- clocking block.
-- the GUARD signal within each of state 
--  blocks is TRUE if `current`  equals the state designator 
--  (reset,  got1,...) of that state  and ...
-- `current` represents the current active state of the 
--  machine. Initially, =reset.

ARCHITECTURE singular_state_machine OF detector IS
  TYPE state IS (reset, got1, got10, got101);
  TYPE state_vector IS ARRAY (NATURAl RANGE <>) OF state;
  FUNCTION one_of(sources:state_vector)RETURN state IS
    BEGIN
	RETURN sources(sources'LEFT);
    END one_of;
    SIGNAL current : one_of state REGISTER := reset;
BEGIN
  clocking : BLOCK (clk = '1' AND NOT clk'STABLE)
  BEGIN
    s1: BLOCK (current = reset AND GUARD)
    BEGIN
	current <= GUARDED got1 WHEN x = '1' ELSE reset;
    END BLOCK s1;
    s2: BLOCK (current = got1  AND GUARD)
    BEGIN
	current <= GUARDED got10 WHEN x = '0' ELSE got1;
    END BLOCK s2;
    s3: BLOCK (current = got10 AND GUARD)
    BEGIN
	current <= GUARDED got101 WHEN x = '1' ELSE reset;
    END BLOCK s3;
    s4: BLOCK (current = got101 AND GUARD)
    BEGIN
	current <= GUARDED got1 WHEN x = '1' ELSE got10;
	z <= '1' WHEN (current = got101 AND x = '1') ELSE '0';
    END BLOCK s4;
  END BLOCK clocking;
END singular_state_machine;

Since there are four concurrent signal assignments that use `current` for their target, this signal is declared as a resolved signal. The logic we used does not allow any more than one driver for this signal at any one time. As soon as a new value is assigned to `current`, the guard expression that allows this assignment to take place becomes FALSE, causing the removal of the previous driving value from it. This leaves the `current` signal with only one active driver at any one time, and the `LEFT in the one_of function returns that one driver.

Allowing Multiple Active States

A standard FSM is defined for one active state at any given time. Handling multiple active states enables us to describe pipeline and multiple state machines. Fig. 8.48 is an alternative description of our detector.

The states are represented by elements of the declared s signal: s(1),..,s(4) are resolved signals of type BIT with the resolution function `oring`. Also, s is a guarded signal of REGISTER kind, initiated to "1000".

Nested in outer clocking block are 4 block statements that correspond to the states of the machine. In a state block, other states become active based on the input conditions. Since four separate signals s (i) are used specify current active states, any number of these states can be active simultaneously. Because the `oring` is associated with each s (i), one or more assignments to s (i) are able to activate that state.

Each state should die out after it conditionally activates its next state(s). This does not happen automatically - all state signals are of the kind of REGISTER. In order to keep at least one driver active and cause all s (i) to become `0` after they cause activation of other states, we drive (last statement) all elements of s with `0` on the rising edge of each clock. The `0` on s (i) is ORed with other values that drive s (i). If this `0` is the only driver for that element, it causes the value to become `0`


ARCHITECTURE multiple_state_machine OF detector IS
    SIGNAL s : ored_bit_vector (1 TO 4) REGISTER := "1000";
BEGIN
  clocking : BLOCK (clk = '1' AND NOT clk'STABLE)
  BEGIN
    s1: BLOCK (s(1) = '1' AND GUARD)
    BEGIN
	s(1) <= GUARDED '1' WHEN x = '0' ELSE '0';
	s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
    END BLOCK s1;
    s2: BLOCK (s(2) = '1'  AND GUARD)
    BEGIN
	s(3) <= GUARDED '1' WHEN x = '0' ELSE '0';
	s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
    END BLOCK s2;
    s3: BLOCK (s(3) = '1' AND GUARD)
    BEGIN
	s(1) <= GUARDED '1' WHEN x = '0' ELSE '0';
	s(4) <= GUARDED '1' WHEN x = '1' ELSE '0';
    END BLOCK s3;
    s4: BLOCK (s(4) = '1' AND GUARD)
    BEGIN
	s(3) <= GUARDED '1' WHEN x = '0' ELSE '0';
	s(2) <= GUARDED '1' WHEN x = '1' ELSE '0';
	z <= '1' WHEN (s(4) = '1' AND x = '1') ELSE '0';
    END BLOCK s4;
    s <= GUARDED "0000";
  END BLOCK clocking;
END multiple_state_machine;

Open Collector Gates

The concept of resolution functions and resolved signals is useful for modeling various bus forms. A bussing structure formed by connecting the outputs of open collector gates is very common. Fig. 8.51(a)ows an open collector NAND gate, and Fig. 8.51(b) shows a 74LSS03 package. Fig. 8.52 shows the VHDL description for the package. If an output is used without a pull-up register (PUR), its value is either `0` or `Z`. To model PUR, resolution functions can be used. The function of a PUR is to produce a `1` if none of its drivers is `0`, and to produce a `0` if at least one driver is `0`. For the qit type, this function is the same as function `anding`. Therefore, we can use the following declaration for modeling a circuit node that is connected to a 5V supply through a PUR: SIGNAL pull_up : anded_qit; Associating this signal with an output port of an open collector gate is equivalent to connecting that output to a PUR in hardware. The resulting Boolean expression on the yy output is: yy=(aa`.bb)`.(bb`.aa)`= (aa XOR bb)` -- pull_up_3 has two drivers which are ANDed by theanding' resolution function.

A General Dataflow Circuit

Hardware descriptions at this level can be used to describe a complete sequential circuit consisting of registers, combinational units, and buses. Using an example, we will show how word specification can be translated into its dataflow hardware description. The circuit to design is a sequential comparator that keeps a modulo-16 count of matching consecutive data set pairs: -- The circuit uses an 8-bit data, a clk, and a reset input. -- The 4-bit output is called matches. If on any two consecutive rising edges of the clock, the same data appears on `data`, then the output will be incremented by 1. -- The synchronous reset of the circuit resets the output count to zero. The hardware implementation of this circuit, using standard parts, requires

- a register for holding the old data,

- a comparator for comparing new and old data,

- a counter for keeping the count, and

- perhaps a few logic gates used as "glue logic".

At the dataflow level, however, there is no need to be concerned with the component level details of this circuit; rather, flow of data between registers and buses can be captured directly in a VHDL description of this unit.
 
-- The dataflow architecture uses the inc function
for incrementingthe 4-bit output counter.
-- on the falling edge, the new data on input lines `data` is 
clocked into the 8-bit buffer.
-- on the same edge, the counter signal is incremented
if the new data and the previousdata are equal.
-- Loading buff and incrementing count are done by 
concurrent signal assignments and take place simultaneously.

FSM description for Synthsis

As we have mentioned before, Synthesis tools usually understand only a subset of the VHDL language. Let us use an example to see how we write VHDL for FSM that can be synthesized easily. We will use a controller for a CPU as an example. Recall that the general architecture of an FSM consists of a combinational block of next state logic, state registers and combinational output logic as shown here:


      inputs
       | | |
       | | |
       | | |     State Regs
     +---------+    +----+        +-------+    
     |  Next   |----| FF |-+------|       |    
     |  State  |    +----+ |      |  O    |    
     |  Logic  |    +----+ |      |  U    |------->  Output signals   
     |         |----| FF |---+----|  T F  | 
     |(Mapping)|    +----+ | |    |  P U  |------->
     |         |    +----+ | |    |  U N  |    
     |         |----| FF |-----+--|  T C  |------->
     |         |    +----+ | | |  |    T  |    
     |         |      ...  | | |  |    I  |------>
     |         |    +----+ | | |  |    O  |    
     |         |----| FF |-------+|    N  |    
     +---------+    +----+ | | | |+-------+    
       | | | |             | | | |
       +-|-|-|-------------+ | | |
         +-|-|---------------+ | |
           +-|-----------------+ |
             +-------------------+


Here we are illustrating a Moore machine. Our example is a simplied CPU controller. We simplied the controller so that we can see how FSm is specified instead of covering all possible functionality. In this example the control unit has three inputs and three outputs. There is also an input for clock as well as a global asynchronous reset signal called rst. The simplified control unit (FSM) has only four states. These states are described using a user defined data typ (recall all user defined data types are of enumeration type). We call this type "t_state" and this type consists of four possible values (states) named "idle", "rw_cycle", "int_cycle", and dma_cycle". We also decided to call the inputs and outputs to the state registers "state" and next_state. there the declaration part of the ARCHITECTURE we have so far is:


	ARCHITECUTRE rtl of FSM is
	    TYPE t_state IS (idle, rw_cycle, int_cylce, dma_cycle);
	    SIGNAL next_state, state : t_state;
	BEGIN

	....

Once the state variables and type is declared we need to define the next state logic (or the mapping function from current state to next state with inputs). One way to describe the logic is through a combinational process. Of course we could use other ways to describe it too. But a large case statement (which is similar to a micro-code mapping table) with a branch for each state of the state machine. The combinatonal process is sensitive to the control inputs and to the signal STATE (just like a state diagram where current state and input determines the next state).


  state_logic: PROCESS (state, rw, int_req, dma_req)
  BEGIN
      CASE state IS
	  WHEN idle =>
	      -- statements
	  WHEN rw_cycle =>
	      -- statements
	  WHEN int_cycle =>
	      -- statements
	  WHEN dma_cycle =>
	      -- statements
      END CASE;
  END PROCESS state_logic;


So far we have omitted the statements at each branch. Obviously within each branch of the case statement (at each state), we should have codes which assign to the next_state signal to define the state transitions. In the following example there is a state transition from idle state to int-cycle if there is an int-req, or there is a transiston to dma_cycle state if there is an dma-req signal.

  state_logic: PROCESS (state, rw, int_req, dma_req)
  BEGIN
      next_state <= state; -- remember you must make a initial assignment
			   -- otherwise it may create unwanted latches
      CASE state IS
	  WHEN idle =>
	      IF (int_req = '1') THEN
		  next_state <= int_cycle;
	      ELSEIF (dma_req = '1') THEN
		  next_state <= dma_cycle;
	      END IF;
	  WHEN rw_cycle =>
	      -- statements
	      ....
      END CASE;
  END PROCESS state_logic;

Now we define the state vector (registers) with another (seperated) clocked process. In this process we define only registers and no combinational logic. We assign the value of next_state to state only when there is a rising edge of clock.


  state_reg: PROCESS (clk, rst)
  BEGIN
      IF rst = '1' THEN state <= idle;
      ELSEIF clk'EVENT AND clk = '1' THEN state <= next_state;
      END IF;
  END PROCESS state_reg;

And finally we may either define the output function logic within the register PROCESS or another seperated combinational PROCESS. In the case of describing a Moore machine it is be recommanded that we define the output process with a seperated PROCESS different from the state register PROCESS.

Arithmetic Operators and Synthesis

Recall when we discuss the VHDL constructs that we said vectors (such as a std_logic_vector), is not considered to represent a number (no value associated with it). VHDL considers a vector as just a collection of single bit values. These bits are associated together for convenience only. As a result of this, by default in VHDL it is NOT possible to perform arithmetic operations such as add, subtract on vectors. Even though relational operations such as greater than or less than can be performed on vectors, extreme caution should be taken since it aligns the vectors for comparison from the left. Vectors of different length may yield unexpected results from what designer intended. The solution is OVERLOADING.