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.
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);
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
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.
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
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.
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;
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
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:
Figure 4.3 shows the logic diagram of the decoder.
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).
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
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.
Figure 4.6 Full adder as two half adders. a) Logic symbol. b) Logic diagram.
--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.
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:
–Y is the twos complement of ; substituting in Equation 4.2, the condition of X > Y is rewritten as:
Or, Equation 4.3 can be rewritten as:
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:
Equation 4.5 states that if X is greater than Y, the sum of X and should be greater than 1...1111. If n adders are used to add X plus
, 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
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:
In this example, n = 3 is being considered. Figure 4.8 shows the logic diagram of the comparator.
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
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.
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.
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. 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.
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
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.
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.
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.
Figure 4.14 Logic diagram of a T flip-flop.
Table 4.4 Excitation Table for a Pulse-Triggered JK Flip-Flop
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
To find the Boolean function of D, form K-maps as shown in Figure 4.15.
Figure 4.15 K-maps of Table 4.5.
From Figure 4.15, the Boolean functions are:
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.
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);
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.”
Figure 4.17 SRAM memory cell. a) Logic symbol. b) Logic diagram.
Table 4.6 Excitation Table of an SRAM Memory Cell
Figure 4.18 K-maps for Table 4.6.
From the K-maps:
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
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
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:
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.
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.
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
Table 4.8b Excitation Table for a Three-Bit Synchronous Counter with Active Low Clear
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.
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).
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.
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.
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
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.
Figure 4.26 K-maps of an even three-bit counter.
From the K-maps, find the Boolean functions:
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.
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;
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.
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.
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).
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
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.
Figure 4.31 K-maps of a three-bit synchronous up/down counter.
From the above Boolean functions, draw the logic diagram of the counter, as shown in Figure 4.32.
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
--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.
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.
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
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:
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.
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 );
//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.
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.
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.
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.
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
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;
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;
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;
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
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;