0% found this document useful (0 votes)
3K views19 pages

SSC07 2004 e

The document describes designing state machines using VHDL. It presents an example of a simple memory controller state machine. First, the traditional design methodology is described, which involves constructing a state flow diagram and state table to determine the next state equations. Then, the state machine is designed using VHDL by translating the state flow diagram into a behavioral description with processes for combinational and sequential logic. This allows the state machine to be described at a higher level without deriving equations. The VHDL implementation produces similar logic to the traditional approach through synthesis.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3K views19 pages

SSC07 2004 e

The document describes designing state machines using VHDL. It presents an example of a simple memory controller state machine. First, the traditional design methodology is described, which involves constructing a state flow diagram and state table to determine the next state equations. Then, the state machine is designed using VHDL by translating the state flow diagram into a behavioral description with processes for combinational and sequential logic. This allows the state machine to be described at a higher level without deriving equations. The VHDL implementation produces similar logic to the traditional approach through synthesis.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Structure of Computer Systems – State Machines in the VHDL Language 1

7. STATE MACHINES IN THE VHDL LANGUAGE

In this laboratory work several techniques are described for designing state machines using the VHDL
language. A simple example is presented first, showing that a behavioral state machine may be described by
simply translating a state flow diagram into case and if statements. Then various techniques that may be used
for state machine synthesis are presented.

7.1. Design Example


As an example, a state machine representing a simple memory controller will be designed, first using
the traditional design methodology, then using the VHDL language.
The memory controller asserts and deasserts the output enable (oe) and write enable (we) signals of a
memory buffer during read and write transactions. The inputs to the memory controller are the ready and
read_write signals from a microprocessor, and the outputs of the controller are the oe and we signals. A new
transaction begins with the assertion of the ready signal following a completed transaction (or upon power-up,
for the initial transaction). One clock cycle after starting a transaction, the value of the read_write signal deter-
mines the type of the transaction: if the read_write signal is asserted, then it is a read transaction; otherwise, it is
a write transaction. A transaction is completed by the assertion of the ready signal, after which a new transaction
can begin. The oe signal is asserted during a read cycle and the we signal is asserted during a write transaction.

7.1.1. Traditional Design


According to traditional design methodology, first a state flow diagram is constructed, from which a
state table may be derived. The equivalent states may be determined and eliminated by comparing rows of the
state table and using an implication table, if necessary. Then the states are assigned and a state transition table is
constructed, from which the next state and output equations may be determined based on the types of flip-flops
used for implementation.
From the controller description, the state flow diagram of Figure 7.1 may be drawn.

Figure 7.1. State flow diagram of the memory controller.


2 Structure of Computer Systems – State Machines in the VHDL Language

For this state machine, there are no equivalent states; all states require different inputs to transition to
the next state, or have different outputs. For implementation the fewest possible number of D-type flip-flops will
be used. The state transition table is constructed, combined with the state assignment table (Table 7.1). The state
assignment is listed in the present-state (PS) column. The next-state (NS) column shows transitions from present
state to next state based upon the present value of the two inputs, read_write and ready. The combinations of
values for these inputs are shown in a row as 00, 01, 11, and 10. Because D-type flip flops are used for imple-
mentation, there is no need to add a column for the inputs of the flip-flops, since this column is identical to the
next-state column. The outputs are listed in the last column.

Table 7.1. The state transition table for the memory controller.
PS (q0q1) NS (Q0Q1) Outputs
Name Code 00 01 11 10 oe we
idle 00 00 01 01 00 0 0
decision 01 11 11 10 10 0 0
write 11 11 00 00 11 0 1
read 10 10 00 00 10 1 0

Then, the next-state equations may be determined for the two state bits. Based on the state transition
table, the Karnaugh maps may be constructed for the Q0 and Q1 next-state bits and for the oe and we outputs,
based on the present-state bits (q0, q1) and the inputs (read_write, ready). These maps are used to find the mini-
mal equations for the next-state bits and for the outputs. Since D-type flip-flops are used for the implementation,
the next-state equations also represent the equations of the flip-flops’ inputs.
The following equations are obtained:

Q0 = q 0 q1 + q0 ⋅ ready (7.1)
Q1 = q 0 q1 ⋅ ready + q 0 q1 ⋅ read _ write + q0 q1 ⋅ ready (7.2)
oe = q0 q1 (7.3)
we = q0 q1 (7.4)

7.1.2. Design Using the VHDL Language


The state flow diagram shown in Figure 7.1 may be translated easily to a high-level VHDL description
without having to perform the state assignment, construct the state transition table, or determine the next-state
equations based on the types of flip-flops available. In VHDL, each state may be translated to an alternative of a
case statement. The state transitions may then be specified with if statements.
To translate the state flow diagram into VHDL, first an enumeration type is defined consisting of the
state names, and then two signals of that type are declared:
type state_type is (idle, decision, read, write);
signal present_state, next_state: state_type;

Next, a process is created. The next state is determined as a function of the present state (pre-
sent_state) and the inputs (read_write and ready). Thus, the sensitivity list of the process will contain
these signals:
proc_comb: process (present_state, read_write, ready)
begin
...
end process proc_comb;

Within the process the state machine transitions are described. A case statement will be used, specify-
ing the outputs for each state and the possible transitions.
The process constructed in this way indicates the transitions performed based on the present state and
the present inputs, but it does not indicate when the next state becomes the present state. This occurs synchro-
nously, on the rising edge of the clock signal, which is described in a second process, presented below.
Structure of Computer Systems – State Machines in the VHDL Language 3

proc_seq: process (clk)


begin
if (clk'event and clk = '1') then
present_state <= next_state;
end if;
end process proc_seq;
The complete description for the memory controller is presented next.

Example 7.1
entity mem_contr is
port (read_write: in bit;
ready, clk: in bit;
oe, we: out bit);
end mem_contr;

architecture state_machine of mem_contr is


type state_type is (idle, decision, read, write);
signal present_state, next_state: state_type;
begin
proc_comb: process (present_state, read_write, ready)
begin
case present_state is
when idle => oe <= '0'; we <= '0';
if (ready = '1') then
next_state <= decision;
else -- else not required
next_state <= idle;
end if;
when decision => oe <= '0'; we <= '0';
if (read_write = '1') then
next_state <= read;
else -- read_write = '0'
next_state <= write;
end if;
when read => oe <= '1'; we <= '0';
if (ready = '1') then
next_state <= idle;
else -- ready = '0'
next_state <= read;
end if;
when write => oe <= '0'; we <= '1';
if (ready = '1') then
next_state <= idle;
else -- ready = '0'
next_state <= write;
end if;
end case;
end process proc_comb;

proc_seq: process (clk)


begin
if (clk'event and clk = '1') then
present_state <= next_state;
end if;
end process proc_seq;

end state_machine;

The behavioral description of the state machine is made easier than the description by specifying the
equations. In the same time, by using such a description the possibility of errors is reduced. Synthesis of the be-
havioral design description will produce a logic similar to that obtained by implementing Equations (7.1) – (7.4).
4 Structure of Computer Systems – State Machines in the VHDL Language

7.2. Design of a Memory Controller


The next design example is also a memory controller, but it has additional functions compared to the
previous memory controller. Figure 7.2 shows the block diagram of a system that uses the memory controller.

Figure 7.2. Block diagram of a system that uses the second memory controller.

Devices on the bus initiate an access to the memory buffer by asserting the bus identification bus_id to
the value F3h. In the next clock cycle, the read_write signal is asserted to indicate a read from the memory
buffer, or it is deasserted to indicate a write to the memory buffer. If the operation executed is a read, either a
single word or a group of four words in burst mode are read. A burst read is indicated by the assertion of the
burst signal during the first read cycle, following which the controller accesses four locations from the memory.
Consecutive locations are accessed following successive assertions of the ready signal. The controller asserts the
output signal oe (output enable) during a read operation, and increments the lowest two bits of the address dur-
ing a burst read operation.
In a write operation to the buffer, always a single word is written. During a write operation the we
(write enable) signal is asserted, allowing data to be written to the memory location specified by addr. A read or
write access is completed upon assertion of the ready signal.
Figure 7.3 shows the state diagram for this memory controller. A synchronous reset signal places the
state machine in the idle state. When the memory buffer is not being accessed, the controller remains in the
idle state. If bus_id is set to F3h while the controller is in the idle state, the state machine transitions to the
decision state. On the next clock cycle, the controller transitions to either the read1 or write state, depend-
ing on the value of the read_write signal. If the access is a read, a single-word read is indicated by the assertion
of the ready signal in the read1 state without the assertion of the burst signal. In this case, the controller returns
to the idle state. A burst read is indicated by the assertion of both ready and burst signals while in the read1
state. In this case, the state machine transitions through each of the read states (read2, read3, read4). During
each of the read states, the oe signal is asserted and addr is incremented.
If the access is a write, indicated by deasserting the read_write signal, the controller asserts the we sig-
nal, waits for the ready signal from the bus, and then returns to the idle state.
The state flow diagram may be translated into a case statement, similar to the state machine from the
previous example. Each state is a branch of the case statement.
This state machine requires a synchronous reset signal. Rather than specifying the reset transition to the
idle state in each branch of the case statement, an if statement may be included at the beginning of the proc-
ess in order to place the machine in the idle state if the reset signal is asserted. In this if statement we must
specify the state of the outputs if the reset signal is asserted. If we do not specify the outputs for this condition,
latches will be created to ensure that the outputs retain their previous values. In order to avoid creation of latches,
we will specify that the outputs have don’t care values when the reset signal is asserted. This will allow to per-
form optimizations for minimizing the output equations. When the reset signal is asserted, the state machine will
transition to the idle state, and the outputs will be decoded from the present state and assigned according to
their definition in the idle state. If values were assigned to the outputs in this initial if statement, the outputs
would become functions of the present state and the reset signal, rather than of the present state alone.
Structure of Computer Systems – State Machines in the VHDL Language 5

Figure 7.3. State flow diagram of the second memory controller.

The sequence required for the synchronous reset is the following:


proc_comb: process (reset, present_state, burst, read_write, ready)
begin
if (reset = '1') then
oe <= '-'; we <= '-'; addr <= "--";
next_state <= idle;
else
case present_state is
...
end case;
end if;
end process proc_comb;

Another possibility is to specify the reset condition after the case statement, as the last statement of the
proc_comb process. In this case, defining the values for the output signals would not be required because the
case statement, in which the outputs are defined, will not be part of the else branch of an if statement. The
sequence required for the synchronous reset in this case would be the following:
proc_comb: process (reset, present_state, burst, read_write, ready)
begin
case present_state is
...
end case;
if (reset = '1') then
next_state <= idle;
end if;
end process proc_comb;

The complete description for the memory controller is given in Example 7.2.
6 Structure of Computer Systems – State Machines in the VHDL Language

Example 7.2
library ieee;
use ieee.std_logic_1164.all;
entity mem_contr is
port (reset, read_write,
ready, burst, clk: in std_logic;
bus_id: in std_logic_vector (7 downto 0);
oe, we: out std_logic;
addr: out (1 downto 0));
end mem_contr;

architecture state_machine of mem_contr is


type state_type is (idle, decision, read1, read2,
read3, read4, write);
signal present_state, next_state: state_type;
begin
proc_comb: process (reset, bus_id, present_state, burst,
read_write, ready)
begin
if (reset = '1') then
oe <= '-'; we <= '-'; addr <= "--";
next_state <= idle;
else
case present_state is
when idle => oe <= '0'; we <= '0'; addr <= "00";
if (bus_id = "11110011") then
next_state <= decision;
else
next_state <= idle; -- else not required
end if;
when decision => oe <= '0'; we <= '0';
addr <= "00";
if (read_write = '1') then
next_state <= read1;
else -- read_write = '0'
next_state <= write;
end if;
when read1 => oe <= '1'; we <= '0'; addr <= "00";
if (ready = '0') then
next_state <= read1;
elsif (burst = '0') then
next_state <= idle;
else
next_state <= read2;
end if;
when read2 => oe <= '1'; we <= '0'; addr <= "01";
if (ready = '1') then
next_state <= read3;
else
next_state <= read2; -- else not required
end if;
when read3 => oe <= '1'; we <= '0'; addr <= "10";
if (ready = '1') then
next_state <= read4;
else
next_state <= read3; -- else not required
end if;
when read4 => oe <= '1'; we <= '0'; addr <= "11";
if (ready = '1') then
next_state <= idle;
else
next_state <= read4; -- else not required
end if;
when write => oe <= '0'; we <= '1'; addr <= "00";
if (ready = '1') then
next_state <= idle;
else
Structure of Computer Systems – State Machines in the VHDL Language 7

next_state <= write; -- else not required


end if;
end case;
end if;
end process proc_comb;

proc_seq: process (clk)


begin
if rising_edge (clk) then
present_state <= next_state;
end if;
end process proc_seq;

end state_machine;

The state machine is described by two processes. One process describes the combinational logic, and
the second describes synchronization of state transitions to the clock signal. The structure of this description is
analogous to the architecture of a CPLD logic block. Decoding of present state and inputs is performed in the
combinational part (the product-term array) of the logic block, and is described in the combinational process of
the source code. Synchronization of the next state is described in the proc_seq process, which describes a bank
of registers such as the macrocells in a logic block.
If an asynchronous reset is needed instead of a synchronous reset, then the proc_seq sequential proc-
ess has to be modified. If the reset signal is used only during initialization or system failure, then an asynchro-
nous reset may be more advantageous than a synchronous reset, because a synchronous reset may require addi-
tional resources of the circuit.
The code presented in Example 7.3 is functionally equivalent to the code in Example 7.2, if it is modi-
fied to use an asynchronous reset signal. In Example 7.3 only one process is used to describe the state transitions
and the synchronization of those transitions to the clock signal. Additional concurrent assignment statements are
used to describe the behavior of the outputs.

Example 7.3
architecture state_machine of mem_contr is
type state_type is (idle, decision, read1, read2,
read3, read4, write);
signal state: state_type;
begin
st_tranz: process (reset, clk)
begin
if (reset = '1') then -- asynchronous reset
state <= idle;
elsif rising_edge (clk) then -- synchronization to clk
case state is
when idle =>
if (bus_id = "11110011") then
state <= decision;
else
state <= idle; -- else not required
end if;
when decision =>
if (read_write = '1') then
state <= read1;
else -- read_write = '0'
state <= write;
end if;
when read1 =>
if (ready = '0') then
state <= read1;
elsif (burst = '0') then
state <= idle;
else
state <= read2;
end if;
when read2 =>
if (ready = '1') then
state <= read3;
8 Structure of Computer Systems – State Machines in the VHDL Language

else
state <= read2; -- else not required
end if;
when read3 =>
if (ready = '1') then
state <= read4;
else
state <= read3; -- else not required
end if;
when read4 =>
if (ready = '1') then
state <= idle;
else
state <= read4; -- else not required
end if;
when write =>
if (ready = '1') then
state <= idle;
else
state <= write; -- else not required
end if;
end case;
end if;
end process st_tranz;

-- Combinatorially decoded outputs

with state select


oe <= '1' when read1 | read2 | read3 | read4,
'0' when others;
we <= '1' when state = write
else '0';
with state select
addr <= "01" when read2,
"10" when read3,
"11" when read4,
"00" when others;

end state_machine;

In the description of Example 7.3, only one state signal is used. The assignment of this signal is syn-
chronous to the clock. For state machines, the two-process coding style of Example 7.2 is recommended, be-
cause the outputs and state transitions may be easily identified. These two-process descriptions are easier to cre-
ate and understand, particularly for large state machines, machines with many transitions, or machines with a
large number of outputs.

7.3. Techniques to Generate the Output Signals


In this section, based on the same memory controller design, the following techniques are presented to
generate state machine outputs for Moore machines:
• Outputs decoded from state bits combinatorially;
• Outputs decoded in parallel output registers;
• Outputs encoded within state bits;
• One-hot encoding.

7.3.1. Outputs Decoded from State Bits


The outputs of the state machine of Example 7.2 and Example 7.3 must be decoded from the present
state of the state bits (Figure 7.4). This combinatorial decoding may require additional logic levels, resulting in
slower propagation from the state bits to the output signals at the device pins.
Structure of Computer Systems – State Machines in the VHDL Language 9

Figure 7.4. State machine with outputs decoded from state registers.

7.3.2. Outputs Decoded in Parallel Output Registers


One method to ensure a faster transmission of the state machine outputs to the device pins is to decode
the outputs from the state bits before these bits are written into the state registers. This can be done using either a
one-process or two-process state machine description. Consider the same example of the memory controller, and
suppose that the addr signal must be available in a shorter time at the device pins. In either case, the assign-
ments to the addr signal must be described outside of the process in which the state transitions are defined. In-
stead of using the present state to determine the address bits, the next_state value will be used. For example,
if in the next state of the machine addr(1) will be '1', the value '1' is stored into a flip-flop on the rising edge of
the clock, and if addr(1) will be '0', the value '0' is stored into that flip-flop. The same technique may be used
for other signals. The concept of storing the values of outputs based on the value of next_state is illustrated in
Figure 7.5.

Figure 7.5. Moore machine with outputs decoded in parallel output registers.

To change the memory controller description in order to include outputs decoded in parallel output reg-
isters, we modify the description of Example 7.2 as shown in Example 7.4.

Example 7.4
library ieee;
use ieee.std_logic_1164.all;
entity mem_contr is
port (reset, read_write,
ready, burst, clk: in std_logic;
bus_id: in std_logic_vector (7 downto 0);
oe, we: out std_logic;
addr: out std_logic_vector (1 downto 0));
end mem_contr;

architecture state_machine of mem_contr is


type state_type is (idle, decision, read1, read2,
read3, read4, write);
signal present_state, next_state: state_type;
signal addr_d: std_logic_vector (1 downto 0);
-- D-inputs to addr flip-flops
10 Structure of Computer Systems – State Machines in the VHDL Language

begin
proc_comb: process (bus_id, present_state, burst,
read_write, ready)
begin
case present_state is -- addr outputs not
-- defined here
when idle => oe <= '0'; we <= '0';
if (bus_id = "11110011") then
next_state <= decision;
else
next_state <= idle;
end if;
when decision => oe <= '0'; we <= '0';
if (read_write = '1') then
next_state <= read1;
else -- read_write = '0'
next_state <= write;
end if;
when read1 => oe <= '1'; we <= '0';
if (ready = '0') then
next_state <= read1;
elsif (burst = '0') then
next_state <= idle;
else
next_state <= read2;
end if;
when read2 => oe <= '1'; we <= '0';
if (ready = '1') then
next_state <= read3;
else
next_state <= read2;
end if;
when read3 => oe <= '1'; we <= '0';
if (ready = '1') then
next_state <= read4;
else
next_state <= read3;
end if;
when read4 => oe <= '1'; we <= '0';
if (ready = '1') then
next_state <= idle;
else
next_state <= read4;
end if;
when write => oe <= '0'; we <= '1';
if (ready = '1') then
next_state <= idle;
else
next_state <= write;
end if;
end case;
end process proc_comb;

with next_state select -- D-inputs to addr


addr_d <= "01" when read2, -- flip-flops
"10" when read3,
"11" when read4,
"00" when others;

proc_seq: process (clk, reset)


begin
if reset = '1' then
present_state <= idle;
addr <= "00"; -- asynchronous reset
-- for addr flip-flops
elsif rising_edge (clk) then
present_state <= next_state;
addr <= addr_d; -- value of addr_d
Structure of Computer Systems – State Machines in the VHDL Language 11

-- stored in addr
end if;
end process proc_seq;

end state_machine;

In this example an additional signal, addr_d, is declared. This signal is used to combinatorially decode
what the values of the addr address bits should be in the next clock cycle. This is done by removing the signal
assignments to these bits from the case statement, where they are based on the present state, and inserting a
concurrent signal assignment statement, where the selection signal is the next state. Therefore, the addr_d signal
will be decoded from the next state rather than the present state. Next, on the rising edge of the clock, the
addr_d signal is assigned to the addr bits in the proc_seq process.
The addr address bits have the same values in the same clock cycle as in the previous implementations,
but now they are available in a shorter time. This is because the addr address bits are stored in flip-flops, and the
outputs of these flip-flops may propagate directly to the device pins rather than propagating through the logic
array.

7.3.3. Outputs Encoded within State Bits


Another method by which the outputs of a state machine are available in shorter time is to use the state
bits themselves as outputs. A counter is an example of a state machine for which the outputs are also the state
bits. This method requires a careful state encoding, because the outputs must correspond to the values held in the
state registers, as shown in Figure 7.6. By using this method, the design will be more difficult to comprehend
and maintain, so it is recommended only for cases that require specific resource and performance optimizations
not provided by the synthesis tools, automatically or through synthesis directives.

Figure 7.6. Moore machine with outputs encoded within state registers.

To illustrate the concept of encoding the outputs within the state registers, we will use the memory con-
troller again. Since there are seven states of the machine, the fewest number of state bits is three, but additional
bits may be needed to encode the outputs. We assume that all the outputs must be propagated in shorter time to
the output pins of the device; these outputs are addr(1), addr(0), oe, and we. If a CPLD is used for the im-
plementation, the maximum number of macrocells required is seven (three state bits and four outputs). The prob-
lem is to create a state encoding so that the outputs will represent a part of the state bits. To choose the encoding,
first we create a table of the present state and the outputs that should be encoded (Table 7.2).

Table 7.2. The outputs of the memory controller as functions of the present state.
State addr(1) addr(0) oe we
idle 0 0 0 0
decision 0 0 0 0
read1 0 0 1 0
read2 0 1 1 0
read3 1 0 1 0
read4 1 1 1 0
write 0 0 0 1

Next, we examine the table, looking for the output combinations that appears with the greatest fre-
quency. If all output combinations were unique, the state encoding would be complete. In this case, the 0000
12 Structure of Computer Systems – State Machines in the VHDL Language

combination appears twice (for the idle and decision states). To distinguish between idle and decision
states, an additional bit is added, st0. We arbitrarily choose this bit to be 0 for idle and 1 for decision. For
the remaining states, we arbitrarily choose the value of st0 to be 0. The final state encoding is presented in Ta-
ble 7.3.
Table 7.3. The outputs of the memory controller encoded within the state bits.
State addr(1) addr(0) oe we st0
idle 0 0 0 0 0
decision 0 0 0 0 1
read1 0 0 1 0 0
read2 0 1 1 0 0
read3 1 0 1 0 0
read4 1 1 1 0 0
write 0 0 0 1 0

With five bits needed for the state encoding, the number of macrocells required is reduced with two
compared to the case in which the outputs are decoded in parallel with or serially from the state bits. In general,
macrocell reduction depends upon the uniqueness of the state machine outputs for the different states. In the
worst case, the same number of macrocells are needed as when the outputs are decoded in parallel registers. For
state machines implemented in CPLDs, this technique will usually require a fewer number of macrocells com-
pared to that required when using the preceding techniques.
In an FPGA device, there is no clear advantage of using this method over the case when the outputs are
decoded in parallel output registers. A more efficient implementation in an FPGA device is obtained by using the
one-hot encoding method, presented in the next section. Synthesis directives may also be used to obtain optimal
implementations. The state machine used as example has few states, few inputs, and the transitions are relatively
simple, so that its implementation in an FPGA device will not differ by much for the different methods used.
To describe the state machine by this method, we have to explicitly declare the state encoding with con-
stants. In Example 7.5, the state signal is declared of type std_logic_vector, rather than of the enumeration
type state_type, and the state encoding is specified by constants. The entity definition is the same and is not
reprinted.

Example 7.5
architecture state_machine of mem_contr is
-- State signal is of type std_logic_vector
-- rather than an enumeration type
signal state: std_logic_vector (4 downto 0);
constant idle: std_logic_vector (4 downto 0) := "00000";
constant decision: std_logic_vector (4 downto 0) := "00001";
constant read1: std_logic_vector (4 downto 0) := "00100";
constant read2: std_logic_vector (4 downto 0) := "01100";
constant read3: std_logic_vector (4 downto 0) := "10100";
constant read4: std_logic_vector (4 downto 0) := "11100";
constant write: std_logic_vector (4 downto 0) := "00010";
begin
st_tranz: process (reset, clk)
begin
if (reset = '1') then
state <= idle;
elsif rising_edge (clk) then
case state is -- outputs not defined here
when idle =>
if (bus_id = "11110011") then
state <= decision;
end if; -- no else; implicit memory
when decision =>
if (read_write = '1') then
state <= read1;
else -- read_write = '0'
state <= write;
end if;
Structure of Computer Systems – State Machines in the VHDL Language 13

when read1 =>


if (ready = '0') then
state <= read1;
elsif (burst = '0') then
state <= idle;
else
state <= read2;
end if;
when read2 =>
if (ready = '1') then
state <= read3;
end if; -- no else; implicit memory
when read3 =>
if (ready = '1') then
state <= read4;
end if; -- no else; implicit memory
when read4 =>
if (ready = '1') then
state <= idle;
end if; -- no else; implicit memory
when write =>
if (ready = '1') then
state <= idle;
end if; -- no else; implicit memory
when others =>
state <= "-----"; -- don’t care state
end case;
end if;
end process st_tranz;

-- Outputs associated with register contents

we <= state(1);
oe <= state(2);
addr <= state (4 downto 3);

end state_machine;

In this example, a single process is used to describe and synchronize the state transitions. This process,
st_tranz, is similar to that of Example 7.3, but this time the case statement contains an additional branch,
when others. This branch is required to cover all possible values of the state signal (this signal, of type
5
std_logic_vector, has 9 possible values). Because there are only seven defined states, the other 25 states
from the possible 32 (25) are illegal states. (More about illegal states and fault tolerance is discussed later.) Be-
cause the state encoding was explicitly declared and was chosen to contain present state outputs, the outputs can
be assigned directly from the state signal.

7.3.4. One-Hot Encoding


One-hot encoding uses n flip-flops to represent a state machine with n states. Each state has its own
flip-flop, and only one flip-flop is set to 1 at any given time. Decoding the present state consists of a simple iden-
tification of the flip-flop that is set. Transition from one state to another is as simple as changing the contents of
the flip-flop for the old state from 1 to 0 and the flip-flop for the new state from 0 to 1.
The primary advantage of the state machines using the one-hot encoding is that the number of gates
required to decode state information for outputs and for state transitions is much lower than the number of gates
required with other methods. This difference in complexity increases as the number of states becomes larger. To
illustrate this aspect, consider a state machine with 18 states that are encoded with two methods, sequential and
one-hot. For sequential encoding, five flip-flops are required, whereas for one-hot encoding eighteen flip-flops
are required. Suppose that Figure 7.7 represents a part of the state flow diagram that indicates all possible transi-
tions to state 15.
14 Structure of Computer Systems – State Machines in the VHDL Language

Figure 7.7. Part of a state flow diagram showing all possible transitions to state 15.

The code fragment that represents this part of the state flow diagram is the following:
case present_state is
when state2 =>
if cond1 = '1' then
next_state <= state15;
else ...
when state15 =>
if ...
elsif cond3 = '0' then
next_state <= state15;
else ...
when state17 =>
if ...
elsif cond2 = '1' then
next_state <= state15;
else ...
end case;

We examine the next-state logic for sequential encoding first. We will denote the sequential state vector
by s, which is 5-bits wide, s4s3s2s1s0. The sequential encoding for state 15 is 01111. Using the state flow diagram
of Figure 7.7, we can write for each of the five bits of vector s an equation that represents the conditions that
cause that bit to be asserted due to a transition to state 15:

si,15 = s 4 ⋅ s 3 ⋅ s 2 ⋅ s1 ⋅ s 0 ⋅ cond1
= s 4 ⋅ s 3 ⋅ s 2 ⋅ s1 ⋅ s0 ⋅ cond 2
= s 4 ⋅ s3 ⋅ s 2 ⋅ s1 ⋅ s 0 ⋅ cond 3

where 0 ≤ i ≤ 4, si represents one of the 5 bits of vector s, and si,15 represents the equations that cause bit si to be
asserted due to transitions to state 15. The expression that corresponds to bit s4 is 0, because transitions to state
15 do not cause this most significant bit of the state vector to be asserted.
Although this equation defines the si bit for transitions to state 15, it is not sufficient to specify bits s0,
s1, s2, and s3. For example, the equation for s0,15 covers only the cases in which bit s0 is asserted due to transitions
to state 15. Bit s0 is also asserted due to transitions to all of the odd states. The logic equations associated with
these transitions may be similar in complexity with the equations for s0,15. To obtain the complete equation for
bit si, each of the equations si,x (where x is an integer from 0 to 17, representing the 18 states) must be summed.
The logic for bit si can be quite complex, even for a relatively simple state flow diagram. In general, the sequen-
tial encoding will create five complex equations for bit si.
We will denote the state vector for one-hot encoding by t, which is 18 bits wide. Bit 15 of this vector,
corresponding to state 15, has the following equation:

t15 = t 2 ⋅ cond1 + t17 ⋅ cond 2 + t15 ⋅ cond 3

This equation can be easily derived from the state flow diagram. Figure 7.8 presents the logic imple-
mentation for transitions to state 15. Whereas the sequential encoding requires 5 complex equations for the next-
state logic, the one-hot encoding requires 18 simple equations. Depending on the target device architecture, a
one-hot encoded state machine may require significantly fewer device resources for implementation compared to
Structure of Computer Systems – State Machines in the VHDL Language 15

a state machine with other encoding. The next-state logic may also require fewer levels of logic between the state
registers, allowing for higher frequency of operation.

Figure 7.8. Next-state logic for transitions to state 15 in the state machine using one-hot encoding.

One-hot encoding is not always the optimal solution, however, mainly because it requires more flip-
flops than sequential encoding. In general, one-hot encoding is more advantageous when the architecture of the
programmable logic device used contains a relatively large number of flip-flops and a relatively small number of
logic gates between the flip-flops. For example, this encoding is most advantageous for state machines imple-
mented in FPGA devices, which usually have a larger number of flip-flops than CPLDs. One-hot encoding may
be the optimal solution even for CPLDs when the next-state logic requires multiple passes through the logic ar-
ray.
In general, using one-hot encoding requires no change to the source code. Many synthesis tools allow to
use a synthesis directive to specify one-hot encoding. These synthesis directives may be in the form of options of
the graphics interface, command-line switches, or language attributes. These attributes are specific to the synthe-
sis tool. For example, some synthesis tools allow to use the state_encoding attribute, which is applied to the
enumeration type used for state definition. In the following fragment, the one_hot value of this attribute speci-
fies the use of one-hot encoding:
type state_type is (idle, decision, read1, read2,
read3, read4, write);
attribute state_encoding of state_type: type is one_hot;
signal present_state, next_state: state_type;
Generating outputs for one-hot encoded state machines is similar to generating outputs for machines in
which the outputs are decoded from state registers. The decoding is very simple, because each state is repre-
sented by a single bit, not an entire vector. The output logic consists of an OR gate, because Moore machines
have outputs that are functions of the machine states, and each state is represented by one bit. The output decod-
ing adds a logic level and the associated delay, just as when the state bits are encoded. In an FPGA device, the
delay associated with an OR gate is acceptable, and it is an improvement upon decoding the outputs from an en-
tire state vector. In a CPLD, the OR gate requires a second pass through the logic array. The outputs may also be
generated using parallel decoding registers, as described earlier. This will eliminate the additional logic level and
the associated delay.
If any output is asserted in one state only, this will be automatically encoded within the state bits. For
example, considering the memory controller, the we signal will be asserted only during the state write:
we <= '1' when present_state = write else '0';

There is a flip-flop directly associated with the write state, so that the value of we signal will be given
by the state of this flip-flop. Consequently, this signal will be available at the device pins or for internal logic
without the additional delay associated with output decoding.
16 Structure of Computer Systems – State Machines in the VHDL Language

7.4. Mealy State Machines


In the previous sections only Moore machines were considered, in which the outputs are functions only
of the present state. Mealy machines may have outputs that are functions of the present state and the present in-
puts, as illustrated in Figure 7.9.

Figure 7.9. Difference between (a) Moore and (b) Mealy state machines.

The additional operations involved in describing Mealy state machines versus Moore machines are
minimal. To implement a Mealy machine, an output must be described as a function of both the state bits and the
inputs. For example, if there is an additional input to the memory controller, called write_mask, that when as-
serted prevents the we signal from being asserted, the logic for the we signal may be described as:
if (present_state = s6) and (write_mask = '0') then
we <= '1';
else
we <= '0';
end if;
The design techniques presented previously to ensure that the outputs are available in a shorter time
cannot be used with a Mealy machine because they are functions of the present inputs also, not only the present
state.

7.5. Other Design Considerations


7.5.1. State Encoding Using Enumeration Types
Enumeration types allow a simple way to encode state machines. When synthesized, state signals are
converted to vectors. Each value of the state type is assigned an encoding. For one-hot encoding, each state value
corresponds to one flip-flop. For other encodings, such as sequential, the minimum number of states required is
the greatest integral value of log2 n, log 2 n , where n is the number of states. If log2 n is not an integral value,
there will be undefined states.
For the memory controller presented as example, seven states were defined. Using sequential encoding,
the state signal will require three flip-flops. From the eight possible states, one is undefined. The sequential en-
coding of the memory controller states for the case when an enumeration type is used for the state signal is
shown in Table 7.4, where the vector representing the state encoding is denoted by q.
Structure of Computer Systems – State Machines in the VHDL Language 17

Table 7.4. Sequential encoding for an enumeration type.


State q2 q1 q0
idle 0 0 0
decision 0 0 1
read1 0 1 0
read2 0 1 1
read3 1 0 0
read4 1 0 1
write 1 1 0
undefined 1 1 1

For the example presented that use an enumeration type, the synthesis tool will assume that the value
111 for vector q is a don’t-care condition. No transitions into or out of the state corresponding to this code are
defined. If the state machine would transition into this undefined, or illegal, state, it would not function in a pre-
dictable manner. The behavior of the state machine, if placed in an illegal state, will depend on the state transi-
tion equations. The advantage of specifying transitions out of an illegal state as don’t-care conditions is that ad-
ditional logic is not required to ensure that the machine will transition out of this state. This additional logic may
require substantial device resources for implementation, especially if there are many undefined states. The dis-
advantage of using these implied don’t-care conditions is that the state machine is less fault-tolerant. The de-
signer should make a decision whether this is acceptable for a particular application.
In practice, glitches, noise, or illegal input combinations may cause one or more flip-flops to change
state, causing the machine to enter an illegal state. The machine may remain in the illegal state permanently, or it
may assert an illegal combination of outputs, which may cause other undesired effects.
State machines can be made fault-tolerant by adding logic that ensures transitions out of illegal states:
• First, the designer should determine how many illegal states are possible. The number of illegal states is
the number of states in the machine subtracted from the number of flip-flops used to encode the ma-
chine, raised to the power of two. For the memory controller, there is a single undefined state.
• Next, the designer has to include a state name in the enumeration type for each undefined state. For ex-
ample:
type state_type is (idle, decision, read1, read2,
read3, read4, write, undefined);

• Finally, a state transition must be specified for the state machine to transition out of this state. This tran-
sition may be specified in the following form:
case present_state is
...
when undefined => next_state <= idle;
end case;

7.5.2. Explicit State Encoding


State machines with explicit state encoding, such as the one of Example 7.5, must explicitly specify
transitions out of undefined or illegal states. For example, the transitions from undefined states to the initial state
may be specified as:
when others => state <= idle;
By specifying transitions from illegal states to a known state, additional logic will be required. The cost
of this solution may not be worth the need for fault tolerance. In this case, rather than specifying that all other
states should transition to a known state, we can explicitly specify that the transition from an illegal state is a
don’t-care condition (that is, we don’t care what state the machine transitions to because we don’t expect the
state machine to get in that state). For explicit encoding, the don’t care conditions may be declared as:
when others => state <= "-----";

where the state signal is assumed to be a 5-bit vector.


18 Structure of Computer Systems – State Machines in the VHDL Language

Whereas don’t-care conditions are implicit in state machines that use enumeration types that don’t spec-
ify all possible combinations of values, the don’t-care conditions must be explicitly defined for state machines
designed with explicit state encoding. Using constants allows the explicit definition of both the don’t-care condi-
tions and the transitions from illegal states.

7.5.3. Fault Tolerance for One-Hot Machines


The possibility for entering illegal states increases when using one-hot encoding or outputs encoded
within state bits. Both techniques may result in many illegal or undefined states. For example, with one-hot en-
coding, there are 2n possible values for the n-bit state vector, while the state machine has only n states. Although
one-hot encoding is usually chosen to achieve an efficient state machine implementation, including logic that
causes all the illegal states to transition to an initial or other known state creates an inefficient implementation.
For example, to completely specify state transitions for an one-hot encoded state machine with 18 states, another
218 – 18 = 262,126 transitions would have to be decoded.
Rather than adding logic to transition out of all illegal states to a known state, a logic may be added that
detects more than one flip-flop being asserted at a time. A collision signal may be generated to detect multiple
flip-flops asserted at the same time. For the case when there are four states denoted by state1, …, state4, the
collision signal has the following form:
collision <= (state1 and (state2 or state3 or state4)) or
(state2 and (state1 or state3 or state4)) or
(state3 and (state1 or state2 or state4)) or
(state4 and (state1 or state2 or state3));
This technique may be extended for any number of states. If it is not necessary for the collision signal to
be decoded in one clock cycle, the pipelining technique may be used to generate this signal. By using this tech-
nique, the maximum operating frequency can be maintained.
The designer must decide how many device resources can be used to increase fault tolerance of the state
machine, or whether the decrease of operating speed due to the additional logic is acceptable.

7.6. Applications
7.6.1. Consider a state machine with three states (s0, s1, s2) and three outputs (out_a, out_b,
out_c). The output out_a must be asserted only in state s0, out_b must be asserted only in state s1, and
out_c must be asserted only in state s2. A possible sequence to generate the outputs is the following:
if (present_state = s0) then
out_a <= '1';
elsif (present_state = s1) then
out_b <= '1';
else -- present_state = s2
out_c <= '1';
end if;
Explain why this syntactically correct sequence is not correct functionally.
7.6.2. Compile the description of the memory controller of Example 7.1 and follow its operation with
the simulator.
7.6.3. Add the sequence required for the asynchronous reset of the memory controller of Example 7.1.
Compile the description in two variants, with the initialization of the output signals in the reset sequence, and
without this initialization. Simulate the operation of both variants.
7.6.4. Compile the description of the memory controller of Example 7.2 and follow its operation with
the simulator.
7.6.5. Modify the description of the memory controller of Example 7.2 to use an asynchronous reset
signal rather than a synchronous reset signal.
7.6.6. Design the second memory controller (Figure 7.2) using the state-machine editor of the Active-
HDL system. Compare the source file obtained with the description of Example 7.2.
Structure of Computer Systems – State Machines in the VHDL Language 19

Figure 7.10. State machine for Application 7.6.7: (a) state flow diagram; (b) output signal table.

7.6.7. Design the state machine of Figure 7.10 using an enumeration type for state definition.
7.6.8. Modify the state-machine description of Application 7.6.7 to encode the outputs within the state
bits.
7.6.9. Design a state machine to detect the bit sequence "11101011". The sequence is applied to the
state machine starting with the most significant bit. Draw the state flow diagram of the state machine, and then
describe the machine in VHDL using two processes and an enumeration type for state definition. Compile the
description and simulate the operation of the state machine.
7.6.10. Design the state machine specified for Application 7.6.9 using the state-machine editor of the
Active-HDL system in two variants: using sequential encoding and one-hot encoding. Compare the source files
obtained.
7.6.11. Design a 16-bit counter using a state machine, not the "+" operator. Compare the result obtained
using sequential encoding with that obtained using one-hot encoding.
7.6.12. Design the control unit for a binary multiplier that implements Booth’s method. Draw the state
flow diagram of the control unit and describe the state machine in VHDL.
7.6.13. Design the control unit for a binary divider that implements the restoring division method. Draw
the state flow diagram of the control unit and use the state-machine editor of the Active-HDL system to generate
the VHDL description of the control unit.

You might also like