CHAPTER   4

STRUCTURAL DESCRIPTION

Chapter Objectives

 

4.1  Highlights of Structural Description

 

Structural description is best implemented when the digital logic of the details of hardware components of the system are known. An example of such a system is a 2x1 multiplexer. The components of the system are known: AND, OR, and NOT gates. Structural description can easily describe these components. On the other hand, it is hard (if not impossible) to describe the digital logic of, say, hormone secretion in the blood; therefore, another description such as behavioral or mixed may be implemented. Structural description is very close to schematic simulation.

In this chapter, structural description is covered. Both gate-level and register-level description are discussed for VHDL and Verilog. Highlights of the structural description can be summerized in the following facts.

Facts

4.2  Organization of Structural Description

 

Listing 4.1 shows an example of HDL code that describes a half adder under the name of system using structural description. The entity (VHDL) or module (Verilog) name is system; there are two inputs, a and b, and two outputs, sum and cout. The entity or module declaration is the same as in other description styles previously covered (data flow and behavioral).

In the VHDL description, the structural code (inside the architecture) has two parts: declaration and instantiation. In declaration, all of the different types of components are declared. For example, the statements

component xor2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

declare a generic component by the name of xor2; the component has two inputs (I1, I2) and one output (O1). The name (identifier) xor2 is not a reserved or predefined word in VHDL; it is a user-selected name. To specify the type of the component (e.g., AND, OR, XOR, etc.), additional information should be given to the simulator (see Listing 4.2). If the system has two or more identical components, only one declaration is needed. The instantiation part of the code maps the generic inputs/outputs to the actual inputs/outputs of the system. For example, the statement

X1 : xor2 port map (a, b, sum);

maps input a to input I1 of xor2, input b to input I2 of xor2, and output sum to output O1 of xor2. This mapping means that the logic relationship between a, b, and sum is the same as between I1, I2, and O1. If xor2 is specified through additional statements to be a XOR gate, for example, then sum = a xor b. A particular order of mapping can be specified as:

X1 : xor2 port map (O1 => S, I1 => b , I2 => a);

S is mapped to O1, b is mapped to I1, and a is mapped to I2. Note that the mapping of S is written before writing the mapping of the inputs; we could have used any other order of mapping. As previously mentioned, structural-description statements are concurrent and are driven by events. This means that their execution depends on events, not on the order in which the statements are placed in the module. So, placing statement A1 before statement X1 in Listing 4.1 does not change the outcome of the VHDL program.

Verilog has a large number of built-in gates. For example, the statement:

xor X1 (sum, a, b);

describes a two-input XOR gate. The inputs are a and b, and the output is sum. X1 is an optional identifier for the gate; the identifier can be omitted as:

xor (sum, a, b);

Verilog has a complete list of built-in primitive gates. The output of the gate sum has to be listed before the inputs a and b. Accordingly, the Verilog code in Listing 4.1 is a complete structural description of a half adder. Figure 4.1 shows a list of gates and their code in Verilog. As in structural VHDL, Verilog statements are concurrent; the order of appearance of statements in the module is irrelevant.

image

Figure 4.1  Verilog built-in gates.

LISTING 4.1  HDL Structural Description

VHDL Description   

--This code is not complete; binding statements should

--be aaded to recognize components

-- xor2 and and2 as 2-input

-- xor and and gate respectively.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity system is

port (a, b : in std_logic;

       sum, cout : out std_logic);

  end system;

  architecture struct_exple of system is

  --start declaring all different types of components

  component xor2

  port (I1, I2 : in std_logic;

      O1 : out std_logic);

  end component;

  component and2

  port (I1, I2 : in std_logic;

      O1 : out std_logic);

  end component;

  begin

  --Start of instantiation statements

  X1 : xor2 port map (a, b, sum);

  A1 : and2 port map (a, b, cout);

  end struct_exple;

 

Verilog Description

module system (a, b, sum, cout);

input a, b;

output sum, cout;

xor X1 (sum, a, b);

/* X1 is an optional identifier; it can be omitted.*/

and a1 (cout, a, b);

/* a1 is optional identifier; it can be omitted.*/

endmodule

 EXAMPLE 4.1   HDL STRUCTURAL DESCRIPTION OF A HALF ADDER

The logic and symbol diagrams of the half adder have been shown before (see Figure 1.1). Listing 4.2 shows the HDL structural code for the half adder. As mentioned before, VHDL does not have built-in gates. To specify xor2 as an EXCLUSIVE-OR gate, bind (link) the component xor2 with an entity bearing the same name. By having the same name, all information in the entity is visible to the component. The entity specifies the relationship between I1, I2, and O1 as EXCLUSIVE-OR; accordingly, the inputs and output of xor2 behave as EXCLUSIVE-OR. The same is done for component and2; it is bound to the entity and2.

LISTING 4.2  HDL Code of Half Adder: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity xor2 is

port(I1, I2 : in std_logic; O1 : out std_logic);

end xor2;

architecture Xor2_0 of xor2 is

begin

    O1 <= I1 xor I2;

end Xor2_0;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity and2 is

    port (I1, I2 : in std_logic; O1 : out std_logic);

end and2;

architecture and2_0 of and2 is

begin

    O1 <= I1 and I2;

end and2_0;

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity half_add is

    port (a, b : in std_logic; S, C : out std_logic);

end half_add;

 

architecture HA_str of half_add is

component xor2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

begin

    X1 : xor2 port map (a, b, S);

    A1 : and2 port map (a, b, C);

end HA_str;

 

Verilog Description

Module system (a, b, sum, cout);

input a, b;

output sum, cout;

xor X1 (sum, a, b);

/* X1 is an optional identifier; it can be omitted.*/

and a1 (cout, a, b);

/* a1 is optional identifier; it can be omitted.*/

endmodule

The VHDL code looks much longer than the Verilog code. This is due to the assumption that the basic VHDL packages do not have built-in libraries or packages for logical gates. The binding method above becomes impractical when the number of gates becomes large. Every time a new description is written, the entities of all gates used must also be written. In the following sections, more efficient ways of binding are discussed.

4.3  Binding

 

Binding in HDL is common practice. Binding (linking) segment1 in HDL code to segment2 makes all information in segment2 visible to segment1. Consider the VHDL code in Listing 4.3.

LISTING 4.3  Binding Between Entity and Architecture in VHDL

entity one is

port (I1, I2 : in std_logic; O1 : out std_logic);

end one;

architecture A of one is

signal s : std_logic;

..........

end A;

architecture B of one is

signal x : std_logic;

.......

end B;

Architecture A is bound to entity one through the predefined word of. Also, architecture B is bound to entity one through the predefined word of. Accordingly, I1, I2, and O1 can be used in both architecture A and architecture B. Architecture A is not bound to architecture B, so signal s is not recognized in architecture B. Likewise, signal x is not recognized in architecture A.

Now consider Listing 4.4, where an entity is bound to a component.

LISTING 4.4  Binding Between Entity and Component in VHDL

entity orgate is

    port (I1, I2 : in std_logic; O1 : out std_logic);

end orgate;

 

architecture Or_dataflow of orgate is

begin

    O1 <= I1 or I2;

end Or_dataflow;

 

entity system is

    port (x, y, z : in std_logic;

    out r : std_logic_vector (3 downto 0);

end system;

 

architecture system_str of system is

component orgate

port (I1, I2 : in std_logic; O1 : std_logic);

end component;

begin

orgate port map (x, y, r(0));

.......

end system_str;

The component orgate is bound to the entity orgate because it has the same name. Architecture Or_dataflow is bound to entity orgate by the word of. All information in the entity is now visible to the component. Accordingly, the relationship between I1, I2, and O1 defined in the architecture or_dataflow is visible to the component orgate; hence, the component orgate is an OR gate.

Now consider another way of VHDL binding where a library or a package is bound to a module. Listing 4.5 shows how a library can be bound to a module.

LISTING 4.5  Binding Between Library and Module in VHDL

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity system is

port (I1, I2 : in std_logic;

O1 : out std_logic_vector (3 downto 0));

 

end system;

architecture lib_bound of system is

signal s : std_logic;

.............

end lib_bound;

IEEE is the name of the library, library and use are a predefined words, and IEEE.STD_LOGIC_1164.ALL refers to the part of the library to be linked. Library IEEE provides the definition for the standard_logic type. By entering the name of the library and the statement use, all information in the library is visible to the whole module. If the first two statements are not written in Listing 4.5, the standard_logic type cannot be recognized. Libraries can also be generated by the user. The HDL simulator generates a library named work every time it compiles HDL code. This library can be bound to another module by using the statement use, as follows:

use entity work.gates (or_gates);

The entity to be bound to the module is gates; gates has an architecture by the name of or_gates, and all information in this architecture is visible to the module wherever the use statement is written. Listing 4.6 shows an example of binding architecture in one module to a component written in another module.

LISTING 4.6  Binding Between a Library and Component in VHDL

--First, write the code that will be bound to another

-- module

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind2 is

    port (I1, I2 : in std_logic; O1 : out std_logic);

end bind2;

 

architecture xor2_0 of bind2 is

begin

O1 <= I1 xor I2;

end xor2_0;

 

architecture and2_0 of bind2 is

begin

    O1 <= I1 and I2;

end and2_0;

 

architecture and2_4 of bind2 is

begin

    O1 <= I1 and I2 after 4 ns;

end and2_4;

 

--After writing the above code; compile it and store it

-- in a known location. Now, open another module

--where the above information is to be used.

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity half_add is

port (a, b : in std_logic; S, C : out std_logic);

end half_add;

architecture HA_str of half_add is

component xor2

    port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component and2

    port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

for all : xor2 use entity work.bind2 (xor2_0);

for all : and2 use entity work.bind2 (and2_4);

begin

X1 : xor2 port map (a, b, S);

A1 : and2 port map (a, b, C);

end HA_str;

The statement for all : xor2 use entity work.bind2 (xor2_0) binds the architecture xor2_0 of the entity bind2 to the component xor2. By this binding, component xor2 behaves as a two-input XOR gate with zero propagation delay. The statement for all : and2 use entity work.bind2 (and2_4) binds the architecture and2_4 of the entity bind2 to the component and2. By this binding, component and2 behaves as a two-input AND gate with a 4-ns propagation delay. In Listing 4.6, it is assumed that both entities bind2 and half_add have the same path (stored in the same directory). Otherwise, the path of the library work has to be specified.

Throughout this chapter, the binding shown in Listing 4.6 is adopted. The codes for all the gates expected are written, and the module is compiled and stored. Whenever we want to use any component from the stored module, we bind it to the current module. Listing 4.31 shows the VHDL binding code used in all examples in this chapter. As previously mentioned, Verilog has all primitive gates built in and ready to use. Verilog modules can be bound by just writing the name of the module to be bound. Listing 4.7 shows such binding.

LISTING 4.7  Binding Between Two Modules in Verilog

module one (O1, O2, a, b);

input [1:0] a;

input [1:0] b;

output [1:0] O1, O2;

two M0 (O1[0], O2[0], a[0], b[0]);

two M1 (O1[1], O2[1], a[1], b[1]);

endmodule

 

module two (s1, s2, a1, b1);

input a1;

input b1;

output s1, s2;

xor (s1, a1, b1);

and (s2, a1, b1);

endmodule

The statement: two M0 (O1[0], O2[0], a[0], b[0]); written in module one binds module two to module one. Accordingly, the relationship between O1, O2, a, and b is as follows:

O1[0] is the output of a two-input XOR gate with a[0] and b[0] as the inputs

O2[1] is the output of a two-input AND gate with a[1] and b[1] as the inputs

Other methods of binding are discussed in Chapters 6 and 8. The following examples cover binding and structural descriptions.

 EXAMPLE 4.2    STRUCTURAL DESCRIPTION OF A 2x1 MULTIPLEXER WITH ACTIVE LOW ENABLE

The truth table and logic diagram of this multiplexer have been covered in Chapter 2. The logic diagram is redrawn here for convenience (see Figure 4.2).

From Figure 4.2, the components of the multiplexer are: two three-input AND gates, three inverters, and one two-input OR gate. Each gate, including the inverter, is assumed to have a 7-ns propagation delay time.

For VHDL, the binding method shown in Listing 4.6 is used. The code to describe these gates is written, compiled, and then stored. Some other gates are included here that might be used for other examples. Listing 4.8 shows the code for several gates.

image

Figure 4.2  Multiplexer. a) Logic diagram. b) Logic symbol.

LISTING 4.8  VHDL Code for Several Gates

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity bind1 is

    port (I1 : in std_logic; O1 : out std_logic);

end bind1;

architecture inv_0 of bind1 is

begin

O1 <= not I1; --This is an inverter with zero delay

end inv_0;

 

architecture inv_7 of bind1 is

begin

O1 <= not I1 after 7 ns; --This is an inverter with a

                         -- 7-ns delay

end inv_7;

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity bind2 is

    port (I1, I2 : in std_logic; O1 : out std_logic);

end bind2;

 

architecture xor2_0 of bind2 is

begin

O1 <= I1 xor I2; --This is exclusive-or with zero

                 -- delay.

end xor2_0;

 

architecture and2_0 of bind2 is

begin

O1 <= I1 and I2; --This is a two input and gate with

                 -- zero delay.

end and2_0;

 

architecture and2_7 of bind2 is

begin

O1 <= I1 and I2 after 7 ns; -- This is a two input and

                            -- gate with 7-ns delay.

end and2_7;

 

architecture or2_0 of bind2 is

begin

O1 <= I1 or I2; -- This is a two input or gate with

                -- zero delay.

end or2_0;

 

architecture or2_7 of bind2 is

begin

O1 <= I1 or I2 after 7 ns; -- This is a two input or

                           -- gate with 7-ns delay.

end or2_7;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity bind3 is

port (I1, I2, I3 : in std_logic; O1 : out std_logic);

end bind3;

 

architecture and3_0 of bind3 is

begin

O1 <= I1 and I2 and I3; -- This is a three input and

                        -- gate with zero delay.

end and3_0;

 

architecture and3_7 of bind3 is

begin

O1 <= I1 and I2 and I3 after 7 ns; --This is a three

                  -- input and gate with 7-ns delay.

                  --

end and3_7;

 

architecture or3_0 of bind3 is

begin

O1 <= I1 or I2 or I3; --This is a three input OR gate

                      --with zero delay.

end or3_0;

 

architecture or3_7 of bind3 is

begin

O1 <= I1 or I2 or I3 after 7 ns; --This is a three

                     --input or gate with 7-ns delay.

end or3_7;

After compilation of the above code, it is stored in a known directory (path). Listing 4.9 shows the HDL code for a 2x1 multiplexer with active low enable. The Verilog description is straightforward using the predefined gates.

LISTING 4.9  HDL Description of a 2x1 Multiplexer with Active Low Enable: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity mux2x1 is

    port (A, B, SEL, Gbar : in std_logic;

        Y : out std_logic);

end mux2x1;

 

architecture mux_str of mux2x1 is

--Start components Declaration

component and3

port (I1, I2, I3 : in std_logic; O1 : out std_logic);

end component;

 

--Only different types of components need be declared.

--Since the multiplexer has two identical AND gates,

--only one is declared.

 

component or2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component Inv

port (I1 : in std_logic; O1 : out std_logic);

end component;

 

signal S1, S2, S3, S4, S5 : std_logic;

for all : and3 use entity work.bind3 (and3_7);

for all : Inv use entity work.bind1 (inv_7);

for Or1 : or2 use entity work.bind2 (or2_7);

begin

--Start instantiation

A1 : and3 port map (A,S2, S1, S4);

A2 : and3 port map (B,S3, S1, S5);

IV1 : Inv port map (SEL, S2);

IV2 : Inv port map (Gbar, S1);

IV3 : Inv port map (S2, S3);

or1 : or2 port map (S4, S5, Y);

end mux_str;

 

Verilog Description

module mux2x1 (A, B, SEL, Gbar, Y);

input A, B, SEL, Gbar;

output Y;

and #7 (S4, A, S2, S1);

or #7 (Y, S4, S5);

and #7 (S5, B, S3, S1);

not #7 (S2, SEL);

not #7 (S3, S2);

not #7 (S1, Gbar);

endmodule

Referring to Listing 4.9, because the multiplexer has two identical AND gates (both three-input AND gates), only one of them is declared in the VHDL description by the statements:

component and3

port (I1, I2, I3 : in std_logic; O1 : out std_logic);

end component;

Similarly, only one inverter is declared. If the two AND gates do not have the same delay time (say, A1 has 0 ns and A2 has 7 ns) then instead of all in the use statement, write:

for A1 : and3 use entity work.bind3 (and3_0);

for A2 : and3 use entity work.bind3 (and3_7);

For the Verilog description, the statement

and #7 (S4, A, S2, S1);

declares a three-input (A, s2, s1) AND gate with propagation delay of seven simulation screen units. Note that s2 or s1 do not need to be declared as wire; Verilog assumes that they are of the same type as A. If a four-input AND gate is needed, the code will be:

and (o1, in1, in2, in3, in4)

where O1 is the output, and in1, in2, in3, and in4 are the inputs. The gate in Verilog can have an optional name as:

or #7 orgate1 (O1, in1, in2)

The statement above describes an OR gate by the name orgate1; it has two inputs (in1, in2) and an output (O1). The name is optional and can be omitted. The simulation waveform of the multiplexer is identical to that of Figure 2.10.

 EXAMPLE 4.3    STRUCTURAL DESCRIPTION OF A 2x4 DECODER WITH TRI-STATE OUTPUT

A decoder is a combinational circuit. The output is a function of the input only. A 2x4 decoder has two inputs and four outputs. For any input only one output is active; all other outputs are inactive. For an active high output decoder, only one output is high. The output can be deactivated or put in high impedance if the decoder has an enable. For a tri-state output, if the enable is inactive, then all the outputs are in high impedance. The output of an n-bit input decoder is 2n bits. Table 4.1 shows the truth table of 2x4 decoder.

Table 4.1  Truth Table for a 2x4 Decoder with Tri-State Outputs

image

Tri-state buffers are used at the output. If the enable is low, then all outputs are in high impedance (Z). From Table 4.1, we can write the Boolean function of the outputs:

image

Figure 4.3 shows the logic diagram of the decoder.

image

Figure 4.3  Logic diagram of a 2x4 decoder with tri-state output.

To write the VHDL code, we first need to write a description of the tri-state buffer gate. The easiest description type that can be written for the tri-state buffer is behavioral, using the if statement. This description is attached to the entity bind2 (see Listing 4.8). Listing 4.10 shows a behavioral description of a tri-state buffer. The Verilog has built-in buffers (see Figure 4.4).

image

Figure 4.4  Verilog built-in buffers.

LISTING 4.10  VHDL Behavioral Description of a Tri-State Buffer

entity bind2 is

port (I1, I2 : in std_logic; O1 : out std_logic);

end bind2;

...........

--Add the following architecture to

--the entity bind2 of Listing 4.8

architecture bufif1 of bind2 is

begin

buf : process (I1, I2)

variable tem : std_logic;

begin

if (I2 =’1’) then

tem := I1;

else

tem := ‘Z’;

end if;

O1 <= tem;

end process buf;

end bufif1;

Now, write the HDL structural description of the decoder as shown in Listing 4.11. Figure 4.5 shows the simulation waveform of the decoder.

LISTING 4.11  HDL Description of a 2x4 Decoder with Tri-State Output

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity decoder2x4 is

    port (I : in std_logic_vector(1 downto 0);

          Enable : in std_logic;

          D : out std_logic_vector (3 downto 0));

end decoder2x4;

 

architecture decoder of decoder2x4 is

component bufif1

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : out std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

for all : bufif1 use entity work.bind2 (bufif1);

for all : inv use entity work.bind1 (inv_0);

for all : and2 use entity work.bind2 (and2_0);

signal s0, s1, s2, s3 : std_logic;

signal Ibar : std_logic_vector (1 downto 0);

-- The above signals have to be declared before they

-- can be used

begin

    B0 : bufif1 port map (s0, Enable, D(0));

    B1 : bufif1 port map (s1, Enable, D(1));

    B2 : bufif1 port map (s2, Enable, D(2));

    B3 : bufif1 port map (s3, Enable, D(3));

    iv0 : inv port map (I(0), Ibar(0));

    iv1 : inv port map (I(1), Ibar(1));

    a0 : and2 port map (Ibar(0), Ibar(1), s0);

    a1 : and2 port map (I(0), Ibar(1), s1);

    a2 : and2 port map (Ibar(0), I(1), s2);

    a3 : and2 port map (I(0), I(1), s3);

end decoder;

 

Verilog Description

module decoder2x4 (I, Enable, D);

input [1:0] I;

input Enable;

output [3:0] D;

wire [1:0] Ibar;

    bufif1 (D[0], s0, Enable);

    bufif1 (D[1], s1, Enable);

    bufif1 (D[2], s2, Enable);

    bufif1 (D[3], s3, Enable);

    not (Ibar[0], I[0]);

    not (Ibar[1], I[1]);

    and (s0, Ibar[0], Ibar[1]);

    and (s1, I[0], Ibar[1]);

    and (s2, Ibar[0], I[1]);

    and (s3, I[0], I[1]);

endmodule

image

Figure 4.5  Simulation waveform of a 2x1 decoder with tri-state output.

 EXAMPLE 4.4   STRUCTURAL DESCRIPTION OF A FULL ADDER

In this example, a full adder (Listing 4.13) is built from two half adders (Listing 4.12). The full adder adds (a + b + cin) to generate sum and carry. A half adder is used to add (a + b) to generate sum1 and carry1. Another half adder is used to add (sum1 + cin) to generate sum and carry2. The carry of the summation (a + b + cin) is the logical OR of carry1 and carry2. Figures 4.6a and 4.6b show the logical symbol and diagram of this full adder, respectively.

For the VHDL code, write the code for half adder. Then, include this code in Listing 4.8. Listing 4.12 shows the code of the half adder as part of Listing 4.8. Now, write the structural description of the full adder as two half adders. Listing 4.13 shows the HDL code for a full adder.

image

Figure 4.6  Full adder as two half adders. a) Logic symbol. b) Logic diagram.

LISTING 4.12  VHDL Description

--This code is to be appended to Listing 4.8

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind22 is

    Port (I1, I2 : in std_logic;

           O1, O2 : out std_logic);

end bind22;

 

architecture HA of bind22 is

component xor2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

 

for A1 : and2 use entity work.bind2 (and2_0);

for X1 : xor2 use entity work.bind2 (xor2_0);

begin

    X1 : xor2 port map (I1, I2, O1);

    A1 : and2 port map (I1, I2, O2);

end HA;

LISTING 4.13  HDL Description of a Full Adder (Figures 4.6a and 4.6b)

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity FULL_ADDER is

    Port (x, y, cin : in std_logic;

          sum, carry : out std_logic);

end FULL_ADDER;

architecture full_add of FULL_ADDER is

component HA

Port (I1, I2 : in std_logic; O1, O2 : out std_logic);

end component;

component or2

Port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

 

for all : HA use entity work.bind22 (HA);

for all : or2 use entity work.bind2 (or2_0);

signal s0, c0, c1 : std_logic;

 

begin

    HA1 : HA port map (y, cin, s0, c0);

    HA2 : HA port map (x, s0, sum, c1);

    r1 : or2 port map (c0, c1, carry);

end full_add;

 

Verilog Description

module FULL_ADDER (x, y, cin, sum, carry);

input x, y, cin;

output sum, carry;

HA H1 (y, cin, s0, c0);

HA H2 (x, s0, sum, c1);

//The above two statements bind module HA

//to the present module FULL_ADDER

    or (carry, c0, c1);

endmodule

module HA (a, b, s, c);

input a, b;

output s, c;

xor (s, a, b);

and (c, a, b);

endmodule

To use the above VHDL code in future examples, it is added to entity bind32 in Listing 4.31.

 EXAMPLE 4.5    STRUCTURAL DESCRIPTION OF A THREE-BIT RIPPLE-CARRY ADDER

In this example, a three-bit ripple-carry adder is described. Then, in Example 4.7, this adder is implemented to build a magnitude comparator. The logic diagram of the adder is as shown in Figure 2.23 of Chapter 2. Listing 4.14 shows the structural description of the three-bit ripple-carry adder.

LISTING 4.14  HDL Description of a Three-Bit Ripple-Carry Adder: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity three_bit_adder is

    port(x, y : in std_logic_vector (2 downto 0);

          cin : in std_logic;

          sum : out std_logic_vector (2 downto 0);

          cout : out std_logic);

end three_bit_adder;

 

architecture three_bitadd of three_bit_adder is

component FULL_ADDER

port (I1, I2, I3 : in std_logic;

    O1, O2 : out std_logic);

end component;

for all : FULL_ADDER

          use entity work.bind32 (full_add);

signal carry : std_logic_vector (1 downto 0);

begin

M0 : FULL_ADDER port map (x(0), y(0), cin, sum(0), carry(0));

M1 : FULL_ADDER port map (x(1), y(1), carry(0), sum(1),

                          carry(1));

M2 : FULL_ADDER port map (x(2), y(2), carry(1), sum(2), cout);

end three_bitadd;

 

Verilog Description

module three_bit_adder (x, y, cin, sum, cout);

input [2:0] x, y;

input cin;

output [2:0] sum;

output cout;

wire [1:0] carry;

FULL_ADDER M0 (x[0], y[0], cin, sum[0], carry[0]);

FULL_ADDER M1 (x[1], y[1], carry[0], sum[1], carry[1]);

FULL_ADDER M2 (x[2], y[2], carry[1], sum[2], cout);

/* It is assumed that the module FULL_ADDER

(Listing 4.13) is attached by the simulator to

the module three_bit_adder so, no need to

rewrite the module FULL_ADDER.*/

endmodule

Inspection of the code in Listing 4.14 shows that there may be lag time between the steady state of each of the adders and the carryout (cout). This lag time produces transient states before the values of the sum and carryout settle. For example, if the inputs to the adder are 101 and 001, and the previous output of the adder is 1001, some transient states can be 0100 and 1010 before the output settles at 0110. The appearance of these transient states is called hazards. These transient states, however, have short duration and may not be noticed.

 EXAMPLE 4.6    STRUCTURAL DESCRIPTION OF A THREE-BIT TWO-STAGE CARRY-SAVE ADDER

The ripple-carry adder in Example 4.5 has a delay that is proportional to the number of bits added. This is because each full adder has to wait for the generation of the carry out of the preceeding full adder to start adding its input bits to this carry out. If each full adder can add its inputs independently from other full adders, the addition will be proportional to just a delay of a single adder because all full adders would be capable of adding their inputs simultanously. Carry-save adders utilize the concept of independent addition; several of the full adders in the carry-save system, but not all, can add their inputs simultanously. Figure 4.7 shows the logic diagram of a three-bit four-word carry-save adder. The adder adds four words (a + b + c + d) where each word is three bits. FA1, FA2, and FA3 add a + b + c and generate sum and partial (not final) carryout at the same time. The same is true for FA4, FA5, and FA6; however, these three adders have to wait on the upper-stage adders (FA1, FA2, and FA3) to complete their addition and generate their carryouts (cr0 and cr1). The adders FA7, FA8, and FA9 are connected as ripple-carry adders; each adder of this stage has to wait for carryout from upper-stage and preceeding full adders. These riple-carry adders can be replaced by lookahead adders to decrease the delay associated with them. If each full adder has a delay of d ns, then the first stage takes 1d to finish its task, the second stage takes 1d to finsh its task, and the last stage takes 3d to finsh its task. The total delay to add four three-bit words is (1 + 1 + 3)d = 5d ns, which is faster than using ripple-carry adders.

image

Figure 4.7  Two-stage carry-save adder.

Listing 4.15 shows the Verilog code for the adder of Figure 4.7. The Listing contains a main module carry_saveadder and another module full_adder. The module full_adder is bound to the main module by a statement such as:

full_adder FA1(a1[0],b1[0],c1[0], sm0,cr0);

where a, b, and c in the full_adder module is linked (replaced) by a1[0], b1[0], and c1[0]. The result of addition sum and carryout is linked (uploaded) to sm0 and cr0, respectively.

LISTING 4.15  Verilog Description of Carry-Save Adder (Figure 4.7)

module carry_saveadder(a1,b1,c1,d1,sum_total,final_carryout);

input[2:0] a1, b1,c1,d1;

output [3:0]sum_total;

output final_carryout;

 

full_adder FA1(a1[0],b1[0],c1[0], sm0,cr0);

//FA1 is a user-selected label

full_adder FA2(a1[1],b1[1],c1[1], sm1,cr1);

full_adder FA3(a1[2],b1[2],c1[2], sm2,cr2);

 

full_adder FA4(sm0,d1[0],1’b0, smm0,crr0);

full_adder FA5(sm1,d1[1],cr0, smm1,crr1);

full_adder FA6(sm2,d1[2],cr1, smm2,crr2);

assign sum_total[0] =smm0;

 

full_adder FA7(crr0,smm1,1’b0, sum_total[1],crrr0);

full_adder FA8(crr1,smm2,crrr0, sum_total[2],crrr1);

full_adder FA9(crr2,crrr1,cr2, sum_total[3],cc);

assign final_carryout = cc;

 

endmodule

module full_adder (a,b,c,Sum,Carryout);

input a,b,c;

output Sum, Carryout;

not (a_bar,a); // this is an inverter

not (b_bar,b);

not (c_bar,c);

and a1 (s0,a_bar,b_bar, c);/*This is And gate with

                           optional name a1*/

and a2 (s1,a_bar,b, c_bar);

and a3 (s2,a,b_bar, c_bar);

and a4 (s3,a,b,c);

or o1(Sum, s0,s1,s2,s3);

and a5 ( s5,a,b);

and a6 ( s6,a,c);

and a7 ( s7,b,c);

or o2( Carryout,s5,s6,s7);

endmodule

 EXAMPLE 4.7    STRUCTURAL DESCRIPTION OF A THREE-BIT MAGNITUDE COMPARATOR USING A THREE-BIT ADDER

Chapter 2 covered a 2x2-bit comparator using truth tables. If the number of bits to be compared is more than two bits, the truth tables become so huge that is too difficult to handle. In this example, a different approach is taken. Consider two numbers X and Y, each of n bits; if X is greater than Y, then:

image

–Y is the twos complement of image; substituting in Equation 4.2, the condition of X > Y is rewritten as:

image

Or, Equation 4.3 can be rewritten as:

image

For n bits, –1 is a string of n bits; each bit is 1. If n = 5, for example −1d= (11111)2, so Equation 4.4 can be rewritten as:

image

Equation 4.5 states that if X is greater than Y, the sum of X and image should be greater than 1...1111. If n adders are used to add X plus image, then for X to be greater than Y, the n-bit sum should be greater than n ones. This can only happen if the n-bit adders have a final carryout of 1. So, if X is added to image using n-bit adders, and the final carryout is 1, then it can be concluded that X > Y. If there is no final carryout, then X ≤ Y. To check for equality, it is noticed that if X = Y then:

image

In this example, n = 3 is being considered. Figure 4.8 shows the logic diagram of the comparator.

image

Figure 4.8  A full-adder-based comparator.

Listing 4.16 shows the HDL code for the comparator. The HDL code for a full adder has already been written (see Listing 4.13). The full-adder components (macros) are used in Listing 4.16. Because they are identical, only one generic full adder is declared as:

component full_adder

port(I1, I2, I3 : in std_logic;

      O1, O2 : out std_logic);

end component;

To use these components, link their work library from Listing 4.13 as:

for all : full_adder use entity work.bind32 (full_add); --VHDL

or, in Verilog, link the module built in Listing 4.13 as:

FULL_ADDER M0 (X[0], Yb[0], 1’b0, sum[0], carry[0]); //Verilog

LISTING 4.16  HDL Description of a Three-Bit Comparator Using Adders

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity three_bit_cmpare is

port (X, Y : in std_logic_vector (2 downto 0);

    xgty, xlty, xeqy : buffer std_logic);

end three_bit_cmpare;

 

architecture cmpare of three_bit_cmpare is

 

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

 

component full_adder

port (I1, I2, I3 : in std_logic;

      O1, O2 : out std_logic);

end component;

component Inv

port (I1 : in std_logic; O1 : out std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

component and3

port (I1, I2, I3 : in std_logic; O1 : out std_logic);

end component;

for all : full_adder use entity work.bind32 (full_add);

for all : Inv use entity work.bind1 (inv_0);

for all : nor2 use entity work.bind2 (nor2_0);

for all : and3 use entity work.bind3 (and3_7);

--To reduce hazards, an AND gate is

--implemented with a 7-ns delay.

signal sum, Yb : std_logic_vector (2 downto 0);

signal carry : std_logic_vector (1 downto 0);

begin

    in1 : inv port map (Y(0), Yb(0));

    in2 : inv port map (Y(1), Yb(1));

    in3 : inv port map (Y(2), Yb(2));

    F0 : full_adder port map (X(0), Yb(0),

                              ‘0’, sum(0), carry(0));

    F1 : full_adder port map (X(1), Yb(1), carry(0),

                        sum(1), carry(1));

    F2 : full_adder port map (X(2), Yb(2), carry(1),

                           sum(2), xgty);

    a1 : and3 port map (sum(0), sum(1), sum(2), xeqy);

    n1 : nor2 port map (xeqy, xgty, xlty);

end cmpare;

 

Verilog Description

module three_bit_cmpare (X, Y, xgty, xlty, xeqy);

input [2:0] X, Y;

output xgty, xlty, xeqy;

wire [1:0] carry;

wire [2:0] sum, Yb;

    not (Yb[0], Y[0]);

    not (Yb[1], Y[1]);

    not (Yb[2], Y[2]);

    FULL_ADDER M0 (X[0], Yb[0], 1’b0, sum[0],

                     carry[0]);

FULL_ADDER M1 (X[1], Yb[1], carry[0], sum[1],

                     carry[1]);

FULL_ADDER M2 (X[2], Yb[2], carry[1], sum[2],

                     xgty);

and #7 (xeqy, sum[0], sum[1], sum[2]);   

/* To reduce hazard use an AND gate with a delay of 7 units*/

nor (xlty, xeqy, xgty);

endmodule

 EXAMPLE 4.8   STRUCTURAL DESCRIPTION OF AN SET-RESET LATCH

A set-reset (SR) latch is a sequential circuit. The output and the next state depends on the input(s) and the current state. It memorizes, as is the case for sequential circuits, one of its states when S = R = 0. Memorization is achieved through feedback between the output Q, its complement, and the inputs. The inputs receive the values of the current output through the feedback lines. The state where S = R = 1 is prohibited because it may lead to unstable output (both Q and acquire the same logic level). The latch is implemented in digital systems as a switch or memory cell for static random-access memory (SRAM). The excitation table of the latch is shown in Table 4.2.

TABLE 4.2  Excitation Table of an SR-Latch

image

Figures 4.9a and 4.9b show the logic symbol and diagram, respectively, of an SR-latch using NOR gates. Notice the connection (feedback) between the output Q and the input of the NOR gate in Figure 4.9b. Listing 4.17 shows the HDL structural description of an SR-latch based on NOR gates.

image

Figure 4.9  SR-Latch. a) Logic symbol. b) Logic diagram.

LISTING 4.17  HDL Description of an SR-Latch with NOR Gates

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity SR_latch is

    port (R, S : in std_logic;

        Q, Qbar : buffer std_logic);

--Q, Qbar are declared buffer because

--they behave as input and output.

 

end SR_latch;

 

architecture SR_strc of SR_latch is

--Some simulators would not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

component nor2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

for all : nor2 use entity work.bind2 (nor2_0);

begin

    n1 : nor2 port map (S, Q, Qbar);

    n2 : nor2 port map (R, Qbar, Q);

end SR_strc;

 

Verilog Description

module SR_Latch (R, S, Q, Qbar);

input R, S;

output Q, Qbar;

nor (Qbar, S,Q);

nor (Q, R, Qbar);

endmodule

To use the above code in future VHDL examples, it is appended to Listing 4.31. Figure 4.10 shows the simulation waveform of the SR-latch.

image

Figure 4.10  Simulation waveform of an SR-latch.

 EXAMPLE 4.9    STRUCTURAL DESCRIPTION OF A D-LATCH WITH ACTIVE LOW CLEAR

A D-latch is a sequential circuit. The output of the latch (Q) follows the input (D) as long as the enable (E) is high. image is the complement of Q. The clear signal is chosen here to be asynchronous active low, which means if the clear signal is low, the output is cleared (Q = 0) momentarily. The latch has been discussed in Chapter 2. The logic symbol and diagram are as shown in Figure 4.11. Listing 4.18 shows the HDL structural description of a D-latch.

image

Figure 4.11   D-Latch with clear. a) Logic symbol. b) Logic diagram.

LISTING 4.18  HDL Description of a D-Latch with Active Low Clear

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity D_LatchWclr is

    port (D, E,clrbar : in std_logic;

            Q, Qbar : buffer std_logic);

end;

architecture D_latch_str of D_LatchWclr is

 

--be sure to use buffer rather than output in all

-- components; some simulators will not map output

--to buffer.

 

component and3

port (I1, I2, I3 : in std_logic;

      O1 : buffer std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

for all : and3 use entity work.bind3 (and3_4);

for all : nor2 use entity work.bind2 (nor2_4);

for all : inv use entity work.bind1 (inv_1);

signal Eb, s1, s2 : std_logic;

begin

    a1 : and3 port map (D, E, clrbar, s1);

    a2 : and3 port map (Eb, D,clrbar, s2);

    in1 : inv port map (E, Eb);

    in2 : inv port map (Qbar, Q);

    n2 : nor2 port map (s1, s2, Qbar);

end D_latch_str;

To use the above code in future examples, it is appended to Listing 4.31.

Verilog Description

module D_latchWclr(D, E,clrbar, Q, Qbar);

input D, E, clrbar;

output Q, Qbar;

/* assume 4 ns delay for and gate and nor gate,

and 1 ns for inverter */

//The clear is active low; if clrbar = 0, Q=0

 

and #4 gate1 (s1, D, E, clrbar);

 

/* the name “gate1” is optional; we could have

   written and #4 (s1, D, E) */

    and #4 gate2 (s2, Eb, Q, clrbar);

    not #1 (Eb, E);

    nor #4 (Qbar, s1, s2);

    not #1 (Q, Qbar);

endmodule

The simulation waveform is the same as in Figure 2.19 except for the addition of signal clrbar; if the clrbar signal is low, Q should go low.

 EXAMPLE 4.10      STRUCTURAL DESCRIPTION OF A PULSE-TRIGGERED, MASTER-SLAVE D FLIP-FLOP WITH ACTIVE LOW CLEAR

The D-latch discussed in Listing 4.18 has a characteristic that may not be desirable in digital circuits such as counters. The D-latch output follows its input as long as the enable is high. In counters, for example, the output is desired to change only once during the active phase of the clock. To achieve this, flip-flops are needed. A master-slave D flip-flop is a sequential circuit where the output follows the input only once at the transition of the clock from inactive to active. Figure 4.12 shows the logic symbol of the master-slave D flip-flop. Table 4.3 shows the excitation table of the flip-flop.

Table 4.3  Excitation Table for the Master-Slave D Flip-Flop

image

The logic diagram of the master-slave flip-flop is shown in Figure 4.12. The flip-flop consists of two active high enable D-latches; the first latch is called the master, and the second is called the slave. The master latch drives the slave. The clock of the master is the invert of the clock of the slave. Because the clock of one of the latches is the invert of the other, at any time one latch will be active while the other is inactive. At the high level of the clock, the slave is active; its output Q follows its input QM (QM is the output of the master). Because the master is inactive at the high level of the clock, any change in D (the input of the slave) is not transmitted to QM, so QM and Q stay the same during the high level of the clock, unaffected by any change in D. Thus, the flip-flop is sensitive to the clock pulse rather than the level, as in a D-latch.

image

Figure 4.12  Logic diagram of a master-slave D flip-flop with active low clear.

Listing 4.19 shows the HDL code of the master-slave D flip-flop. In the VHDL code, there is already code for the D_latchWclrbar (see Listing 4.18); this code is attached to the flip-flop code by the statement

for all : D_latchWclrbar use entity work.

            bind32(D_latch_Wclr);

which links the architecture D_latch_Wclr to the current module. In Verilog, we link the module D_latchWclr to the module D_FFMasterWclr by the statement

D_latchWclr D0 (D, clkb,clrbar, Q0, Qb0);

Note that the order of the linked parameters (D, clkb, clrbar, Q0, and Qb0) to match D, E, clrbar, Q, and Qbar of the D_latchWclr module, respectively, for proper mapping.

LISTING 4.19  HDL Description of a Master-Slave D Flip-Flop with Active Low Clear

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity D_FFMasterWclr is

    Port (D, clk, clrbar : in std_logic;

           Q, Qbar : buffer std_logic);

end D_FFMasterWclr ;

 

architecture D_FF_str of D_FFMasterWclr is

 

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component D_latchWclrbar

port (I1, I2, I3 : in std_logic;

       O1, O2 : buffer std_logic);

end component;

for all : D_latchWclrbar use

    entity work. bind32(D_latch_Wclr);

for all : inv use entity work.bind1 (inv_1);

signal clkb, clk2, Q0, Qb0 : std_logic;

begin

    D0 : D_latchWclrbar port map (D, clkb,clrbar, Q0, Qb0);

    D1 : D_latchWclrbar port map (Q0, clk2, clrbar, Q, Qbar);

    in1 : inv port map (clk, clkb);

    in2 : inv port map (clkb, clk2);

end D_FF_str;

 

Verilog Description

module D_FFMasterWclr(D, clk,clrbar, Q, Qbar);

input D, clk, clrbar;

output Q, Qbar;

not #1 (clkb, clk);

not #1 (clk2, clkb);

D_latchWclr D0 (D, clkb,clrbar, Q0, Qb0);

D_latchWclr D1 (Q0, clk2,clrbar, Q, Qbar);

endmodule

To use the above VHDL code in future examples, it is appended to entity bind32 in Listing 4.31.

Figure 4.13 shows the simulation waveform of the master-slave D flip-flop. It is clear from the figure that signal D is sampled only at the transition of the clock from low to high. If D changes during the high level (or the low level) of the clock, the output Q remains the same; it does not respond to this change. Compare Figure 4.13 with Figure 2.19 and notice the difference between a latch and a flip-flop. During the high level of the clock (called enable in the latch), Q follows D for the latch. In the flip-flop, Q follows D only at the clock transitions from low to high.

image

Figure 4.13  Simulation waveform of a master-slave D flip-flop.

 EXAMPLE 4.11      STRUCTURAL DESCRIPTION OF A PULSE-TRIGGERED MASTER-SLAVE JK FLIP-FLOP WITH ACTIVE LOW CLEAR

A JK flip-flop can be viewed as an extension of the SR-latch. The flip-flop has all the allowed states of the SR. The prohibited state in the SR-latch is replaced by a toggle state where the output of the flip-flop is complemented every time J = K = 1. Table 4.4 shows the excitation table of a pulse-triggered JK flip-flop. Another type of flip-flop is the T flip-flop, where a JK flip-flop with terminal J is connected to terminal K to form terminal T, is shown in Figure 4.14.

image

Figure 4.14  Logic diagram of a T flip-flop.

Table 4.4  Excitation Table for a Pulse-Triggered JK Flip-Flop

image

The Boolean function of a JK flip-flop can be derived from a D flip-flop. Table 4.5 shows the J and K values and the corresponding D values. The D values are obtained by finding the value of D that can produce the transition from Q to Q+. For example, if Q = 0, and Q+ is 1, then D should be 1. In fact, the value of D will be equal to Q+ for all transitions.

Table 4.5  Relationship Between JK Flip-Flop and D Flip-Flop

image

To find the Boolean function of D, form K-maps as shown in Figure 4.15.

image

Figure 4.15  K-maps of Table 4.5.

From Figure 4.15, the Boolean functions are:

image

Equation 4.7 is used to build a master-slave JK flip-flop from a master-slave D flip-flop. Figure 4.16 shows a master-slave JK flip-flop generated from a master-slave D flip-flop.

image

Figure 4.16  Pulse-triggered master-slave JK flip-flop.

Listing 4.20 shows the HDL code for the master-slave JK flip-flop illustrated in Figure 4.16.

LISTING 4.20  HDL Description of a Master-Slave JK Flip-Flop: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity JK_FLFL is

    port (J, K, clk, clrbar : in std_logic;

          Q, Qbar : buffer std_logic);

 

-- Q and Qbar are declared buffer so they can be input

-- or output

 

end JK_FLFL;

 

architecture JK_Master of JK_FLFL is

 

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component or2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component D_FFMasterWclr

port (D, clk, clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end component;

for all : and2 use entity work.bind2 (and2_4);

for all : or2 use entity work.bind2 (or2_4);

for all : inv use entity work.bind1 (inv_1);

for all : D_FFMasterWclr use

          entity work. D_FFMasterWclr (D_FF_str);

signal s1, s2, Kb, DD : std_logic;

begin

    a1 : and2 port map (J, Qbar, s1);

    a2 : and2 port map (Kb, Q, s2);

    in1 : inv port map (K, Kb);

    or1 : or2 port map (s1, s2, DD);

    DFF : D_FFMasterWclr port map (DD, clk,clrbar, Q, Qbar);

end JK_Master;

 

Verilog Description

module JK_FF (J, K, clk,clrbar, Q, Qbar);

input J, K, clk, clrbar;

output Q, Qbar;

wire s1, s2;

    and #4 (s1, J, Qbar);

    and #4 (s2, Kb, Q);

    not #1 (Kb, K);

    or #4 (DD, s1, s2);

D_FFMasterWclr D0 (DD, clk,clrbar, Q, Qbar);

endmodule

module D_FFMasterWclr(D, clk,clrbar, Q, Qbar);

 

/* no need to rewrite this module here if it has

been already attached to the above module (JK_FF). */

 

input D, clk, clrbar;

output Q, Qbar;

 

    not #1 (clkb, clk);

    not #1 (clk2, clkb);

    D_latchWclr D0 (D, clkb,clrbar, Q0, Qb0);

    D_latchWclr D1 (Q0, clk2,clrbar, Q, Qbar);

 

endmodule

 

module D_latchWclr(D, E,clrbar, Q, Qbar);

/* no need to rewrite this module here if it has

been already attached to the above module (JK_FF). */

 

input D, E, clrbar;

output Q, Qbar;

/* assume 4 ns delay for and gate and nor gate,

and 1 ns for inverter */

//The clear is active low; if clrbar = 0, Q=0

 

and #4 gate1 (s1, D, E, clrbar);

 

/* the name “gate1” is optional; we could have

    written and #4 (s1, D, E) */

    and #4 gate2 (s2, Eb, Q, clrbar);

    not #1 (Eb, E);

    nor #4 (Qbar, s1, s2);

    not #1 (Q, Qbar);

endmodule

Notice here that the VHDL code in Listing 4.20 is getting shorter (the VHDL code is not shorter but getting shorter) compared to the Verilog code. This is due to the fact that VHDL user-built components are being linked, such as and2, or2, and inv. Their codes do not need to be rewritten because they are linked to the current module.

 EXAMPLE 4.12   STRUCTURAL DESCRIPTION OF AN SRAM CELL

A simple memory cell has been designed using an SR-latch; Figure 4.17a shows the symbol diagram of the cell. The cell has tri-state output. If the select line (Sel) is low, the output of the cell is in high impedance. A read/write (R/W) input signal controls the cell’s cycle type. If R/W is high, the cell is in read cycle; if it is low, the cell is in write cycle. Table 4.6 shows the excitation table of the cell with inputs (select, R/W, data in, current state) and the corresponding outputs (next state, output). From the current state and next state, S and R of the latch are determined according to Table 4.2. For example, if the current state is 0 and next state 0, then two combinations of SR can generate this transition: S = 0, R = 0, and S = 0, R = 1, so SR = 0x when x is “don’t care.”

image

Figure 4.17  SRAM memory cell. a) Logic symbol. b) Logic diagram.

Table 4.6  Excitation Table of an SRAM Memory Cell

image

Figure 4.18  K-maps for Table 4.6.

From the K-maps:

image

The logic diagram of the cell is shown in Figure 4.17b.

The code for the memory cell is shown in Listing 4.21. The VHDL code uses the SR-latch that was designed in Listing 4.17 as a component (macro), using the statement

component SR_Latch

port (I1, I2 : in std_logic;

O1, O2 : buffer std_logic);

end component;

 

which declares a generic SR-latch. This latch is linked to the memory-cell code by the    statement

 

for all : SR_Latch use entity work.bind22 (SR_Latch);

The VHDL statement

SR1 : SR_Latch port map (R, S, Q, open);

assigns R and S as the inputs of the SR-latch SR1. The noninverted output of the latch is assigned to Q, and the inverted output is left open; open is a VHDL predefined word. For Verilog, link the module of the SR-latch that has been designed in Listing 4.17 to the memory cell code by the statement:

SR_Latch RS1 (R, S, Q, Qbar);

which links the module SR_Latch to the current module memory.

LISTING 4.21  HDL Description of an SRAM Memory Cell: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity memory is

    port (Sel, RW, Din : in std_logic;

           O1: buffer std_logic );

 

end memory;

 

architecture memory_str of memory is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

 

component and3

port (I1, I2, I3 : in std_logic; O1 : out std_logic);

end component;

 

component inv

port (I1 : in std_logic; O1 : out std_logic);

end component;

 

component or2

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

 

component bufif1

port (I1, I2 : in std_logic; O1 : out std_logic);

end component;

 

component SR_Latch

port (I1, I2 : in std_logic;

    O1, O2 : buffer std_logic);

end component;

for all : and3 use entity work.bind3 (and3_0);

for all : inv use entity work.bind1 (inv_0);

for all : or2 use entity work.bind2 (or2_0);

for all : bufif1 use entity work.bind2 (bufif1);

for all : SR_Latch use entity work.bind22 (SR_Latch);

signal RWb, Dinb, S, S1, R, O11, Q : std_logic;

begin

    in1 : inv port map (RW, RWb);

    in2 : inv port map (Din, Dinb);

    a1 : and3 port map (Sel, RWb, Din, S);

    a2 : and3 port map (Sel, RWb, Dinb, R);

    SR1 : SR_Latch port map (S, R, Q, open);

--open is a predefined word;

--it indicates that the port is left open.

    a3 : and3 port map (Sel, RW, Q, S1);

    or1 : or2 port map (S1, S, O11);

    buf1 : bufif1 port map (O11, Sel, O1);

end memory_str;

Verilog Description

module memory (Sel, RW, Din, O1);

input Sel, RW, Din;

output O1;

    not (RWb, RW);

    not (Dinb, Din);

    and (S, Sel, RWb, Din);

    and (R, Sel, RWb, Dinb);

    SR_Latch RS1 (R, S, Q, Qbar);

    and (S1, Sel, RW, Q);

    or (O11, S1, S);

    bufif1 (O1, O11, Sel);

endmodule

 EXAMPLE 4.13      STRUCTURAL DESCRIPTION OF A THREE-BIT UNIVERSAL SHIFT REGISTER

Figure 4.19 shows the symbol and logic diagram of a three-bit universal shift register. The register can be loaded externally from a three-bit data P on the positive edge of the clock. The data stored in the register can be right shifted with one-bit DSR replacing the most significant bit of Q every shift. The data stored in the register can also be left shifted with one-bit DSL replacing the least significant bit of Q every shift. The truth table of the register is shown in Table 4.7. Listing 4.22 shows the Verilog code for the shift register. To test the shift function of the register, load external data (P) using the load function and then shift left or right.

Table 4.7  Truth Table for the Shift Register

image

image

Figure 4.19  Universal shift register with clear. a) Symbol diagram. b) Logic diagram.

LISTING 4.22  Verilog Description of a Three-Bit Universal Shift Register

module shft_regsterUniv(clk, clrbar,

s0,s1,P,DSR,DSL,Q,Qb);

input clk, clrbar,s0,s1,DSR,DSL;

output [2:0] Q,Qb,P;

not (s0bar, s0);

not (s0t,s0bar);

not (s1bar, s1);

not (s1t, s1bar);

 

and #4 a0(aa0, DSR, s1bar,s0t);

and #4 a1(aa1, s0t, s1t,P[2]);

and #4 a2(aa2, s0bar, s1t,Q[1]);

and #4 a3(aa3, s0bar, s1bar,Q[2]);

or #4 or2 (D2,aa0,aa1,aa2,aa3);

D_FFMasterWclr DFM0(D2,clk,clrbar,Q[2],Qb[2]);

 

and #4 a4(aa4, Q[2], s1bar,s0t);

and #4 a5(aa5, s0t, s1t,P[1]);

and #4 a6(aa6, s0bar, s1t,Q[0]);

and #4 a7(aa7, s0bar, s1bar,Q[1]);

or #4 or1 (D1,aa4,aa5,aa6,aa7);

D_FFMasterWclr DFM1(D1,clk, clrbar,Q[1],Qb[1]);

 

and #4 a8(aa8, Q[1], s1bar,s0t);

and #4 a9(aa9, s0t, s1t,P[0]);

and #4 a10(aa10, s0bar, s1t,DSL);

and #4 a11(aa11, s0bar, s1bar,Q[0]);

or #4 or0 (D0,aa8,aa9,aa10,aa11);

D_FFMasterWclr DFM2(D0,clk,clrbar,Q[0], Qb[0]);

endmodule

4.4  State Machines

 

Synchronous sequential circuits are called state machines. The main components of the state machine are latches and flip-flops; additional combinational components may also be present. Synchronous clock pulses are fed to all flip-flops and latches of the machine. There are two types of synchronous sequential circuits: Mealy and Moore circuits. The output or next state of Mealy circuits depends on the inputs and the present (current) state of the flip-flops/latches. The output or next state of the Moore circuit depends only on the present states. The present state and next state for a particular flip-flop are the same pin (output Q). The current state is the value of Q just before the present clock pulse or edge; the next state is the value of Q after the clock pulse or the edge. To build a state machine, the following steps are performed:

  1. Determine the number of states. If the system is n-bit, then the number of flip-flops is n, and the number of states is 2n. The number of flip-flops here is calculated according to the classical method, where the number of flip-flops is the minimum possible. Another method in which each state is represented by one flip-flop is frequently used when the number of bits is getting too large to handle by the classical method. For example, if the system is three bits, then the classical method requires three flip-flops, while the one flip-flop per state method requires eight flip-flops. In this chapter, the classical method is implemented.
  2. Construct a state diagram that shows the transition between states. At each state, consider it as the current state; after the clock is active (edge or pulse), the system moves from current state to next state. Determine the next state according to the input if the system is Mealy or according to the current state only if the system is Moore. Also, determine the output (if any) of the system at this current state.
  3. From the state diagram, construct the excitation table that tabulates the inputs and the outputs. The inputs always include the current states, and the outputs always include the next states. The table also includes the inputs of the flip-flops or latches that constitute the state machine. For example, if the flip-flops implemented in a certain machine are JK flip-flops, then the inputs J and K of the flip-flop are determined according to the transition from current to next state. If, for example, the current state is 0 and the next is 0, then J = 0 and K = x (don’t care). If the flip-flops are D flip-flops, then the Ds of the flip-flops are the same as the corresponding next states.
  4. Find J and K in terms of the inputs and minimize using K-maps or any other appropriate method.
  5. If using structural description to simulate the system, draw a logic diagram of the system using appropriate available macros such as latches, adders, and flip-flops.

The following examples are state machines. More examples of state machines and counters will be discussed in Chapters 6 and 7.

 EXAMPLE 4.14      STRUCTURAL DESCRIPTION OF A THREE-BIT SYNCHRONOUS COUNTER WITH ACTIVE LOW CLEAR

A synchronous counter can be viewed as a simple finite state machine. The logic symbol of the counter is shown in Figure 4.20. The counter is constructed from JK flip-flops.

image

Figure 4.20  Logic symbol of a three-bit counter with active low clear.

The state diagram of the counter is shown in Figure 4.21. Because the counter counts from 0 to 7, three flip-flops are needed to cover that count. The transition depends on the current state and the input (clrbar). Usually D flip flops are used; however, we will use JK flip flops just to practice with their implementation in the state machine. The next step is to construct the excitation table.

image

Figure 4.21  State diagram of a three-bit counter with active low clear.

Table 4.8a shows the excitation table of a JK flip-flop, and Table 4.8b shows the excitation table of the counter.

Table 4.8a  Excitation Table for a JK Flip-Flop

image

Table 4.8b  Excitation Table for a Three-Bit Synchronous Counter with Active Low Clear

image

image

Now, construct the K-maps of the Table 4.8b. The J-K flip-flops with active low clear previously constructed in Example 4.11 are used here. Accordingly, the clear action will be done by just activating the clear function of the JK flip-flops. Figure 4.22 shows the K-maps of Table 4.8b.

image

Figure 4.22  K-maps of Table 4.8b.

From Table 4.b and the K-maps:

J0 = K0=1

J1 = K1 = q0

J2 = K2= q0 q1

Next, draw the logic diagram of the counter (see Figure 4.23).

image

Figure 4.23  Logic diagram of a three-bit synchronous counter with active low clear using master-slave JK flip-flops.

Now, write the structural description of the counter. The previously built macros and modules are used, as is the JK flip-flop designed in Listing 4.20. In VHDL, declare it as component:

component JK_FLFL

port (J, K, clk, clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end component;

for all : JK_FLFL

    use entity work. JK_FLFL (JK_Master);

Be sure to attach all the entities needed, such as entity JK_FLFL, and be sure to compile all of those entities to generate the work library before using them in the entity CTStatemachine.

In Verilog, link the current module to the JK_FF module written in Listing 4.20b. As an example of this linking, when J = K = 1:

JK_FF FF0(1’b1, 1’b1, clk, clrbar, q[0], qb[0]);

Listing 4.23 shows the HDL code of the counter. The basic VHDL package does not include definitions of the components JK_FLFL and and2. Several CAD vendors can provide packages that contain these definitions; if these packages are included in Listing 4.23, there is no need for component declaration statements for them.

LISTING 4.23  HDL Description of a Three-Bit Synchronous Counter Using Master-Slave JK Flip-Flops: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity CTStatemachine is

    port( clk, clrbar : in std_logic;

        Q, Qbar: buffer std_logic_vector (2 downto 0));

end CTStateMachine;

 

architecture ct_3 of CTStateMachine is

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component JK_FLFL

port (J, K, clk, clrbar : in std_logic;

       Q, Qbar : buffer std_logic);

end component;

for all : and2 use entity work.bind2 (and2_4);

for all : JK_FLFL use entity work.

          JK_FLFL (JK_Master );

 

--Be sure to attach the entity-architectures

-- shown above

signal J2,K2 : std_logic;

 

begin

JK0 : JK_FLFL port map (‘1’, ‘1’, clk, clrbar, Q(0), Qbar(0));

JK1 : JK_FLFL port map (q(0), q(0), clk, clrbar, Q(1), Qbar(1));

A1: and2 port map (q(0), q(1), J2);

A2: and2 port map (q(0), q(1), K2);

JK2 : JK_FLFL port map (J2, K2, clk, clrbar, Q(2), Qbar(2));

end ct_3;

 

Verilog Description

module CTstatemachine(clk, clrbar, q, qb);

input clk, clrbar;

output [2:0] q, qb;

 

JK_FF FF0(1’b1, 1’b1, clk, clrbar, q[0], qb[0]);

 

assign J1 = q[0]; /* a buffer could have been used here

        and in all assign statement in this module*/

 

assign K1 = q[0];

JK_FF FF1 (J1, K1, clk, clrbar, q[1], qb[1]);

 

and A1 (J2, q[0], q[1]);

assign K2 = J2;

JK_FF FF2(J2, K2, clk, clrbar, q[2], qb[2]);

endmodule

The simulation waveform of the counter is shown in Figure 4.24.

image

Figure 4.24  Simulation waveform of a three-bit synchronous counter with active low clear.

 EXAMPLE 4.15      STRUCTURAL DESCRIPTION OF A THREE-BIT SYNCHRONOUS EVEN COUNTER WITH ACTIVE HIGH HOLD

Assume the counter here is counting up. The number of flip-flops is three. First, draw the state diagram of the counter as shown in Figure 4.25. For all even current states, the next state is the next even. For example, if the current state is 010 (2), then the next state is 100 (4). For any odd state (invalid state), the next state can be selected to be any state that ensures the continuity of the count. For example, if the current state is the invalid state 001, the next state can be 000. In the case of invalid states, choose the next state that yields the minimum number of components or minterms; this is done by assigning “don’t cares” to the next state of invalid state and selecting 1 or 0 instead of the “don’t care” that yields to more minimizations. This will be explained when the excitation table is formed.

image

Figure 4.25  State diagram of an even three-bit counter. The Hold is shown in the diagram as only input.

From the state diagram, generate the excitation table. Table 4.9 shows the excitation table of the counter using D flip-flops. The Ds of the flip-flop are the same as the next state.

Table 4.9  Excitation Table for a Three-Bit Even Counter

image

image

From the excitation table, generate the K-maps. Figure 4.26 shows the K-maps of the counter. Referring to the K-maps, for odd states any next state can be assigned because odd states are not valid. The only restriction is that the next state should yield a valid state. Select the next state that yields elimination of more terms. For example, if the current state is 101, select the next state 100; this yields less minterms.

image

Figure 4.26  K-maps of an even three-bit counter.

From the K-maps, find the Boolean functions:

image

Using the above Boolean functions, draw the logic diagram of the counter. Figure 4.27 shows the logic symbol and logic diagram of the counter.

image

Figure 4.27  Three-bit even counter. a) Logic symbol. b) Logic diagram.

Next, write the HDL code for the counter. The macros for the D master-slave flip-flops developed in Listing 4.19 are used. In VHDL code:

component D_FFMasterWclr

port (D, clk, clrbar : in std_logic;

         Q, Qbar : buffer std_logic);

end component;

for all : D_FFMasterWclr use

          entity work. D_FFMasterWclr (D_FF_str);

In Verilog, write the code that links the D_FFMaster designed in Listing 4.19 to the new module:

D_FFMasterWclr DFF0 (1’b0, clk, clrbar, Q[0], Qbar[0]);

Listing 4.24 shows the HDL code of the counter.

LISTING 4.24  HDL Description of a Three-Bit Synchronous Even Counter with Hold: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity CTR_EVEN is

port (H, clk, clrbar : in std_logic;

Q, Qbar : buffer std_logic_vector (2 downto 0));

 

-- Input clrbar is added to help in testing;

-- set clrbar to low initially when testing

--to clear the output and then set it back to high

 

end CTR_EVEN;

 

architecture Counter_even of CTR_EVEN is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

 

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

 

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

 

component or2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

 

component and3

port (I1, I2, I3 : in std_logic;

O1 : buffer std_logic);

end component;

 

component or3

port (I1, I2, I3 : in std_logic;

O1 : buffer std_logic);

end component;

 

component D_FFMasterWclr

port (D, clk, clrbar : in std_logic;

        Q, Qbar : buffer std_logic);

end component;

 

for all : D_FFMasterWclr use

          entity work. D_FFMasterWclr (D_FF_str);

for all : inv use entity work.bind1 (inv_0);

for all : and2 use entity work.bind2 (and2_0);

for all : and3 use entity work.bind3 (and3_0);

for all : or2 use entity work.bind2 (or2_0);

for all : or3 use entity work.bind3 (or3_0);

signal Hbar, a1, a2, a3, a4,

             a5, OR11, OR22 : std_logic;

begin

DFF0 : D_FFMasterWclr port map (‘0’, clk, clrbar, Q(0),Qbar(0));

inv1 : inv port map (H, Hbar);

an1 : and2 port map (Hbar, Qbar(1), a1);

an2 : and3 port map (H, Q(1), Qbar(0), a2);

r1 : or2 port map (a2, a1, OR11);

 

DFF1 : D_FFMasterWclr port map (OR11, clk, clrbar,

                                 Q(1), Qbar(1));

an3 : and3 port map   (Q(2), Qbar(1), Qbar(0), a3);

an4 : and3 port map (Qbar(0), H, Q(2), a4);

an5 : and3 port map (Hbar, Qbar(2), Q(1), a5);

r2 : or3 port map (a3, a4, a5, OR22);

 

DFF2 : D_FFMasterWclr port map (OR22, clk, clrbar,

                                 Q(2), Qbar(2));

end Counter_even;

 

Verilog Description

module CTR_EVEN(H, clk, clrbar, Q, Qbar);

// Input clrbar is added to help in testing;

//set clrbar to low initially when testing

//to clear the output and then set it back to high

 

input H, clk, clrbar;

output [2:0] Q, Qbar;

 

D_FFMasterWclr DFF0 (1’b0, clk, clrbar, Q[0], Qbar[0]);

not (Hbar, H);

and (a1, Qbar[1], Hbar);

and (a2, H, Q[1], Qbar[0]);

or (OR1, a1, a2);

 

D_FFMasterWclr DFF1 (OR1, clk, clrbar, Q[1], Qbar[1]);

and (a3, Q[2], Qbar[1], Qbar[0]);

and (a4, Qbar[0], H, Q[2]);

and (a5, Hbar, Qbar[2], Q[1]);

or (OR2, a3, a4, a5);

 

D_FFMasterWclr DFF2 (OR2, clk, clrbar, Q[2], Qbar[2]);

endmodule

The simulation waveform of the counter is shown in Figure 4.28. As shown in the figure, the Hold is active high. If it is high and the clock pulse is present, the counter holds its output Q to the present value. Some transient states may appear in the simulation due to hazards.

image

Figure 4.28  Simulation waveform of an even counter with Hold.

 EXAMPLE 4.16      STRUCTURAL DESCRIPTION OF A THREE-BIT SYNCHRONOUS UP/DOWN COUNTER WITH ACTIVE HIGH CLEAR

The logic symbol of the three-bit synchronous up/down counter is shown in Figure 4.29. The number of flip-flops is three. TC is a terminal count; it is active when the counter completes its count. In this example, TC is high when the count is up to seven or down to zero. The clear here is active high; if it is high, the output of the counter is set to zero. Again just to practice with JK flip-flops we will use them here rather than using D flip-flops.

image

Figure 4.29  Symbol logic diagram of an up/down three-bit counter.

The state diagram of the counter is shown in Figure 4.30. The input signal, Dir, determines whether the counter counts up or down. If Dir = 0, the counter counts down, if Dir = 1, the counter counts up. From the state diagram, generate the excitation table of the counter (see Table 4.10).

image

Figure 4.30  State diagram of three-bit synchronous up/down counter.

Table 4.10  Excitation Table for a Three-Bit Up/Down Counter with a
Terminal Count Using Master-Slave JK Flip-Flops

image

Next, use K-maps to find the Boolean function of the outputs. The clear function will be provided by activating the clear of the JK flip-flop that was covered in Example 4.11. Accordingly, the clear input (clr) in Table 4.10 is not included in the Boolean function of the outputs. Figure 4.31 shows the K-maps from which the following Boolean functions are obtained.

image

Figure 4.31  K-maps of a three-bit synchronous up/down counter.

image

From the above Boolean functions, draw the logic diagram of the counter, as shown in Figure 4.32.

image

Figure 4.32  Logic diagram of a three-bit synchronous up/down counter (for only J0, J1, K0, and K1).

Listing 4.25 shows the HDL code for the counter. To reduce the hazards use gates with a propagation delay. Four nanoseconds are assigned for all primitive gates except for the inverter which is assigned 1 ns.

LISTING 4.25  HDL Description of a 3-Bit Synchronous Up/Down Counter with Clear and Terminal Count—VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity up_down is

    port (clr, Dir, clk : in std_logic;

          TC : buffer std_logic;

    Q, Qbar : buffer std_logic_vector (2 downto 0));

end up_down;

 

architecture Ctr_updown of up_down is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

 

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

 

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component or2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component or3

port (I1, I2,I3 : in std_logic; O1 : buffer std_logic);

end component;

component and3

port (I1, I2, I3 : in std_logic;

        O1 : buffer std_logic);

end component;

 

component and4

port (I1, I2, I3, I4 : in std_logic;

      O1 : buffer std_logic);

end component;

 

component JK_FLFL

port (J, K, clk, clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end component;

 

for all : JK_FLFL use entity work.

          JK_FLFL (JK_Master );

for all : inv use entity work.bind1 (inv_1);

for all : and2 use entity work.bind2 (and2_4);

for all : and3 use entity work.bind3 (and3_4);

for all : and4 use entity work.bind4 (and4_4);

for all : or2 use entity work.bind2 (or2_4);

for all : or3 use entity work.bind3 (or3_4);

--Be sure that all the reference entities

--above such as JK_FLFL

--are attached in the project.

signal clrbar, Dirbar, J1, K1, J2, K2 : std_logic;

signal s : std_logic_vector (5 downto 0);

begin

    in1 : inv port map (clr, clrbar);

    in2 : inv port map (Dir, Dirbar);

    an1 : and2 port map (Dirbar, Qbar(0), s(0));

    an2 : and2 port map (Dir, Q(0), s(1));

    an3 : and3 port map (Dirbar, Qbar(1), Qbar(0), s(2));

    an4 : and3 port map (Dir, Q(1), Q(0), s(3));

    an5 : and4 port map (Dir, Q(1), Q(0), Q(2), s(4));

    an6 : and4 port map (Dirbar, Qbar(1),

                          Qbar(0), Qbar(2), s(5));

 

    r0 : or3 port map (s(0), s(1), Q(1), J1);

    r1 : or2 port map (s(0), s(1), K1);

    r2 : or2 port map (s(2), s(3), J2);

    K2 <= J2;

    r3 : or2 port map (s(4), s(5), TC);

 

      JKFF0 : JK_FLFL port map

               (‘1’, ‘1’, clk, clrbar, Q(0), Qbar(0));

     JKFF1 : JK_FLFL port map

               (J1, K1, clk, clrbar, Q(1), Qbar(1));

     JKFF2 : JK_FLFL port map

               (J2, K2, clk, clrbar, Q(2), Qbar(2));

end Ctr_updown;

 

Verilog Description

module up_down(clr, Dir, clk, Q, Qbar, TC);

 

input clr, Dir, clk;

output [2:0] Q, Qbar;

output TC;

not #1 (clrbar, clr);

not #1 (Dirbar, Dir);

and #4 a1(s0, Dirbar, Qbar[0]);

and #4 a2(s1, Dir, Q[0]);

and #4 a3(s2, Dirbar, Qbar[0], Qbar[1]);

and #4 a4(s3, Q[0], Q[1], Dir);

and #4 a5(s4, Dirbar, Qbar[0], Qbar[1], Qbar[2]);

and #4 a6(s5, Q[0], Q[1], Q[2],Dir);

   

or #4 r1(J1, s0, Q[1], s1);

or #4 r2(K1, s0, s1);

or #4 r3(J2, s2, s3);

assign K2 = J2;// a buffer can be

//used to generate the above statement

or #4 r4(TC, s4, s5);

   

JK_FF JKFF0 (1’b1, 1’b1, clk, clrbar, Q[0], Qbar[0]);

JK_FF JKFF1 (J1, K1, clk, clrbar, Q[1], Qbar[1]);

JK_FF JKFF2 (J2, K2, clk,clrbar, Q[2], Qbar[2]);

/*Be sure that all the reference entities above

such as JK_FLFL are attached in the project.*/

endmodule

The simulation waveform of the counter is shown in Figure 4.33. When the count is three, the Dir (up/down) is changed from down to up count. Due to the synchronous nature of the Dir signal, the counter continues counting down to two, then starts counting up to three, four, five, and so forth.

image

Figure 4.33  The simulation waveform of an up/down counter.

 EXAMPLE 4.17      STRUCTURAL DESCRIPTION OF A THREE-BIT SYNCHRONOUS DECADE COUNTER

A cecade up counter counts from zero to nine, and the number of flip-flops to cover all counts is four. The state diagram of the counter is shown in Figure 4.34a. There are invalid states from 10 to 14. If any one of these invalid states is a current state, the next state can be any state that restores continuity of the count. As before, the next state selected should be the ones that yields more minimization. This is determined when the K-maps are generated. Figure 4.34 shows the final state diagram after taking into consideration the K-maps.

image

Figure 4.34  State diagram (final) of a decade counter.

Next, construct the excitation table. Table 4.11 shows the excitation table of the decade counter.

Table 4.11  Excitation Table for a Decade Counter with a Terminal Count Using D Master-Slave Flip-Flops

image

K-maps of the outputs are shown in Figure 4.35.

All Ds of the D flip-flops are equal to the corresponding next state. For example, when the current state is 0101 (5), the next state is 0110 (6), and D0 = 0, D1 = 1, D2 = 1, and D3 = 0. Applying K-maps (Figure 4.35) to Table 4.11 gives:

image

image

Figure 4.35  K-maps for a decade counter. All “don’t cares” have been assigned 0 or 1 to yield to minimum components.

From the Boolean functions, draw the logic diagram of the counter. Figure 4.36 shows the logic diagram of the counter. Listing 4.26 shows the HDL code for the counter.

image

Figure 4.36  Logic diagram of a decade counter.

LISTING 4.26  HDL Description of a Three-Bit Synchronous Decade Counter with Terminal Count: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity decade_ctr is

    port (clk, clr : in std_logic;

    Q, Qbar : buffer std_logic_vector (3 downto 0);

    TC : buffer std_logic);

end decade_ctr;

 

architecture decade_str of decade_ctr is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component buf

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component and3

port (I1, I2, I3 : in std_logic;

      O1 : buffer std_logic);

end component;

component and4

port (I1, I2, I3, I4 : in std_logic;

        O1 : buffer std_logic);

end component;

component or2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component or3

port (I1, I2, I3 : in std_logic;

      O1 : buffer std_logic);

end component;

 

component D_FFMasterWclr

port (D, clk, clrbar : in std_logic;

       Q, Qbar : buffer std_logic);

end component;

 

for all : D_FFMasterWclr use entity

          work. D_FFMasterWclr (D_FF_str);

for all : inv use entity work.bind1 (inv_1);

for all : buf use entity work.bind1 (buf_1);

for all : and2 use entity work.bind2 (and2_4);

for all : and3 use entity work.bind3 (and3_4);

for all : and4 use entity work.bind4 (and4_4);

for all : or2 use entity work.bind2 (or2_4);

for all : or3 use entity work.bind3 (or3_4);

signal s : std_logic_vector (6 downto 0);

signal D : std_logic_vector (3 downto 0);

signal clrbar : std_logic;

begin

i1 : inv port map( clr, clrbar);

b1 : buf port map (Qbar(0), D(0));

DFF0 : D_FFMasterWclr port map (D(0), clk, clrbar,

                                Q(0), Qbar(0));

 

--Assume AND gates and OR gates have 4 ns propagation

--delay and invert has 1 ns.

a1 : and3 port map (Qbar(3), Qbar(1), Q(0), s(0));

a2 : and2 port map (Q(1), Qbar(0), s(1));

r1 : or2 port map (s(0), s(1), D(1));

DFF1 : D_FFMasterWclr port map (D(1), clk, clrbar,

                                Q(1), Qbar(1));

 

a3 : and2 port map (Q(2), Qbar(1), s(2));

a4 : and2 port map (Q(2), Qbar(0), s(3));

a5 : and3 port map (Q(1), Q(0), Qbar(2), s(4));

r2 : or3 port map (s(2), s(3), s(4), D(2));

DFF2 : D_FFMasterWclr port map (D(2), clk, clrbar,

                                Q(2), Qbar(2));

 

a6 : and2 port map (Q(3), Qbar(0), s(5));

a7 : and4 port map (Q(0), Q(1), Q(2), Qbar(3), s(6));

r3 : or2 port map (s(5), s(6), D(3));

DFF3 : D_FFMasterWclr port map (D(3), clk, clrbar,

                                Q(3), Qbar(3));

a8 : and4 port map (Q(0), Qbar(1), Qbar(2), Q(3), TC);

 

end decade_str;

 

Verilog Description

module decade_ctr(clk, clrbar,Q, Qbar, TC );

input clk,clrbar;

//use clrbar input to clear the counter when simulting

output [3:0] Q, Qbar;

output TC;

wire [3:0] D;

wire [6:0] s;

buf #1 (D[0], Qbar[0]);

 

D_FFMasterWclr DFF0 (D[0], clk, clrbar, Q[0], Qbar[0]);

/*Assume and gates and or gates have 4 ns propagation

delay and invert has 1 ns.*/

 

and #4 (s[0], Qbar[3], Qbar[1], Q[0]);

and #4 (s[1], Q[1], Qbar[0]);

 

or #4 (D[1], s[0], s[1]);

D_FFMasterWclr FF1 (D[1], clk, clrbar, Q[1], Qbar[1]);

 

and #4 (s[2],Q[2], Qbar[1]);

and #4 (s[3],Q[2], Qbar[0]);

and #4 (s[4],Q[1], Q[0], Qbar[2]);

or #4 (D[2], s[2], s[3], s[4]);

D_FFMasterWclr FF2 (D[2], clk,clrbar, Q[2], Qbar[2]);

and #4 (s[5], Q[3], Qbar[0]);

and #4 (s[6], Q[0], Q[1], Q[2], Qbar[3]);

or #4 (D[3], s[5], s[6]);

D_FFMasterWclr FF3 (D[3], clk,clrbar, Q[3], Qbar[3]);

and #4 (TC, Q[0], Qbar[1], Qbar[2], Q[3]);

 

endmodule

Figure 4.37 shows the simulation waveform of the decade counter.

image

Figure 4.37  Simulation waveform of the decade counter.

4.5  generate (HDL), generic (VHDL), and parameter (Verilog)

 

The predefined word generate is mainly used for repetition of concurrent statements. Its counterpart in behavioral description is the For-Loop, and it can be used to replicate structural or gate-level description statements. generate has several formats, one of which is covered here. See Chapter 7 for more formats.

In VHDL, the format for the generate statement is:

L1 : for i in 0 to N generate

v1 : inv port map (Y(i), Yb(i));

--other concurrent statements can be entered here

end generate;

The above statement describes N + 1 inverters (assuming inv was declared as an inverter component with input Y and output Yb). The input to inverter is Y(i), and the output is Yb(i). L1 is a required label for the generate statement.

An equivalent generate statement in Verilog is:

generate

genvar i;

for (i = 0; i <= N; i = i + 1)

begin : u

not (Yb[i], Y[i]);

end

endgenerate

The statement genvar i declares the index i of the generate statement; genvar is a predefined word. U is a label for the predefined word begin; and begin must have a label.

The words generic (in VHDL) and parameter (in Verilog) are used to define global constants. The generic statement can be placed within entity, component, or instantiation statements. The following generic VHDL statement inside the entity declares N as a global constant of value 3:

entity compr_genr is

generic (N : integer := 3);

port (X, Y : in std_logic_vector (N downto 0);

  xgty, xlty, xeqy : buffer std_logic);

The following Verilog statement declares N as a global constant with a value of 3:

parameter N = 3;

input [N:0] X, Y;

The following examples cover generate, generic, and parameter.

 EXAMPLE 4.18      STRUCTURAL DESCRIPTION OF (N+1)-BIT MAGNITUDE COMPARATOR USING THE GENERATE STATEMENT

In Listing 4.16, a three-bit comparator has been described. In this section, an (N+1)-bit comparator using the generate statement is introduced. Listing 4.28 shows the HDL code for the (N+1)-bit comparator. Referring to Listing 4.28, the following statements generate N+1 inverters, N+1 full adders, and N+1 two-input and gates:

G1 : for i in 0 to N generate

v1 : inv port map (Y(i), Yb(i));

FA : full_adder port map (X(i), Yb(i),

carry(i), sum(i), carry(i+1));

a1 : and2 port map (eq(i), sum(i), eq(i+1));

end generate G1;

The following Verilog statements also generate N+1 inverters, N+1 full adders, and N+1 two-input and gates:

generate

genvar i;

for (i = 0; i <= N; i = i + 1)

begin : u

not (Yb[i], Y[i]);

FULL_ADDER FA (X[i], Yb[i], carry [i], sum [i], carry[i+1]);

and (eq[i+1], sum[i], eq[i]);

end

LISTING 4.28  HDL Description of N-Bit Magnitude Comparator Using the generate Statement: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity compr_genr is

generic (N : integer := 3);

    port (X, Y : in std_logic_vector (N downto 0);

    xgty, xlty, xeqy : buffer std_logic);

end compr_genr;

 

architecture cmpare_str of compr_genr is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

 

component full_adder

port (I1, I2, I3 : in std_logic;

      O1, O2 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

signal sum, Yb : std_logic_vector (N downto 0);

signal carry, eq : std_logic_vector (N + 1 downto 0);

 

for all : full_adder use entity work.bind32 (full_add);

for all : inv use entity work.bind1 (inv_1);

for all : nor2 use entity work.bind2 (nor2_7);

for all : and2 use entity work.bind2 (and2_7);

begin

     carry(0) <= ‘0’;

    eq(0) <= ‘1’;

   

    G1 : for i in 0 to N generate

    v1 : inv port map (Y(i), Yb(i));

    FA : full_adder port map (X(i), Yb(i), carry(i),

    sum(i), carry(i+1));

    a1 : and2 port map (eq(i), sum(i), eq(i+1));

end generate G1;

xgty <= carry(N+1);

xeqy <= eq(N+1);

n1 : nor2 port map (xeqy, xgty, xlty);

 

end cmpare_str;

Verilog Description

module Compr_genr(X, Y, xgty, xlty, xeqy);

parameter N = 3;

input [N:0] X, Y;

output xgty, xlty, xeqy;

wire [N:0] sum, Yb;

wire [N+1 : 0] carry, eq;

assign carry[0] = 1’b0;

assign eq[0] = 1’b1;

 

generate

 

genvar i;

for (i = 0; i <= N; i = i + 1)

    begin : u

    not (Yb[i], Y[i]);

/* The above statement is equivalent to assign Yb = ~Y if outside the generate loop */

 

    FULL_ADDER FA(X[i], Yb[i], carry [i], sum [i], carry[i+1]);

         /*be sure that the module FULL_ADDER

          is entered (attached) in the project*/

    and (eq[i+1], sum[i], eq[i]);

    end

endgenerate

assign xgty = carry[N+1];

assign xeqy = eq[N+1];

nor (xlty, xeqy, xgty);

 

endmodule

 EXAMPLE 4.19      STRUCTURAL DESCRIPTION OF AN N-BIT ASYNCHRONOUS DOWN COUNTER USING THE GENERATE STATEMENT

Asynchronous counters differ from synchronous counters in the way the clock is connected to each flip-flop. In synchronous counters, all flip-flops are driven by the same clock. In asynchronous counters, each flip-flop may be driven by a different clock. Figure 4.38 shows an n-bit asynchronous counter using JK flip-flops. The clock of the first flip-flop is the main clock. The clock of the second flip-flop is the output of the first JK flip-flop. This pattern is repeated where the clock of the ith flip-flop is driven by the output of (i–1)th flip-flop.

image

Figure 4.38  Logic diagram of n-bit asynchronous down counter.

Asynchronous counters suffer more from hazards than synchronous counters. This is due to the way the clock of each flip-flop is connected. Each flip-flop has to wait until the output of the preceding flip-flop settles. During the period before the flip-flop settles, there will be transient states. Listing 4.29 shows the HDL code for an n-bit asynchronous counter. To use generate effectively, the n flip-flops should be described by a general statement that will be replicated. All flip-flops, except the first, have a repeated pattern: the clock of the ith flip-flop is the output of the (i–1)th. To bring the first flip-flop into this pattern, concatenate the clock and the Qs of all flip-flops in one vector, S, that represents all the clocks:

s <= (Q & clk); --VHDL

assign s = {Q, clk}; //Verilog

LISTING 4.29  HDL Description of an N-Bit Asynchronous Down Counter Using generate: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity asynch_ctr is

Generic (N : integer := 3);

 

-- This is a 3-bit counter. If a different number of

-- bits is needed, simply change the

-- value of N here only.

    port (clk, clrbar : in std_logic;

    Q, Qbar : buffer std_logic_vector (N-1 downto 0));

 

end asynch_ctr;

 

architecture CT_strgnt of asynch_ctr is

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer.

component JK_FLFL

port (J, K, clk, clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end component;

 

for all : JK_FLFL use entity work.

                  JK_FLFL (JK_Master );

 

-- For bind32, see Listing 4.17a

 

signal h, l : std_logic;

signal s : std_logic_vector (N downto 0);

begin

h <= ‘1’;

l <= ‘0’;   

s <= (Q & clk);

 

-- s is the concatenation of Q and clk. We need

-- this concatenation to

-- describe the clock of each JK flip-flop.

Gnlop : for i in (N-1) downto 0 generate

 

G1 : JK_FLFL port map (h, h, s(i), clrbar,

                       Q(i), Qbar(i));

end generate GnLop;

end CT_strgnt;

 

Verilog Description

module asynch_ctr(clk,clrbar, Q, Qbar);

 

parameter N = 3;

/* This is a 3-bit counter. If a different number of

bits is needed, simply change the value

of N here only.*/

 

input clk, clrbar;

output [N-1:0] Q, Qbar;

wire [N:0] s;

assign s = {Q, clk};

/* s is the concatenation of Q and clk.

   This concatenation is needed to describe the clock

   of each JK flip-flop. */

      generate

      genvar i;

      for (i = 0; i < N; i = i + 1)

 

      begin : u

 

      JK_FF JKFF0 (1’b1, 1’b1, s[i],clrbar, Q[i],

                      Qbar[i]);

      // JK_FF is as shown in Listing 4.17b

      end

      endgenerate

 

endmodule

Figure 4.39 shows the simulation waveform of the counter with N = 3. The waveform may contain several transient states.

image

Figure 4.39  Simulation waveform of n-bit asynchronous down counter (n = 3).

 EXAMPLE 4.20      STRUCTURAL DESCRIPTION OF AN N-BIT MEMORY WORD USING GENERATE

In Listing 4.21, a single memory cell is described. The cell here is expanded to n bits using the generate statement. Listing 4.30 shows the HDL code for the n-bit memory word. Referring to Listing 4.30, the VHDL statements

G1 : for i in 0 to N generate

M : memory_cell port map (sel, R_W, Data_in(i),

Data_out(i));

end generate;

and the Verilog statements

generate

genvar i;

for (i = 0; i <= N; i = i + 1)

begin : u

memory M1 (sel, R_W, Data_in [i], Data_out[i]);

end

endgenerate

replicate the memory cell designed in Listing 4.29 n times.

LISTING 4.30  HDL Description of N-Bit Memory Word Using generate: VHDL and Verilog

VHDL Description

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity Memory_word is

Generic (N : integer := 7);

    port (Data_in : in std_logic_vector (N downto 0);

          sel, R_W : in std_logic; Data_out : out

          std_logic_vector (N downto 0));

end Memory_word;

 

architecture Word_generate of Memory_word is

component memory_cell

Port (Sel, RW, Din : in std_logic;

       O1 : buffer std_logic );

end component;

 

for all : memory_cell use entity

          work.memory (memory_str);

begin

G1 : for i in 0 to N generate

M : memory_cell port map (sel, R_W, Data_in(i),

                          Data_out(i));

end generate;

end Word_generate;

 

Verilog Description

module Memory_Word (Data_in, sel, R_W, Data_out);

 

parameter N = 7;

input [N:0] Data_in;

input sel, R_W;

output [N:0] Data_out;

 

generate

genvar i;

for (i = 0; i <= N; i = i + 1)

begin : u

memory M1 (sel, R_W, Data_in [i], Data_out[i]);

 

end

 

endgenerate

endmodule

LISTING 4.31  VHDL Code for Components Used for Binding in Chapter 4

--Some simulators will not allow mapping between

--buffer and out. In this

--case, change all out to buffer as it is done here.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind1 is

port (O1 : buffer std_logic; I1 : in std_logic);

end bind1;

architecture inv_0 of bind1 is

begin

O1 <= not I1;

end inv_0;

architecture inv_1 of bind1 is

begin

O1 <= not I1 after 1 ns;

end inv_1;

 

architecture inv_7 of bind1 is

begin

O1 <= not I1 after 7 ns;

end inv_7;

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity bind2 is

port (O1 : buffer std_logic; I1, I2 : in std_logic);

end bind2;

 

architecture xor2_0 of bind2 is

begin

O1 <= I1 xor I2;

end xor2_0;

architecture and2_0 of bind2 is

begin

O1 <= I1 and I2;

end and2_0;

architecture and2_4 of bind2 is

begin

O1 <= I1 and I2 after 4 ns;

end and2_4;

 

architecture and2_7 of bind2 is

begin

O1 <= I1 and I2 after 7 ns;

end and2_7;

 

architecture or2_0 of bind2 is

begin

O1 <= I1 or I2;

end or2_0;

 

architecture or2_7 of bind2 is

begin

O1 <= I1 or I2 after 7 ns;

end or2_7;

 

architecture nor2_0 of bind2 is

begin

O1 <= I1 nor I2;

end nor2_0;

 

architecture nor2_7 of bind2 is

begin

O1 <= I1 nor I2 after 7 ns;

end nor2_7;

 

architecture nor2_4 of bind2 is

begin

O1 <= I1 nor I2 after 4 ns;

end nor2_4;

 

architecture bufif1 of bind2 is

begin

buf : process (I1, I2)

variable tem : std_logic;

begin

if (I2 =’1’)then

tem := I1;

else

tem := ‘Z’;

end if;

O1 <= tem;

end process buf;

end bufif1;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind3 is

port (O1 : buffer std_logic;

I1, I2, I3 : in std_logic);

end bind3;

 

architecture and3_0 of bind3 is

begin

O1 <= I1 and I2 and I3;

end and3_0;

 

architecture and3_4 of bind3 is

begin

O1 <= I1 and I2 and I3 after 4 ns;

end and3_4;

 

architecture and3_7 of bind3 is

begin

O1 <= I1 and I2 and I3 after 7 ns;

end and3_7;

 

architecture or3_0 of bind3 is

begin

O1 <= I1 or I2 or I3;

end or3_0;

 

architecture or3_7 of bind3 is

begin

O1 <= I1 or I2 or I3 after 7 ns;

end or3_7;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind22 is

Port (O1, O2 : buffer std_logic;

I1, I2 : in std_logic);

end bind22;

 

architecture HA of bind22 is

component xor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

for A1 : and2 use entity work.bind2 (and2_0);

for X1 : xor2 use entity work.bind2 (xor2_0);

      begin

      X1 : xor2 port map (I1, I2, O1);

      A1 : and2 port map (I1, I2, O2);

      end HA;

 

architecture SR_Latch of bind22 is

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

for all : nor2 use entity work.bind2 (nor2_0);

 

begin

n1 : nor2 port map (I1, O1, O2);

n2 : nor2 port map (I2, O2, O1);

end SR_Latch;

 

architecture D_latch of bind22 is

component and2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

for all : and2 use entity work.bind2 (and2_4);

for all : nor2 use entity work.bind2 (nor2_4);

for all : inv use entity work.bind1 (inv_1);

signal I2b, s1, s2 : std_logic;

begin

a1 : and2 port map (I1, I2, s1);

a2 : and2 port map (I2b, O1, s2);

in1 : inv port map (I2, I2b);

in2 : inv port map (O2, O1);

n2 : nor2 port map (s1, s2, O2);

end D_latch;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity bind32 is

port (I1, I2, I3 : in std_logic;

O1, O2 : buffer std_logic);

 

end bind32;

 

architecture full_add of bind32 is

component HA

port (I1, I2 : in std_logic;

      O1, O2 : buffer std_logic);

end component;

component or2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

for all : HA use entity work.bind22 (HA);

for all : or2 use entity work.bind2 (or2_0);

signal s0, c0, c1 : std_logic;

 

begin

HA1 : HA port map (I2, I3, s0, c0);

HA2 : HA port map (I1, s0, O1, c1);

r1 : or2 port map (c0, c1, O2);

end full_add;

 

architecture D_latch_Wclr of bind32 is

component and3

port (I1, I2, I3 : in std_logic;

      O1 : buffer std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

for all : and3 use entity work.bind3 (and3_4);

for all : nor2 use entity work.bind2 (nor2_4);

for all : inv use entity work.bind1 (inv_1);

signal I2b, s1, s2 : std_logic;

begin

a1 : and3 port map (I1, I2, I3, s1);

a2 : and3 port map (I2b, O1,I3, s2);

in1 : inv port map (I2, I2b);

in2 : inv port map (O2, O1);

n2 : nor2 port map (s1, s2, O2);

end D_latch_Wclr;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity D_LatchWclr is

port (D, E,clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end;

 

architecture D_latch_str of D_LatchWclr is

component and3

port (I1, I2, I3 : in std_logic;

      O1 : buffer std_logic);

end component;

component nor2

port (I1, I2 : in std_logic; O1 : buffer std_logic);

end component;

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

for all : and3 use entity work.bind3 (and3_4);

for all : nor2 use entity work.bind2 (nor2_4);

for all : inv use entity work.bind1 (inv_1);

signal Eb, s1, s2 : std_logic;

begin

a1 : and3 port map (D, E, clrbar, s1);

a2 : and3 port map (Eb, D,clrbar, s2);

in1 : inv port map (E, Eb);

in2 : inv port map (Qbar, Q);

n2 : nor2 port map (s1, s2, Qbar);

end D_latch_str;

 

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

 

entity D_FFMasterWclr is

Port (D, clk, clrbar : in std_logic;

      Q, Qbar : buffer std_logic);

end D_FFMasterWclr ;

 

architecture D_FF_str of D_FFMasterWclr is

component inv

port (I1 : in std_logic; O1 : buffer std_logic);

end component;

component D_latchWclrbar

port (I1, I2, I3 : in std_logic;

      O1, O2 : buffer std_logic);

end component;

for all : D_latchWclrbar use entity

          work. bind32(D_latch_Wclr);

for all : inv use entity work.bind1 (inv_1);

signal clkb, clk2, Q0, Qb0 : std_logic;

begin

D0 : D_latchWclrbar port map (D, clkb,clrbar, Q0, Qb0);

D1 : D_latchWclrbar port map (Q0, clk2, clrbar, Q,

Qbar);

in1 : inv port map (clk, clkb);

in2 : inv port map (clkb, clk2);

end D_FF_str;

4.6  Summary

 

In this chapter, the fundamentals of structural description have been covered. Gate-level description was discussed and implemented to build more complex structures (macros). Verilog has built-in gates such as and, or, nand, nor, and buf. Basic VHDL does not have built-in gates, but these gates can be built by using the predefined word component and binding it to written behavioral descriptions. Both VHDL and Verilog have the predefined command generate for replicating structural macros. Table 4.11 shows a list of the VHDL statements covered in this chapter, along with their Verilog counterparts (if any).

Table 4.12  Summary of VHDL Statements and Their Verilog Counterparts

image

4.7  Exercises

 

  1. Design a four-bit parity generator. The output is 0 for even parity and 1 for odd parity. Write both the VHDL and Verilog codes.
  2. Design a counter that counts 0, 1, 3, 6, 7, 0, 1... using the state-machine approach. Show all details of your answer. Write both the VHDL and Verilog codes.
  3. Referring to Listing 4.26 (Verilog), change the count from down to up and rewrite the code.
  4. Translate the VHDL code shown in Listing 4.32 to Verilog. What is the logic function of the system?

    LISTING 4.32  Code for Exercise 4.4

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    entity system is

    Port (a, b, c : in std_logic;

          d, e : buffer std_logic );

    end system;

     

    architecture prob_6 of system is

    component xor2

    port (I1, I2 : in std_logic; O1 : buffer std_logic);

    end component;

    component and2

    port (I1, I2 : in std_logic; O1 : buffer std_logic);

    end component;

     

    component or3

    port (I1, I2, I3 : in std_logic;

    O1 : buffer std_logic);

     

    end component;

     

    component inv

    port (I1 : in std_logic; O1 : buffer std_logic);

    end component;

     

    for all : xor2 use entity work.bind2 (xor2_0);

    for all : and2 use entity work.bind2 (and2_0);

    for all : inv use entity work.bind1 (inv_0);

    for all : or3 use entity work.bind3 (or3_0);

    signal s1, s2, s3, s4, abar, bbar, cbar : std_logic;

    begin

    x1 : xor2 port map (a, b, s1);

    x2 : xor2 port map (s1, c, d);

    c1 : inv port map (a, abar);

    c2 : inv port map (b, bbar);

    c3 : inv port map (a, cbar);

    a1 : and2 port map (abar, b, s2);

    a2 : and2 port map (abar, c, s3);

    a3 : and2 port map (b, c, s4);

    r1 : or3 port map (s2, s3, s4, e);

    end prob_6;

  5. Construct a two-digit decade counter that counts from 0 to 99. Use the module of the decade counter in Listing 4.26. Write both the VHDL and Verilog codes. (Hint: use the terminal count, TC, to cascade the decade counters.)
  6. Write VHDL description for the universal shift register discussed in Example 4.13.
  7. Repeat Example 4.14 using D flip-flops.
  8. Repeat Example 4.16 using D flip-flops.
  9. Use generate and parameter to write a Verilog code for an n-bit subtractor.