Naeih Botros
Naeih Botros
Naeih Botros
DIGITAL DESIGN
VHDL AND VERILOG
Nazeih Botros
This publication, portions of it, or any accompanying software may not be reproduced in any way,
stored in a retrieval system of any type, or transmitted by any means, media, electronic display
or mechanical display, including, but not limited to, photocopy, recording, Internet postings,
or scanning, without prior permission in writing from the publisher.
The publisher recognizes and respects all marks used by companies, manufacturers, and developers as
a means to distinguish their products. All brand names and product names mentioned in this book are
trademarks or service marks of their respective companies. Any omission or misuse (of any kind) of service
marks or trademarks, etc. is not an attempt to infringe on the property of others.
Our titles are available for adoption, license, or bulk purchase by institutions, corporations, etc.
For additional information, please contact the Customer Service Dept. at 800-232-0223(toll free).
All of our titles are available in digital format at authorcloudware.com and other digital vendors. Companion
files (figures and code listings) for this title are available by contacting [email protected]. The sole
obligation of MERCURY LEARNING AND INFORMATION to the purchaser is to replace the disc, based on defective
materials or faulty workmanship, but not based on the operation or functionality of the product.
LICENSE, DISCLAIMER OF LIABILITY, AND LIMITED WARRANTY
By purchasing or using this book (the “Work”), you agree that this license grants
permission to use the contents contained herein, but does not give you the right
of ownership to any of the textual content in the book or ownership to any of the
information or products contained in it. This license does not permit uploading
of the Work onto the Internet or on a network (of any kind) without the writ-
ten consent of the Publisher. Duplication or dissemination of any text, code,
simulations, images, etc. contained herein is limited to and subject to licensing
terms for the respective products, and permission must be obtained from the
Publisher or the owner of the content, etc., in order to reproduce or network
any portion of the textual material (in any media) that is contained in the Work.
MERCURY LEARNING AND INFORMATION (“MLI” or “the Publisher”) and anyone
involved in the creation, writing, or production of the companion disc, accom-
panying algorithms, code, or computer programs (“the software”), and any ac-
companying Web site or software of the Work, cannot and do not warrant the
performance or results that might be obtained by using the contents of the
Work. The author, developers, and the Publisher have used their best efforts
to insure the accuracy and functionality of the textual material and/or programs
contained in this package; we, however, make no warranty of any kind, express
or implied, regarding the performance of these contents or programs. The
Work is sold “as is” without warranty (except for defective materials used in
manufacturing the book or due to faulty workmanship).
The author, developers, and the publisher of any accompanying content, and
anyone involved in the composition, production, and manufacturing of this
work will not be liable for damages of any kind arising out of the use of (or the
inability to use) the algorithms, source code, computer programs, or textual
material contained in this publication. This includes, but is not limited to, loss
of revenue or profit, or other incidental, physical, or consequential damages
arising out of the use of this Work.
The sole remedy in the event of a claim of any kind is expressly limited to re-
placement of the book, and only at the discretion of the Publisher. The use of
“implied warranty” and certain “exclusions” vary from state to state, and might
not apply to the purchaser of this product.
PREFACE
Book Organization
The following is a brief description of the subjects that are covered in each
chapter.
Chapter 1: Covers structure of the HDL module, operators including logical,
arithmetic, relational and shift, data types such as scalar, composite and file, and
a brief comparison between VHDL and Verilog. The chapter also covers how to
simulate and test HDL code using test benches
Chapter 2: Covers: a) Analysis and design of combinational circuits such as
adders, subtractors, decoders, multiplexers, comparators and simple multipliers,
and sequential circuits such as latches; b) Simulation of the above combinational
and sequential circuits using VHDL and Verilog data-flow description. The
description includes covering of logical operators, concurrent signal-assignment
statements, time delays, and vectors.
Chapter 3: Covers: a) Analysis and design of sequential circuits such as D flip-
flop, JK flip-flop, T flip-flop, binary counters, and shift register; b) Understand
the concept of some basic genetic and renal systems; c) Implementation of
xii • PREFACE
Booth algorithm; d) Simulation of the systems in (a), (b), and (c) using VHDL
and Verilog behavioral description. The description includes covering of the
sequential statements if, case, loop casex, casez, when, report, $display,
wait, loop, exit, next, always, repeat, forever, and initial.
Chapter 5: Covers:
a) Analysis and design of primitive gates and simple logics using transistors
(switches); b) Simulation of the above logics using HDL switch-level description.
The description includes the Verilog statements nmos, pmos, cmos, supply1,
supply0, tranif0, tran, and tranif0.
The book is also appropriate for short courses for digital design engineers.
Suggested courses that could use this book are: digital logic design, computer
architecture, HDL programming and synthesis, application-specific integrated
circuits (ASICs) design, or digital design projects.
student became familiar with the basic rules of HDL language and is ready
to learn the other language (Verilog). I covered Verilog material of Chapters
1 and 2. After Chapter 2 until the end of the semester, I have covered both
VHDL and Verilog at the same time in the same order as the Chapters of the
book. The order of these Chapters after Chapter 2 is: 1) Chapter 3, “Behavioral
description”; VHDL and Verilog have several similarities on behavioral
statements such as if, case, and loop. 2) Chapter 4, “Structural Description,”
again both languages have many similarities except the VHDL does not have
built-in components as the Verilog does. By including packages, VHDL can
use components very similar to that of Verilog. 3) Chapter 5, “Switch-Level
Description,” -again VHDL does not have built-in constructs for switch-level
descriptions, but we can include packages that allow us to write VHDL switch
level statements very close to that of Verilog. 4) Chapter 6, “Procedures, Tasks,
and Functions,” here VHDL and Verilog have many similarities. 5) Chapter 7,
“Mixed-Type Description.” 6) Chapter 8, “Advanced HDL Description.”
7) Chapter 9, “Mixed Language Description”; the student now knows both
VHDL and Verilog; in this chapter he will learn how to mix between VHDL
and Verilog constructs. 8) Chapter 10, “Synthesis Basics.”
Companion Files
Companion files (figures and code listings) for this title are available by
contacting [email protected].
Nazeih Botros
Carbondale, IL
February, 2015
CONTENTS
Preface xi
Chapter 1 Introduction 1
1.1 Hardware Description Language 1
1.2 Structure of the HDL Module 2
1.2.1 Structure of the VHDL Module 4
1.2.2 Structure of the Verilog Module 6
1.3 Styles (Types) Of Description 8
1.3.1 Data Flow Description 8
1.3.2 Behavioral Description 9
1.3.3 Structural Description 10
1.3.4 Switch-Level Description 11
1.3.5 Mixed-Type Description 12
1.3.6 Mixed-Language Description 13
1.4 Ports 13
1.4.1 VHDL Ports 14
1.4.2 Verilog Ports 14
1.5 Operators 14
1.5.1 Logical Operators 15
1.5.1.1 VHDL Logical Operators 15
1.5.1.2 Verilog Logical Operators 16
1.5.2 Relational Operators 17
1.5.2.1 VHDL Relational Operators 18
1.5.2.2 Verilog Relational Operators 18
1.5.3 Arithmetic Operators 19
1.5.3.1 VHDL Arithmetic Operators 20
1.5.3.2 Verilog Arithmetic Operators 21
1.5.3.3 Arithmetic Operator Precedence 21
1.5.4 Shift and Rotate Operators 21
1.5.4.1 VHDL Shift/Rotate Operators 22
1.5.4.2 Verilog Shift Operators 22
1.6 Data Types 23
1.6.1 VHDL Data Types 23
1.6.1.1 Scalar Types 24
1.6.1.2 Composite Types 27
1.6.1.3 Access Types 28
1.6.1.4 File Types 28
1.6.1.5 Other Types 28
vi • CONTENTS
Index 559
CHAPTER
1
INTRODUCTION
Chapter Objectives
O Understand the basics of hardware description language (HDL)
O Learn how the HDL module is structured
O Learn the use of operators in HDL modules
O Learn the different types of HDL objects
O Understand and analyze the half-adder circuit
O Understand the function of a simulator
O Understand the function of a synthesizer
O Understand the main differences between VHDL and Verilog HDL
gral part of such tools. HDL offers the designer a very efficient tool for
implementing and synthesizing designs on chips.
The designer uses HDL to describe the system in a computer-language
code that is similar to several commonly used software languages such as C.
Debugging the design is easy because HDL packages implement simula-
tors and test benches. The two widely used hardware description languages
are VHDL and Verilog. Because the two languages are implemented in
both academia and industry, this book covers both languages.
After writing and testing the HDL code, the user can synthesize the
code into digital logic components such as gates and flip-flops that can be
downloaded into FPGAs or compatible electronic components. Usually,
the CAD package that has HDL will also have a synthesizer. The HDL
and synthesizer have made the task of designing complex systems much
easier and faster than before. It is worth mentioning here that the currently
available synthesizers have some limitations and cannot synthesize all HDL
constructs; however, continuous improvement of the synthesizers is being
undertaken by the electronic industry.
HDL has gone through continuous improvement since its inception.
Verilog was introduced in 1980s and has gone through several iterations
and standardization by the Institute of Electrical and Electronic Engineers
(IEEE), such as in December 1995 when Verilog HDL became IEEE
Standard 1364-1995, in 2001 when IEEE Std. 1364-2001 was introduced,
and in 2005 when IEEE 1800-2005 was introduced. VHDL, which stands
for very-high-speed integrated circuit (VHSIC) hardware description lan-
guage, was developed in the early 1980s. In 1987, the IEEE Standard 1076-
1987 version of VHDL was introduced, and several upgrades followed.
In 1993, VHDL was updated and more futures were added; the result of
this update was IEEE Standard 1076-1993. Recently, in 2008, the VHDL
IEEE 1076-2008 was introduced.
Input Output
a b S C
0 0 0 0
1 0 1 0
0 1 1 0
1 1 0 1
The Boolean function of the output of the adder is obtained from the
truth table. The Boolean function of the output is generated using mint-
erms (where the output has a value of 1) or maxterms (where the output has
a value of 0). The Boolean function using minterms in the sum of products
(SOP) form is
S= a b+ab=ab (1.1)
C=ab (1.2)
After minimization (a a = 0 and bb =0), the SOP and the POS yield
identical Boolean functions. Figure 1.1a shows the logic symbol of the half
adder. Figure 1.1b shows the logic diagram of the half adder.
4 • HDL WITH DIGITAL DESIGN
a S
Half a
adder S
b
b C
C
a) b)
FIGURE 1.1 Half adder. a) Logic symbol. b) Logic diagram.
(see Section 1.4.1 for details on port modes). The type of these input signals
is bit and determines the allowed values that signals a and b can take. Type
bit allows the signal to take only either logic 0 or logic 1. There are several
other types, such as std_logic, real, and integer (see Section 1.6.1).
The entity also has two output ports, S and C; they are declared as outputs
with the predefined word out, and their type is bit. The order in which the
input and output ports are written inside the parentheses is irrelevant. The
output ports could have been listed before the input ports.
The last line of the entity’s code uses the predefined word end, and
it ends the entity. The name of the entity can follow the word end, as in
end Half_adder, or the name of the entity can be omitted and only end
is entered.
The semicolon (;) is an important character in HDL. It is used as a
separator similar to the carriage return character used in C language. For
example, the port statement can be written as:
port( a: in bit;
b : in bit;
S : out bit;
C: out bit);
The carriage return between the statements does not convey any in-
formation; it is the semicolon that signals a new statement. Ports can be
declared in, out, inout, buffer, or linkage (see Section 1.4.1).
The second construct of the VHDL module, the architecture, describes
the relationship between the inputs and outputs of the system. Architecture
has to be bound to an entity. This relationship can be described using sev-
eral sources; one of these sources is the Boolean function of the outputs.
Other sources for describing the relationship between the output(s) and the
input(s) are discussed in Section 1.3. Multiple architectures can be bound
to the same entity, but each architecture can be bound to only one entity.
Listing 1.1 shows an example of an architecture bound to the entity Half_
adder. The architecture is declared by the predefined word architecture,
followed by a user-selected name; this name follows the same name-select-
ing guidelines as the entity. In Listing 1.1, the name of the architecture is
dtfl_half. The name is followed by the predefined word of, followed
by the name of the entity. The predefined word of binds the architecture
dtfl_half to the entity Half_adder. Binding here means the information
listed in the entity is visible to the architecture.
6 • HDL WITH DIGITAL DESIGN
assign S = a ^ b; // statement 1
assign C= a & b; // statement 2
endmodule
The semicolon (;) plays the same rule as in VHDL module; it is a line
separator. Carriage return here does not indicate a new statement, the
semicolon does. Following the module statement, the input and output
port modes are declared. For example, the statement input a; declares
signal a as an input port. The modes of the ports are discussed in Section
1.4.2. In contrast to VHDL, the type of the input and output port signals
need not be declared. The order of writing the inputs and outputs and their
declaration is irrelevant. For example, the inputs and outputs in Listing 1.2
can be written as:
module half_adder (a,b, S, C);
output S;
output C;
input a;
input b;
8 • HDL WITH DIGITAL DESIGN
Also, more than one input or output could be entered on the same line
by using a comma (,) to separate each input or output as:
module half_adder (a,b, S, C);
output S, C;
input a, b;
in Section 1.2 where the Boolean function of S and C have been imple-
mented to describe the half adder; see Listing 1.1 (VHDL) and Listing 1.2
(Verilog).
Read
a, b
a≠b? S=0
NO
YES
S=1
begin
if (a /= b) then
S <= ‘1’;
else
S <= ‘0’;
--Blank lines are allowed
end if;
end process;
end beh_half;
Verilog Description
module Half_adder(a,b,S,C);
input a,b;
output S, C;
reg S,C;
// Blank lines are allowed
always @ (a,b)
begin
if (a != b)
S = 1’b1;
else
S = 1’b0;
end
endmodule
component xor2
--The above statement is a component statement
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 struct_exple;
Verilog Description
module Half_adder1(a,b,S,C);
input a, b;
output S,C;
and a1(C,a,b);
//The above statement is AND gate
xor x1(S,a,b);
//The above statement is EXCLUSIVE-OR gate
endmodule
Verilog Description
module invert(y,a);
input a;
output y;
supply1 vdd;
supply0 gnd;
pmos p1(y, vdd, a);
nmos n1(y, gnd, a);
/The above two statement are using the two primi-
tives pmos and nmos/
endmodule
library IEEE;
use ieee.std_logic_1164.all;
entity HA is
--For correct binding between this VHDL code and the above
--Verilog code, the entity has to be named here as HA
port (a, b : in std_logic; s, c: out std_logic);
end HA;
architecture HA_Dtflw of HA is
begin
s <= a xor b;
c <= a and b;
end HA_Dtflw;
1.4 Ports
A simple definition of ports can be stated as a communication means
between the system to be described and the environment.
14 • HDL WITH DIGITAL DESIGN
1.5 Operators
HDL has an extensive list of operators. These operators are used ex-
tensively in every chapter of the book. Operators perform a wide variety of
functions. These functions can be classified as:
Q Logical (see Section 1.5.1), such as AND, OR, and XOR
Q Relational (see Section 1.5.2) to express the relation between objects.
These operators include equality, inequality, less than, less than or
equal, greater than, and greater than or equal.
INTRODUCTION • 15
OR Bit Bit
| Bit Bit
^ Bit Bit
INTRODUCTION • 17
~ Bit Bit
/ mod (%)
+ -
These objects can assume different types; these types can be classified into
five groups depending on the nature of the values the object can assume:
scalar, composite, access, file, and other.
Bit Type
The only values allowed here are 0 or 1. It is used to describe a signal
that takes only 1 (high) or 0 (low). The signal cannot take other values such
as high impedance (open). An example of implementing this type is when
the type of a port signal is described as:
port (I1, I2 : in bit; O1, O2 : out bit);
Signals I1, I2, O1, and O2 can assume only 0 or 1. If any of these sig-
nals must assume other levels or values, such as high impedance, bit type
cannot be used.
Boolean Type
This type can assume two values: false (0) or true (1). Both true
and false are predefined words. One of the most frequent applications
of the Boolean type is in the if statement (see Chapter 3). Consider the
statements:
If (y = B) then
S := ‘1’;
else
S := ‘0’;
end if;
+2,147,483,647. The user can specify a shorter range by using the pre-
defined word range. The predefined word natural can be used instead
of integer if the values of the object are always positive, including 0. An
example of the integer type is in the implementation of the exponent op-
erator (see Section 1.5.3.1). The exponent has to be of type integer, such
as X2 or Xy, where y is declared as integer. The port can also be
declared as type integer:
port (I1 : in natural; I2 : in bit; O1 : out integer; O2 : Boolean);
Another predefined type positive restricts the values an object can
take to be positive and higher than 0.
Real Type
This type accepts fractions, such as .4502, 12.5, and –5.2E–10 where
E–10 = 10–10. An example of using real type is:
a character. The characters are associated with ASCII values. For example,
character A has the ASCII value of 41 in hex. More discussion on characters
can be found in Chapter 8 and Chapter 3.
Physical Type
This type has values that can be measured in units, such as time (e.g.,
second, millisecond, microsecond) and voltage (e.g., volt, millivolt, micro-
volts). An example of type time is:
constant Delay_inv : time := 1 ns;
The above statement states that the constant Delay_inv is of type
time, and its initial value is one nanosecond (1 ns). The word time is pre-
defined; the units of time are as follows:
fs femtosecond
ps = 1,000 fs
ns = 1,000 ps
us = 1,000 ns
ms = 1,000 us
sec = 1,000 ms
min = 60 sec
hr = 60 min
User-Defined Types
The user can define a type by using the predefined word type as shown
below:
type op is (add, mul, divide, none);
variable opcode : op := mul;
Type op is user defined. The variable opcode is of type op and can
therefore be instantiated to: add, mul, divide, or none. More discussion
about user-defined types can be found in Chapter 7.
Severity Type
This type is used with the assert statement (see Chapter 8). An object
with type severity can take one of four values: note, warning, error, or
failure. An example of this type is as follows:
Bit_vector Type
The bit_vector type represents an array of bits; each element of the
array is a single bit. The following example illustrates the implementation
of type bit_vector:
Port (I1 : in bit; I2 : in bit_vector (5 downto 0); Sum : out bit);
In the above statement, port I2 is declared as type bit_vector; it
has six bits. Possible values of I2 include 110110, 011010, and 000000 or
any other six-bit number. More details about bit_vector can be found in
Chapter 2.
Array Type
This type is declared by using the predefined word array. For ex-
ample, the following statements declare the variable memory to be a single-
dimensional array of eight elements, and each element is an integer:
subtype wordN is integer;
type intg is array (7 downto 0) of wordN;
...........
variable memory : intg;
Record Type
An object of record type is composed of elements of the same or differ-
ent types. An example of record type is shown below:
Type forecast is
record
Tempr : integer range -100 to 100;
28 • HDL WITH DIGITAL DESIGN
Day : real;
Cond : bit;
end record;
............
Std_Logic Type
Std_Logic has nine values, including 1 and 0. Package std_logic_1164
should be attached to the VHDL module. The nine values of std_logic
type are shown in Table 1.12.
TABLE 1.12 Values of Std_Logic Type
Value Definition
U Uninitialized
X Unknown
0 Low
1 High
Z High impedance
W Weak unknown
L Weak low
H Weak high
- Don’t care
Std_logic_vector Type
The type std_logic_vector represents an array. Each element of the
array is a single bit of type std_logic. The following example illustrates
the implementation of type std_logic_vector:
Port (I1 : in bit; I2 : in std_logic_vector (5 downto 0);
Sum : out bit);
Signed
Signed is a numeric type. It is declared in the external package
numeric_std and represents signed integer data in the form of an array. The
leftmost bit is the sign; objects of type signed are represented in 2’ comple-
ment form. Consider the statement:
Variable prod : signed (3 downto 0) := 1010;
Unsigned
The type unsigned represents unsigned integer data in the form of an
array of std_logic and is a part of the package numeric_std. The following
example illustrates type unsigned:
Variable Qout : unsigned (3 downto 0) := 1010;
The above statement declares variable Qout as of type unsigned, it has
four bits, and its initial value is 1010, or 10 (in decimal).
1.6.2.1 Nets
Nets are declared by the predefined word wire. Nets have values that
change continuously by the circuits that are driving them. Verilog supports
four values for nets, as shown in Table 1.13.
TABLE 1.13 Verilog Net Values
Value Definition
0 Logic 0 (false)
1 Logic 1 (true)
X Unknown
Z High impedance
Examples of net types are as follows:
wire sum;
wire S1 = 1’b0;
The first statement declares a net by the name sum. The second state-
ment declares a net by the name of S1; its initial value is 1’b0, which rep-
resents 1 bit with value 0.
1.6.2.2 Register
Register, in contrast to nets, stores values until they are updated.
Register, as its name suggests, represents data-storage elements. Register
is declared by the predefined word reg. Verilog supports four values for
register, as shown in Table 1.14.
INTRODUCTION • 31
Value Definition
0 Logic 0 (false)
1 Logic 1 (true)
X Unknown
Z High impedance
An example of register is:
reg Sum_total;
The above statement declares a register by the name Sum_total.
1.6.2.3 Vectors
Vectors are multiple bits. A register or a net can be declared as a vector.
Vectors are declared by brackets [ ]. Examples of vectors are:
wire [3:0] a = 4’b1010;
reg [7:0] total = 8’d12;
The first statement declares a net a. It has four bits, and its initial value
is 1010 (b stands for bit). The second statement declares a register total.
Its size is eight bits, and its value is decimal 12 (d stands for decimal). Vec-
tors are implemented in almost all subsequent chapters.
1.6.2.4 Integers
Integers are declared by the predefined word integer. An example of
integer declaration is:
integer no_bits;
The above statement declares no_bits as an integer.
1.6.2.4 Real
Real (floating-point) numbers are declared with the predefined word
real. Examples of real values are 2.4, 56.3, and 5e12. The value 5e12 is
equal to 5 × 1012. The following statement declares the register weight as
real:
real weight;
1.6.2.5 Parameter
Parameter represents a global constant. It is declared by the pre-
defined word parameter. The following is an example of implementing
parameters:
32 • HDL WITH DIGITAL DESIGN
To change the size of the inputs x and y, the size of the nets sum, and
the size of net Yb to eight bits, the value of N is changed to seven as:
parameter N = 7
1.6.2.6 Arrays
Verilog, in contrast to VHDL, does not have a predefined word for ar-
ray. Registers and integers can be written as arrays. Consider the following
statements:
parameter N = 4;
parameter M = 3;
The above statements declare an array by the name carry. The array
carry has five elements, and each element is four bits. The four bits are in
two’s complement form. For example, if the value of a certain element is
1001, then it is equivalent to decimal –7. Arrays can be multidimensional.
See Chapter 7 for more details on arrays.
3. Write the code. If writing a VHDL module, be sure to attach all the nec-
essary packages and libraries. At this step, some HDL packages require
the user to select the type of synthesis technology and chip type before
compilation.
4. Compile the code using the compiler supplied by the HDL package.
The compiler checks that the code satisfies the rules of the language and
displays any errors. Some compilers suggest how to fix the errors.
5. After successful compilation, the code is tested to see that it correctly
describes the system. This test is done by selecting the input and
output signals to be tested. For example, if a 2 x 1 multiplexer is be-
ing described, the two inputs, the select line, and the output might be
selected. The way these signals are selected differs from one simulator
to the other; there might be different ways to select signals even within
the same simulator. Some simulators are graphical. All signals in the
system are displayed in graphical fashion; the user selects the signals and
assigns initial values for them. The user then clicks a button to run the
simulation, and a simulation screen appears showing the waveform of
the selected signals. Some other simulators allow the user to write HDL
code, called test bench, for testing the source code.
6. After the simulation verifies that the signals behave as expected, the
compiled code can be synthesized. The simulator CAD package usu-
ally has a synthesizer. The synthesizer converts the compiled code into
a schematic and generates a net list. However, due to limitation in the
available synthesizers, some statements may not be synthesized and the
user may opt to change these statements if possible. The net list can be
downloaded onto a chip, usually field-programmable gate arrays. Chap-
ter 10 illustrates how to convert the HDL code to gate level or RTL, the
forms closest to the schematic original that the synthesizer can down-
load onto the chip.
Appendix A shows example of Steps 1–6 including a test bench.
Data Types
VHDL: Definitely a type-oriented language, and VHDL types are built
in or users can create and define them. User-defined types give the user
a tool to write the code effectively; these types also support flexible
coding. VHDL can handle objects with multidimensional array types.
Another data type that VHDL supports is the physical type; the physi-
cal type supports more synthesizable or targeted design code.
Verilog: Compared to VHDL, Verilog data types are very simple and
easy to use. All types are defined by the language.
Ease of Learning
VHDL: For beginners, VHDL may seem hard to learn because of its
rigid type requirements. Advanced users, however, may find these rigid
type requirements easier to handle.
Verilog: Easy to learn, Verilog users just write the module without
worrying about what library or package should be attached. Many of
the statements in the language are very similar to those in C language.
1.9 Summary
In this chapter, several introductory VHDL and Verilog topics have
been covered. The structure of the HDL module was discussed. The
VHDL module has two major constructs: an entity and architecture,
which are bound to the entity. Verilog has a module construct.
Operators, which perform a wide variety of operations, have been cov-
ered. Arithmetic operators (see summary in Table 1.15) perform arithme-
tic operations such as multiplication and division. Relational operators (see
summary in Table 1.16) perform comparisons such as greater than and
equality. Shift operators (see summary in Table 1.17) perform bit shifts
such as a logical shift (a specified number of bit positions) right. Logical
operators (see summary in Table 1.18) perform logical operations such as
AND.
Data types have also been covered, including bit, std_logic, std_log-
ic_vector, and array (for VHDL), and real, integer, reg, and wire (for
Verilog). The following description styles have been briefly contrasted: data
flow, behavioral, structural, switch level, mixed type, and mixed language.
Finally, a brief comparison of VHDL and Verilog has been presented.
TABLE 1.15 Summary of Arithmetic Operators for VHDL and Verilog
1.10 Exercises
2
DATA-FLOW DESCRIPTION
Chapter Objectives
O Understand the concept of data-flow description in both VHDL and
Verilog
O Understand events and concurrent statements
O Identify the basic statements and components of data-flow descrip-
tion such as logical operators, signal-assignment statements, the
assign statement, time delays, and vectors
O Review and understand K-maps, Boolean function, and fundamen-
tals of some digital logic systems such as full adder, full subtractor,
2x1 multiplexer, 2x2 combinational multiplier, two-bit comparator,
delay latch, ripple-carry adder, and carry-lookahead adder
a s1
b
b
AND-OR y y
c c
d s2
Verilog description
module andor (a,b,c,d, y );
input a,b,c,d;
output y;
wire s1, s2; / wire statement here is not necessarily
needed since s1 and s2 are single bit/
assign s1 = a & b; //statement 1.
assign s2 = c & d; //statement 2.
assign y = s1 | s2; //statement 3.
endmodule
Using a CAD package with HDL simulator (see Appendix A), the code
in Listing 2.1 can be simulated on the screen of the computer, and a wave-
form showing a graphical relationship between the input and the output
can be obtained. Figure 2.2 shows such a waveform.
b
c
y
s1
s2
T0 T1 T2
FIGURE 2.2 Simulation waveform for the AND-OR circuit shown in Figure 2.1.
Referring to Listing 2.1, the input and output signals are declared in
the entity (module) as ports. In HDL, a signal has to be declared before it
can be used (although in Verilog, it is not necessarily needed if the signal is
42 • HDL WITH DIGITAL DESIGN
In the above Verilog statement, there are no explicit units of time; 100
means 100 simulation screen time units. If the simulation screen time units
are defined as nanoseconds (ns), for example, then 100 will mean 100 nanosec-
onds. The declaration and assignment can be combined in one statement as:
Constant period : time := 100 ns; -- VHDL
time period = 100 //Verilog
44 • HDL WITH DIGITAL DESIGN
Verilog description
module and_orDlyVr( a,b,c,d, y );
input a,b,c,d;
output y;
time dly = 10;
wire s1, s2;
/ wire above is not necessarily needed
since s1 and s2 are single bit/
assign # dly s1 = a & b; //statement 1.
assign # dly s2 = c & d; //statement 2.
assign # dly y = s1 | s2; //statement 3.
endmodule
DATA-FLOW DESCRIPTION • 45
b
c
s1
s2
10 10 10 10 10
ns ns ns ns ns
T0 T1 T2 T3 T4 T5 T6 T7 T8
FIGURE 2.3 Simulation waveform of Listing 2.2.
Figure 2.3 shows the simulation waveform of Listing 2.2. Table 2.1
shows analysis of the waveform according to Listing 2.2. At T0, an event oc-
curred on signal a and signal b (both changed from 0 to 1). This event will
invoke execution of statement 1. The right-hand side (R.H.S) of statement
1 is calculated at T0 as (1 and 1 = 1). However, this value of 1 will not as-
signed to s1 at T0; rather, it will be assigned at T0 + 10 ns = T1. The rest of
Table 2.1 could be understood by following the same analysis that has been
done above at T0.
TABLE 2.1 Analysis of Waveform of Figure 2.3
(Contd.)
46 • HDL WITH DIGITAL DESIGN
Input Output
a b c Carryout Sum
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1
DATA-FLOW DESCRIPTION • 47
The Boolean function of the Sum and Carryout can be obtained from
K-maps as shown in Figure 2.4.
bc 00 01 11 10
a
0 1 1
1 1 1
bc 00 01 11 10
a
0 1
1 1 1 1
a Sum
Full
b
adder
c
Carryout
(a)
a a' b b' c c'
a'
b'
c a
b
a'
b
c'
a
Sum Carryout
c
a
b''
c
b
c
a
b
c
(a)
FIGURE 2.5 A full Adder. a) Logic symbol. b) Logic diagram.
The full adder can be built from several existing logic components such
as two half adders and multiplexers (see Exercise 2.1 at the end of this
chapter). Building a full adder from two half adders is based on the follow-
ing analysis.
The full adder adds a plus b plus c = carryout sum. If the addition is
performed in two steps: a plus b = C1 S, and c plus S = C2 sum (sum is the
sum of the three bits). C1 and C2 cannot have a value of 1 at the same time.
If C1 has value of 1, then C2 has to be 0 and vice versa. For example, to
add 1 plus 1 plus 1, divide the addition in two halves; the first half is 1 plus
1 = 10, and the second half is 0 plus 1 = 1. The carryout will be (C1 or C2);
in this example, it is 1 and the sum = 1. Figure 2.6 shows the logic diagram
of the full adder built from two half adders.
DATA-FLOW DESCRIPTION • 49
a
Sum
b
c Half adder
Half adder
Carryout
Listing 2.3 shows the HDL code for the full adder as shown in
Figure 2.5. Review Section 1.5.1 to know the VHDL and Verilog logical
operators. The code assumes no delay time. The parenthesis in the code, as
in C language, gives the highest priority to the expression within the paren-
thesis and makes the code more readable.
LISTING 2.3 HDL Code of the Full Adder From Figure 2.5
VHDL description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fulladder is
Port ( a,b,c : in std_logic;
sum, Carryout : out std_logic);
end fulladder;
architecture flad_dtfl of fulladder is
begin
Sum <= (not a and not b and c) or
(not a and b and not c) or
(a and not b and not c) or
(a and b and c);
Carryout <= (a and b) or (a and c) or (b and c);
end flad_dtfl;
Verilog description
module fulladder(a, b, c);
output Sum, Carryout;
input a, b, c;
assign Sum = (~ a & ~ b & c)|( ~ a & b & ~c)|
( a & ~b & ~c)|( a & b & c) ;
Figure 2.7 shows the waveform of a full adder with no delay time.
a
b
Sum
Carryout
FIGURE 2.7 Simulation waveform of a full adder with no delay time.
Input Output
a b c Borrow Diff
0 0 0 0 0
0 0 1 1 1
0 1 0 1 1
0 1 1 1 0
1 0 0 0 1
1 0 1 0 0
1 1 0 0 0
1 1 1 1 1
Compare the Diff in Table 2.3 and the Sum in Table 2.2; they are iden-
tical, so the Boolean function of the Diff is the same as the sum in Equation
2.3. For the Borrow, draw the K-map as shown in Figure 2.8.
DATA-FLOW DESCRIPTION • 51
bc 00 01 11 10
a
0 0 1 1 1
1 0 0 1
Input Output
SEL Gbar Y
X H L
L L A
H L B
If the enable (Gbar) is high (1), the output is low (0) regardless of the
input. When Gbar is low (0), the output is A if SEL is low (0), or the output is
B if SEL is high (1). From Table 2.4, the Boolean function of the output Y is:
Y = (S1 and A and SEL) or (S1 and B and SEL); S1 is the invert of Gbar
52 • HDL WITH DIGITAL DESIGN
Figure 2.9a shows the logic symbol, and Figure 2.9b shows the gate-
level structure of the multiplexer.
Gbar
A A S4
2x1 Y Y
Mux
B
B SEL
S2 S3 S5
SEL Gbar
S1
(a) (b)
FIGURE 2.9 2x1 Multiplexer. a) Logic symbol. b) Logic diagram.
Listing 2.4a shows the HDL code. To generate the code, follow Figure
2.9b. Propagation delay time for all gates is assumed to be 7 ns. Because
this is a data-flow description, the order in which the statements are written
in the code is irrelevant. For example, statement st6 could have been writ-
ten at the very beginning instead of statement st1. The logical operators
in VHDL and (Verilog) implemented in this Listing are: OR (|), AND (&),
and NOT (~).
Verilog Description
module mux2x1 (A, B, SEL, Gbar, Y);
input A, B, SEL, Gbar;
output Y;
wire S1, S2, S3, S4, S5;
time dly = 7;
/ Assume 7 time units delay for all and, or, not operations. The
delay here is expressedin simulation screen units. /
Figure 2.10 shows the simulation waveform for the 2x1 multiplexer.
SEL
Gbar
Y
time
T0 T1 T2 T3 T4 T5
100 ns
200 ns
228 ns
300 ns
321 ns
114 ns
// Verilog:
assign # 21 Y = ~ (Gbar) & ((SEL & B ) | (~ SEL & A));
LISTING 2.4b HDL Code of a 2x1 Multiplexer Using Verilog Conditional (?)
module Mux2x1_conditional(input A,B,SEL,Gbar, output Y );
assign Y = (Gbar) ? 1’b0 : (SEL & B ) | (~ SEL & A);
endmodule
Inputs Outputs
b a D3 D2 D1 D0
0 0 0 0 0 1
0 1 0 0 1 0
1 0 0 1 0 0
1 1 1 0 0 0
From Table 2.5, the Boolean function of the outputs can be written as:
D0 = a b
D1 = a b
D2 = a b
D3 = a b
Figure 2.11 shows the logic symbol and logic diagram of the decoder.
56 • HDL WITH DIGITAL DESIGN
D0
D0
a D1
a
b D2 D1
2x4
Decoder
D3 D2
b D3
Verilog description
module decoder2x4( a, b, D);
input a,b;
output [3:0]D;
assign D[0] = ~a & ~ b;
assign D[1] = a & ~ b;
assign D[2] = ~a & b;
assign D[3] = a & b;
endmodule
DATA-FLOW DESCRIPTION • 57
a1 a0 b1 b0 P3 P2 P1 P0
0 0 x x 0 0 0 0
x x 0 0 0 0 0 0
0 1 0 1 0 0 0 1
0 1 1 0 0 0 1 0
0 1 1 1 0 0 1 1
1 0 0 1 0 0 `1 0
1 0 1 0 0 1 0 0
1 0 1 1 0 1 1 0
1 1 0 1 0 0 1 1
1 1 1 0 0 1 1 0
1 1 1 1 1 0 0 1
x- indicates don’t care
DATA-FLOW DESCRIPTION • 59
b1b0 00 01 11 10
a1a0
00
01 1 1
11 1 1
10
P0 = f(a1,a0,b1,b0) = (5,7,13,15)
b1b0 00 01 11 10
a1a0
00
01 1 1
11 1 1
10 1 1
P1 = f(a1,a0,b1,b0) = (6,7,9,11,13,14)
b1b0 00 01 11 10
a1a0
00
01
11 1
10 1 1
P2 = f(a1,a0,b1,b0) = (10,11,14)
FIGURE 2.13 K-maps of 2x2 Combinational Multiplier.
60 • HDL WITH DIGITAL DESIGN
From the K-maps and Table 2.6, the product can be written as:
P0 = a0 b0
P1= a1 a0 b1 + a0 b0 b1 + a1 b0 b1 + a0 a1 b0
P2= a0 a1 b1 + a1 b0 b1
P3= a0 a1 b0 b1
Figure 2.14a shows the logic symbol, and Figure 2.14b shows the logic
diagram of the multiplier. The HDL code is shown in Listing 2.5, and the
simulation waveform is shown in Figure 2.15.
2
a0 a0' b0 b0' a1 a1' b1 b1'
a
b0'
a0'
b0
b1
b1
b1
a0
a1
a1
a1
b0
a0
a1'
a0
b1
4
2x2 P
a1
b0'
b1
Multiplier
a1
b0
b1'
2 a0'
b a1
b0
P3 P2 P1 P0
(a) S(b)
FIGURE 2.14 2x2 combinational multiplier. a) Logic symbol. b) Logic diagram.
LISTING 2.5 HDL Code for a 2x2 Unsigned Combinational Array Multiplier:
VHDL and Verilog
VHDL Description
--For simplicity, propagation delay times are not
-- considered here.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mult_comb is
port ( a,b: in std_logic_vector (1 downto 0);
P : out std_logic_vector ( 3 downto 0));
end mult_comb;
architecture mult_dtfl of mult_comb is
begin
P(0) <= a(0) and b(0);
P(1) <= (not a(1) and a(0) and b(1)) or
DATA-FLOW DESCRIPTION • 61
Verilog Description
module mult_arry (a, b, P);
input [1:0] a, b;
output [3:0] P;
/For simplicity, propagation delay times are not
considered in this example./
assign P[0] = a[0] & b[0];
assign P[1] = (~a[1] & a[0]& b [1]) |
(a[0] & ~b[0]& b [1])|
(a[1] & b[0]& ~b [1]) |
(~a[0] & a[1]& b [0]);
assign P[2] = (~a[0] & a[1]& b [1]) |
(a[1] & ~b[0]& b [1]);
assign P[3] = (a[0] & a[1]& b[0] & b [1]);
a 0 1 2 3
b 0 1 2 3 1 2 3 1 2 3
P 0 1 2 3 2 4 6 3 6 9
FIGURE 2.15 Simulation output for a two-bit multiplier.
D Q
D-Latch
E Qbar
DQ 00 01 11 10
E
0 0 1 1 0
1 0 0 1
Q = f(E,D,Q) = ∑(1,3,6,7)
FIGURE 2.17 K-map for Q.
From Figure 2.17, Q and Qbar are found:
Q EQ ED
Qbar = Q
Figure 2.18 shows the logic diagram of D-latch; the diagram is drawn to
be identical to that of the chip 74LS75.
D
E
Qbar
entity D_Latch is
port (D, E : in std_logic;
Q, Qbar : buffer std_logic);
end D_Latch;
Verilog Description
module D_latch (D, E, Q, Qbar);
input D, E;
output Q, Qbar;
time Delay_EorD = 9;
time Delay_inv = 1;
assign #Delay_EorD Qbar = ~((E & D) | (~E & Q));
assign #Delay_inv Q = ~ Qbar;
endmodule
DATA-FLOW DESCRIPTION • 65
9 ns
Q
1 ns
Qbar
X(0)
X>Y
X(1)
2x2
X=Y
Comparator
Y(0)
X<Y
Y(1)
Input Output
X(1) X(0) Y(1) Y(0) X>Y X<Y X=Y
0 0 0 0 0 0 1
0 0 0 1 0 1 0
0 0 1 0 0 1 0
0 0 1 1 0 1 0
0 1 0 0 1 0 0
0 1 0 1 0 0 1
0 1 1 0 0 1 0
0 1 1 1 0 1 0
1 0 0 0 1 0 0
1 0 0 1 1 0 0
1 0 1 0 0 0 1
1 0 1 1 0 1 0
1 1 0 0 1 0 0
1 1 0 1 1 0 0
1 1 1 0 1 0 0
1 1 1 1 0 0 1
If the number of bits increases, the table becomes huge, and other ap-
proaches should be used, such as implementation of n-full adders to con-
struct n×n comparators (see Chapter 4). After constructing the truth table,
K-maps are used (see Figure 2.21) to obtain the minimized Boolean func-
tion of the output of the comparator. Listing 2.7 shows the HDL descrip-
tion. The simulation waveform is shown in Figure 2.22.
Y( Y(
X( 1)Y( 00 01 11 10 X(
1)Y
00 01 11 10
1)X 0) 1)X (0)
(0) (0)
00 00 1 1 1
01 1 01 1 1
11 1 1 1 11
10 1 1 10 1
X>Y X<Y
FIGURE 2.21 K-maps for Table 2.4.
DATA-FLOW DESCRIPTION • 67
entity COMPR_2 is
port (x, y : in std_logic_vector(1 downto 0);
xgty, xlty : buffer std_logic;
xeqy : out std_logic);
end COMPR_2;
xlty <= (y(1) and not x(1)) or ( not x(0) and y(0)
and y(1)) or (not x(0) and not x(1) and y(0));
xeqy <= xgty nor xlty;
end COMPR_DFL;
Verilog Description
module compr_2 (x, y, xgty, xlty, xeqy);
input [1:0] x, y;
output xgty, xlty, xeqy;
assign xgty = (x[1] & ~ y[1]) | (x[0] & ~ y[1]
& ~ y[0]) | (x[0] &
x[1] & ~ y[0]);
assign xlty = (y[1] & ~ x[1] ) | (~ x[0] &
y[0] & y[1]) |(~ x[0] &
~ x[1] & y[0]);
assign xeqy = ~ (xgty | xlty);
endmodule
68 • HDL WITH DIGITAL DESIGN
X 0 1 2 3
Y 0 1 2 3 1 2 3 1 2 3
X>Y
X<Y
X=Y
c(1) c(0)
cout one-bit adder one-bit adder one-bit adder cin
Carry Generator
Listings 2.8 and 2.9 show the HDL code for the ripple-carry adder and
the carry-lookahead adders, respectively. A 4.0-ns delay is assumed for all
gate types. A constant of type time delay_gt is declared, and 4 ns is as-
signed to it:
constant delay_gt : time := 4 ns; -- VHDL
time delay_gt = 4; // Verilog
LISTING 2.8 Three-Bit Ripple-Carry Adder Case Study
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity adders_RL 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 adders_RL;
begin
sum(0) <= (x(0) xor y(0)) xor cin after 2delay_gt;
Verilog Description
module adr_rcla (x, y, cin, sum, cout);
input [2:0] x, y;
input cin;
output [2:0] sum;
output cout;
// I. RIPPLE CARRY ADDER
wire c0, c1;
time delay_gt = 4;
//Assume 4.0-ns propagation delay for all gates.
begin
Verilog Description
// II. CARRY-LOOKAHEAD ADDER
module lkahd_adder (x, y, cin, sum, cout);
input [2:0] x, y;
input cin;
output [2:0] sum;
output cout;
/Assume 4.0-ns propagation delay for all gates
including a 3-input xor./
Figure 2.25 shows the waveform for both ripple-carry and carry-looka-
head adders without taking gate delay into consideration. Because there is
no delay, the two adders have identical waveforms. From the waveform, it
can be concluded that both adders are functioning correctly. Figures 2.26a
and 2.26b show the waveforms for ripple-carry and carry-lookahead after
taking the gate delay into consideration, respectively.
x 7 6 5 4 3 2 1 0 2 1 0
y 5 4
cin
sum 4 3 2 1 0 7 6 5 7 6 5
cout
FIGURE 2.25 Simulation waveform for a three-bit adder with no gate delay.
x 000 101
y 000 011
cin
cout
3x8 = 24 ns
(a)
74 • HDL WITH DIGITAL DESIGN
x 000 101
y 000 011
cin
cout
4x4 = 16 ns
(b)
FIGURE 2.26 Simulation waveforms for three-bit adders with a 4-ns gate delay. a) Ripple-carry adder. b)
Carry-lookahead adder.
To calculate the worst delay, values are selected for the inputs x, y, and
cin to obtain the maximum possible delay; this is done by selecting those
values that cause a change in all the carryout signals. The values x = y = cin
= 0 are selected to generate a zero signal on all the outputs, and then the
values x = 5, y = 3, and cin = 1. In Figure 2.26a, the total worst delay is 24
ns. Because there are three one-bit adders, and each has a worst delay of 8
ns (two XOR gates), the total worst delay is 8 × 3 = 24 ns, which is equal to
the number of one-bit adders times the delay of one one-bit adder.
In Figure 2.26b, the total worst delay is 16 ns, which is four times the
delay of a single gate (4 ns). If the number of input bits of the lookahead
adder is increased, the total worst delay is still the same 16 ns. More adders
will be discussed in Chapter 4.
may not terminate the program, but the outcome of the program may not
be as expected.
Code Error
entity mult_comb The word is is missing
port (a; b : in std_logic_vector(1 downto 0)); Semicolon is inserted
instead of comma (a, b)
P : std_logic_vector (3 downto 0) The direction of the port P
is missing (out)
architecture MULT_DF of mult_cmb is The name of the entity is
misspelled: it should be
(mult_comb)
P(0) = a(0) and b(0); The signal-assignment
statement operator is wrong
(“<=” should replace “=”)
P(3) <= a(0) and a(1) b(0) and b(1); The “and” operator is
missing in a(1)b(0);
P(0) <= a(0) and b(2); The index of “b” is out of
range: it should be 0 or 1
end MUL_DF; The name of the architec-
ture is misspelled: it should
be MULT_DF
P(0) <= a(0) and b0; b0 is not the same as b(0)
--No Library listed on first line of code
entity errors is
port (t, t1: in std_logic ; IEEE.STD_LOGIC_1164.
b,c: out std_logic); ALL Library has to be
end errors; entered to use std-logic
architecture Behavioral of errors is
begin
b <= t; b should be declared as
c <=b; buffer since it is appearing
Behavioral; on both right- and left-hand
end
76 • HDL WITH DIGITAL DESIGN
2.5 Summary
This chapter discussed data-flow descriptions based mainly on writing
the Boolean function(s) of the system. The Boolean function is coded as sig-
nal-assignment statements. In VHDL, the signal-assignment operator <= is
implemented to assign a value to a signal; in Verilog, the signal-assignment
operator is assign. Logical operators such as and (&), or (|), and xor
(^) have been implemented to describe the Boolean function in VHDL
(Verilog) code. The following table summarizes the commands that have
been used in this Chapter. Table 2.11 lists data-flow commands/compo-
DATA-FLOW DESCRIPTION • 77
2.6 Exercises
endmodule
T=100 T=150 T=165 T=200 T=250 T=300
a 1 0 0 1 0 1
b 1 1 1 0 0 1
s1 0
s2 0
Explain how you obtained the values for s1 and s2 at time T = 165 ns.
Translate the Verilog code to VHDL.
4. Referring to Case Study 2.1, increase the number of bits from three
to four. Derive the Boolean functions of both the ripple-carry and the
carry-lookahead adders. Simulate the adders and calculate the worst
delay between the input and output using Verilog description. Contrast
your results with Figure 2.16 and explain.
5. The following VHDL code describes an SR-latch. Translate the code to
Verilog.
entity SR is
port (S, R : in bit; Q : buffer bit; Qb : out bit);
end SR;
architecture SR_DtFL of SR is
begin
Q <= S or (not R and Q);
Qb <= not Q;
end SR_DtFL;
6. Describe a system that divides D/V to give a quotient, Q, and Remain-
der, R. The dividend, D, is three bits; the divisor, V, is two bits. If
V = 0, set a flag Z to 1. Write the truth table of the system and obtain the
Boolean functions of Q, R, and Z. Use VHDL and Verilog to describe
the system.
7. Change the multiplier in Example 2.5 to multiply XY where X is three
bits and Y is two bits. Find the Boolean function of the output and de-
scribe the system using VHDL and Verilog.
8. Write the VHDL and Verilog code describing the full subtractor shown
in Example 2.2.
9. Use the conditional operator in Example 2.3b to describe a 2x1 multi-
plexer with active high enable. If the enable is inactive (low), the output
CHAPTER
3
BEHAVIORAL DESCRIPTION
Chapter Objectives
O Understand the concept of sequential statements and how they dif-
fer from concurrent statements
O Identify the basic statements and components of behavioral de-
scriptions such as process, variable-assignment statements if,
case, casex, casez, when, report, $display, wait, loop,
exit, next, always, repeat, forever, and initial
O Review and understand the basics of digital logic systems such as D
flip-flop, JK flip-flop, T flip-flop, binary counters, and shift register
O Understand the concept of some basic genetic and renal systems
O Both VHDL and Verilog descriptions are discussed
Facts
Q The behavioral description describes the system by showing how out-
puts behave with the changes in inputs.
Q In this description, details of the logic diagram of the system are not
needed; what is needed is how the output behaves in response to a
change in the input.
Q In VHDL, the major behavioral-description statement is process. In
Verilog, the major behavioral-description statements are always and
initial.
Q For VHDL, the statements inside the process are sequential. In Verilog,
all statements are concurrent (see “Analysis of VHDL Code” in Ex-
ample 3.5).
VHDL Verilog
Event on I1 Event on I1
activates the activates
process ALWAYS
I1 I1
I2 I2
10 ns 10 ns
O1 O1
O2 O2
Referring to the Verilog code in Listing 3.1, always is the Verilog behav-
ioral statement. In contrast to VHDL, all Verilog statements inside always
are treated as concurrent, the same as in the data-flow description (see
82 • HDL WITH DIGITAL DESIGN
Section 2.2). Also, here any signal that is declared as an output or appears
at the left-hand side of a signal-assignment statement should be declared
as a register (reg) if it appears inside always. In Listing 3.1, O1 and O2 are
declared outputs, so they should also be declared as reg.
end half_add;
architecture behave_ex of half_add is
begin
process (I1, I2)
begin
O1 <= I1 xor I2 after 10 ns; -- statement 1
O2 <= I1 and I2 after 10 ns; -- statement 2
-- The above two statements are signal-assignment
-- statements with 10 nanoseconds delays.
--
--Other behavioral (sequential) statements can be added
-- here
end process;
end behave_ex;
Verilog Description
module half_add (I1, I2, O1, O2);
input I1, I2;
output O1, O2;
reg O1, O2;
/ Since O1 and O2 are outputs and they are
written inside “always,” they should be
declared as reg /
Varb: process(t1)
Signl: process(t1) variable temp1, temp2: bit;
begin begin
st1: S1 <= t1; st3: temp1: = t1;
st2: S2 <= not S1; st4: temp2: = not temp1;
end process; st5: S1 <= temp1;
st6: S2 <= temp2;
end process;
t1
t1
temp1
S1
temp2
S2
S1
T0 T1
S2
T0 T1
FIGURE 3.2 Signal versus variable in VHDL.
3.4.1 IF Statement
IF is a sequential statement that appears inside process in VHDL or
inside always or initial in Verilog. It has several formats, some of which
are as follows:
VHDL IF-Else Formats
if (Boolean Expression) then
statement 1;
statement 2;
statement 3;
.......
else
statement a;
statement b;
statement c;
.......
end if;
Verilog
if (clk == 1’b1)
// 1’b1 means 1-bit binary number of value 1.
temp = s1;
else
temp = s2;
Verilog
if (clk == 1)
begin
temp = s1;
end
Verilog
if (Boolean Expression1)
begin
statement1; statement 2;.....
end
else if (Boolean expression2)
begin
statementi; statementii;.....
end
else
begin
statementa; statement b;....
end
Verilog
if (signal1 == 1’b1)
temp = s1;
else if (signal2 == 1’b1)
88 • HDL WITH DIGITAL DESIGN
temp = s2;
else
temp = s3;
Read
input d,E
d Q
NO Q,Qb retain
E = 1? previous values
D-Latch
YES
E Qb Q=d
Qb = not Q
(a) (b)
FIGURE 3.3 D-Latch. a) Logic symbol. b) Flowchart.
Figure 3.4 shows the waveform for Listing 3.2. Clearly, from the wave-
form, the code correctly describes a D-latch where Q follows d when E is
high; otherwise, d retains its previous value. Also, Qb is the invert of Q at all
90 • HDL WITH DIGITAL DESIGN
times.
Q
Qb
Next, the same VHDL code from Listing 3.2 is rewritten using signal-assign-
ment statements. Listing 3.3 shows the VHDL behavioral code for a D-Latch
using signal-assignment statements.
LISTING 3.3 VHDL Code for Behavioral Description of a D-Latch Using
Signal-Assignment Statements
entity Dltch_sig is
port (d, E : in bit; Q : buffer bit; Qb : out bit);
--Q is declared as a buffer because it is an
--input/output signal; it appears on both the left
-- and right hand sides of assignment statements.
end Dltch_sig;
architecture DL_sig of Dltch_sig is
begin
process (d, E)
begin
if E = ‘1’ then
Q <= d; -- signal assignment
Qb <= not Q; -- signal assignment
end if;
end process;
end DL_sig;
Figure 3.5 shows the simulation waveform of Listing 3.3. The figure shows Q is
following Qb, which is an error because Qb should be the invert of Q. This error
is due to the sequential execution of the signal-assignment statements in the
behavioral description (see details below).
BEHAVIORAL DESCRIPTION • 91
Qb
output Q, Qb;
reg Q, Qb;
always @ (d, E)
begin
if (E == 1)
begin
Q = d;
Qb = ~ Q;
end
end
endmodule
Read
A, B, SEL,
Gbar
Gbar NO Y = high
Gbar = 0?
Impedance
A YES
YES
B
Y=B
SEL
(a) (b)
FIGURE 3.6 2x1 Multiplexer. a) Logic symbol. b) Flow chart.
-- multiplexer.
begin
if Gbar = ‘0’ then
if SEL = ‘1’ then
temp := B;
else
temp := A;
end if;
--Now assign the variable temp to the output
Y <= temp;
else
Y <= ‘Z’;
end if;
end process;
end MUX_bh;
Verilog Description
module mux2x1 (A, B, SEL, Gbar, Y);
input A, B, SEL, Gbar;
output Y;
reg Y;
always @ (SEL, A, B, Gbar)
begin
if (Gbar == 1)
Y = 1’bz;
else
begin
if (SEL)
Y = B;
else
Y = A;
end
end
endmodule
LISTING 3.6 HDL Description of a 2x1 Multiplexer Using Else-IF
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity MUXBH is
BEHAVIORAL DESCRIPTION • 95
Verilog Description
module MUXBH (A, B, SEL, Gbar, Y);
input A, B, SEL, Gbar;
output Y;
reg Y; / since Y is an output and appears inside
always, Y has to be declared as reg( register) /
SEL
Gbar
High impedance
FIGURE 3.7 Simulation waveform of a 2x1 multiplexer.
If, for example, test value1 is true (i.e., it is equal to the value of the
control expression), statements1 is executed. The case statement must
include all possible conditions (values) of the control-expression. The
statement when others (VHDL) or default (Verilog) can be used to
guarantee that all conditions are covered. The case resembles IF except
the correct condition in case is determined directly, not serially as in IF
statements. The begin and end are not needed in Verilog if only a single
BEHAVIORAL DESCRIPTION • 97
statement is specified for a certain test value. The case statement can be
used to describe data listed into tables.
Verilog
case sel
2’b00 : temp = I1;
2’b01 : temp = I2;
2’b10 : temp = I3;
default : temp = I4;
endcase
In Example 3.7, the control is sel. If sel = 00, then temp = I1, if sel
= 01, then temp = I2, if sel = 10, then temp = I3, if sel = 11 (others or de-
fault), then temp = I4. All four test values have the same priority; it means
that if sel = 10, for example, then the third (VHDL) statement (temp :=
I3) is executed directly without checking the first and second expressions
(00 and 01).
J Q
JK
Flip-
Flop
0x 1x x0
K
Qb
0 1
clk x1
(a) (b)
FIGURE 3.8 JK flip-flop. a) Logic symbol. b) State diagram.
Table 3.2 shows the excitation table of the JK flip-flop. It conveys the
same information as the state diagram. The state diagram (Figure 3.8b)
shows the possible states (two in this case: q can take 0 or 1), state 0 and
state 1. The transition between these states has to occur only at the positive
edges of the clock. If the current state is 0 (q = 0), then the next state is 0(1)
if JK = 0x(1x), where x is “don’t care.” If the current state is 1 (q = 1), then
the next state is 1(0) if JK = x0(x1). Table 3.2 shows the same results as the
state diagram. For example, a transition from 0 to 1, according to the excita-
tion table, can occur if JK = 10 or JK = 11, which is JK = 1x.
TABLE 3.2 Excitation Table of a Positive Edge-Triggered JK Flip-Flop
JK 01 10 00 11
clk
Qb
FIGURE 3.9 Simulation waveform of a positive edge-triggered JK flip-flop.
LISTING 3.7 HDL Code for a Positive Edge-Triggered JK Flip-Flop Using the
case Statement
VHDL Description
library ieee;
use ieee.std_logic_1164.all;
entity JK_FF is
port(JK : in bit_vector (1 downto 0);
clk : in std_logic; q, qb : out bit);
end JK_FF;
architecture JK_BEH of JK_FF is
begin
P1 : process (clk)
variable temp1, temp2 : bit;
begin
if rising_edge (clk) then
100 • HDL WITH DIGITAL DESIGN
case JK is
when “01” => temp1 := ‘0’;
when “10” => temp1 := ‘1’;
when “00” => temp1 := temp1;
when “11” => temp1 := not temp1;
end case;
q <= temp1;
temp2 := not temp1;
qb <= temp2;
end if;
end process P1;
end JK_BEH;
Verilog Description
module JK_FF (JK, clk, q, qb);
input [1:0] JK;
input clk;
output q, qb;
reg q, qb;
always @ (posedge clk)
begin
case (JK)
2’d0 : q = q;
2’d1 : q = 0;
2’d2 : q = 1;
2’d3 : q =~ q;
endcase
qb =~ q;
end
endmodule
count from 0 to 9 (Mod10). Synchronous clear means that clear resets the
counter when the clock is active; in contrast, asynchronous clear resets the
counter instantaneously. The counter can be depicted by a flowchart show-
ing its function (see Figure 3.10). Although the flowchart here represents
a counter, it could have represented any other system with the same be-
havior. The excitation table for the three-bit binary counter is as shown in
Table 3.3. The logic symbol is shown in Figure 3.10a.
Read
current state
NO
+ve edge
(clk)?
YES
q2 q1 q0 clear = 1? Q=0
YES
NO
Three-bit counter
TABLE 3.3 Excitation Table of a Three-Bit Binary Counter with Synchronous Active High Clear
Input Output
clk clr Current State Next State
H xxx 000
L 000 001
L 001 010
102 • HDL WITH DIGITAL DESIGN
Input Output
clk clr Current State Next State
L 010 011
L 011 100
L 100 101
L 101 110
L 110 111
L 111 000
L x hold
The most efficient approach to describe the above counter is to use the
fact that the next state is the increment of the present for upward counting.
The goal here, however, is to use the case statement. Table 3.3 is treated as
a look-up table. Listing 3.8 shows the HDL code for the counter. To assign
initial values, such as 101, to the count at the start of simulation in Verilog,
the procedural initial is used as follows:
initial
begin
q = 3’b101;
end
The begin and end can be omitted if there is a single initial state-
ment.
In VHDL, the initial value is assigned to the variable temp after the
statement process, as shown:
ctr : process (clk)
variable temp : std_logic_vector (2 downto 0) := “101”;
begin
Any value assigned to a variable written between process and its begin
is acquired only once at the beginning of the simulation; subsequent execu-
tion of the process will not reassign that value to the variable unless a new
simulation is executed. Figure 3.11 shows the simulation waveform of the
counter.
LISTING 3.8 HDL Code for a Three-Bit Binary Counter Using the case
Statement
VHDL Description
library IEEE;
BEHAVIORAL DESCRIPTION • 103
use IEEE.STD_LOGIC_1164.ALL;
entity CT_CASE is
port (clk, clr : in std_logic;
q : buffer std_logic_vector (2 downto 0));
end CT_CASE;
architecture ctr_case of CT_CASE is
begin
ctr : process(clk)
variable temp : std_logic_vector (2 downto 0) := “101”;
--101 is the initial value, so the counter starts from
-- 110
begin
if rising_edge (clk) then
if clr = ‘0’ then
case temp is
when “000” => temp := “001”;
when “001” => temp := “010”;
when “010” => temp := “011”;
when “011” => temp := “100”;
when “100” => temp := “101”;
when “101” => temp := “110”;
when “110” => temp := “111”;
when “111” => temp := “000”;
when others => temp := “000”;
end case;
else
temp := “000”;
end if;
end if;
q <= temp;
end process ctr;
end ctr_case;
Verilog Description
module CT_CASE (clk, clr, q);
input clk, clr;
output [2:0] q;
reg [2:0] q;
initial
/ The above initial statement is to force
the counter to start from initial count q=110 /
104 • HDL WITH DIGITAL DESIGN
q = 3’b101;
always @ (posedge clk)
begin
if (clr == 0)
begin
case (q)
3’d0 : q = 3’d1;
3’d1 : q = 3’d2;
3’d2 : q = 3’d3;
3’d3 : q = 3’d4;
3’d4 : q = 3’d5;
3’d5 : q = 3’d6;
3’d6 : q = 3’d7;
3’d7 : q = 3’d0;
endcase
end
else
q = 3’b000;
end
endmodule
clk
clr
q 5 6 7 0 1 0 1 2 3 4 5
FIGURE 3.11 Simulation waveform of a three-bit positive edge-triggered counter with active high
synchronous clear.
ther) and 23 maternal (from the mother). Sex cells (sperm and ova) each
contain half the total number of chromosomes (i.e., 23).
Q Deoxyribonucleic acid (DNA): A polymer of deoxyribonucleotides
in the form of a double helix. It is the genetic molecule of life and codes
the sequence of amino acids in proteins. Only identical twins have iden-
tical DNA. Otherwise, DNA differs from one person to another.
Q Gametes: Sex cells that contain half of the number of chromosomes.
In humans, these cells comprise the genetic makeup of eggs and sperm.
Each gamete cell contains 23 chromosomes. When a male mates with a
female, the two sex cells (egg and sperm) combine to form a single cell
called a zygote. Gametes for blood types have a single allele: A, B, or O.
Q Gene: A heritable unit in a chromosome, it is a series of nucleotide
bases on the DNA molecule that codes for polypeptides (chains of
amino acids). Humans have about 30,000 genes.
• Allele: An alternate form of a gene.
• Codominant alleles: Both alleles are expressed equally. The alleles
for blood types A and B are codominant. If combined from a male
and a female, the children will be blood type AB.
• Dominant allele: An allele that, if combined with other recessive
alleles, suppresses their expressions. In blood types, alleles A and B
are dominant.
• Recessive allele: An allele that, if combined with other dominant
alleles, is suppressed. For example, the brown-eye allele is dominant
to the blue-eye allele. If a male with blue eyes mates with a female
with brown eyes, their children (assuming complete dominance of
the brown-eye allele) will have brown eyes. For blood types, the O
allele is recessive to A and B.
Q Genotype: The type of alleles in the cell. In the blood example, geneo-
type is the concatenation of the parental and maternal alleles such as
AO, AB, OO.
Q Heterozygous in a gene: Two different alleles are inherited. For
blood types, heterozygous alleles can be AB, AO, or BO.
Q Homozygous genes: These cells contain the same alleles of the gene.
A person who is homozygous for the brown-eye gene has inherited two
alleles for brown eyes, one from their mother and one from their father.
106 • HDL WITH DIGITAL DESIGN
A person who is homozygous for blood type A has two A alleles, one
parental and one maternal.
Q Phenotype: The expression that results from allele combinations. For
example, the phenotype of the genotype AO is blood type A because A
is dominant and O is recessive. The phenotype of genotype AB is blood
type AB because A and B are codominant.
To find all possible genotypes and phenotypes of human blood, a table
is constructed to show all possible blood alleles (A, B, O) from male and
female gametes. Then, determine the offspring’s genotype. From the geno-
type, the phenotype is determined according to the type of allele (recessive,
dominant, or codominant). Table 3.4a shows all possible genotypes, and
Table 3.4b shows all possible phenotypes for the offspring.
TABLE 3.4 Genotypes and Phenotypes of Human Blood
A. Genotypes
♂ A B O
♀
A AA AB AO
B AB BB BO
O AO BO OO
B. Phenotype
♂ A B O
♀
A A AB A
B AB B B
O A B O
Tables 3.4a and 3.4b are look-up tables, and the case statement can
be used to describe the table. Listing 3.9 shows the code for describing the
genotypes and phenotypes using case. As shown in the Listing, the alleles
are decoded into two bits and entered in the entity as type bit_vector; the
output it is decoded in three bits and entered in the entity as a three-bit
vector. The two statements
geno := allelm & allelf; -- VHDL
geno = {allelm , allelf}; // Verilog
concatenate allelm and allelf into one vector, geno, using the concat-
BEHAVIORAL DESCRIPTION • 107
enation operator & for VHDL or { , } for Verilog (see Section 1.5.3). For ex-
ample, if allelm = 10, and allelf = 11, after concatenation, geno = 1011.
LISTING 3.9 HDL Code for Genotypes and Phenotypes Using the case State-
ment: VHDL and Verilog
This program takes the blood genotypes (alleles) of a male and a female
and generates the possible blood phenotypes of their offspring. The state-
ment report (VHDL) or display (Verilog) is used to print the phenotype
on the screen of the simulator. The male allele is allelm, and allelf is the
female allele. Both allelm and allelf are decoded as 00 for genotype A,
01 for B, or 10 for O. Phenotype A is decoded as 000, B as 001, AB as 010,
O as 011, and an illegal allele entry as 111. Figure 3.12 shows the simulation
waveform for genotypes and phenotypes of human blood.
VHDL Description
library ieee;
use ieee.std_logic_1164.all;
entity Bld_type is
port (allelm, allelf : in bit_vector (1 downto 0);
pheno : out bit_vector (2 downto 0));
end Bld_type;
architecture GEN_BLOOD of Bld_type is
begin
Bld : process (allelm, allelf)
variable geno : bit_vector(3 downto 0);
begin
geno := allelm & allelf;
case geno is
when “0000” => pheno <= “000”;
report “phenotype is A “;
--report statement is close to printf in C language.
--The statement here prints on the screen whatever
--written between the quotations.
when “0001” => pheno <= “010”;
report “phenotype is AB “;
when “0010” => pheno <= “000”;
report “phenotype is A “;
108 • HDL WITH DIGITAL DESIGN
Verilog Description
module bld_type (allelm, allelf, pheno);
input [1:0] allelm, allelf;
output [2:0] pheno;
reg [2:0] pheno;
reg [3:0] geno;
always @ (allelm, allelf)
begin
allelm 11 10 01 00 11 10 01 00 11 10 01 00
allelf 10 01 00
geno 1110 1010 0110 0010 1101 1001 0101 0001 1100 1000 0100 0000
pheno 111 011 001 000 111 001 001 010 111 000 010 000
FIGURE 3.12 Simulation waveforms for genotypes and phenotypes of human blood. The phenotype is also
printed (not shown here) on the main screen of the simulator.
allelm ? O B A ? O B A ? O B A
allelf O B A
geno ?? OO BO AO ?? OB BB AB ?? OA BA AA
pheno ? O B A ? B B AB ? A AB A
FIGURE 3.13 Simulation waveforms for genotypes and phenotypes of human blood using character type.
For Verilog, each ASCII character is represented by eight bits (two hex
digits). In Listing 3.10, allelm is represented as one character (two hex
digits); the output pheno is represented to two charcters (four hex digits of
a total of sixteen bits). The character assignment, same as in VHDL, is done
between double quotations. Figure 3.13 shows the simulation waveform of
Listing 3.10.
LISTING 3.10 HDL Code for Genotypes and Phenotypes Using the case
Statement and Character Type
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity bld_charctr is
port ( allelem, allelef : in string(1 to 1) ;
pheno : out string (1 to 2));
end bld_charctr;
architecture Bld_beh of bld_charctr is
begin
end process;
end Bld_beh;
Verilog Description
module Bld_typeCharctr(allelm, allelf, pheno);
case (geno)
“AA”: pheno = “A “;
“AB”: pheno = “AB”;
“AO”: pheno = “A “;
“BB”: pheno = “B “;
“BA”: pheno = “AB”;
“BO”: pheno = “B “;
“OA”: pheno = “A “;
“OB”: pheno = “B “;
“OO”: pheno = “O “;
default : pheno = “??”; //?? means invalid entry
endcase
end
endmodule
112 • HDL WITH DIGITAL DESIGN
the Verilog description for a four-bit priority encoder. Figure 3.14 shows
the simulation waveform of Listing 3.11.
TABLE 3.5 Truth Table for Four-Bit Encoder
Input Output
a b
xxx1 1
xx10 2
x100 4
1000 8
Others 0
LISTING 3.11 Verilog Description for a Four-Bit Priority Encoder Using
casex
module Encoder_4 (Int_req, Rout_addrs);
input [3:0] Int_req;
output [3:0] Rout_addrs;
reg [3:0] Rout_addrs;
always @ (Int_req)
begin
casex (Int_req)
4’bxxx1 : Rout_addrs=4’d1;
4’bxx10 : Rout_addrs=4’d2;
4’bx100 : Rout_addrs=4’d4;
4’b1000 : Rout_addrs= 4’d8;
default : Rout_addrs=4’d0;
endcase
end
endmodule
begin
p1 :process
variable a1: std_logic := ‘0’;
begin
a <= a1;
wait for 10 ns;
a1 := not a1;
end process;
p2 :process
variable b1: std_logic := ‘0’;
begin
b <= b1;
wait for 20 ns;
b1 := not b1;
end process;
BEHAVIORAL DESCRIPTION • 115
p3 :process
variable c1: std_logic := ‘0’;
begin
c <= c1;
wait for 40 ns;
c1 := not c1;
end process;
END;
Verilog
module waitstatement(a,b,c);
output a,b,c;
reg a,b,c;
initial
begin
// Initialize Inputs
a = 0;
b = 0;
c = 0;
end
always
begin
#10 ;
a = ~ a;
end
always
begin
#20 ;
b = ~ b;
end
always
begin
#40 ;
c = ~ c;
end
endmodule
116 • HDL WITH DIGITAL DESIGN
c
FIGURE 3.15 Simulation waveform of Listing 2.12.
3.4.4.1 For-Loop
The HDL general format for a For-Loop is:
for <lower index value> <upper index value> <step>
statements1; statement2; statement3; ….
end loop
If the value of index is between lower and upper, all statements writ-
ten inside the body of the loop are executed. For each cycle, the index is
modified at the end loop according to the step. If the value of index is not
between the lower and upper values, the loop is terminated.
Verilog For-Loop
for (i = 0; i <= 2; i = i + 1)
begin
BEHAVIORAL DESCRIPTION • 117
if (temp[i] == 1’b1)
begin
result = result + 2i;
end
end
statement1; statement2; ....
The index is i, the lower value is 0, the upper value is 2, and the step
is 1. All statements between the for statement and end loop (VHDL) or
end (Verilog) are executed until the index i goes out of range. At the very
beginning of the loop, i takes the value of 0, and the statements if and re-
sult are executed as:
if temp(0) = ‘1’ then
result := result + 20;
3.4.4.2 While-Loop
The general format of the While-Loop is:
while (condition)
Statement1;
Statement2;
…………
end
As long as the condition is true, all statements written before the end of
the loop are executed. Otherwise, the program exits the loop.
Verilog While-Loop
while (i < x)
begin
i = i + 1;
z = i z;
end
In the above example, the condition is (i < x). As long as i is less than
x, i is incremented, and the product i z (i multiplied by z) is calculated
and assigned to z.
between next and end loop. The index is incremented, and if its value is
still within the loop’s range, the loop is repeated. Otherwise, the program
exits the loop.
LISTING 3.13 HDL Code for a Four-Bit Counter With Synchronous Clear:
VHDL and Verilog
VHDL Description
library ieee;
use ieee.std_logic_1164.all;
entity CNTR_LOP is
port (clk, clr : in std_logic; q :
buffer std_logic_vector (3 downto 0));
end CNTR_LOP;
architecture CTR_LOP of CNTR_LOP is
begin
ct : process(clk)
variable temp :
std_logic_vector (3 downto 0) := “0000”;
variable result : integer := 0;
begin
if rising_edge (clk) then
if (clr = ‘0’) then
result := 0;
-- change binary to integer
lop1 : for i in 0 to 3 loop
if temp(i) = ‘1’ then
result := result + 2i;
end if;
end loop;
-- increment result to describe a counter
result := result + 1;
-- change integer to binary
for j in 0 to 3 loop
if (result MOD 2 = 1) then
temp (j) := ‘1’;
BEHAVIORAL DESCRIPTION • 121
Verilog Description
module CNTR_LOP (clk, clr, q);
input clk, clr;
output [3:0] q;
reg [3:0] q;
integer i, j, result;
initial
begin
q = 4’b0000; //initialize the count to 0
end
always @ (posedge clk)
begin
if (clr == 0)
begin
result = 0;
//change binary to integer
for (i = 0; i < 4; i = i + 1)
begin
if (q[i] == 1)
result = result + 2i;
end
result = result + 1;
for (j = 0; j < 4; j = j + 1)
begin
if (result %2 == 1)
q[j] = 1;
else
q[j] = 0;
result = result/2;
end
end
122 • HDL WITH DIGITAL DESIGN
else q = 4’b0000;
end
endmodule
Read
current state
NO
+ve edge
(clk)?
YES
NO
LISTING 3.14 HDL Code for a Four-Bit Counter with Synchronous Hold:
VHDL and Verilog
VHDL Description
library ieee;
use ieee.std_logic_1164.all;
entity CNTR_Hold is
port (clk, hold : in std_logic;
q : buffer std_logic_vector (3 downto 0));
end CNTR_Hold;
architecture CNTR_Hld of CNTR_Hold is
begin
ct : process (clk)
variable temp : std_logic_vector
(3 downto 0) := “0000”;
-- temp is initialized to 0 so count starts at 0
variable result : integer := 0;
begin
if rising_edge (clk) then
result := 0;
124 • HDL WITH DIGITAL DESIGN
for (i = 0; i <= 3; i = i + 1)
begin
if (q[i] == 1)
result = result + 2i;
end
result = result + 1;
for (i = 0; i <= 3; i = i + 1)
begin
if (hold == 1)
i = 4; //4 is out of range, exit.
else
begin
if (result %2 == 1)
q[i] = 1;
else
q[i] = 0;
result = result/2;
end
end
end
endmodule
clk
hold
q 0 1 2 3 4 4 5 6 7 8 9
FIGURE 3.17 Simulation waveform of a four-bit binary counter with synchronous hold.
bit that replaces the vacant bit after shift. Other registers may have load and
bidirectional shifts; these registers are called universal shift registers and
are covered in Chapter 4.
10111101
Register A
Listing 3.15 shows a HDL code for describing a logical shift, as shown
in Figure 3.18, using the Loop statement. The code shifts register q n bits
right or left logically. The number of bits to be shifted is determined by
user-selected parameter N. The code resembles the preserved statement
sll and slr in VHDL and ( << and >>) in Verilog. See Section 1.5.4.
%c for character
%s for string
%v for binary and strength
LISTING 3.15 HDL Code for Logical Shifting of a Register Using the Loop
Statement
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity shift_register is
port(start : in std_logic; shft: in std_logic;
N: in natural;
q : out std_logic_vector(7 downto 0))
end shift_register;
--N is number of shifts selected by the user
architecture shift_righLift of shift_register is
begin
st: process (start)
variable vq : std_logic_vector (7 downto 0)
:= “11001110”;
--initial values for the vector is selected to be
-- 1100110
begin
if (start =’1’) then
lop2: for j in 1 to N loop
lop1: for i in 0 to 6 loop
if shft =’0’ then
--shft = 0 is logical right shift; =1 logical left
-- shift
vq(i) := vq(i+1);
vq(7) :=’0’;
else
vq(7-i ) := vq(6-i);
vq(0) := ‘0’;
end if;
end loop lop1;
end loop lop2;
end if;
q <= vq;
128 • HDL WITH DIGITAL DESIGN
end shift_righLift;
Verilog Description
module shft_regVerilog(start,shft, N,q);
input start,shft;
input [7:1] N;
//N is number of requested shifts
output [7:0]q;
reg [7:0]q;
integer i,j;
initial
q = 8’b01100110;
/initial values for the vector is selected to be
1100110 /
else
begin q[7-i] = q[6-i];
q[0] = 1’b0; end
$display (“ shft = %d”, shft);
BEHAVIORAL DESCRIPTION • 129
end
end
end
endmodule
LISTING 3.16 HDL Code for Calculating the Factorial of Positive Integers:
VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--The above library statements can be omitted;
--however no error if it is not omitted.
--The basic VHDL has type “natural.”
entity factr is
port(N : in natural; z : out natural);
end factr;
architecture factorl of factr is
begin
process (N)
variable y, i : natural;
begin
y := 1;
130 • HDL WITH DIGITAL DESIGN
i := 0;
while (i < N) loop
i := i + 1;
y := y i;
end loop;
z <= y;
end process;
end factorl;
Verilog Description
module factr (N, z);
input [5:0] N;
output [15:0] z;
reg [15:0] z;
/ Since z is an output, and it will appear inside
“always,” then Z has to be declared “reg” /
integer i;
always @ (N)
begin
z = 16’d1;
i = 0;
while (i < N)
begin
i = i + 1;
z = i z;
end
end
endmodule
in terms of its bit order at the beginning and end of the string. For example,
the number 0111011 has the following bit order:
Bit order 6543210
0111011
The number above has two strings. One string has two 1s, begins at
bit 0, and ends at bit 1. The other string has three 1s, begins at bit 3, and
ends at bit 5. The value of any binary number is equal to (2end1+1 2begin1)
+ (2end2+1 2begin2)+ ….., where begin1 and begin2 are the bit orders of
the beginning of string1 and string2, respectively, and end1 and end2 are
the bit orders of the end of string1 and string2, respectively. So, 0111011 =
(22 20) +(26 23) = 3 + 56 = 59. For the multiplication Z = multiplier (X)
× multiplicand (Y), we can write:
Z = {(2end1+1 2begin1) + (2end2+1 2begin2)+...}Y
process (X, Y)
variable temp : signed (1 downto 0);
variable sum : signed (7 downto 0);
variable E1 : unsigned (0 downto 0);
variable Y1 : signed (3 downto 0);
begin
sum := “00000000”; E1 := “0”;
for i in 0 to 3 loop
temp := X(i) & E1(0);
Y1 := - Y;
case temp is
when “10” => sum (7 downto 4) :=
sum (7 downto 4) + Y1;
when “01” => sum (7 downto 4) :=
sum (7 downto 4) + Y;
when others => null;
end case;
sum := sum srl 1; --This is a logical
--shift of one position to the right
sum (7) := sum(6);
E1(0) := x(i);
end loop;
if (y = “1000”) then
sum := - sum;
end if;
z <= sum;
end process;
end booth_4;
Verilog Description
module booth (X, Y, Z);
input signed [3:0] X, Y;
BEHAVIORAL DESCRIPTION • 135
Y1 = - Y;
case (temp)
2’d2 : Z [7 : 4] = Z [7 : 4] + Y1;
2’d1 : Z [7 : 4] = Z [7 : 4] + Y;
default : begin end
endcase
Z = Z >>> 1;
/The above statement is arithmetic shift of one position to
the right/
E1 = X[i];
end
if (Y == 4’d8)
Q The major target of ADH is the renal cells, specifically, the collecting
ducts of the nephrons.
Q ADH causes the kidney to reabsorb (conserve) water. Absence of ADH
causes the kidney to excrete water as urine.
Q Alcohol and caffeine inhibit ADH release and promote more urine.
100
ADH
80
60
ADH
=
–4 BP
40
+ 180
20
10 20 30 40 50 60 70 80 90
Blood pressure BP
FIGURE 3.22 Concentration of ADH versus blood pressure (units are arbitrary).
138 • HDL WITH DIGITAL DESIGN
VHDL cannot directly multiply or add. In contrast, Verilog allows for di-
rect addition and multiplication if BP and ADH are declared as bit vectors.
Figure 3.23 shows the simulation waveform of an ADH-BP relationship.
Verilog Description
module ADH_BEH (clk, BP, ADH);
input clk;
input [8:0] BP;
// Assume BP takes only positive integer values
output [8:0] ADH;
reg [8:0] ADH;
always @ (clk)
begin
if (clk == 1)
BEHAVIORAL DESCRIPTION • 139
begin
if (BP <= 20) ADH = 100;
else if (BP > 45.0) ADH = 0;
else
ADH = BP (-4) + 180.0;
end
end
endmodule
clk
BP 30 7 20 40 45
(contd.)
140 • HDL WITH DIGITAL DESIGN
3.6 Summary
In this chapter, the basics of behavioral description have been covered,
including the statements process (VHDL) and always (Verilog). Some se-
quential statements have also been discussed such as IF, wait, case,
and Loop. These sequential statements have to appear inside process in
VHDL or inside always or initial in Verilog. In VHDL, all signal-assign-
ment statements inside process are executed sequentially. Here, sequen-
tially means calculating the values of the left-hand side of the statements
in the order in which they are written. After calculation, the values are as-
signed taking into consideration any delay times. In Verilog, all statements
BEHAVIORAL DESCRIPTION • 141
VHDL Verilog
process always
variable ------
------- reg
if;else;endif if;else;begin end
if;elsif;else;endif if;else if;else;begin end
case endcase case begin end
for loop for
while loop while
next, exit -----
------- repeat, forever
MOD %
signed signed
srl 1 >> 1
integer integer
wait for 10 ns #10
3.7 Exercises
6. Using the Booth algorithm (see Case Study 3.1), modify the code to
satisfy all the following requirements:
• The multiplier and the multiplicand are five bits each.
• If the multiplier or the multiplicand is 0, the product should be 0
without going through the multiplication steps.
• If the multiplier or the multiplicand is 1 (decimal), the product
should be equal to the multiplicand or the multiplier, respectively,
without going through the multiplication steps.
7. In Case Study 3.2, it was assumed that the relationship between ADH
and BP is linear: Bp (-4) + 180 (VHDL). Change this relationship
to be exponential: ADH = a exp (b BP). The value of ADH is 100 for
BP 20 and stays at 10 for BP 45. Write the VHDL code using the
case statement to describe this relationship. You can approximate the
values of ADH to be integers but be as accurate as possible.
8. Design an arithmetic and logical unit (ALU) that performs addition,
subtraction, multiplication, and integer division. The input to the ALU
is two signals, A and B, of integer type. The output is signal Z of integer
type. The ALU performs the operations according to a signal called op_
code. This op_code is of character type, and Table 3.10 shows the value
of the op_code (in character) and the selected operation.
TABLE 3.10 op_code and the selected operation
op_code Operation
add Add A to B and store the result in Z
sub Subtract B from A and store the result in Z
multply Multiply A x B and store the result in Z
dvdInt Divide A by B and store the result in Z
CHAPTER
4
STRUCTURAL DESCRIPTION
Chapter Objectives
O Understand the concept of structural description, including the
binding of modules
O Identify the basic statements of structural description, such as com-
ponent, use, and, or, not, xor, nor, generate, generic, and
parameter
O Review and understand the fundamentals of digital logic design
for digital systems, such as adders, multiplexers, decoders, com-
parators, encoders, latches, flip-flops, counters, shift registers, and
memory cells
O Understand the concept of sequential finite-state machines
Facts
Q Structural description simulates the system by describing its logical
components. The components can be gate level (such as AND gates,
OR gates, or NOT gates), or components can be in a higher logical level,
such as register-transfer level (RTL) or processor level.
Q It is more convenient to use structural description than behavioral
description for systems that require specific design constraints. Con-
sider, for example, a system performing the operation A + B = C. In
behavioral description, the addition can be written as C = A + B with no
choice in selecting the type of adders used to perform this addition. In
structural description, the type of adder, such as look-ahead adders, can
be selected.
Q All statements in structural description are concurrent. At any simula-
tion time, all statements that have an event are executed concurrently.
Q A major difference between VHDL and Verilog structural description
is the availability of components (especially primitive gates) to the user.
Verilog recognizes all the primitive gates such as AND, OR, XOR, NOT,
and XNOR gates. Basic VHDL packages do not recognize any gates un-
less the package is linked to one or more libraries, packages, or modules
that have the gate description. Usually, the user develops these links, as
will be done in this chapter.
Q Although structural description is implemented in this chapter to simu-
late digital systems, this does not mean that only one type of description
(structural) can be used in a module. In fact, in most descriptions of
complex systems, mixed-type descriptions (e.g., data flow, behavioral,
structural, or switch-level) are used in the same module (see Chapter 7).
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 differ-
ent types of components are declared. For example, the statements
component xor2
port (I1, I2 : in std_logic; O1 : out std_logic);
end component;
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 state-
ments 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);
146 • HDL WITH DIGITAL DESIGN
buf not
and nand
or nor
xor xnor
FIGURE 4.1 Verilog built-in gates.
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
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;
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
STRUCTURAL DESCRIPTION • 149
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 li-
braries 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 seg-
ment1. Consider the VHDL code in Listing 4.3.
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;
end system;
architecture lib_bound of system is
signal s : std_logic;
.............
end lib_bound;
STRUCTURAL DESCRIPTION • 151
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);
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 propaga-
tion 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 primi-
tive gates built in and ready to use. Verilog modules can be bound by just writ-
ing the name of the module to be bound. Listing 4.7 shows such binding.
STRUCTURAL DESCRIPTION • 153
Gbar
2x1 Y
Mux A S4
Y
B B
SEL
S2 S3 S5
Gbar
SEL S1
FIGURE 4.2 Multiplexer. a) Logic diagram. b) Logic symbol.
gates are included here that might be used for other examples. Listing 4.8
shows the code for several gates.
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;
entity bind2 is
port (I1, I2 : in std_logic; O1 : out std_logic);
end bind2;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity bind3 is
port (I1, I2, I3 : in std_logic; O1 : out std_logic);
end bind3;
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;
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;
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
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);
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 de-
clared 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)
TABLE 4.1 Truth Table for a 2x4 Decoder with Tri-State Outputs
Inputs Outputs
Enable I1 I2 D3 D2 D1 D0
0 x x Z Z Z Z
1 0 0 0 0 0 1
1 0 1 0 0 1 0
1 1 0 0 1 0 0
1 1 1 1 0 0 0
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 Bool-
ean function of the outputs:
D0 = I0 I1
D1 = I0 I1
D2 = I0 I1
D3 = I0 I1
Figure 4.3 shows the logic diagram of the decoder.
s0 D0
s1 D1
I0
I1 s2 D2
s3
D3
Enable
FIGURE 4.3 Logic diagram of a 2x4 decoder with tri-state output.
160 • HDL WITH DIGITAL DESIGN
in out in out
Enable Enable
bufif1 notif1
in out in out
Enable Enable
bufif0 notif0
FIGURE 4.4 Verilog built-in buffers.
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;
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
I 11 10 01 00 11 10 01 00 11 10
Enable
x sum
carry
y
cin
(a)
x
sum
y
cin Half adder
Half adder
carry
(b)
FIGURE 4.6 Full adder as two half adders. a) Logic symbol. b) Logic diagram.
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;
164 • HDL WITH DIGITAL DESIGN
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);
STRUCTURAL DESCRIPTION • 165
endmodule
module HA (a, b, s, c);
input a, b;
output s, c;
xor (s, a, b);
and (c, a, b);
endmodule
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;
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);
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 tran-
sient states is called hazards. These transient states, however, have short
duration and may not be noticed.
lay 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 associ-
ated 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.
final_carryout
sumtotal[3] sumtotal[2] sumtotal[1] sumtotal[0]
FIGURE 4.7 Two-stage carry-save adder.
168 • HDL WITH DIGITAL DESIGN
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);
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);
STRUCTURAL DESCRIPTION • 169
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
XY>0 (4.2)
–Y is the twos complement of Y = Y + 1; substituting in Equation 4.2,
the condition of X > Y is rewritten as:
X+ Y +1>0 (4.3)
Or, Equation 4.3 can be rewritten as:
X + Y > 1 (4.4)
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:
X + Y = 1……1111 (4.6)
170 • HDL WITH DIGITAL DESIGN
Y2 X2 Y1 X1 Y0 X0
To use these components, link their work library from Listing 4.13 as:
for all : full_adder use entity work.bind32 (full_add); --VHDL
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;
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));
172 • HDL WITH DIGITAL DESIGN
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
S Q
R
Q
R Q Qbar
S
(a) (b)
FIGURE 4.9 SR-Latch. a) Logic symbol. b) Logic diagram.
end SR_latch;
Verilog Description
module SR_Latch (R, S, Q, Qbar);
input R, S;
output Q, Qbar; It works properly for any (order of) test case;
nor (Qbar, S,Q); even with certain delay for NOR gates
nor (Q, R, Qbar);
endmodule
Qbar
FIGURE 4.10 Simulation waveform of an SR-latch.
D Q
D-Latch
D
E Qbar
clrbar Q
E Qbar
clrbar
(a) (b)
FIGURE 4.11 D-Latch with clear. a) Logic symbol. b) Logic diagram.
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);
176 • HDL WITH DIGITAL DESIGN
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.
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
clrbar
Q0
D d Q d Q Q
D-Latch D-Latch
C Qb C Qb Qbar
clk2
clkb
clk
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
178 • HDL WITH DIGITAL DESIGN
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 mod-
ule, respectively, for proper mapping.
entity D_FFMasterWclr is
Port (D, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic);
end D_FFMasterWclr ;
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;
STRUCTURAL DESCRIPTION • 179
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
clrbar
clk
Q
FIGURE 4.13 Simulation waveform of a master-slave D flip-flop.
J Q
T
T Flip-
Flop
K
Qb
clk
FIGURE 4.14 Logic diagram of a T flip-flop.
J K Q clk Q+
0 0 Q0 Q0
0 1 x 0
1 0 x 1
1 1 Q0 Q0
J K Q clk Q+ D
0 0 0 0 0
0 0 1 1 1
0 1 0 0 0
0 1 1 0 0
1 0 0 1 1
1 0 1 1 1
1 1 0 1 1
1 1 1 0 0
STRUCTURAL DESCRIPTION • 181
KQ 00 01 11 10
J
00 0 1 0 0
01 1 1 0 1
D
FIGURE 4.15 K-maps of Table 4.5.
From Figure 4.15, the Boolean functions are:
D=KQ+JQ (4.7)
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.
J S1
DD
d Q Q
D
Master-Slave
S2
Kb
K
Q Q
clk
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.
182 • HDL WITH DIGITAL DESIGN
entity JK_FLFL is
port (J, K, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic);
end JK_FLFL;
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);
STRUCTURAL DESCRIPTION • 183
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);
endmodule
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
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 rewrit-
ten because they are linked to the current module.
O1
S Q
SEL
R Q O1
CELL
R/W
Din
RW
Din Sel
(a) (b)
FIGURE 4.17 SRAM memory cell. a) Logic symbol. b) Logic diagram.
STRUCTURAL DESCRIPTION • 185
Din Q 00 01 11 10 Din Q 00 01 11 10
Sel R/W Sel R/W
00 0 0 0 0 00 0 0 0 0
01 0 0 0 0 01 0 0 0 0
11 0 x x 0 11 x 0 0 x
10 0 0 x 1 10 x 1 0 1
S R
Din Q 00 01 11 10
Sel R/W
00 Z Z Z Z
01 Z Z Z Z
11 0 1 1 0
10 0 0 1 1
O1
FIGURE 4.18 K-maps for Table 4.6.
186 • HDL WITH DIGITAL DESIGN
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
STRUCTURAL DESCRIPTION • 187
end memory;
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;
188 • HDL WITH DIGITAL DESIGN
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
Clrbar s1 s0 Action
0 x x Clear (Q = 0)
1 1 1 Load P into Q (Q = P) at the positive edge of the clock
1 0 1 Shift right, DSR replaces Q2 at the positive edge of the clock
1 0 1 Shift left, DSL replaces Q0 at the positive edge of the clock
1 0 0 Hold (Q retains its current value with the clock)
STRUCTURAL DESCRIPTION • 189
P P P
s
P
s
D SR DSR DSL
a a a a a a a a a a a a
D SL
Shif t Q or or
or
reg ist
er
D D D
D Q D Q D Q
Clr
bar
clk clk clk
clk
s clrbar
s Q Q Q
(a) (b)
FIGURE 4.19 Universal shift register with clear. a) Symbol diagram. b) Logic diagram.
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 dia-
gram of the system using appropriate available macros such as latches,
adders, and flip-flops.
The following examples are state machines. More examples of state ma-
chines and counters will be discussed in Chapters 6 and 7.
Three-bit Counter
clr
clrbar clk
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.
192 • HDL WITH DIGITAL DESIGN
1
S7 S0
1
1 0
0
S6 0 S1
0 1
1 0
0
S5 S2
1
S4 S3 1
1
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
Inputs Outputs
Current State J K Next State
0 1 x 1
0 0 x 0
1 x 1 0
1 x 0 1
TABLE 4.8B Excitation Table for a Three-Bit Synchronous Counter with Active Low Clear
Inputs Outputs
Input Current State Next State Flip-Flops
clrbar q2 q1 q0 q2+ q1+ q0+ J2K2 J1K1 J0K0
0 x x x 0 0 0 xx xx xx
1 0 0 0 0 0 1 0x 0x 1x
1 0 0 1 0 1 0 0x 1x x1
1 0 1 0 0 1 1 0x x0 1x
1 0 1 1 1 0 0 1x x1 x1
1 1 0 0 1 0 1 x0 0x 1x
1 1 0 1 1 1 0 x0 1x x1
STRUCTURAL DESCRIPTION • 193
Inputs Outputs
Input Current State Next State Flip-Flops
clrbar q2 q1 q0 q2 +
q1 +
q0 +
J2K2 J1K1 J0K0
1 1 1 0 1 1 1 x0 x0 1x
1 1 1 1 0 0 0 x1 x1 x1
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. Ac-
cordingly, 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.
q1q0 00 01 11 10
q2
0 1
1 X X X X
J2 = K2
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).
clrbar
1
JK2 JK1 JK0
q2 q1 q0
Q K Q K Q K
K2 K1 K0
clk
FIGURE 4.23 Logic diagram of a three-bit synchronous counter with active low clear using master-slave JK
flip-flops.
194 • HDL WITH DIGITAL DESIGN
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 defi-
nitions; if these packages are included in Listing 4.23, there is no need for
component declaration statements for them.
entity CTStatemachine is
port( clk, clrbar : in std_logic;
Q, Qbar: buffer std_logic_vector (2 downto 0));
end CTStateMachine;
end component;
for all : and2 use entity work.bind2 (and2_4);
for all : JK_FLFL use entity work.
JK_FLFL (JK_Master );
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;
assign K1 = q[0];
JK_FF FF1 (J1, K1, clk, clrbar, q[1], qb[1]);
clk
clrbar
q 0 1 2 3 4 5 6 7 0 1 2 0
FIGURE 4.24 Simulation waveform of a three-bit synchronous counter with active low clear.
196 • HDL WITH DIGITAL DESIGN
1
Assume the counter here is
S7
counting up. The number of flip-
0 S0 flops is three. First, draw the state
diagram of the counter as shown in
0
1 Figure 4.25. For all even current
S6 S1 states, the next state is the next
even. For example, if the current
state is 010 (2), then the next state
S2
1 is 100 (4). For any odd state (in-
S5
valid state), the next state can be
0 selected to be any state that en-
0
S4 sures the continuity of the count.
1
For example, if the current state is
S3 the invalid state 001, the next state
FIGURE 4.25 State diagram of an even three-bit can be 000. In the case of invalid
counter. The Hold is shown in the diagram as only input. 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.
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
Inputs Outputs
Current state Next State Flip-Flops
H Q2 Q1 Q0 Q2 +
Q1+ Q0 +
D2 D1 D0
0 0 0 0 0 1 0 0 1 0
0 0 0 1 0 1 0 0 0 0
0 0 1 0 1 0 0 1 0 0
0 0 1 1 1 0 0 0 0 0
0 1 0 0 1 1 0 1 1 0
0 1 0 1 0 1 0 0 0 0
STRUCTURAL DESCRIPTION • 197
Inputs Outputs
Current state Next State Flip-Flops
H Q2 Q1 Q0 Q2 +
Q1+ Q0 +
D2 D1 D0
0 1 1 0 0 0 0 0 0 0
0 1 1 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 0 0 0 0
1 0 1 0 0 1 0 0 1 0
1 0 1 1 0 0 0 0 0 0
1 1 0 0 1 0 0 1 0 0
1 1 0 1 0 0 0 0 0 0
1 1 1 0 1 1 0 1 1 0
1 1 1 1 0 0 0 0 0 0
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.
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
H Q2 H Q2
00 1 1 0 0 00 0 0 1 1
01 1 1 0 0 01 1 0 0 0
11 0 0 0 1 11 1 0 0 1
10 0 0 0 1 10 0 0 0 0
D1 D2
FIGURE 4.26 K-maps of an even three-bit counter.
From the K-maps, find the Boolean functions:
D0 = 0
D1 = Q1 H + HQ1 Q0
D2 = Q2 Q1 Q0 + Q0 HQ2 + H Q2 Q1
198 • HDL WITH DIGITAL DESIGN
Using the above Boolean functions, draw the logic diagram of the coun-
ter. Figure 4.27 shows the logic symbol and logic diagram of the counter.
Q0 Q1 Q2 Q0 Q1 Q2
Three-bit Counter
Hold clk
Q2 Q1 Q0
Q d Q d Q d 0
Q2 Q1 Q0
Q Q Q
clk
H
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 mas-
ter-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]);
entity CTR_EVEN is
port (H, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic_vector (2 downto 0));
end CTR_EVEN;
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;
200 • HDL WITH DIGITAL DESIGN
component D_FFMasterWclr
port (D, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic);
end component;
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
clk
Q 0 2 4 6 0 2 4 4 4 4 6 0
FIGURE 4.28 Simulation waveform of an even counter with Hold.
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).
Dir = 0 (down) Clear/TC
Dir = 1 (up)
0/1 1/0
0/1 1/0 S7 S0
Clear/TC 0/0
S7 S0 0/0
0/0 1/0
0/0 1/0
S6 1/0 1/0 S1
S6 1/0 S1
1/0
0/0
0/0 1/0 1/0
1/0 1/0 0/0 1/0
0/0 1/0
S5 S2 S5 S2
0/0 0/0
S4 S3 0/0 S4 S3 0/0
0/0 0/0
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
Inputs Outputs
Input Current State Next State Output Flip-Flop
Clr Dir Q2 Q1 Q0 Q2 +
Q1 +
Q0 +
TC J2K2 J1K1 J0K0
1 x x x x 0 0 0 0 xx xx xx
0 0 0 0 0 1 1 1 1 1x 1x 1x
0 0 0 0 1 0 0 0 0 0x 0x x1
0 0 0 1 0 0 0 1 0 0x x1 1x
0 0 0 1 1 0 1 0 0 0x 1x x1
0 0 1 0 0 0 1 1 0 x1 1x 1x
0 0 1 0 1 1 0 0 0 x0 0x x1
0 0 1 1 0 1 0 1 0 x0 x1 1x
0 0 1 1 1 1 1 0 0 x0 x0 x1
0 1 0 0 0 0 0 1 0 0x 0x 1x
0 1 0 0 1 0 1 0 0 0x 1x x1
0 1 0 1 0 0 1 1 0 0x x0 1x
0 1 0 1 1 1 0 0 0 1x x1 x1
0 1 1 0 0 1 0 1 0 x0 0x 1x
0 1 1 0 1 1 1 0 0 x0 1x x1
0 1 1 1 0 1 1 1 0 x0 x0 1x
0 1 1 1 1 0 0 0 1 x1 x1 x1
STRUCTURAL DESCRIPTION • 203
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.
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
Dir Q2 Dir Q2
00 1 1 1 1 00 1 1 1 1
01 1 1 1 1 01 1 1 1 1
11 1 1 1 1 11 1 1 1 1
10 1 1 1 1 10 1 1 1 1
J0 K0
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
Dir Q2 Dir Q2
00 1 0 1 1 00 1 0 0 1
01 1 0 1 1 01 1 0 0 1
11 0 1 1 1 11 0 1 1 0
10 0 1 1 1 10 0 1 1 0
J1 K1
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
Dir Q2 Dir Q2
00 1 0 0 0 00 1 0 0 0
01 1 0 0 0 01 1 0 0 0
11 0 0 1 0 11 0 0 1 0
10 0 0 1 0 10 0 0 1 0
J2 K2
FIGURE 4.31 K-maps of a three-bit synchronous up/down counter.
J0 =K0=1
J1 = Dir Q0+ Q1 + DirQ0, K1 = Dir Q0+DirQ
J2 = Q0Q1Dir + Dir Q0 Q1 , K2 = J2
TC = Dir Q0 Q1 Q2 + QoQ1A2Dir
204 • HDL WITH DIGITAL DESIGN
From the above Boolean functions, draw the logic diagram of the coun-
ter, as shown in Figure 4.32.
clr
Q K K2 Q K K1 Q K K0
clk
Q2 Q2 Q1 Q1 Q0 Q0
K1 J1
Q1
Q0 Q0
Dir
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 haz-
ards use gates with a propagation delay. Four nanoseconds are assigned for
all primitive gates except for the inverter which is assigned 1 ns.
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;
STRUCTURAL DESCRIPTION • 205
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;
Verilog Description
module up_down(clr, Dir, clk, Q, Qbar, TC);
clk
Up
H Down
Q 0 7 6 5 4 3 2 3 4 5 6 7
FIGURE 4.33 The simulation waveform of an up/down counter.
that yields more minimization. This is determined when the K-maps are
generated. Figure 4.34 shows the final state diagram after taking into con-
sideration the K-maps.
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
Inputs Outputs
Current State Next State Output
Q3 Q2 Q1 Q0 Q3+ Q2+ Q1+ Q0+ TC
0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 1 0 0
0 0 1 0 0 0 1 1 0
0 0 1 1 0 1 0 0 0
0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 1 0 0
0 1 1 0 0 1 1 1 0
0 1 1 1 1 0 0 0 0
1 0 0 0 1 0 0 1 0
1 0 0 1 0 0 0 0 1
1 0 1 0 1 0 1 1 0
1 0 1 1 0 1 0 0 0
1 1 0 0 1 1 0 1 0
1 1 0 1 0 1 0 0 0
1 1 1 0 1 1 1 1 0
1 1 1 1 0 0 0 0 0
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:
D0 = Q0
D1 = Q3 Q1 Q0 + Q1 Q0
D2 = Q2 Q1 + Q2 Q0 + Q1Q0 Q2
D3 = Q3 Q0 + Q0Q1Q2 Q3
TC = Q0 Q1 Q2 Q3
STRUCTURAL DESCRIPTION • 209
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
Q3Q2 Q3Q2
00 1 0 0 1 00 0 1 0 1
01 1 0 0 1 01 0 1 0 1
11 1 0 0 1 11 0 0 0 1
10 1 0 0 1 10 0 0 0 1
D0 D1
Q1Q0 00 01 11 10 Q1Q0 00 01 11 10
Q3Q2 Q3Q2
00 0 0 1 0 00 0 0 0 0
01 1 1 0 1 01 0 0 1 0
11 1 1 0 1 11 1 0 0 1
10 0 0 1 0 10 1 0 0 1
D2 D3
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.
Q D Q D Q D Q D
Q Q Q Q
Q3 Q3 D3 Q2 Q2 D2 Q1 Q1 D1 Q0 Q0
TC D3 D2 D1
Q3 Q1 Q1 Q3
Q3 Q0 Q1Q2 Q0 Q2
Q1 Q2 Q0Q1 Q3 Q0
Q2 Q2
Q0 Q1
Q0 Q0
FIGURE 4.36 Logic diagram of a decade counter.
210 • HDL WITH DIGITAL DESIGN
component D_FFMasterWclr
port (D, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic);
STRUCTURAL DESCRIPTION • 211
end component;
end decade_str;
212 • HDL WITH DIGITAL DESIGN
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]);
endmodule
clk
Q 0 1 2 3 4 5 6 7 8 9 0 1
TC
FIGURE 4.37 Simulation waveform of the decade counter.
STRUCTURAL DESCRIPTION • 213
The words generic (in VHDL) and parameter (in Verilog) are used to
define global constants. The generic statement can be placed within en-
tity, 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);
parameter N = 3;
input [N:0] X, Y;
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);
STRUCTURAL DESCRIPTION • 215
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);
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;
216 • HDL WITH DIGITAL DESIGN
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 /
endmodule
Qn Q2 Q1 Q0
Q J Q J Q J Q J
1 1 1 1
Q K Q K Q K Q K
clk
FIGURE 4.38 Logic diagram of n-bit asynchronous down counter.
end asynch_ctr;
component JK_FLFL
port (J, K, clk, clrbar : in std_logic;
Q, Qbar : buffer std_logic);
end component;
signal h, l : std_logic;
signal s : std_logic_vector (N downto 0);
begin
h <= ‘1’;
l <= ‘0’;
s <= (Q & clk);
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./
generate
genvar i;
for (i = 0; i < N; i = i + 1)
begin : u
endmodule
clk
Transient
states
Q 0 7 6 5 4 3 2 1 0 7 6 5
FIGURE 4.39 Simulation waveform of n-bit asynchronous down counter (n = 3).
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
STRUCTURAL DESCRIPTION • 221
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;
entity bind2 is
port (O1 : buffer std_logic; I1, I2 : in std_logic);
end bind2;
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;
library IEEE;
224 • HDL WITH DIGITAL DESIGN
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;
begin
n1 : nor2 port map (I1, O1, O2);
n2 : nor2 port map (I2, O2, O1);
end SR_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;
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;
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;
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 ;
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
228 • HDL WITH DIGITAL DESIGN
VHDL Verilog
generate generate
port map Built in
and2, or2, xor2, nor2, and, or, xor, nor,
xnor2, inv xnor, not
(The above VHDL gates are user-built)
use library Built in
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;
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;
5
SWITCH-LEVEL DESCRIPTION
Chapter Objectives
O Understand the concept of describing and simulating digital
systems using transistors
O Identify the basic statements of switch-level description in Verilog,
such as nmos, pmos, cmos, supply1, supply0, tranif0, tran,
and tranif0
O Develop a counterpart VHDL switch-level package that matches the
switch-level functions of the Verilog description
O Review and understand the fundamentals of transistors and how
they can be implemented as switches
O Review Boolean functions for combinational circuits
Facts
Q Switch-level description implements switches (transistors) to describe
relatively small-scale digital systems.
Q Switch-level description is usually implemented in very-large-scale inte-
grated (VLSI) circuit layouts.
232 • HDL WITH DIGITAL DESIGN
Q Switch-level description is the lowest HDL logic level that can be used
to simulate digital systems.
Q Only small-scale systems can be simulated using pure switch-level
description. If the system is not small, a huge number of switches are
needed, which may render the simulation impractical.
Q Switch-level description is routinely used along with other types of mod-
eling to describe digital systems.
Q The switches used in this chapter are assumed to be perfect; they are
either open (high impedance) or closed (zero impedance).
Q In contrast to Verilog, basic VHDL does not have built-in statements
such as nmos, pmos, and cmos. To use these statements in VHDL, user-
built packages must be developed or supplied by the vendor.
Source Source
Gate Gate
Drain Drain
(a) (b)
FIGURE 5.1 MOS switch. a) NMOS. b) PMOS.
Gate
0 1 X Z
0 Z 0 L L
Drain 1 Z 1 H H
X Z X X X
Z Z Z Z Z
TABLE 5.1B Relationship Between Source, Drain, and Gate in PMOS Switches
Gate
0 1 X Z
0 0 Z L L
Drain 1 1 Z H H
X X Z X X
Z Z Z Z Z
For an NMOS switch, the Verilog code is:
nmos n1 (drain, source, gate) //The switch name “n1” is optional.
234 • HDL WITH DIGITAL DESIGN
LISTING 5.1 VHDL Behavioral Code for NMOS and PMOS Switches
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mos is
Port (O1 : out std_logic; I1, I2 : in std_logic);
end mos;
begin
switch : process (I1, I2)
variable temp : std_logic;
begin
case I2 is
when ‘0’=> temp := ‘Z’;
when ‘1’ => temp := I1;
when others => case I1 is
when ‘0’ => temp := ‘L’;
when ‘1’ => temp := ‘H’;
when others => temp := I1;
SWITCH-LEVEL DESCRIPTION • 235
end case;
end case;
O1 <= temp;
end process switch;
end nmos_behavioral;
architecture pmos_behavioral of mos is
begin
switch : process (I1, I2)
variable temp : std_logic;
begin
case I2 is
when ‘1’=> temp := ‘Z’;
when ‘0’ => temp := I1;
when others => case I1 is
when ‘0’ => temp := ‘L’;
when ‘1’ => temp := ‘H’;
when others => temp := I1;
end case;
end case;
O1 <= temp;
end process switch;
end pmos_behavioral;
To write the NMOS and PMOS codes as components, bind the entity
of Listing 5.1 to a component statement. Listing 5.2 shows such binding.
LISTING 5.2 VHDL Code for NMOS and PMOS Switches as Components
architecture nmos of mos is
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
y y
g1
g1
g2
g2 g2 g1 g2 g1
d d d d
(a) (b) (c) (d)
FIGURE 5.2 Combination of switches. a) Two NMOS switches in serial.
b) Two PMOS switches in serial. c) Two NMOS switches in parallel.
d) Two PMOS switches in parallel.
g1 g2 y
1 1 d
0 1 Z
1 0 Z
0 0 Z
Now, consider two PMOS switches connected in serial (Figure 5.2b).
The path between y and d is closed (ON) only when both g1 and g2 are at
0; at this instant, y = d. The path is open (OFF) if g1 or g2 is at 1. Table 5.2b
summarizes the relationship between y and d.
TABLE 5.2B Two PMOS Switches Connected in Serial (Figure 5.2b)
g1 g2 y
1 1 Z
0 1 Z
1 0 Z
0 0 d
SWITCH-LEVEL DESCRIPTION • 237
When two NMOS switches are connected in parallel (Figure 5.2c), the
path between y and d is open only when both g1 and g2 are 0. Otherwise, it
is closed, and y = d, as shown in Table 5.2c
TABLE 5.2C Two NMOS Switches Connected in Parallel (Figure 5.2c)
g1 g2 y
1 1 d
0 1 d
1 0 d
0 0 Z
For two PMOS switches connected in parallel (Figure 5.2d), the path
between y and d is open only when both g1 and g2 are at 1. Otherwise, it is
closed, and y = d, as shown in Table 5.2d.
TABLE 5.2D Two PMOS Switches Connected in Parallel (Figure 5.2d)
g1 g2 y
1 1 Z
0 1 d
1 0 d
0 0 d
Input Output
a y
0 1
1 0
238 • HDL WITH DIGITAL DESIGN
supply1 and supply0 are predefined words that represent high voltage
and ground, respectively. In VHDL, these two voltage levels are created by
using constant declaration statements:
constant vdd : std_logic := ‘1’;
constant gnd : std_logic := ‘0’;
LISTING 5.3 HDL Code for an Inverter: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Inverter is
port (y : out std_logic; a : in std_logic);
end Inverter;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module invert (y, a);
input a;
output y;
supply1 vdd; /supply1 is a predefined word for the
high voltage./
supply0 gnd; /supply0 is a predefined word for the
ground./
pmos p1 (y, vdd, a); /the name “p1” is optional; it
can be omitted./
nmos n1 (y, gnd, a); /the name “n1” is optional; it can
be omitted. /
endmodule
Input Output
a b y
0 0 0
1 0 0 vdd
0 1 0
a
1 1 1
From Table 5.4, two switch combinations are b
needed: one to pull y up to vdd only when both gates
y
of the combination are at level 1 (Table 5.2a satisfies
this requirement), and another combination to pull y
to ground whenever one of the gates is at level 0 (Ta-
gnd
ble 5.2b satisfies this requirement). The final design is
FIGURE 5.4 Switch-level
composed of two serial NMOS switches and two paral- logic diagram of an AND
lel PMOS switches. Figure 5.4 shows the switch-level gate with week output.
240 • HDL WITH DIGITAL DESIGN
diagram of the AND gate. The design here will yield to week output, see
Example 5.6 for details.
From Figure 5.4, write the HDL code. Listing 5.4 shows the HDL
code of a two-input AND gate.
LISTING 5.4 HDL Code for a Two-Input AND Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity and2gate is
port (y : out std_logic; a, b : in std_logic);
end and2gate;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module and2gate (y, a, b);
input a, b;
output y;
supply1 vdd;
SWITCH-LEVEL DESCRIPTION • 241
supply0 gnd;
Input Output
a b y
0 0 0
1 0 1
0 1 1
1 1 1
From the table, notice that to design switch-level circuits for the OR
gate, two complementary combinations are needed (see Table 5.2). The
first combination pulls y down to ground level only when both gates are
at level 0 (Table 5.2b satisfies this requirement). The second combination
pulls y up to vdd when either g1 or g2 is at level 1 (Table 5.2c satisfies this
requirement). The switch-level OR gate consists of two complementary
combinations: two serial PMOS switches and two parallel NMOS switches.
Figure 5.5 shows the switch-level diagram of a two-input OR gate.
242 • HDL WITH DIGITAL DESIGN
vdd
a
b
gnd
FIGURE 5.5 Switch-level logic diagram of an OR gate.
From Figure 5.5, the HDL code is written using the macros pmos and
nmos. Listing 5.5 shows the HDL code of the switch-level two-input OR
gate.
entity or2gate is
port (y : out std_logic; a, b : in std_logic);
end or2gate;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module OR2gate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
As shown in Figure 5.5, the PMOS switches pull y down to ground lev-
el, and the NMOS switches pull y up to vdd level. This arrangement results
in degraded outputs and should be avoided. Degraded outputs, when cas-
caded, can deteriorate the final outputs and render them unrecognizable.
To generate strong outputs, the NMOS switches should pull the output
down to ground, and the PMOS switches should pull the output up to vdd.
If we want to design a switch-level OR gate with strong output, we should
follow a different approach (see Section 5.5).
Input Output
a b y
0 0 1
1 0 1
0 1 1
1 1 0
244 • HDL WITH DIGITAL DESIGN
LISTING 5.6 HDL Code for a Two-Input NAND Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity nand2gate is
port (y : out std_logic; a, b : in std_logic);
end nand2gate;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module NAND2gate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
nmos (s1, gnd, b);
nmos (y, s1, a);
pmos (y, vdd, a);
pmos (y, vdd, b);
endmodule
Input Output
a b y
0 0 1
1 0 0
0 1 0 vdd
1 1 0
Referring to Table 5.7, we can design the gate us- a
ing two complementary switch combinations (see Ta-
ble 5.2). The first combination pulls y up to vdd when
b
the gate levels of both switches are at 0 (Table 5.2b
satisfies this requirement). The second combination y
pulls y down to ground level when either switch gate
is at level 1 (Table 5.2c satisfies this requirement).
The final design consists of two complementary com-
binations: two serial PMOS switches and two parallel gnd
NMOS switches. Figure 5.7 shows the switch-level FIGURE 5.7 Switch-level
logic diagram of an NOR
logic diagram of the NOR gate. gate.
246 • HDL WITH DIGITAL DESIGN
From Figure 5.7, write the HDL code. Listing 5.7 shows the HDL
code of the NOR gate using the two macros pmos and nmos.
LISTING 5.7 HDL Code for a Two-Input NOR Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity nor2gate is
port (y : out std_logic; a, b : in std_logic );
end nor2gate;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module nor2gate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
nmos (y, gnd, a);
SWITCH-LEVEL DESCRIPTION • 247
LISTING 5.8 HDL Code for a Two-Input AND Gate with Strong Output:
VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
248 • HDL WITH DIGITAL DESIGN
entity and2Sgate is
port (y : out std_logic; a, b : in std_logic);
end and2Sgate;
architecture and_strong of and2Sgate is
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
for all : pmos use entity work.mos (pmos_behavioral);
for all : nmos use entity work.mos (nmos_behavioral);
constant vdd : std_logic := ‘1’;
constant gnd : std_logic := ‘0’;
signal s1, y1 : std_logic;
begin
-- NAND
n1 : nmos port map (s1, gnd, b);
n2 : nmos port map (y1, s1, a);
p1 : pmos port map (y1, vdd, a);
p2 : pmos port map (y1, vdd, b);
-- Invert
n3 : nmos port map (y, gnd, y1);
p3 : pmos port map (y, vdd, y1);
end and_strong;
Verilog Description
module and2Sgate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
//NAND
nmos (s1, gnd, a);
nmos (y1, s1, b);
SWITCH-LEVEL DESCRIPTION • 249
//inverter
nmos (y, gnd, y1);
pmos (y, vdd, y1);
endmodule
LISTING 5.9 HDL Code of a Two-Input OR Gate with Strong Output: VHDL
and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity OR2Sgate is
port (y : out std_logic; a, b : in std_logic);
end OR2Sgate;
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
--NOR
n1 : nmos port map (y1, gnd, a);
n2 : nmos port map (y1, gnd, b);
p1 : pmos port map (s1, vdd, a);
p2 : pmos port map (y1, s1, b);
--Invert
n3 : nmos port map (y, gnd, y1);
p3 : pmos port map (y, vdd, y1);
end orgate_strong;
Verilog Description
module OR2Sgate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
//NOR
nmos (y1, gnd, a);
nmos (y1, gnd, b);
pmos (s1, vdd, a);
pmos (y1, s1, b);
SWITCH-LEVEL DESCRIPTION • 251
//inverter
nmos (y, gnd, y1);
pmos (y, vdd, y1);
endmodule
Input Output
a b c y
0 0 0 1
1 0 0 1
0 1 0 1
1 1 0 1
1 0 1 1
1 0 1 1
1 1 0 1
1 1 1 0
As shown in Table 5.8, the output is vdd
0 only when a, b, and c are 1. Table 5.2a,
when extended to three switches, indi-
cates the use of three NMOS switches
connected in serial as the pull-down a
combination. For the pull-up combi- b
c y
nation, Table 5.2d, extended to three
switches, needs three PMOS switch-
es connected in parallel. Figure 5.10
shows the switch-level logic diagram for
a three-input NAND gate.
gnd
Listing 5.10 shows the HDL code FIGURE 5.10 Switch-level logic diagram of a
for the three-input NAND gate using three-input NAND gate.
pmos and nmos switches.
252 • HDL WITH DIGITAL DESIGN
LISTING 5.10 HDL Code for a Three-Input NAND Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity nand3gate is
port (y : out std_logic; a, b, c : in std_logic);
end nand3gate;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
Verilog Description
module nand3gate (a, b, c, y);
input a, b, c;
output y;
supply1 vdd;
supply0 gnd;
Input Output
a b c y
0 0 0 1
1 0 0 0
0 1 0 0
1 1 0 0
0 0 1 0
1 0 1 0
0 1 0 0
1 1 1 0
Referring to Table 5.9, the NOR gate has vdd
LISTING 5.11 HDL Code for a Three-Input NOR Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity nor3gate is
port (y : out std_logic; a, b, c : in std_logic);
end nor3gate;
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
begin
n1 : nmos port map (y, gnd, a);
n2 : nmos port map (y, gnd, b);
n3 : nmos port map (y, gnd, c);
Verilog Description
module nor3gate (a, b, c, y);
input a, b, c;
output y;
supply1 vdd;
supply0 gnd;
nmos (y, gnd, a);
SWITCH-LEVEL DESCRIPTION • 255
d d d
e e e
FIGURE 5.12 Gate-level logic diagram for y = abc+de .
Listing 5.12 shows the HDL code for the logic using pmos and nmos
switches.
LISTING 5.12 HDL Code for the Logic y = abc+de : VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity simple_logic is
port (y : out std_logic; a, b, c, d : in std_logic);
end simple_logic;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
begin
n1 : nmos port map (s1, gnd, c);
n2 : nmos port map (s2, s1, b);
n3 : nmos port map (y, s2, a);
n4 : nmos port map (y, gnd, d);
p1 : pmos port map (y, s3, a);
p2 : pmos port map (y, s3, b);
p3 : pmos port map (y, s3, c);
p4 : pmos port map (s3, vdd, d);
end ABC;
Verilog Description
module simple_logic (a, b, c, d, e, y);
input a, b, c, d, e;
output y;
SWITCH-LEVEL DESCRIPTION • 257
supply1 vdd;
supply0 gnd;
nmos (s1, gnd, c);
nmos (s2, s1, b);
nmos (y, s2, a);
nmos (s3, gnd, e);
nmos (y, s3, d);
Listing 5.13 shows the HDL code for the XNOR gate. Two inverters
are used to generate the inverse of a and b. If the true and complement
logic of a and b are available, there is no need for the inverters.
LISTING 5.13 HDL Code for a XNOR Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity XOR_XNOR is
port (y : out std_logic; a, b : in std_logic);
end XOR_XNOR;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
end XNORgate;
Verilog Description
module XOR_XNOR (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
XOR/XNOR gates are very important because they are the basic com-
ponents in full adders. They have also been implemented in comparison
260 • HDL WITH DIGITAL DESIGN
LISTING 5.14 HDL Code for a XNOR Gate: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity XNOR_degrade is
Port (y : out std_logic; a, b : in std_logic);
end XNOR_degrade;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
begin
p1 : pmos port map (s0, vdd, b);
p2 : pmos port map (y, s0, a);
n1 : nmos port map (s0, gnd, b);
n2 : nmos port map (y, b, a);
end XNORgate;
SWITCH-LEVEL DESCRIPTION • 261
Verilog Description
module gate (a, b, y);
input a, b;
output y;
supply1 vdd;
supply0 gnd;
Input Output
a b Sel E y
x x x 0 1
0 0 0 1 1
1 0 0 1 1
0 1 0 1 0
1 1 0 1 0
0 0 1 1 1 (Contd.)
1 0 1 1 0
262 • HDL WITH DIGITAL DESIGN
Input Output
a b Sel E y
0 1 1 1 1
1 1 1 1 0
From Table 5.10, note that y is 0 when Sel = 1 and a = 1 or when Sel =
0 and b = 1, so the pull-down combination is two NMOS switches in serial
driven by a and Sel connected in parallel, with two serial switches driven by
b and Sel . When E = 0, y = 1; this is a PMOS (pull-up) switch. The switch
level of the multiplexer is shown in Figure 5.16.
vdd
Sel
b p5 p4
E s3 p1
Sel
a p3 p2
n5 n3
s2 s1
n4 n2
s0
n1
gnd
FIGURE 5.16 Switch-level logic diagram for a 2x1 multiplexer with active high enable and complement out-
put. Assume Sel signal is available.
Listing 5.15 shows the HDL code for the multiplexer.
SWITCH-LEVEL DESCRIPTION • 263
LISTING 5.15 HDL Code for a 2x1 Multiplexer with Active High Enable and
Complement Output: VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux2x1 is
port (a, b, Sel, E : in std_logic;
ybar : out std_logic);
end mux2x1;
architecture mux2x1switch of mux2x1 is
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
begin
--Invert signal Sel. If the complement of Sel is
--available then, there is no need for
--the following pair of transistors.
end mux2x1switch;
Verilog Description
module mux2x1 (a, b, Sel, E, ybar);
input a, b, Sel, E;
output ybar;
supply1 vdd;
supply0 gnd;
endmodule
S
n2 n1
R
Q
gnd
Qbar FIGURE 5.18 Switch-level logic diagram
FIGURE 5.19 Simulation waveform of an SR-Latch. of an SR-latch.
266 • HDL WITH DIGITAL DESIGN
component nmos
port (O1 : inout std_logic; I1, I2 : in std_logic);
--port O1 is selected here to be inout to match
--its use in the latch circuit
end component;
component pmos
port (O1 : inout std_logic; I1, I2 : in std_logic);
--port O1 is selected here to be inout
--to match its use in the latch circuit
end component;
begin
n1 : nmos port map (Qbar, gnd, S);
n2 : nmos port map (Qbar, gnd, Q);
p1 : pmos port map (s0, vdd, Q);
p2 : pmos port map (Qbar, s0, S);
Verilog Description
module SR_latch (S, R, Q, Qbar);
input S, R;
output Q, Qbar;
supply1 vdd;
supply0 gnd;
The basic VHDL package does not have a built-in code for CMOS
switches, but it can be built as a macro consisting of the NMOS switch and
PMOS switch described in Section 5.3.2. Listing 5.17 shows VHDL code
for the CMOS switch shown in Figure 5.20.
LISTING 5.17 VHDL Code for the CMOS Switch in Figure 5.19.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity CMOS is
port (output : out std_logic;
input, gn, gp : in std_logic);
end CMOS;
component nmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
begin
n1 : nmos port map (output, input, gn);
p1 : pmos port map (output, input, gp);
end macro;
p3 p4 E
s2
E
p1 p2
D Q
n2 n4
s0 s1
n1 n3 Q
gnd
FIGURE 5.21 Switch-level logic diagram of a D-latch using PMOS and NMOS
switches. Inverters between Q and Q and between E and E are not shown.
270 • HDL WITH DIGITAL DESIGN
LISTING 5.18 Verilog Code for a D-Latch Using NMOS and PMOS Switches
module D_latch (D, E, Q, Qbar);
input D, E;
output Q, Qbar;
supply1 vdd;
supply0 gnd;
endmodule
5.6.1.2 Switch-Level Logic Diagram of a D-Latch Using CMOS Switches
Figure 5.22 shows the switch-level logic diagram of the D-latch. When
enable (E) is high, CMOS switch c1 is closed, CMOS switch c2 is opened,
and Q follows D. When E is low, CMOS switch c1 is opened, CMOS switch
c2 is closed, and Q retains its previous value.
vdd
E
Q
D
C1
gnd
vdd
E E
C2
Q
gnd
Listing 5.19 shows the HDL code for the D-latch. Due to the nature of
signal Q, where it is an input and output with more than one source (one
CMOS switch and an inverter), Q is declared as inout. Because there are
three inverters, the inverter module discussed in Listing 5.3 is bound to the
current module D-Latch, rather than writing three individual inverters. In
VHDL, use the statement:
for all : invert use entity work.
inverter (Invert_switch);
LISTING 5.19 HDL Code for a D-Latch Using CMOS Switches: VHDL and
Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity D_Latch is
port (D, E : in std_logic; Q, Qbar : inout std_logic);
-- Referring to Figure 5.22, signal Q is
--input and output and has multiple
--sources (the inverter and the CMOS switches,
--so Q has to be declared as
--inout. All other ports are also adjusted in
--the following components to be inout.
end D_Latch;
end DlatchCmos;
Verilog Description
module D_latch (D, E, Q, Qbar);
input D, E;
output Q, Qbar;
cmos (Q, D, E, Ebar);
cmos (Q, s1, Ebar, E);
invert inv1 (Ebar, E);
invert inv2 (Qbar, Q);
invert inv3 (s1, Qbar);
endmodule
VHDL does not have built-in switches, but these switches can be built
as in Section 5.3.2.
Listing 5.20 shows the same Verilog code in Listing 5.12, but tranif1
and tranif0 are used instead of NMOS and PMOS switches.
LISTING 5.20 HDL Code for the Logic y = abc+de : VHDL and Verilog
module simple_logic (a, b, c, d, e, y);
input a, b, c, d, e;
output y;
supply1 vdd;
supply0 gnd;
endmodule
5.8 Summary
In this chapter, HDL descriptions based on switches have been pre-
sented. The switches are built from perfect transistors. The transistor is
either conducting to saturation or not conducting; this corresponds to two
switch states, closed and open, respectively. Switch-level is the lowest lev-
el of HDL description. Verilog has an extensive switch-level description
library. Standard VHDL does not have switch-level; if we use VHDL for
switch-level description, packages have to built or imported from vendors.
274 • HDL WITH DIGITAL DESIGN
VHDL switches have also been built as components (see Chapter 4).
The power supply (vdd) and ground (gnd) in all systems covered in this
chapter are the sources of the strongest 1s and 0s; nmos switches pass strong
0, and pmos switches pass strong 1. To produce strong output signals, nmos
switches are employed as pull-down to ground networks, and pmos switches
are employed as pull-up to vdd networks. Parallel and serial combinations
of pmos and nmos switches have been implemented to describe combina-
tional and sequential circuits. Other switches such as cmos, tran, tra-
nif0, and tranif1, constructed from parallel combinations of NMOS and
PMOS switches, have been also been discussed.
Many publications are available on the examples covered in this chap-
ter. These publications may use innovative ways to reduce the number of
transistors. The reader is encouraged to consult them (see References) if
the main goal is to find a design with the minimum number of transistors.
5.9 Exercises
In all the following questions, unless otherwise mentioned, choose the
design that yields strong outputs.
supply1 vdd;
supply0 gnd;
endmodule
3. For the XNOR gate discussed in Listing 5.13, use NAND gates and
inverters to design the XNOR gate. Write the switch-level Verilog code
and verify your design. Contrast this approach with that of Listing 5.13
in terms of the total number of transistors needed.
4. Referring to Listing 5.15, construct the gate level of the multiplexer
using NOR gates and inverters. Write the switch-level VHDL code and
verify your design. What is the total number of transistors used in this
gate-level design?
5. Design the switch level for an SR-latch from the Boolean function using
the minimum number of switches. Compare the number of switches
used with that of Listing 5.15. Write the VHDL code and verify your
design by simulation.
6. Write the VHDL code for Listing 5.18. Verify your code by simulation.
7. In Figure 5.22, the control E is active high. Modify the figure to show an
active low enable.
8. Repeat Listing 5.15 using tranif0 and tranif1 instead of PMOS and
NMOS switches.
9. Add active low clear signal to the D-Latch in Example 5.14 and rewrite
the VHDL and Verilog codes.
5.10 References
Wang, J., S. Fang, and W. Feng. 1995. New Efficient Designs for XOR and
XNOR Functions on the Transistor Level. IEEE Journal of Solid State
Circuits 29:780–786.
Weste, Neil H. E. and D. Harris, CMOS VLSI Design, 3rd ed. Upper Saddle
River, NJ: Addison-Wesley, 2004.
CHAPTER
6
PROCEDURES, TASKS, AND
FUNCTIONS
Chapter Objectives
O Understand the concept of procedures (VHDL), tasks (Verilog), and
functions (both VHDL and Verilog)
O Review and understand how to convert between different types of
data
O Review signed vector multiplication
O Understand combinational arrays multiplier
O Review IEEE 754 representation of floating point
O Understand a simple enzyme mechanism
Facts
Procedures, tasks, and functions are HDL tools to optimize the writ-
ing style of HDL code. They are implemented to instantiate a seg-
ment or a construct of code. Instead of writing the segment/construct
every time it is needed, a single call statement to a function, task, or
procedure that references the segment/construct is all that is needed.
Procedures and tasks can have more than one input and more than
one output. Functions have a single output, but they can have more
than one input.
278 • HDL WITH DIGITAL DESIGN
The body of the procedure contains the behavioral statements that de-
scribe the details of the procedure, mainly the relationship between the
input(s) and the output(s). The body of the procedure cannot include the
behavioral statement process. An example of a procedure is:
procedure exmple (signal a : in std_logic;
signal y : out std_logic) is
PROCEDURES, TASKS, AND FUNCTIONS • 279
variable x : std_logic;
begin
x := a;
case x is
…………………
end case;
y <= x;
end exmple;
addr is the name (identifier) of the task. The outputs are cc and dd,
and the inputs are aa and bb. task is a predefined word. The body of the
task shows the relationship between the outputs and inputs. An example of
the body of a task is:
begin
cc = aa ^ bb;
.............
end
endtask
The body of the task cannot include always or initial. A task must be
called within the behavioral statement always or initial (see Chapter 3).
An example of calling the task addr is:
............
always @ (a, b)
begin
addr (c, d, a, b);
end
addr is the name of the task. Inputs a and b are passed to aa and bb.
The outputs of the task cc and dd are passed, after execution, to c and
d, respectively. Verilog has a large number of built-in tasks included in its
package.
x
sum
y
cin Half adder
Half adder
carry
Listing 6.1 shows the HDL code for the full adder using procedure
(VHDL) and task (Verilog). Referring to the VHDL Listing, the code for
the half adder is written as a procedure:
procedure Haddr(sh, ch : out std_logic;
ah, bh : in std_logic) is
begin
sh := ah xor bh;
ch := ah and bh;
end Haddr;
The name of the above procedure is Haddr; the inputs are sh and
ch, and the outputs are ah and bh. The type of the outputs and inputs is
std_logic. The code of the procedure is based on the Boolean functions
of the half adder. To call the procedure, the call statement has to be inside
process. To call the procedure Haddr:
Haddr (sum1, c1, y, cin);
where Haddr is the name of the procedure, and the values y and cin
are passed to the inputs of the procedure ah and bh, respectively. After
calculating the outputs (sh and ch), the procedure passes the value of those
outputs to sum1 and c1, respectively.
For the Verilog code, the task is:
task Haddr;
output sh, ch;
input ah, bh;
begin
sh = ah ^ bh;
ch = ah & bh;
end
endtask
282 • HDL WITH DIGITAL DESIGN
The name of the task is Haddr; the inputs are ah and bh, and the outputs
are sh and ch. The task code is based on the Boolean functions of the half
adder. To call task, it has to be inside always or initial because task is
a behavioral (sequential) statement. Therefore, to call the task Haddr:
Haddr (sum1, c1, y, cin);
where haddr is the name of the task. The values y and cin are passed
to the inputs of the task ah and bh, respectively. After calculating the out-
puts (sh and ch), the task passes the value of the outputs to sum1 and c1,
respectively.
LISTING 6.1 HDL Description of a Full Adder Using procedure and task:
VHDL and Verilog
VHDL Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity full_add is
port (x, y, cin : in std_logic; sum, cout : out std_logic);
end full_add;
begin
tem2 := c1 or c2;
sum <= tem1;
cout <= tem2;
end process;
end two_halfs;
Verilog Description
module Full_add (x, y, cin, sum, cout);
//The full adder is built from two half adders
input x, y, cin;
output sum, cout;
reg sum, sum1, c1, c2, cout;
always @ (x, y, cin)
begin
task Haddr;
//This task describes the half adder
output sh, ch;
input ah, bh;
begin
sh = ah ^ bh;
ch = ah & bh;
end
endtask
endmodule
Notice that the half adder procedure (task) was executed twice, but
the body of the procedure (task) was only written once.
entity adder_ripple is
generic (N : integer := 3);
port (x, y : in std_logic_vector (N downto 0);
cin : in std_logic;
begin
addrpl : process (x, y, cin)
variable c1, c2, tem1, tem2 : std_logic;
variable cint : std_logic_vector (N+1 downto 0);
variable sum1 : std_logic_vector (N downto 0);
begin
cint(0) := cin;
for i in 0 to N loop
Faddr (sum1(i), cint(i+1), x(i), y(i), cint(i));
--The above statement is a call to the procedure Faddr
end loop;
sum <= sum1;
PROCEDURES, TASKS, AND FUNCTIONS • 285
Verilog, however, is flexible when dealing with data types and allows com-
putational operations between different types without any conversion.
However, to understand task, Verilog code will be used to describe con-
version examples.
In Chapter 3, behavioral code was written for conversions between bi-
nary and integer data. Here, procedure (task) is used to perform the
conversion.
Listing 6.3 shows the HDL code for converting an unsigned binary vec-
tor to an integer. The conversion is based on accumulating the weighted
sum of the binary bits. The code
result := result + 2i; --VHDL
int = int + 2i //Verilog
LISTING 6.3 HDL Code for Converting an Unsigned Binary to an Integer Us-
ing procedure and task: VHDL and Verilog
entity Bin_Int is
generic (N : natural := 3);
PROCEDURES, TASKS, AND FUNCTIONS • 287
result := 0;
for i in bin’Range loop
begin
process (X_bin)
variable tem : natural;
begin
bti (X_bin, tem, Z);
Y_int <= tem;
end process;
end convert;
288 • HDL WITH DIGITAL DESIGN
task bti;
parameter P = N;
output integer int;
output Z;
input N;
input [P:0] bin;
integer i, result;
begin
int = 0;
//change binary to integer
for (i = 0; i <= P; i = i + 1)
begin
if (bin[i] == 1)
int = int + 2i;
end
if (int == 0)
Z = 1’b1;
else
Z = 1’b0;
end
endtask
endmodule
Y_int 14 13 3 0 9 5 1
Z
FIGURE 6.2 Simulation output for binary-to-integer conversion.
LISTING 6.4 HDL Code for Converting a Fraction Binary to Real Using pro-
cedure and task: VHDL and Verilog
VHDL: Converting a Fraction Binary to Real Using procedure
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Bin_real is
generic (N : integer := 3);
port (X_bin : in std_logic_vector (0 to N); Y : out real);
end Bin_real;
architecture Bin_real of Bin_real is
procedure binfloat (a : in std_logic_vector (0 to 3);
float : out real) is
j := 1.0;
for i in 0 to N loop
j := j/ 2.0;
tem := tem + j;
end if;
end loop;
float := tem;
end binfloat;
begin
always @ (X_bin)
begin
binfloat (X_bin, Z);
end
task binfloat;
parameter P = N;
input [0:P] a;
output real float;
integer i;
begin
float = 0.0;
for (i = 0; i <= P; i = i + 1)
begin
if (a[i] == 1)
float = float + 1.0 / 2(i+1);
PROCEDURES, TASKS, AND FUNCTIONS • 291
LISTING 6.5 HDL Code for Converting an Unsigned Integer to Binary Using
procedure and task: VHDL and Verilog
VHDL: Converting an Unsigned Integer to Binary Using procedure
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Int_Bin is
generic (N : integer := 3);
port (X_bin : out std_logic_vector (N downto 0);
Y_int : in integer;
flag_even : out std_logic);
end Int_Bin;
begin
if (int MOD 2 = 0) then
--The above statement checks int to see if it is even.
flag <= ‘1’;
else
flag <= ‘0’;
end if;
for i in 0 to N loop
begin
process (Y_int)
variable tem : std_logic_vector (N downto 0);
variable tem_int : integer ;
begin
tem_int := Y_int;
itb (tem, flag_even, N, tem_int);
X_bin <= tem;
end process;
end convert;
Verilog: Converting an Unsigned Integer to Binary Using task
module Int_Bin (X_bin, flag_even, Y_int );
/In general Verilog, in contrast to VHDL, does not
strictly differentiate between integers and binaries;
PROCEDURES, TASKS, AND FUNCTIONS • 293
if (int %2 == 0)
//The above statement checks int to see if it is even.
flag = 1’b1;
else
flag = 1’b0;
for (j = 0; j <= P; j = j + 1)
begin
if (int %2 == 1)
bin[j] = 1;
else
bin[j] = 0;
int = int/2;
end
end
endtask
endmodule
294 • HDL WITH DIGITAL DESIGN
Y_int 12 0 15 7 8 9
Flag_even
FIGURE 6.4 Simulation output for integer conversion to binary.
Verilog
if (bin [P] == 1)
int = int - 2(P+1);
To know whether the parity is odd or even, the 1s in the input data
are counted and stored in the variable parity. Then, parity is divided
by two: if there is a remainder, the parity is odd. Otherwise, it is even. The
built-in function modulus, mod (VHDL) or % (Verilog), is used to determine
whether parity is odd or even as follows:
VHDL
if (parity mod 2 = 1) then
--if parity is divisible by 2, then it is even,
--otherwise it is odd.
even <= ‘0’;
else
even <= ‘1’;
end if;
Verilog
if ((parity % 2) == 1)
//if parity is divisible by 2, then it is even,
otherwise it is odd.
even = 0;
else
even = 1;
The signal even_parity in Listing 6.6 identifies the parity of the input
data. If the parity is even, then even_parity is one, otherwise, it is zero.
LISTING 6.6 HDL Code for Converting a Signed Binary to an Integer Using
procedure and task: VHDL and Verilog.
VHDL: Converting a Signed Binary to an Integer Using procedure
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity signed_btoIn is
296 • HDL WITH DIGITAL DESIGN
result := 0;
for i in 0 to M loop
if binsg(i) = ‘1’ then
result := result + 2i;
parity := parity + 1;
end if;
end loop;
end sbti;
begin
PROCEDURES, TASKS, AND FUNCTIONS • 297
process (X_bin)
variable tem : integer;
begin
sbti (X_bin, N, tem, even_parity);
Y_int <= tem;
end process;
end convert;
parameter N = 3;
input signed [N:0] X_bin;
output integer Y_int;
output even_parity;
reg even_parity;
always @ (X_bin)
begin
sbti (Y_int, even_parity, N, X_bin);
end
task sbti;
parameter P = N;
output integer int;
output even;
input N;
input [P:0] bin;
integer i;
reg parity;
begin
int = 0;
parity = 0;
//change binary to integer
for (i = 0; i <= P; i = i + 1)
298 • HDL WITH DIGITAL DESIGN
begin
if (bin[i] == 1)
begin
int = int + 2i;
parity = parity + 1;
end
end
if ((parity % 2) == 1)
even = 0;
else
even = 1;
if (bin [P] == 1)
int = int - 2(P+1);
end
endtask
endmodule
Y_int 7 –5 –2 –3 3 –4
even_parity
FIGURE 6.5 Simulation output for converting a signed binary to an integer.
LISTING 6.7 VHDL Code for Converting an Integer to a Signed Binary Using
procedure
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity signed_IntToBin is
generic (N : integer := 3);
port (X_bin : out signed (N downto 0); Y_int : in integer);
end signed_IntToBin;
end loop;
if (flag = ‘1’) then
sbin := - bin;
else sbin := bin;
end if;
end sitb;
begin
process (Y_int)
variable tem : signed (N downto 0);
begin
sitb(tem, N, Y_int);
X_bin <= tem;
end process;
end convert;
d=a×b (6.1)
where a is a row vector with three elements, and b is a column vector
with three elements. Accordingly, d is a row vector with three elements.
Equation 6.1 can be written as: b0
d = a0 a1 a2 × b1 (6.2)
b2
From Equation 6.2,
d = a0 b0 + a1 b1 + a2 b2 (6.3)
In this example, all elements of Equation 6.3 are signed binary. To mul-
tiply two signed numbers, Booth algorithm (as discussed in Chapter 3) is
implemented. Listing 6.8 shows the HDL code for signed vector multipli-
cation using procedure (task). The inputs to the multiplication algorithm
are written as:
port (a0, a1, a2, b0, b1, b2 : in signed (N downto 0);
d : out signed (3N downto 0));
If a large number of elements are being multiplied, the above code may
not be practical because a large number of ports must be listed. In Chapter 7,
PROCEDURES, TASKS, AND FUNCTIONS • 301
the ports are listed as an array; this will shorten the code. The Booth algo-
rithm is written as a procedure or task with the declaration:
VHDL
procedure booth (X, Y : in signed (3 downto 0);
Z : out signed (7 downto 0));
Verilog
task booth;
input signed [3:0] X, Y;
output signed [7:0] Z;
where the inputs are X and Y, and the output is Z. The procedure (task) is
restricted to 4x4 bits. The procedure (task) can be generalized to multiply
any NxN bits (see Exercise 6.2). The three procedure (task) callings calcu-
late the partial products a0b0, a1b1, and a2b2 as:
booth (a0, b0, tem0);
booth (a1, b1, tem1);
booth (a2, b2, tem2);
The partial products are stored in the eight-bit registers tem0, tem1, and
tem2, respectively. To find the product d, add tem0 + tem1 + tem2, and,
according to Listing 6.8, the product is stored in ten-bit register d. By
choosing ten bits, any overflow is avoided that might occur after accumulat-
ing the partial products in register d. To calculate d in Verilog, simply write:
d = tem0 + tem1 + tem2;
In VHDL, the language is strictly type and size oriented, so the VHDL
simulator may not perform the above operation because d has a different
size than tem0, tem1, and tem2. Several approaches can be taken to adjust
the size. The approach here is to convert tem0, tem1, and tem2 to integers
by using the procedure sbti and add all integers and convert back to bi-
nary by using the procedure sitb. Another approach is to extend the sizes
of tem0, tem1, and tem2 to ten bits and then add tem0+tem1+tem2 (see
Exercise 6.1).
entity Vector_Booth is
generic (N : integer := 3);
port (a0, a1, a2, b0, b1, b2 : in signed (N downto 0);
d : out signed (3N downto 0));
end Vector_Booth;
sum := -sum;
end if;
Z := sum;
end booth;
PROCEDURES, TASKS, AND FUNCTIONS • 303
for i in 0 to M loop
if (temp_int MOD 2 = 1) then
bin (i) := ‘1’;
else
bin (i) := ‘0’;
end if;
temp_int := temp_int/2;
end loop;
if (flag = ‘1’) then
sbin := -bin;
else
sbin := bin;
end if;
end sitb;
begin
304 • HDL WITH DIGITAL DESIGN
result := 0;
for i in 0 to M loop
if binsg(i) = ‘1’ then
result := result + 2i;
end if;
end loop;
begin
process (a0, b0, a1, b1, a2, b2)
variable tem0, tem1, tem2 : signed ((2N + 1) downto 0);
variable d_temp : signed (3N downto 0);
variable temi0, temi1, temi2, temtotal : integer;
begin
--Find the partial products a0b0, a1b1, a2b2
booth (a0, b0, tem0);
booth (a1, b1, tem1);
booth (a2, b2, tem2);
d <= d_temp;
end process;
end multiply;
parameter N = 3;
input signed [N:0] a0, a1, a2, b0, b1, b2;
output signed [3N : 0] d;
reg signed [2N+1 : 0] tem0, tem1, tem2;
begin
Z = 8’d0;
E1 = 1’d0;
for (i = 0; i < 4; i = i + 1)
begin
temp = {X[i], E1}; //This is catenation
Y1 = -Y; //Y1 is the 2’ complement of Y
case (temp)
2’d2 : Z [7:4] = Z [7:4] + Y1;
2’d1 : Z [7:4] = Z [7:4] + Y;
default : begin end
endcase
Z = Z >> 1; /This is a logical shift of one position to
the right/
Z[7] = Z[6];
/The above two statements perform arithmetic shift
306 • HDL WITH DIGITAL DESIGN
end
if (Y == 4’b1000) Z = -Z;
end
endtask
endmodule
a b
c1 X(i–1)
FSA c2
S1 X(i)
c
b S
(a)
0 1 0 1 0 1 0 0 0 1
0
0 0
FSA 0 FSA 0 FSA 0 FSA 0 FSA comp
0
0 0 0 1
1 0 1 0 0
1
FSA 1 FSA 1 FSA 1 FSA comp
0 1
0 0 1 1 1
1
0
1
FSA FSA FSA comp
0 0 0
0 1
P4 P3 P2 P1 P0
1 1 0 1 0
(b)
FIGURE 6.7 A combinational array multiplier a) Cells comp and FAS. b) A multiplier circuit
that multiplies -3 × 2 where x = 2 and b = -3.
Borrow : out std_logic) is
begin
Diff := (not a and not b and c) or
(not a and b and not c) or
(a and not b and not c) or
(a and b and c);
Borrow := ((not a) and c) or ((not a) and b) or (b and c);
begin
B1: process (start,x,y)
variable s1, s2: std_logic;
variable T : std_logic_vector(3 downto 0);
begin
if (start = ‘1’) then
f := “00000”; E := “00000”;z := “00000”;
carry_temp := “000000”;
T := (x & ‘0’);-- T now represents all the inputs to
--cells COMP including the initial
--zero on the first COMP cell.
for layer in 0 to 2 loop
carry_temp(0) := ‘0’;
COMPR (T,layer,s1,s2);
end loop;
end if;
p <= z;
end process B1;
end boothar;
Verilog
module bootharrayTask(start, x, y, p);
PROCEDURES, TASKS, AND FUNCTIONS • 311
input start;
input [2:0] x;
input [4:0]y;
output [4:0] p;
/input y is 3-bit with additional 2 bits as sign extension/
if (start == 1’b1)
begin
T = {x,1’b0};/ T now represents all the inputs to
cells COMP including the initial
zero on the first COMP cell./
f = 5’d0; E = 5’d0; p = 5’d0; carry_temp = 6’d0;
for (layer = 0; layer <= 2; layer = layer + 1)
begin
carry_temp [0] = 1’b0;
COMPR (T,layer,s1,s2);
if (s1 == 1’b0)
begin
for (j = 0; j <= (4-layer); j = j+1)
begin
end
end
end
end
end
task COMPR;
input [3:0]n1;
input integer i;
output c1, c2;
begin
c1 = n1[i+1] ^ n1[i];
c2 = n1[i+1] & ( ~ n1[i]);
end
endtask
task Fulladdr;
input a, b,c;
output sum, Carryout;
reg sum, Carryout;
begin
sum = (~a & ~b & c) |
(~a & b & ~ c) |
(a & ~ b & ~ c) |
(a & b & c);
Carryout = (a & b) | (a & c) | (b & c);
end
PROCEDURES, TASKS, AND FUNCTIONS • 313
endtask
task Fullsub;
input a, b,c;
output Diff, Borrow;
begin
Diff = (~a & ~b & c) |
(~a & b & ~ c) |
(a & ~ b & ~ c) |
(a & b & c);
Borrow = ((~ a) & c) | ((~ a) & b) | (b & c);
end
endtask
endmodule
E E
n n
z Substrate z
y y Substrate
m m
e e
(a) (b)
FIGURE 6.8 Binding between substrate and enzyme. (a) Strong. (b) Week.
314 • HDL WITH DIGITAL DESIGN
The binding strength between the substrate and the enzyme is mea-
sured by a parameter called the dissociation constant (M). If M is large, the
binding or affinity between substrate and enzyme is weak and vice versa.
The rate of reaction between an enzyme with dissociation constant, M, and
a substrate with concentration, S, is represented by Equation 6.4
S
V = Vmax (6.4)
S+M
where S is the concentration of the substance and Vmax is the maximum pos-
sible rate of reaction when S >> M. Usually, Vmax is assigned the value of
1 (100%), and accordingly, V is measured as a fraction or percentage.
Figure 6.9 shows a graphical representation of Equation 6.4 for a dissociation
constant of three units. Notice that if S = M, then V = 0.5Vmax, so M can be
viewed as the concentration of substrate at which the rate of reaction is 50%
of Vmax. Figure 6.9 shows the relationship between the substrate concentra-
tion, S, and rate of reaction, V.
1.0
V
0.8
0.5
0.3
0.0
1 5 10 15 20
S
FIGURE 6.9 Relationship between the substrate concentration, S, and rate of reaction, V.
Listing 6.10 shows the HDL code describing the enzyme-substrate ac-
tivity. The challenge here is to write HDL code that can operate on real
numbers. Recall that V is a fraction if Vmax is taken as 1.
PROCEDURES, TASKS, AND FUNCTIONS • 315
LISTING 6.10 HDL Description for Enzyme Activity Using procedure and
task:VHDL and Verilog
VHDL: Enzyme Activity Using procedure
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
-- A description of enzyme-substrate binding mechanism.
-- S= (Vmax S)/(S + M) where S is the substrate
-- concentration, M is the dissociation constant, and Vmax
-- is the maximum rate of reaction. In this example,
-- Vmax = 1. The inputs are S and M in binary (fraction);
-- the output v is in Q4 format. This means that v is
-- always less than one, with the binary point placed to
-- the left of the most significant bit. For example,
-- if v = 1010, the decimal equivalent is .5 + .125 =
-- 0.625. To calculate v, convert S and M to real fraction,
-- find the real value of (S/(S + M)), convert this real
-- value to Q4 by multiplying it with 24 = 16, and
316 • HDL WITH DIGITAL DESIGN
entity enzyme_beh is
port (S : in std_logic_vector (0 to 3);
M : in std_logic_vector(0 to 3);
v : out real ; intg_bin : out integer;
start: in bit);
end enzyme_beh;
for i in 0 to 3 loop
j := j/ 2.0;
if (a(i) = ‘1’) then
tem := tem + j;
end if;
end loop;
float := tem;
end flt;
procedure rltointg (a1 : in real ; Bin1 : out integer ) is
begin
P1 : process(S, M, start)
variable temp1, temp11, vmax : real;
variable temp2: integer := 0;
begin
if (start = ‘1’) then
vmax := 1.0;
flt( S,temp1);
flt( M,temp11);
temp1 := Vmax ( temp1/(temp1 + temp11));
v <= temp1;
temp1 := temp1 16.0;
rltointg (temp1, temp2);
intg_bin <= temp2;
end if;
end process P1;
end enzyme;
input real r;
output [3:0] v1;
real temp;
begin
temp = r;
v1 = 4’b0000;
while (temp >= 0.5)
begin
v1 = v1 + 1;
temp = r - 1.0 v1;
end
end
endtask
endmodule
FIGURE 6.10 Simulation output of the relationship between substrate concentration, S, and rate of reac-
tion, V, for M = 3 units.
6.3 Functions
Functions are behavioral statements. As is the case when calling proce-
dure or task, functions must be called within process (VHDL) or always
or initial (Verilog). Functions take one or more inputs, and, in contrast
to procedure or task, they return only a single output value.
entity Func_exm is
port (a1, b1 : in std_logic; d1 : out std_logic);
end Func_exm;
begin
process (a1, b1)
begin
d1 <= exp (a1, b1);
--The above statement is a function call
end process;
end Behavioral;
In Listing 6.11, the name of the function is exp; it has two inputs, a and
b, of type std_logic. The type of the output to be returned is std_logic.
The output to be returned is d. The function, as seen from its body, is
performing a xor function on the inputs a and b. To call the function, it
should be written inside a process. The function is called by the following
statement:
d1 <= exp (a1, b1);
declares a function with the name (identifier) exp. The function has two
inputs, a and b, and one output, exp. All inputs are one-bit data, and the
output is also one-bit data. The inputs and output can take 0, 1, x (“don’t
care”), or Z (high impedance). The body of the function follows the declara-
tion in which the relationship between the output and the inputs is stated.
An example of a function and its call is shown in Listing 6.12. The function
calculates exp = a XOR b.
function exp ;
input a, b;
begin
exp = a ^ b;
end
endfunction
endmodule
322 • HDL WITH DIGITAL DESIGN
LISTING 6.13 HDL Function to Find the Greater of Two Signed Numbers:
VHDL and Verilog
VHDL Function to Find the Greater of Two Signed Numbers
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity greater_2 is
port (x, y : in signed (3 downto 0);
z : out signed (3 downto 0));
end greater_2;
begin
PROCEDURES, TASKS, AND FUNCTIONS • 323
process (x, y)
begin
z <= grt (x, y); --This is a function call.
end process;
end greater_2;
begin
if (a >= b)
grt = a;
else
grt = b;
end
endfunction
endmodule
3
EXAMPLE 6.12 FUNCTION TO FIND THE FLOATING SUM Y = (-1) (x) , i i
0<X<1 i=0
Q4 format. This means that the binary point is at the left of the most sig-
nificant bit of x, and the total number of bits is four. For example, if the
number is 1010, then its decimal value is 2–1 + 0 + 2–3 + 0 = 0.5 + 0.125 =
0.625. The output y in this example is assigned a Q8 format. To calculate y,
3
first convert x to real, then calculate the real sum of (-1)i (x)i = 1 – x +
i=0
x2 – x3. To convert the sum to Q8, multiply the real sum by 28; this generates
a real number. This real number is converted to an integer, and finally, the
integer is converted to binary. For example, if x = 1011, the following steps
are executed:
begin
PROCEDURES, TASKS, AND FUNCTIONS • 325
rti = r;
end
endfunction
The statement rti = r; has a left-hand rti of type integer and a right-
hand side of r (real). Verilog allows this mixing of two types; it calculates the
right-hand side as real, and when assigned to the left-hand side, the type is
converted from real to integer.
3
LISTING 6.14 HDL Code for y = (-1)i (x)i , 0 < x < 1: VHDL and Verilog
i=0
VHDL Floating Sum Description
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity segma is
port (x : in std_logic_vector (0 to 3);
y: out std_logic_vector (7 downto 0));
end segma;
for i in 0 to 3 loop
j := j/ 2.0;
tem := tem + j;
end if;
end loop;
float := tem;
end flt;
326 • HDL WITH DIGITAL DESIGN
for i in 0 to N loop
if (temp_int MOD 2 = 1) then
bin(i) := ‘1’;
else bin(i) := ‘0’;
end if;
temp_int := temp_int/2;
end loop;
end itb;
function exp (a : in std_logic_vector (0 to 3))
return std_logic_vector is
variable z1 : real;
variable intgr : integer;
variable tem : std_logic_vector (7 downto 0);
PROCEDURES, TASKS, AND FUNCTIONS • 327
begin
flt (a, z1);
z1 := 1.0 - z1 + z1 z1 - z1 z1 z1;
z1 := z1 256.0; -- 256 is for 8 bits
rltointg (z1, intgr);
itb (tem, 7, intgr);
return tem;
end exp;
begin
sg1 : process (x)
variable tem1 : std_logic_vector (7 downto 0);
variable tem2: integer;
begin
tem1 := exp(x);
y <= tem1;
end segm_beh;
begin
rti = r;
end
endfunction
function [7:0] exp;
input [0:3] a;
328 • HDL WITH DIGITAL DESIGN
real z1;
integer i;
begin
z1 = 0.0;
for (i = 0; i <= 3; i = i + 1)
begin
if (a[i] == 1)
z1 = z1 + 1.0 / 2(i+1);
/The above statement multiplies
each bit by its weight/
end
end
endfunction
endmodule
accuracy is 1/16; any number less than 1/16 will not be represented with
100% accuracy and may be considered (depending on the rounding systems
used) as zero. On the other hand, floating-point representation, which rep-
resents the number using exponent and mantessa fields, are more accurate
and is the common representation for real numbers in computers. Because
any number can be represented with unlimited variations of exponent and
mantessa, the Institute of Electrical and Eleconics Engineers (IEEE) has
established a standard format (IEEE 754) for the representation of float-
ing-point numbers. According to this format, any floating-point number is
represented by 32 bits for single precision and 64 bits for double precision,
as shown in Figure 6.12. The value of the number N is:
N=(-1)s x (1 + Fraction) x 2(Exponent – Bias)
The fraction is less than one and is represented by 23 bits for
single precision and 53 for double precision. The “1” that is
added to the fraction is hidden and does not appear in the for-
mat (see Figure 6.12). The bias is 127 for single precision and
1023 for double precision. For example, the number 0.5 × 2-10 is
represented in single precision as
00111010110000000000000000000000
where the sign is positive (0); the exponent is 127 + (-10) =
11710 = 011101012; the fraction is
100000000000000000000002
0 1 8 9 31
Exponent Fraction
S
8 bits 23 bits
(a)
0 1 10 11 63
Exponent Fraction
S
11 bits 52 bits
(b)
FIGURE 6.12 IEEE 754 floating-point representation. a) Single precision. b) Double precision.
Listing 6.15 shows a Verilog code for the conversion of any positive
number to the IEEE 754 single-precision floating-point representation.
For example, if the number is x = 24.0, it is converted first to (1 + fraction)
2(Exponent – Bias) by dividing x by 24 which yields to x = 1.5 × 24; the fraction is
0.5, and the exponent is 127 + 4 = 131. The output IEEE_flt for x = 24.0 is:
01000001110000000000000000000000
330 • HDL WITH DIGITAL DESIGN
real Mant;integer i;
always @ (start,x,j)
begin
if (start == 1’b1)
begin
end
end
Mant = x-1.0;
begin
IEEE_flt [9+i] = 1’b1;
Mant = Mant-1.0;
end
end
IEEE_flt [0] = 1’b0;
IEEE_flt [1:8] = j[7:0];
end
endmodule
6.4 Summary
In this chapter, procedure (VHDL), task (Verilog), and function
(both VHDL and Verilog) have been covered. Procedures, tasks, and func-
tions can optimize the style of writing HDL code; they shorten the code.
The procedure/task has a declaration statement and a body, and it can have
more than one input and more than one output. On the other hand, a func-
tion can have more than one input but only one output. VHDL allows pro-
cedure calls to be written inside functions; Verilog does not allow such calls.
6.5 Exercises
4. Derive the HDL code (both VHDL and Verilog) for the function y = Ln
x; 0 < x < 1. Express y in Q15 format. Hint: use polynomial representa-
tion for Ln (x).
5. Write a function to calculate the area of a sphere, given the radius.
6. Rewrite the code for the Booth array (Listing 6.9) to simulate an NxN
array multiplier. Hint: For N layers, the bottom layer contains N cells,
and the number of cells increases by one.
7. In Listings 6.10 and 6.14, the VHDL code for the procedure rlto-
intg does not round off. For example, if the real value is 215.3175, the
procedure will output 216 for the integer equivalent. On the other hand,
the Verilog code of the procedure is rounding off. Rewrite the VHDL
procedure so it will round off. Adjust the VHDL code to output the
same value as the Verilog.
8. Repeat Listing 6.15 but for positive or negative numbers and use
double precision.
6.6 Reference
Hayes, J., Computer Architecture and Organization, 3rd ed. McGraw Hill, Boston,
Massachusetts, USA, 1998.
CHAPTER
7
MIXED-TYPE DESCRIPTION
Chapter Objectives
O Learn how to use different types (styles) of descriptions to write
HDL modules
O Learn which type or style of description to use for optimal writing
style
O Understand the concept of packages in VHDL and how to use them
O Practice with single and multidimensional arrays
O Practice with real (floating) numbering systems
O Practice user-defined types
O Practice using finite sequential-state machines
O Review and understand the steps needed to design and describe a
basic computer
entity ALUS2 is
port (a, b : in std_logic_vector (3 downto 0);
cin : in std_logic; opc : in op;
z : out std_logic_vector (7 downto 0);
cout : buffer std_logic);
end ALUS2;
LISTING 7.3 HDL Code for Finding the Greatest Element of an Array: VHDL
and Verilog
VHDL: Finding the Greatest Element of an Array
library IEEE;
use IEEE.STD_LOGIC_1164.all;
constant M : integer := 3;
MIXED-TYPE DESCRIPTION • 339
end array_pkg;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.array_pkg.all;
-- The above statement makes the package array_pkg visible
-- in this module.
entity array1 is
generic (N : integer :=4; M : integer := 3);
begin
com: process (a)
variable grtst : wordN;
begin
grtst := “0000”;
end max;
constant M : integer := 3;
package booth_pkg is
constant N : integer := 4;
--N + 1 is the number of elements in the array.
constant M: integer := 3;
--M + 1 is the number of bits of each element
--of the array.
end booth_pkg;
sum (7 downto 4) + Y;
when others => null;
end case;
sum := sum srl 1;
sum(7) := sum(6);
E1(0) := x(i);
end loop;
if (y = “1000”) then
sum := -sum;
--If Y = 1000; then Y1 is calculated as 1000;
--that is -8, not 8 as expected. This is because Y1 is
--4 bits only. The statement sum = -sum corrects
--this error.
end if;
Z := sum;
end booth;
end booth_pkg;
-- We start writing the multiplication algorithm using
-- the package booth_pkg
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.booth_pkg.all;
entity vecor_multply is
generic (N : integer := 4; M : integer := 3);
--N + 1 is the number of elements in the array; M + 1 is
-- the number of bits of each element.
begin
process (a, b)
variable temp : signed (7 downto 0);
variable temp5 : signed (3N downto 0) := “0000000000000”;
begin
344 • HDL WITH DIGITAL DESIGN
for i in 0 to 4 loop
booth(a(i), b(i), temp);
end multply;
always @ (start)
begin
a[0] = 4’b1100;
a[1] = 4’b0000;
a[2] = 4’b1001;
a[3] = 4’b0011;
a[4] = 4’b1111;
b[0] = 4’b1010;
b[1] = 4’b0011;
b[2] = 4’b0111;
b[3] = 4’b1000;
b[4] = 4’b1000;
d = 0;
for (i = 0; i <= N; i = i + 1)
begin
booth (a[i], b[i], temp);
d = d + temp;
end
end
MIXED-TYPE DESCRIPTION • 345
task booth;
input signed [3:0] X, Y;
output signed [7:0] Z;
reg signed [7:0] Z;
reg [1:0] temp;
integer i;
reg E1;
reg [3:0] Y1;
begin
Z = 8’d0;
E1 = 1’d0;
for (i = 0; i < 4; i = i + 1)
begin
temp = {X[i], E1}; //This is catenation
Y1 = -Y; //Y1 is the 2’complement of Y
case (temp)
2’d2 : Z[7:4] = Z[7:4] + Y1;
2’d1 : Z[7:4] = Z[7:4] + Y;
default : begin end
endcase
Z = Z >> 1;
/The above statement is a logical shift of
one position to the right/
Z[7] = Z[6];
/The above two statements perform arithmetic shift where the
sign of the number is preserved after the shift. /
E1 = X[i];
end
if (Y == 4’b1000)
Z = -Z;
end
346 • HDL WITH DIGITAL DESIGN
endtask
endmodule
Figure 7.1 shows the simulation output of the vector multiplication. Ar-
ray a is written here in integer format for convenience:
a = {–1 3 –7 0 –4}
b = {–8 –8 7 3 –6}
multiplying a × b = 8 – 24 – 49 + 0 + 24 = –41 =d
As shown in Figure 7.1, d has the correct value of –41.
d 1111111010111
FIGURE 7.1 Simulation output of vector multiplication.
constant N : integer := 4;
-- N+1 is the number of elements in the array.
-- this is [N+1,N+1] matrix with N+1 rows and N+1 columns
348 • HDL WITH DIGITAL DESIGN
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.twodm_array.all;
entity two_array is
Port (N, M : integer; z : out integer);
end two_array;
begin
com : process (N, M)
variable t : integer;
constant y : strng2 := ((7, 6, 5, 4, 3), (6, 7, 8, 9, 10),
(30, 31, 32, 33, 34), (40, 41, 42, 43, 44),
(50, 51, 52, 53, 54));
begin
t := y (N)(M);
integer i,j,K = 0;
always @ ((start == 1’b1),N,M)
begin
K = 0;
for (i = 0; i <= N1; i= i +1)
begin
for (j = 0; j <= M1; j= j +1)
begin
K= K +1;
Y[i][j]= K;
end
end
Z = Y[N][M];
end
endmodule
Figure 7.2 shows the VHDL simulation output of Listing 7.5. From the
simulation:
N 0 0 0 2 4 4
M 0 3 4 4 4 3
Z 54 51 50 30 7 6
FIGURE 7.2 VHDL simulation output of the array in Listing 7.5.
350 • HDL WITH DIGITAL DESIGN
1 2 3 4 5 4 5 6 7 8
6 7 8 9 10 9 10 11 12 13
11 12 13 14 15 14 15 16 17 18
16 17 18 19 20 19 20 21 22 23
21 22
23 24 25 24 25 26 27 28
The addition is done by adding row by row. Listing 7.6 shows the HDL
description of the addition of two [5×5] matrices. In VHDL, the two ma-
trices are entered as inputs. In Verilog, the two matrices are generated by
two loops.
package twodm_array is
constant N : integer := 4;
-- N+1 is the number of elements in the array.
-- This is an NxN matrix with N rows and N columns.
subtype wordg is integer;
type strng1 is array (N downto 0) of wordg;
type strng2 is array (N downto 0) of strng1;
end twodm_array;
begin
com : process (x, y)
variable t : integer := 0;
begin
for i in 0 to 4 loop
for j in 0 to 4 loop
t := x(i)(j) + y(i)(j);
z(i)(j) <= t;
end loop;
end loop;
end process com;
end sum;
begin
K =0;
for (i = 0; i <= N1; i= i +1)
begin
for (j = 0; j <= M1; j= j +1)
begin
K= K +1;
Y[i][j]= K;
X[i][j] = K + 3;
end
end
Z = Y[N][M];
end
end
end
endmodule
After simulation of the above code, the sum matrix is displayed as:
5 7 9 11 13
15 17 19 21 23
25 27 29 31 33
35 37 39 41 43
45 47 49 51 53
end TO_UNSIGN;
end codes_Arithm;
entity ALU_mixed is
begin
a3 := a1 a2;
temp := TO_UNSIGN(a3);
--The function «TO_UNSIGN» is a user-defined function
--written in the user-defined package «codes_arithm.»
when divide =>
a3 := a1 / a2;
temp := TO_UNSIGN(a3);
end case;
z <= temp;
end process;
end ALU_mixed;
Figure 7.4 shows the simulation output of the ALU. Notice the integer
division of 5 / 7 = 0.
cin
16x8
8 RAM 8
Data in (Data_in) Data out (Data_out)
Read/write (R_wr)
FIGURE 7.5 A block diagram of 16×8 static memory.
The function table of the memory is shown in Table 7.2. Listing 7.8
shows the HDL code for the RAM.
TABLE 7.2 Function Table of SRAM
constant M : integer := 7;
--M+1 is the number of bits of each element
--of the array.
subtype wordN is std_logic_vector (M downto 0);
type strng is array (N downto 0) of wordN;
end array_pkg;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.array_pkg.all;
entity memory16x8 is
generic (N : integer := 15; M : integer := 7);
--N+1 is the number of words in the memory; M+1 is the
--number of bits of each word.
Port (Memory : inout strng; CS : in std_logic;
ABUS: in unsigned (3 downto 0);
Data_in : in std_logic_vector (7 downto 0);
R_WRbar : in std_logic;
Data_out : out std_logic_vector (7 downto 0));
end memory16x8;
A := TO_INTEGER (ABUS);
-- TO_INTEGER is a built-in function
end if;
else
Data_out <= “ZZZZZZZZ”;
--The above statement describes high impedance.
end if;
end process com;
end SRAM;
if (CS == 1’b1)
begin
if (R_WRbar == 1’b0)
begin
Memory [ABUS] = Data_in;
end
else
362 • HDL WITH DIGITAL DESIGN
The simulation output of Listing 7.8 is shown in Figure 7.6. Data are
written in memory locations 0, 14, 15, and 8, and the contents of two mem-
ory locations, 0 and 15, are read; the read data match the written. The
memory is deselected by setting CS to zero, and consequently, the memory
Data_out, as expected, goes on high impedance.
CS
R_WRbar
ABUS 0 14 15 8 0 15 8 14
LISTING 7.9 HDL Code for the State Machine in Figure 7.7: VHDL and
Verilog
VHDL State-Machine Description
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use work.types.all;
entity state_machine is
port (A, clk : in std_logic; pres_st : buffer states;
Z : out std_logic);
end state_machine;
364 • HDL WITH DIGITAL DESIGN
begin
end if;
end case;
pres_st <= present;
end if;
end process FM;
end st_behavioral;
input A, clk;
output [1:0] pres_st;
output Z;
reg Z;
initial
begin
pres_st = 2’b00;
end
always @ (posedge clk)
begin
case (pres_st)
`state0 :
begin
if (A == 1)
begin
present = `state1;
Z = 1’b0;
end
else
begin
366 • HDL WITH DIGITAL DESIGN
present = `state0;
Z = 1’b1;
end
end
`state1 :
begin
if (A == 1)
begin
present = `state2;
Z = 1’b0;
end
else
begin
present = `state3;
Z = 1’b0;
end
end
`state2 :
begin
if (A == 1)
begin
present = `state3;
Z = 1’b1;
end
else
begin
present = `state0;
Z = 1’b0;
end
end
`state3 :
begin
if (A == 1)
begin
present = `state0;
Z = 1’b0;
end
else
begin
present = `state2;
Z = 1’b0;
end
end
MIXED-TYPE DESCRIPTION • 367
endcase
pres_st = present;
end
endmodule
clk
FIGURE 7.8 Simulation waveform of the state machine shown in Figure 7.7.
IR PC AR Memory
Inputs OP Code 3 4 4 16x8 bits
bits bits bits
.........
Decoder
ACH 8 bits ACL 8 bits DR 8 bits
.....
Start
FIGURE 7.9 Registers in the basic computer.
Bit 7 6 5 4 3 2 1 0
OP Code Address
Start Reset
CPU on?
No
Yes
AR ← PC
DR ← M[AR]
Fetch
PC ← PC+1 cycle
IR ← DR(5–7)
AR ← DR(0–3)
Decode IR
performing the three steps of the fetch cycle, while state3 performs the
execute cycle (see Figure 7.11).
1 ADD 9
is stored in memory location 1, the op code is ADD, and the address is 9.
The instruction adds the contents of the accumulator (AC) to the contents
372 • HDL WITH DIGITAL DESIGN
Start
CPU is on? No
Yes
Reset
state0
state1
Halt
state3
simulates an AND gate. The signal clk simulates the clock signal of
the CPU; if the switch is off, the clock signal to the CPU is inactive, and
accordingly, the CPU is inactive. The statement
z(0) <= ACL(6) xor ACL (5) xor ACL (4)xor
ACL (3)xor ACL (2)xor ACL (1)xor ACL (0);
description, rather than the behavioral of this parity generator circuit. The
statements
ARI := TO_INTEGER(AR);
DR := Memory (ARI);
package Comp_Pkg is
constant N: integer := 15;
--N+1 is the number of elements in the array.
constant M : integer := 7;
--M+1 is the number of bits of each element
--of the array.
end Comp_Pkg;
MIXED-TYPE DESCRIPTION • 375
entity computer_basic is
end computer_basic;
begin
begin
case pres_st is
when state0 =>
next_st := state1;
--This is fetch cycle
AR := PC;
case IR is
when «111» =>
--The op code is CLA
ACL <= «00000000»;
next_st := state0;
next_st := state0;
begin
if (Reset == 1’b1)
begin
pres_st = state0;
Reset = 1’b0;
PC = 4’d0;
Memory [0] = 8’hE0; Memory [1] = 8’h29;
Memory [2] = 8’h8A; Memory [3] = 8’h4B;
Memory [4] = 8’h6C; Memory [5] = 8’h8D;
Memory [6] = 8’hCE; Memory [7] = 8’hA0;
Memory [8] = 8’h00; Memory [9] = 8’h0C;
Memory [10] = 8’h05; Memory [11] = 8’h04;
Memory [12] = 8’h09; Memory [13] = 8’h03;
Memory [14] = 8’h09;
Memory [15] = 8’h07;
end
case (pres_st)
state0 :
begin
next_st = state1;
AR = PC;
end
state1 :
//This is fetch cycle
begin
next_st = state2;
DR = Memory [AR];
end
state2 :
//This is fetch cycle
begin
next_st = state3;
PC = PC + 1;
IR = DR [7:5];
AR = DR [3:0];
end
state3 :
//This is execute cycle
380 • HDL WITH DIGITAL DESIGN
begin
case (IR)
3’d7 :
//The op code is CLA
begin
ACL = 8’d0;
next_st = state0;
end
3’d1 :
//The op code is ADD
begin
DR = Memory [AR];
ACL = ACL + DR;
next_st = state0;
end
3’d2 :
//The op code is MULT
begin
DR = Memory [AR];
PR = ACL DR;
ACL = PR [7:0];
ACH = PR [15:8];
next_st = state0;
end
3’d3 :
//The op code is DIVID
begin
DR = Memory [AR];
ACL = ACL / DR;
next_st = state0;
end
3’d4 :
//The op code is XOR
begin
DR = Memory [AR];
ACL = ACL ^ DR;
next_st = state0;
end
3’d6 :
//The op code is NAND
begin
MIXED-TYPE DESCRIPTION • 381
DR = Memory [AR];
ACL = ~(ACL & DR);
next_st = state0;
end
3’d5 :
//The op code is PRITY
begin
ACL[7] = z;
next_st = state0;
end
3’d0 :
//The op code is HALT
begin
next_st = state3;
end
default :
begin
end
endcase
end
default :
begin
end
endcase
pres_st = next_st;
end
endmodule
ACL
(In decimal) 0 12 9 36 4
ACH 0
(In decimal)
FIGURE 7.13 Simulation output of the accumulator register.
382 • HDL WITH DIGITAL DESIGN
7.5 Summary
This chapter covered mixed-type descriptions (HDL code that includes
more than one style of description in the same module). An example of
mixed description is when we write a module using behavioral and data-
flow statements. In some systems, one part can be best described by be-
havioral statements, and other parts of the system can be best described
by data-flow description. Instead of writing a module with only behavioral
or only data flow, we write the module using both behavioral and data-flow
descriptions; that is what is defined as mixed-type description.
An example to illustrate the mixed-type description is the ALU of a
computer. Some operations of the ALU, such as division, are usually de-
scribed by behavioral statements because it is not easy to find the Boolean
function or the hardware logic for division. Other operations, such as addi-
tion, may be described by data-flow or structural description because it is
usually easy to find the logic diagram of adders. In addition to mixed-type
descriptions, packages and single/multidimensional arrays were covered.
Packages are an essential construct in VHDL code. User-defined types,
components, functions, and procedures can be written in a package and
made visible to a VHDL module by attaching (including) the package with
the module.
7.6 Exercises
1. Write the HDL code to find the value and the order of the smallest ele-
ment in an array. The elements are four-bit signed numbers. Simulate
and verify your code.
2. Given an array of N elements, write the HDL code to organize the ele-
ments of the array in ascending order. All elements are integers.
3. Consider the code shown in Listing 7.11.
LISTING 7.11 Exercise 7.3
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package arrypack is
MIXED-TYPE DESCRIPTION • 383
constant N : integer := 2;
constant M : integer := 1;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.arrypack.all;
entity exercise is
Port(N, M, P : integer; z : out integer);
end exercise;
begin
com : process (N, M, P)
variable t : integer;
constant y : arry3 := (((5, 4, 3), (8, 9, 10), (32, 33, 34)),
((42, 43, 44), (52, 53, 54), (-10, -7, -5)));
begin
t := y (N)(M)(P);
z <= t;
end process com;
end exercise;
a) What is the value of the following elements of y?
y (0,0,0), y (0,0,1), y (0,0,2), y (0,1,2), y (1,1,2), y (1,2,2)
b) If we change all (N downto 0) and (M downto 0) in package ar-
rypack to (0 to N) and (0 to M), what will be the values of the
elements in part a?
384 • HDL WITH DIGITAL DESIGN
4. Repeat Listing 7.8 but for a memory of 128×16. Store the following data
in the corresponding memory locations:
Memory Location in Decimal Contents in Decimal
0 123
127 1025
55 35
105 801
99 0
Verify your storage by reading the data from the above locations.
5. For the state diagram shown in Figure 7.14, write a behavioral HDL
program to simulate the state machine. Verify your answer by simula-
tion.
0/1
state0
1/0
1/1
1/0
1/1
state2
7. For Case Study 7.1, increase the memory size to 32×16. Also, change all
instructions so the result of each instruction is stored in a memory loca-
tion rather than the accumulator. The address of this memory location
is the same as the address provided in the instruction. For example, the
instruction ADD 9 would mean the addition of the contents of AC to
the contents of memory location 9 with storage of the result in memory
location 9. Keep the size of all registers at eight bits. Rewrite the VHDL
code shown in Listing 7.10 and verify by simulation.
CHAPTER
8
ADVANCED HDL DESCRIPTION
Chapter Objectives
O Explore several advanced topics in HDL Description, such as file
processing, character and string implementation, and the type re-
cord
O Understand VHDL Assert and Block statements
O Understand Verilog user-defined primitives
O Acquire a basic knowledge of cache memories
O Acquire a basic knowledge of artificial neural networks
The above statement declares a file with mode infile, and the subtype of
the file is text. The IEEE package textio should be attached (see exam-
ples in the following sections). VHDL has built-in procedures for file han-
dling. These procedures include file_open, readline, writeline, read,
write, and file_close. In the following sections, each of these procedures
is briefly discussed.
8.1.1.1 File_open
The file_open procedure opens the file; files cannot be accessed if not
opened. This procedure has the following declaration:
Procedure file_open (status : file_open_status, infile : file
type, external_name : in string,
open_kind : file_open_kind) is
The statement status enables the VHDL to keep track of the activities of
the file (e.g., open, close, read, etc.); infile is the type (mode) of the file.
The infile is used for input files (their contents will be read), and outfile is
used for output files (they will be written into). The external_name is the
name of the file to be opened; the name has to be in string form such as
“rprt.txt” or “testfile.txt.” The open_kind is the mode of opening the
read_mode or write_mode. An example of implementing file_open is:
file_open (fstatus, infile, “testfile.txt”, read_mode);
closes the open file infile. The name and path of infile are specified in
the procedure file_open. The following statement closes outfile:
file_close (outfile);
8.1.1.3 Readline
The predefined procedure readline reads a line from the file opened
in read mode. An example of implementing this procedure is:
readline (infile, temp);
The above statement reads a line from infile and stores the line in variable
temp. Variable temp has to be of predefined type line. The name and type
of infile should have been stated in the procedure file_open. Inside the file
specified by infile, a carriage return is the separator between the lines. If
readline is repeated before closing the file, another line is read. A carriage
return indicates a new line.
8.1.1.4 Writeline
The predefined procedure writeline writes a line into an outfile that
is open for write mode. An example of implementing this procedure is:
writeline (outfile, temp);
The above statement writes a line stored in the variable temp into the
file outfile. Variable temp has to be of type line. The name and path of
outfile should be specified in the procedure file_open. Only integers, real
values, or characters can be written into outfile. If writeline is repeated
before closing outfile, a new line is stored in outfile.
390 • HDL WITH DIGITAL DESIGN
8.1.1.5 Read
To read an integer, a character, or a real value from a line in an infile
that is open for read mode, the procedure read is used. For example, if
intg1 has been declared as of type integer, the statement
read (temp, intg1);
performs a single read of an integer from line temp of the open file (for read
mode) and stores the value of this integer in intg1. If a character or a real
value is to be read, the variable intg1 should be of type character or real,
respectively. If intg1 is a single value (not an array), each time the read op-
eration is executed, a single word of the line is read and stored in intg1. If
the read statement is repeated before closing the file, the next word in the
line is read and stored in intg1.
8.1.1.6 Write
The procedure write stores an integer, a character, or a real value from
a line to an outfile that is open for write_mode. For example, if intg1 has
been declared as type integer, the statement
write (temp, intg1);
stores the integer intg1 in the line temp of the open outfile, which is in
write mode. If a character or a real value is to be written, the variable intg1
should be of type character or real, respectively. Each time the write
operation is executed, a single word is stored in the line. If the write state-
ment is repeated before closing the file, a new value of intg1 is stored in
the line.
8.1.2.1 $fopen
The task $fopen is used to open files. It is the counterpart of the
VHDL procedure file_open. The format for opening a file is:
ADVANCED HDL DESCRIPTION • 391
8.1.2.2 $fclose
The task $fclose closes a file indicated by the channel number. For
example the task
$fclose (ch1);
closes the file testfile.txt.
8.1.2.3 $fdisplay
The task $fdisplay is the counterpart of write in VHDL. It can write
variables, signals, or quoted strings. The format of $fdisplay is as follows:
$fdisplay (channel, V1, V2, V3, ....);
where V1, V2, V3, and so on are variables, signals, or quoted strings. For
example, consider the following $fdisplay task:
$fdisplay (ch1, “item description quantity”);
The number of spaces displayed in the file between each string is the
same number of spaces inside the quotations.
8.1.2.4 $fmonitor
The task $fmonitor has the following format:
$fmonitor (channel, V1, V2, V3,…..)
The task monitors and records the values of V1, V2, V3, and so on. For
example, consider the following $fmonitor task:
$fmonitor (ch1, “ %b”, quantity);
The above task monitors the variable quantity and records its value in
binary in the file testfile.txt indicated by ch1, and %b indicates binary
392 • HDL WITH DIGITAL DESIGN
three, and the fourth by four. The products are stored in the integer vari-
ables z, z1, z2, and z3, respectively.
To calculate the products, open the file, read its contents, perform the
multiplication, and close the file. Referring to Listing 8.1, the statement
file_open (fstatus, infile, “file_int.txt”, read_mode);
reads a line from the file file_int.txt and stores this line in the vari-
able temp of type line. If the statement is repeated, temp acquires the
next line. The statement
read (temp, count);
reads a single integer from the line temp and stores the integer in the
variable count. If the statement is repeated, count will acquire the next
integer from the same line. The statement
file_close (infile);
LISTING 8.1 VHDL Code for Reading and Processing a Text File Containing
Integers
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity FREAD_INTG is
port (START : in std_logic;
z, z1, z2, z3 : out integer);
end FREAD_INTG;
process (START)
394 • HDL WITH DIGITAL DESIGN
begin
if (START = ‘1’) then
--open the file file_int.txt in read mode
file_open (fstatus, infile, “file_int.txt”, read_mode);
--Read the first line of the file and store the line in temp
readline (infile, temp);
-- temp now has the data: 12 -3 5
After the code in Listing 8.1 executes, z, z1, z2, and z3 take the fol-
lowing values:
z = 24, z1 = –15, z2 = 15, z3 = 80
LISTING 8.2 VHDL Code for Reading a Text File Containing Real Numbers
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
396 • HDL WITH DIGITAL DESIGN
entity FREAD_REAL is
port (START : in std_logic;
z, z1, z2, z3 : out real);
end FREAD_REAL;
process (START)
file infile : text;
variable fstatus : file_open_status;
variable count : real;
--Variable count has to be of type real
variable temp : line;
begin
if (START = ‘1’) then
--Open the file
file_open (fstatus, infile,
“file_real.txt”, read_mode);
-- Read a line
readline (infile, temp);
--multiply by 4
z3 <= 4.0 count;
file_close (infile);
end if;
end process;
end FILE_BEHAVIOR;
After executing Listing 8.2, z, z1, z2, and z3 take the following values:
z = –26.8, z1 = –28.27, z2 = 0.069, z3 = –221.28
entity FREAD_character is
port (START : in std_logic;
z, z1, z2, z3 : out character);
end FREAD_character;
398 • HDL WITH DIGITAL DESIGN
process (START)
file infile : text;
variable fstatus : file_open_status;
variable count : character;
-- Variable count has to be of type character
variable temp : line;
begin
After the code in Listing 8.3 executes, z, z1, z2, and z3 take the fol-
lowing values:
z = A, z1 = 5, z2 = B, z3 = M
Reading files has been covered in the previous examples. The follow-
ing examples cover writing into files. As mentioned, VHDL files can store
integers, real values, and characters.
ADVANCED HDL DESCRIPTION • 399
The above statement stores the integer z into the line temp. Quoted char-
acters can be stored in temp as follows:
write (temp, “This is an integer file”);
The above procedure, writeline, writes the line temp into the outfile,
Wfile_int.txt.
LISTING 8.4 VHDL Code for Writing Integers to a File
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
entity FWRITE_INT is
port (START : in std_logic);
end FWRITE_INT;
process (START)
file outfile : text;
variable fstatus : file_open_status;
--declare temp as of type line
variable temp : line;
variable z,z1,z2,z3 : integer := 6;
400 • HDL WITH DIGITAL DESIGN
begin
if(START = ‘1’ ) then
z := 12; z1 := 23; z2 := -56; z3 := -45;
file_open (fstatus, outfile,
“Wfile_int.txt”, write_mode);
--The generated file “Wfile_int.txt” is in
--the same directory as this VHDL module
--Insert the title of the file Wfile_int.txt.
--Your simulator should support formatted text;
--if not, remove all formatted statements “ “.
In the same way as was done in Listing 8.4, characters or real numbers
can be written into an outfile.
LISTING 8.5 VHDL Code for Writing a Package Containing a String of Five
Characters
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package array_pkg is
constant N : integer := 4;
--N+1 is the number of elements in the array.
subtype wordChr is character;
type string_chr is array (N downto 0) of wordChr;
end array_pkg;
LISTING 8.6 VHDL Code for Reading a String of Characters into an Array
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
402 • HDL WITH DIGITAL DESIGN
entity FILE_CHARCTR is
port (START : in std_logic; z : out string_chr);
end FILE_CHARCTR;
process (START)
file infile : text;
variable fstatus : file_open_status;
variable count : string_chr;
variable temp : line;
begin
file_open (fstatus, infile, “myfile1.txt”, read_mode);
readline (infile, temp);
file_close (infile);
end process;
end FILE_BEHAVIOR;
After the code in Listing 8.6 is executed, the signal z contains “S” “T”
“O” “R” “E.”
hexadecimal values for several characters. Notice that A has the lowest hex
value among the letters, while Z has the highest. In this example, we want
to find the word that has the lowest ASCII hex value.
TABLE 8.1 ASCII Character Hexadecimal Values
each word. If the value of the word is less than the value of smallest, then
smallest assumes the value of this word. Otherwise, smallest retains its
value. Continue this comparison until the last word in the file is encoun-
tered. The code tests each word to see if it is “END.” If it is, then the pro-
gram stops; if not, the program continues. The statement that checks for
the word “END” in Listing 8.7 is a while-loop:
while (count /= (‘E’, ‘N’, ‘D’, ‘ ‘, ‘ ‘)) loop
The operator /= is the logic NOT EQUAL. The variable count has to be
declared as type character. The above loop will continue running until the
variable count is equal to END. The statement
read (temp, count);
reads a character word from the line temp. Because count is declared as an
array of characters (string_chr), each time a word is read, the ASCII value
corresponding to the characters of the word (see Table 8.1) is computed
and stored in the variable count. This is how the VHDL determines that
“ADD” is less than “AND.”
Listing 8.7 VHDL Code for Finding the Smallest ASCII Value
--The following package needs to be attached
--to the main module.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package array_pkg is
constant N : integer := 4;
--N+1 is the number of elements in the array.
subtype wordChr is character;
type string_chr is array (N downto 0) of wordChr;
end array_pkg;
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use work.array_pkg.all;
end SMALLEST_CHRCTR;
begin
process (START)
file infile : text;
variable fstatus : file_open_status;
variable count, smallest :
string_chr := (‘z ‘, ‘z ‘, ‘z ‘, ‘z ‘, ‘z ‘);
begin
file_open (fstatus, infile,
“f_smallest.txt”, read_mode);
while (count /= (‘E’, ‘N’, ‘D’, ‘ ‘, ‘ ‘)) loop
readline (infile, temp);
read (temp, count);
if (count < smallest) then
smallest := count;
end if;
end loop;
z <= smallest;
file_close (infile);
end process;
end BEHAVIOR_SMALLEST;
LISTING 8.8 VHDL Code for Finding the Integer Code for a Mnemonic Code
--The following package needs to be
--attached to the main module
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package array_pkg is
constant N : integer := 4;
--N+1 is the number of elements in the array.
subtype wordChr is character;
type string_chr is array (N downto 0) of wordChr;
end array_pkg;
entity OPCODES is
port (assmbly_code : in string_chr; z : out string_chr;
z1 : out integer);
ADVANCED HDL DESCRIPTION • 407
end OPCODES;
begin
process (assmbly_code)
file infile : text;
begin
file_open (fstatus, infile, “cods.txt”, read_mode);
for i in 0 to 8 loop
-– while loop could have been used instead
-- of for loop. See Exercise 8.3.
file_close(infile);
end process;
end BEHAVIOR;
408 • HDL WITH DIGITAL DESIGN
Listing 8.9 shows the code for an assembler. The assembly program to
be translated is written in the file asm.txt (see Figure 8.8). Integer op-
codes are assigned to the mnemonic codes, as shown in Table 8.2. This as-
signment is arbitrary; the programmer can assign any pattern of code to the
mnemonic code as long as each code has a unique
ORG 200
CLA 0 integer value. In this example, the same code pat-
ADD 9 tern is followed as in Figure 8.6. The mnemonic
XOR 10 codes ORIG and END have no integer codes; they
MULT 11 are called pseudo codes. ORIG tells the assembler
DIVID 12
the starting memory location where the output of
XOR 13
NAND 14 the assembler is stored. END tells the assembler
PRITY 0 where the last line of the assembly program is.
HALT 0 Figure 8.9 shows the flowchart of our assembler.
HLT 5
END
FIGURE 8.8 File asm.txt.
ADVANCED HDL DESCRIPTION • 409
Start
Finish Yes
Is the code
END?
No
The assembler first reads a line from the assembly file asm.txt. In
Listing 8.9, the line is read by the read procedure readline:
readline (infile, regstr);
The infile is the file asm.txt. If the first line is read, the contents of reg-
str would be:
ORIG 200
The read procedure above stores one word (an array of five charac-
ters) in temp. If this is the first line of asm.txt, then temp = “ORIG.” As
shown in Figure 8.9, the assembler tests the code to see what type it is. In
the case of ORIG, the if statement is used as follows:
if (temp = (‘O’,’R’,’I’,’G ‘,’ ‘)) then
read (regstr, ctr);
If the code is “ORIG,” the same line is read again, which results in storing
the value 200 in ctr. If the code of the first line is not “ORIG,” an error
is reported. After the first line is finished (see Figure 8.9), the subsequent
lines are read, and the case statement is used to determine the codes and
the addresses. For example, the statements
when (‘M’,’U’,’L’,’T’,’ ‘) => code := 2;
write (regstw, code);
write (regstw, “ “);
write (regstw, addr);
writeline (outfile, regstw);
package array_pkg is
constant N : integer := 4;
--N+1 is the number of elements in the array.
end array_pkg;
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use work.array_pkg.all;
end ASSMBLR;
process (START)
file infile : text;
file outfile : text;
begin
file_open (fstatus, infile, “asm.txt”, read_mode);
412 • HDL WITH DIGITAL DESIGN
for i in 0 to 11 loop
--while-loop could have been used instead of for-loop.
else
read (regstr, addr);
write (regstw, ctr);
write (regstw, “ “);
ctr := ctr + 1;
case temp is
end if;
end loop;
file_close(infile);
file_close (outfile);
end process;
end BEHAVIOR_ASSM;
Figure 8.10 shows the outfile “outf.txt” after translating Figure 8.8.
Notice that in Figure 8.8, the code “HALT” was intentionally miswritten
as “HLT.” Listing 8.9 spotted this error and reported it in outf.txt (see
Figure 8.10).
Figure 8.11 shows the rewritten assembly program (Figure 8.8) and
intentionally omits “ORIG” from the first line of code. According to Listing
8.9, this is an error.
ADVANCED HDL DESCRIPTION • 415
CLA 0
ADD 9
XOR 10
MULT 11
DIVID 12
XOR 13
NAND 14
PRITY 0
HALT 0
HLT 5
END
FIGURE 8.11 Variation of the infile asm.txt. ORIG is omitted.
Figure 8.12 shows the contents of the outfile according to the infile
of Figure 8.11.
b = 2a (8.1)
It is desired to record the value of the outputs as the inputs from a file
named file4.txt change. This file is located in the same path as the Verilog
module that accesses it. Listing 8.10 shows the Verilog code. The file file4.
txt is opened using the task $fopen:
ch1 = $fopen(“file4.txt”);
where file4.txt is the name of the file, and ch1 is the indicator of the
416 • HDL WITH DIGITAL DESIGN
channel that keeps track of the opened file. To write headings to the file,
the task $fdisplay is used. For example, the following statement leaves
two spaces, one blank line, one tab(t), and writes the heading “This is
file4.txt,” and then leaves a blank line:
$fdisplay (ch1, “ \n\tThis is file4.txt\n”);
To monitor any signals, the task $fmonitor is used. This task monitors the
value of the signal and prints this value into the file. For example, the state-
ment:
$fmonitor (ch1,” %d\t\t%d%b\n”,a,b,
b);
monitors the value of signals a and b. These values are printed in file4.txt
as follows: leave two spaces, print a in decimal, insert two tabs, print the
value of b in decimal, leave thirty spaces, print the same value of b in binary.
initial
begin
ch1 = $fopen(“file4.txt”);
$fdisplay (ch1, “\n\t\t\t This is file4.txt \n”);
$fdisplay (ch1, “ Input a in Decimal\t
\t Output b in Decimal\t\t Output b in Binary\n “);
/The above statement when entered in the Verilog module
should be entered in one line without carriage return /
end
always @ (a)
begin
b = 2 a;
$fmonitor (ch1,”\t%d\t\t\t\t%d\t\t\t\t%b \n”, a,b, b);
end
endmodule
This is file4.txt
Input a in decimal Output b in decimal Output b in binary
0 0 000
1 2 010
2 4 100
3 6 110
FIGURE 8.13 File4.txt of Listing 8.10.
Type forecast is
Record
Tempr : integer range -100 to 100;
Day : weekdays;
Cond : weather;
end record;
begin
case Day_in is
418 • HDL WITH DIGITAL DESIGN
end record;
end package weather_fcst;
end WEATHER_FRCST;
begin
case Day_in is
else
report (“invalid units”);
end if;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package stack_pkg is
constant N : integer := 15;
ADVANCED HDL DESCRIPTION • 423
1111
Data_in
Data_in
Memory
Stack Full
Data_in
Data_in Stack_pointer
Stack
Data_in
Data_in
Data_in
0000 Stack Empty
FIGURE 8.15 A block diagram of memory and the memory stack.
constant M : integer := 3;
--N+1 is the number of elements in the array.
subtype Memoryword is std_logic_vector (M downto 0);
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use work.stack_pkg.all;
entity stck_asrt is
generic (N : integer := 15; M : integer := 3);
Port (action : in stack; Data_in : in std_logic_vector
(M downto 0); clk : in std_logic);
end stck_asrt;
begin
stk : process (action, data_in, clk)
variable stack_pointer : integer := 0;
variable Mem_comp : Memory;
begin
if (rising_edge (clk)) then
case action is
when push =>
Mem_comp (stack_pointer) := data_in;
stack_pointer := stack_pointer + 1;
--if the operation is push, the stack pointer is
-- incremented as shown above.
--
assert (stack_pointer < 5)
report “ stack is full-program halts”
severity Failure;
end if;
end process;
end Behavioral;
Figure 8.16 shows the simulation waveform for Listing 8.13. The figure
shows the operation push where the stack pointer is incremented every
time a data is pushed. In the figure, the data has a single value = 1011.
Action push
data_in 1011
clk
Simulator halts
FIGURE 8.16 Simulation waveform of the stack in Listing 8.13.
Listing 8.14 shows the VHDL code for describing a four-bit D latch. The
block is guarded by the condition E = 1 where E is the enable of the latch;
the four output signals Q are guarded by following the input signal D. Be sure
that your simulator can handle the block and the block-guarded statements.
426 • HDL WITH DIGITAL DESIGN
Listing 8.14 VHDL Code for a Four-Bit D-Latch Using Block Statement
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity BLCKstatement is
port(E: in std_logic; D: in std_logic_vector (3 downto 0);
Q: out std_logic_vector ( 3 downto 0));
end BLCKstatement;
The body of the primitive is entered after the end of the module; the
primitive is called from within the module. All entries in the table of the
primitive can have only a single bit. The primitive is allowed to have one
output only; primitive Sample has an output outp. The primitive Sample
has three inputs inp1, inp2, and inp3. The predefined word table allows
the user to enter a table that consists of values of the inputs and the out-
put. Value4 is the value of the output giving the input as value1, value2,
value3 corresponding to inp1, inp2, and inp3. Valu1, valu2, valu3, and
valu4 can include 0, 1, or x (don’t care). Two types of primitives are dis-
cussed here: combinational and sequential. In combinational, the output in
the table depends on the inputs only; the table resembles the truth table
of combinational circuits. In sequential, the output depends on the current
state and the input; the table resembles the transition table of sequential
circuits. The following examples will clarify the implementation of user-
defined primitives.
Input Output
SEL Gbar Y
X H L
L L A
H L B
428 • HDL WITH DIGITAL DESIGN
The Verilog code for the description of the muliplexer using UDP is
shown in Listing 8.15. Notice that the entered values can be 0, 1, x, or ?.
The operator x is the “don’t care;” the operator ? can assume the values 0,
1, or x.
LISTING 8.15 Verilog Code 2x1 Multiplexer with Active Low Enable Using
Combinational User-Defined Primitive
module Mux2x1Prmtv(A, B, SEL, Gbar,Y);
input A,B,SEL,Gbar;
output Y;
endmodule
primitive multiplexer (mux, enable, control, dataA, dataB) ;
output mux;
input enable, control, dataA, dataB;
table
// enable control dataA dataB mux
1 ? ? ? : 0;
0 0 1 ? : 1;
0 0 0 ? : 0;
0 1 ? 1 : 1;
0 1 ? 0 : 0;
0 x 0 0 : 0;
0 x 1 1 : 1;
endtable
endprimitive
LISTING 8.16 Verilog Code for a D-Latch with Active High Clear Using
Sequential User-Defined Primitive
module latchprimitive(E, clr,D, Q, Qbar);
input E, clr,D;
output Q,Qbar;
endmodule
Clr
D Don’t care
E Don’t care
Qbar
the data from the main memory to the cache takes a relatively long time
because the main memory is relatively slow compared to the cache. So, to
speed up the microcomputer, the requested data by the CPU should be
made available in the cache. If the requested data is found in the cache, it
is called a hit; otherwise, it is a miss. A parameter called the hit ratio calcu-
lates the ratio of the number of hits divided by the total number of requests
or references. Obviously, to improve the performance of the computer, the
hit ratio has to be as high as possible. For the CPU to identify the data in
the cache to determine whether a hit or a miss has occurred, a mapping
between the data in the main memory and the cache should be established.
This mapping is to assure that the data that have moved from the main
to the cache can be identified. Several mapping schemes such associative,
random, direct, and set-associative mapping are implemented in the cache
system. Direct mapping is also known as one-way set-associative mapping.
Here, direct and set-associative mapping are discussed; for more informa-
tion on the cache system, refer to Hayes, 1998 [1] and Patterson, 2011 [2].
To illustrate the mapping schemes, consider a main memory of 16x4 bits
and a four-word cache. The width of the cache will be determined accord-
ing to the mapping scheme. Let’s assume that the data in the main memory
are as shown in Table 8.5.
TABLE 8.5 Contents of Main Memory in Decimal
word, for example, this address is 00002. To move the data of this location
to the cache using direct mapping, the address is partitioned into two fields,
tag and cache address, which is called an index. Because the cache is four
words, the index is two bits. Because the index is two bits, the tag is what-
ever is left from the four-bit memory address, which will be two bits; the
memory address is divided into the index of two bits (the least significant
two bits) and the tag of two bits (the most significant two bits). For the first
memory word, the index is 00 and the tag is 00. For the memory address
0001, the index is 01 and the tag is 00. The data of value 3 will be stored in
the cache address of 00; for the same data word, the tag (00) is inserted at
the left of the data. In binary, the data is stored in location 00 of the cache,
000011, a total of six bits. The contents of the cache memory after filling
the cache with the first four main memory words are shown in Table 8.6.
The information in the index and the tag can retrace the data to its memory
location. For example, the index 11 (cache memory location 11) and the
corresponding tag 00 are pointing at main memory location (0011), and the
data in this location is 1010.
TABLE 8.6 Contents of Cache Memory in Binary
The array M consists of sixteen four-bit words (elements). The data in the
main memory are entered for each element of the array; for example, M[12]
= 4’d6 means that location 12d of the main memory is assigned the data 6.
The cache memory is represented by the array cache:
reg [N:0] cache [0:3];
The array cache consists of four words, and each word is four bits.
The CPU requests data from the cache by issuing a memory address
where the data is stored. The Listing allows the user to select a one-way
or two-way by entering 0 or 1, respectively, for the case-control expression
cachemapping. The statement
ADVANCED HDL DESCRIPTION • 433
cache[cpuaddress1 [1:0]] =
{cpuaddress1[3:2],M[cpuaddress1]};
concatenates ({) bits 2-3 of the issued CPU address with the main-memory
data in the address issued by the CPU. For example, if the CPU issues a
main-memory address of 0100 (4), then location 00 (index) of the cache will
have 01 (tag) concatenated with M (4), which is 7, so location 00 of the cache
will have 010111.
i
n
t d
a e bit0
g x data
0000 0011
0001 0100
0010 1001
bit3
1110 1100
1111 1011
t i data
a n
g d
e
x
00 000011 00
01 000100 01 bit0
bit0
10 001001 10 001001 111100 bit11
11 bit5 11
(a) (b)
FIGURE 8.18 Mapping schemes. a) One-way set-associative mapping. b) Two-way set-associative mapping.
LISTING 8.17 Verilog Code for One- and Two-Way Set-Associative Mapping
//single word mapping, one and two-way
module casheMem(start, cachemapping, cpuaddress1,
cpuaddress2 );
parameter N= 5;
parameter N1=11;
input start;
input cachemapping;
input [3:0] cpuaddress1, cpuaddress2;
case (cachemapping)
begin
cache2[cpuaddress1 [1:0]]
={cpuaddress1[3:2],M[cpuaddress1]};
cache2[cpuaddress2 [1:0]]
={cpuaddress2[3:2],M[cpuaddress2]};
end
end
endcase;
end
endmodule
checks to see if a hit or a miss has occurred for a given index. If the tag
cpuaddress[3:2] matches either one of the two tags stored in the cache
at the given index, a hit has occurred. The two tags are data [11:10] and
data [5:4].
always @(cpuaddress)
begin
/fill two-way the cache in order starting from
memory location 0; s0 locations 0000 and 0100
will occupy the first cache location/
end
endmodule
LISTING 8.19 Verilog Code for Two-Way Set-Associative Cache System with
Replacement
module FIFOreplace(cpuaddress, hitORmiss);
parameter N1=11;
input [3:0] cpuaddress;
output [48:1] hitORmiss ;
reg [48:1] hitORmiss;
reg [N1+1:0] cache [0:3];
reg [3:0] M [0:15];
reg [N1+2:0] data;
initial
begin
/fill the cache in two-way set associative mapping
in order starting from memory
location 0; so locations 0000 and 0100
will occupy the first cache word/
438 • HDL WITH DIGITAL DESIGN
always @(cpuaddress)
begin
hitORmiss = “miss”;
data = cache[cpuaddress[1:0]];
end
endmodule
O4
Theta4
Dendrites 4
(input)
W43
O3
Soma (body) W41 3 W42
and cell
nucleus
W31 W32
Theta3
O1 O2
1 2
Axons
(output) I1 I2
FIGURE 8.20 A biological neuron. FIGURE 8.21 A simple XOR artificial neural network.
node4. Wij represents the weight between node j and node i. Because the
network, shown in Figure 8.21, functions as a XOR gate, the inputs and the
output of the network should satisfy Table 8.7.
TABLE 8.7 Values of the Inputs and the Desired Outputs for an XOR Artificial Neural Network
f(wt) 1.0
0.5
–3 –2 –1 1 2 3
wt
FIGURE 8.22 The firing function.
In Step 5, select another input and repeat Steps 3–4. Average the four
4 errors and the four 3 obtained from the four input sets. You can take the
root mean square of the errors instead of the simple average.
In Step 6, use the following equations to update the weights with the
new errors calculated in Step 5:
Calculate
outputs State0
Equation 2
Calculate errors
State1
Equations 3-4
No
Record the
number of
iterations
State2
Update weights
Equations 5-7
Listing 8.20 shows the HDL code for the artificial neural network of
Figure 8.21. For simplicity, the network is trained only for input I1 = 0 and
I2 = 1. The desired output for this set of inputs, as shown in Table 8.7, is 1.
The training is done with the help of a finite-state machine. A flow chart
of this machine is shown in Figure 8.23. As shown, the machine has four
states: state0, state1, state2, and state3. State0 corresponds to Step 3, state1
corresponds to Step 4, state2 corresponds to Step 6, and state3 corresponds
to Step 7.
entity neural is
end neural;
begin
--The firing function here is a straight line with
--saturation levels at both the positive and negative ends
if (wt <= -2.2) then
wt_rl := 0.06;
elsif (wt > 2.5) then
wt_rl := 1.0;
else
wt_rl := 0.20 wt + 0.5;
end if;
return wt_rl;
end firing;
begin
ADVANCED HDL DESCRIPTION • 445
case pres_st is
when state0 =>
O4 := firing (wtsum);
pres_st := state1;
pres_st := state0;
when state3 =>
--Finish; report results
W41_O <= W41;
W42_O <= W42;
W43_O <= W43;
W32_O <= W32;
W31_O <= W31;
Theta3_O <= Theta3;
Theta4_O <= Theta4;
output4 <= O4;
end case;
end if;
end process train;
end Behavioral;
8.6 Summary
In this chapter, some advanced descriptions were covered. File pro-
cessing in both VHDL and Verilog were discussed. To access any file, the
file has to be opened before it is accessed. VHDL has several file-process-
ADVANCED HDL DESCRIPTION • 447
8.7 Exercises
1. Write the following data in the VHDL text file exercise_ch8. In the
file, keep the format and type of the data as it is shown below:
THIS IS THE FILE OF THE EXERCISE OF CHAPTER 8
Training data is 5 3.1 -1.5
Nodes A, B, C, D
Test data 23 12 -5
END
2. Write the VHDL code to store the following words in a file called
greatest.txt. The words in the file should appear as follows:
ADD
STORE
COMPARE
ZEROS
SUB
STOP
Write the code (in the same module or a new one) to find the word in the
above file that has the greatest ASCII value. Also, find its order (e.g., the
order of the word STORE is 1).
Notice that for the statement ADD Data1, Data1 is an address, and the
value of this address is 208. Your code should find this address; do not
manually substitute 208 for the address.
Label Code Address
ORG 200
CLA 0
ADD Data1
XOR Data2
MULT Data3
XOR Data2
NAND Data4
PRITY 0
HALT 0
Data1: 7
Data2: 5
Data3: 4
Data4: 2
END
5. Build a package with procedures to find the integer code given the mne-
monic code.
6. Use Verilog file processing to compute and display the values of Y when
X changes incrementally from 0 to 9. The relationship between X and Y
is:
Y = X2 – 2X + 1
begin
case Day_in is
using this additional bit or any other extra bits. Your replacement algo-
rithm should still be based on FIFO.
13. Simulate the code shown in Listing 8.20 using a threshold of 10–8. What
are the final values of the weights? How many cycles does it take the
program to reach these final values?
14. In Case Study 8.1, a network was trained for the inputs I1 = 0 and I2 =
1. Here, we want to train the network for all possible inputs. This can be
done in the following steps:
Step 1: Initialize the weights (as was done in the case study).
Step 2: Calculate the actual outputs for each input using the same set
of weights.
Step 3: Calculate the errors separately for each of the four actual out-
puts; each input set has its desired output. For example, the in-
put set I1 = 1, I2 = 1 has a desired output of 0.
Step 4: Take the average of the four errors and consider this average the
ERROR.
Step 5: Update the weights using the ERROR as was done in the case
study.
Step 6: Repeat Steps 2–5 until the ERROR is lower than the threshold.
8.8 References
Hayes, J. P., Computer Architecture and Organization, 3rd ed. McGraw Hill,
1998.
Patterson, A., and Hennessy, J. Computer Organization and Design, 4th ed.
Morgan Kaufmann, 2011
Haykin, S., Neural Networks, 2nd ed. Prentice Hall, 1999.
CHAPTER
9
MIXED-LANGUAGE DESCRIPTION
Chapter Objectives
O Understand the concept of mixed-language description
O Learn the advantages of mixing VHDL and Verilog modules
O Learn how to invoke a Verilog module from a VHDL module
O Learn how to invoke a VHDL module from a Verilog module
O Learn the current limitations of mixed-language description
Facts
Q To write HDL code in mixed language, the simulator used with the
HDL package should be able to handle a mixed-language environment.
452 • HDL WITH DIGITAL DESIGN
entity VHD_enty is
port (x, y : in std_logic; O1, O2 : out std_logic);
end VHD_enty;
end VHD_enty;
Consider the following statement in Listing 9.1:
VHD_enty V1 (a,b,c,d)
The simulator looks first in the Verilog module to see if there are any
Verilog modules by the name of VHD_enty. If it could not find one, the
simulator looks in the VHDL entities. When the simulator finds an entity
with the name VHD_enty, it binds this entity to the Verilog module. In List-
ing 9.1, input a is passed to input port x; input b is passed to input y. The
VHDL entity calculates the outputs O1 and O2; these two outputs are passed
to the Verilog outputs c and d, respectively. Invoking a VHDL module is
very similar to invoking a function or a task.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Ver_VHD is
port (a, b : in std_logic; c : out std_logic);
end Ver_VHD;
end component;
.......
end Ver_VHD;
//This is the Verilog module
module V_modl (x, y, z);
input x, y;
output z;
endmodule
declares a component by the name of V_modl with two input ports, x and
y, and an output port z. The Verilog module V_modl has the same name
(including the case) as the component and identical inputs and outputs. Ac-
cordingly, the Verilog module V_modl is bound to the VHDL component
V_modl. If the Verilog module describes, for example, a two-input XOR
gate, then in the VHDL module, component V_modl is a two-input XOR
gate. In the following sections, complete examples of mixed-language de-
scriptions are covered.
x
sum
y
cin Half adder
Half adder
carry
library IEEE;
use ieee.std_logic_1164.all;
entity HA is
--For correct binding between this VHDL code and the above
--Verilog code, the entity has to be named HA.
port (a, b : in std_logic; s, c : out std_logic);
end HA;
architecture HA_Dtflw of HA is
begin
s <= a xor b;
c <= a and b;
end HA_Dtflw;
The outputs of the entity s and c are passed to the outputs of the module
HA, s0 and c0.
MIXED-LANGUAGE DESCRIPTION • 457
3 3 3 3 3 3
A3 A2 A1
Three-bit cr1 Three-bit cr0 Three-bit
c0
carrylook carrylook carrylook
ahead ahead ahead
3 3 3
output carry_out;
wire cr0, cr1;
endmodule
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- This is a VHDL data-flow code for a 3-bit
--carry-lookahead adder.
entity adders_RL 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 adders_RL;
A B
3 3
Three one-bit
Carry_out full adders cin
see Figure 9-4
3
Z_flag 3
Sum_3
FIGURE 9.3 Block diagram of a three-bit adder with a zero flag.
460 • HDL WITH DIGITAL DESIGN
sum
X
cin
cout
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity full_add is
Port (X, Y, cin : in std_logic;
sum, cout : out std_logic);
--This is a 1-bit full adder component built from
--AND-OR-NOT gates; see Figure 9.4.
end full_add;
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;
end inv_0;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity bind2 is
port (I1, I2 : in std_logic; O1 : out std_logic);
end bind2;
architecture and2_0 of bind2 is
MIXED-LANGUAGE DESCRIPTION • 463
begin
O1 <= I1 and I2;
end and2_0;
architecture or2_0 of bind2 is
begin
O1 <= I1 or I2;
end or2_0;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity bind3 is
port (I1, I2, I3 : in std_logic; O1 : out std_logic);
end bind3;
entity bind4 is
Port (I1, I2, I3, I4 : in std_logic;
O1 : out std_logic);
end bind4;
architecture or4_0 of bind4 is
begin
O1 <= I1 or I2 or I3 or I4;
end or4_0;
Q0
D_in d Q d Q Q_out
D-Latch D-Latch
C Qb C Qb Qb_out
clk2
clkb
clk
FIGURE 9.5 Logic diagram of a master-slave D flip-flop.
endmodule
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity D_Latch is
--The entity has the same name as
--the calling Verilog module
end D_Latch;
begin
D_in
D_out
Db_out
9 ns 1 ns
FIGURE 9.6 Simulation waveform of a master-slave D flip-flop.
genvar i;
for (i = 0; i <= N; i = i + 1)
begin : u
466 • HDL WITH DIGITAL DESIGN
genvar i;
for (i = 0; i <= N; i = i + 1)
begin : u
and (eq[i+1], sum[i], eq[i]);
end
endgenerate
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity FULL_ADDER is
Port (A, B, cin : in std_logic;
sum_1, cout : out std_logic);
end FULL_ADDER;
begin
case y is
when “000” => sum_1 <= ‘0’; cout <= ‘0’;
when “110” => sum_1 <= ‘0’; cout <= ‘1’;
when “101” => sum_1 <= ‘0’; cout <= ‘1’;
when “011” => sum_1 <= ‘0’; cout <= ‘1’;
when “111” => sum_1 <= ‘1’; cout <= ‘1’;
when others => sum_1 <= ‘1’; cout <= ‘0’;
--Others here refer to 100, 001, 010
468 • HDL WITH DIGITAL DESIGN
end case;
end process;
end beh_vhdl;
declare a component by the name of and2. The component has two input
ports, x and y, and one output port, z. To link this component to a Verilog
module, the module has to have the same name and ports as the compo-
nent. The Verilog module is written as:
module and2 (x, y, z);
It has the same name and the same ports, so all Verilog statements pertain-
ing to x, y, and z are visible to the VHDL module. In the Verilog module,
write:
and(z,x,y);
entity andgate is
port (a, b : in std_logic; c : out std_logic);
end andgate;
end component;
begin
g1 : and2 port map (a, b, c);
end andgate;
//This is the Verilog module
module and2 (x, y, z);
input x, y;
output z;
and( z, x , y);
endmodule
The above module has the same name and ports as the VHDL component
jk_verilog. Accordingly, the relationship between the input and output
ports described in the Verilog module is visible to the VHDL component.
The Verilog module describes, in behavioral style, a JK flip-flop with an
active high clear. Hence, the VHDL component jk_verilog is also a JK
flip-flop with an active high clear.
entity JK_FF is
Port (Jx, Kx, clk, clx : in std_logic;
Qx, Qxbar : out std_logic);
end JK_FF;
MIXED-LANGUAGE DESCRIPTION • 471
jk1 : jk_verilog port map (Jx, Kx, clk, clx, Qx, Qxbar);
end JK_FF;
module jk_verilog (j, k, ck, clear, q, qb);
// The module name jk_verilog matches
// the name of the VHDL components
reg q, qb;
reg [1:0] JK;
always @ (posedge ck, clear)
begin
if (clear == 1)
begin
q = 1’b0;
qb = 1’b1;
end
else
begin
JK = {j, k};
case (JK)
2’d0 : q = q;
2’d1 : q = 0;
2’d2 : q = 1;
2’d3 : q = ~q;
endcase
qb = ~q;
end
end
endmodule
472 • HDL WITH DIGITAL DESIGN
clk
clx
Jx
Kx
Qx
Qxbar
clr
Q J Q J Q J clrbar
clrbl
JK2 JK1 JK0
Q K Q K Q K 1
The Verilog module can accept a signal, variable, or constant, but it may not
accept the value 1. Therefore, we declare a signal named high and assign it
a value of 1 as follows:
high <= ‘1’;
FF0 : JK_FF port map (clrb1, High, clk, q(0), qb(0));
LISTING 9.10 Mixed-Language Description of Three-Bit Counter with Clear
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity countr_3 is
port (clk, clrbar : in std_logic;
q, qb : inout std_logic_vector (2 downto 0));
end countr_3;
component JK_FF
port (I1, I2, I3 : in std_logic;
O1, O2 : inout std_logic);
end component;
component inv
474 • HDL WITH DIGITAL DESIGN
component and2
port (I1, I2 : in std_logic; O1 : out std_logic);
end component;
component or2
port (I1, I2 : in std_logic; O1 : out std_logic);
end component;
signal J1, K1, J2, K2, clr, clrb1, s1, high : std_logic;
begin
input I1;
output O1;
MIXED-LANGUAGE DESCRIPTION • 475
assign O1 = ~I1;
endmodule
nous counters were discussed and described using the generate statement.
Here, we use mixed-language description to invoke a Verilog module from
a VHDL module. Listing 9.11 shows the mixed-language description of the
counter.
rc0
Q(n-1) Q1 Q0
Q J Q J Q J
1 1 1
Q K Q K Q K
clk
FIGURE 9.10 Logic diagram of an n-bit synchronous counter with ripple carry-out.
entity asynch_ctrMx is
Generic (N : integer := 3);
end asynch_ctrMx;
component jkff is
--This is a JK flip-flop with a clear bound to Verilog
MIXED-LANGUAGE DESCRIPTION • 477
-- module jkff
signal h, l : std_logic;
signal s : std_logic_vector (N downto 0);
signal s1 : std_logic_vector (N downto 0);
signal C_tem : std_logic_vector (N-1 downto 0);
begin
h <= ‘1’;
l <= ‘0’;
s <= (C_tem & clk);
clk
clear
C 0 7 6 5 4 3 2
Cbar 7 0 1 2 3 4 5
FIGURE 9.11 Simulation waveform for an n-bit asynchronous counter. The simulation pattern might be
different than shown due to the presence of transient states (hazards).
MIXED-LANGUAGE DESCRIPTION • 479
component nmos_verlg
--This component, after linking to a
--Verilog module, behaves as an nmos switch
port (O1 : out std_logic; I1, I2 : in std_logic);
end component;
component pmos_verlg
--This component, after linking to a Verilog module,
-- behaves as a pmos switch.
port (O1 : out std_logic; I1, I2 : in std_logic);
480 • HDL WITH DIGITAL DESIGN
end component;
--constant vdd : std_logic := ‘1’;
--constant gnd : std_logic := ‘0’;
end mux2x1switch;
output O1;
pmos (O1, I1, I2);
endmodule
All xs are ignored; for example, b = 1 if and only if the least significant
bit of a is 1, regardless of the value of the high-order bits of a. Another
Verilog variation of case is the casez (see Chapter 3), where z is the high
impedance. VHDL does not have an exact replica of casex or casez. With
mixed-language description, we can instantiate a command similar to casex
and casez in the VHDL module. Listing 9.13 shows a mixed-language de-
scription that instantiates a command by the name of cas_x in the VHDL
module; this command performs the same function as the Verilog casex.
Listing 9.13 represents a four-bit priority encoder. This encoder was dis-
cussed in Chapter 3. The truth table of the encoder is shown in Table 9.2.
TABLE 9.2 Truth Table for a Four-Bit Encoder
Input Output
a b
xxx1 1
xx10 2
x100 4
1000 8
Others 0
entity P_encodr is
482 • HDL WITH DIGITAL DESIGN
component cas_x
--The name of the component is identical to the name of the
--Verilog module
end component;
begin
end P_encodr;
endcase
end
endmodule
pass, and band pass. Low-pass filters allow frequencies below a certain
threshold (called the cutoff frequency) to pass with or without minimal
attenuation. All frequencies above the threshold are attenuated; frequen-
cies close to the cutoff are less attenuated than those frequencies far from
the cutoff. High-pass filters pass frequencies higher than the cutoff with
or without minimal attenuation. Frequencies lower than the cutoff are at-
tenuated, and frequencies close to the cutoff are less attenuated than those
signals far from the cutoff.
Figure 9.12 shows a low-pass filter consisting of a resistance (R) con-
nected in serial with a capacitance (C). The impedance of the capacitance
is (1/jwC) where w = 2f, f is the frequency, and j = 1 . The ratio of the
output signal (Vo) to the input signal (Vi) is:
Vo 1/jwC 1 (9.1)
Vi R 1/jwC jwCR 1
(Vo/Vi) is called the transfer function of the filter (H(w)). The square of the
amplitude of the transfer function can be written as:
[H(w)]2 = 1 (9.2)
2
w CR 1
The cutoff frequency wc = (1/RC) (9.3)
Substitute Equation 9.3 into Equation 9.2 to get:
1
[H(w)]2 = (w/w )2 1 (9.4)
c
Vi C Vo
As shown in the entity Filter_draw, the inputs and outputs are se-
lected to be of type std_logic_vector. The output [H(w)]2 in Equation
9.4 is represented by the signal Hw_vhd. The inputs w and wc in Equation
9.4 are represented by w and w_ctoff. To simplify the description, all inputs
and outputs are assumed to be integers. We could have selected the type of
inputs and outputs in the entity to be integer, but here we want to practice
converting from one type to another. Also, we want an easy link between
the VHDL and Verilog ports because integer ports are not allowed to be
mapped from Verilog to VHDL. If the output Hw_vhd is calculated as in
Equation 9.4, using integer division, the output would be zero for all values
of w because the numerator is always less than the denominator. Instead,
we calculate Equation 9.4 as real division and then scale it up by multiply-
ing it by 100. For example, if w = 3 units, and the cutoff = 4 units, then from
Equation 9.4:
1
Real (Hw_vhd) = = 0.64
(3/ 4) 2 1
After scaling up by 100, then Hw_vhd = 64
Because VHDL files accept only integers, real values, and characters, we
write a VHDL function to convert from std_logic_vector to integer. In
Listing 9.14, the user-defined function TO_Intgr converts std_logic_vec-
tor to integer. To invoke the Verilog module from the VHDL module, we
write a component declaration in the VHDL module:
component flter_RC
port (I1, I2 : in std_logic_vector (3 downto 0);
O1 : out std_logic_vector (7 downto 0));
end component;
MIXED-LANGUAGE DESCRIPTION • 485
The name of the component is flter_RC; it has two input ports, I1 and I2 of
type std_logic_vector, and one output port, O1 of type std_logic_vec-
tor. To invoke the Verilog module, we declare the module as follows:
module flter_RC (I1, I2, O1);
input [3:0] I1, I2;
output [7:0] O1;
The above Verilog module has the same name and ports as the VHDL
component; thus, the module is visible to the VHDL module. In the Ver-
ilog module, we perform the real division O1 = 1/[(I1/I2)2 + 1]. Because I1
and I2 are not declared as real, the division will be performed as integer,
and O1 will be zero for all values of I1 and I2. To avoid this, we multiply
I1 and I2 by 1.0:
s1 = ((1.0 I1) / (1.0 I2)) 2;
S = 1.0 / (1.0 + s1);
S and s1 are declared as real; the value of S is the real value of the divi-
sion 1/[(I1/I2)2 + 1]. The output of the Verilog module, O1, is calculated by
multiplying S by 100. This output is passed to the VHDL module. As can
be seen, Verilog, in contrast to VHDL, is flexible in handling different data
types. We would not have been able to easily perform the real division in
VHDL. After calculating the output, it is entered into a text file. All of the
data in std_logic_vector to be entered into the file must be converted to
integers because files cannot take the type std_logic_vector.
entity Filter_draw is
Port (w, w_ctoff : in std_logic_vector (3 downto 0);
Hw_vhd : out std_logic_vector (7 downto 0));
end Filter_draw;
begin
result := 0;
lop1 : for i in a’ range loop
if a(i) = ‘1’ then
result := result + 2i;
end if;
end loop;
return result;
end TO_Intgr;
component flter_RC
--The name of the component “flter_RC” is the same name as
-- the Verilog module.
port (I1, I2 : in std_logic_vector (3 downto 0);
O1 : out std_logic_vector (7 downto 0));
end component;
signal Hw_tmp : std_logic_vector (7 downto 0);
begin
dw : flter_RC port map (w, w_ctoff, Hw_tmp);
begin
--Files can take integer, real, or character;
--they cannot take std-logic-vector; so convert to integer.
file_close (outfile);
Hw_vhd <= Hw_tmp;
end process fl;
end Filter_draw;
real S, s1;
always @ (I1, I2)
begin
s1 = ((1.0I1)/(1.0 I2))2 ;
/we multiply by 1.0 so the division is done in real
format./
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity muxVHDL is
port(G1,SL1,A1,B1: in std_logic; Y1: out std_logic);
end muxVHDL;
begin
pl1: Mux2x1Prmtvvlog port map(G1,SL1,A1,B1,Y1);
end Behavioral;
1 ? ? ? : 0;
0 0 1 ? : 1;
0 0 0 ? : 0;
0 1 ? 1 : 1;
0 1 ? 0 : 0;
490 • HDL WITH DIGITAL DESIGN
0 x 0 0 : 0;
0 x 1 1 : 1;
endtable
endprimitive
9.5 Summary
This chapter discussed mixed-language descriptions: HDL code that
includes constructs from both VHDL and Verilog. To be able to write in
mixed-language style, the simulator should be able to handle mixed-lan-
guage description. Presently, mixed-language description has some limita-
tions. The main limitation is that in the VHDL module, only the entire
Verilog module can be invoked; conversely, in the Verilog module, only the
entire VHDL entity can be invoked. We have seen how to invoke/instanti-
ate a VHDL entity from a Verilog module and how to invoke/instantiate a
Verilog module from a VHDL component. To invoke a VHDL entity from
a Verilog module, the module statement is written in Verilog. The name of
the module should be identical to the name of the entity, and the parameter
types of the module should match the types of the ports of the entity. For
example, the module statement:
HA H1 (y, cin, s0, c0);
written in a Verilog module invokes a VHDL entity named HA. In the Veril-
og module, no other module should have the name HA. On the other hand,
MIXED-LANGUAGE DESCRIPTION • 491
9.6 Exercises
Without using a computer, find any error(s) in Listing 9.16. Correct the
errors (if any), and write the values of c and d if a = 1 and b = 0. Verify
your answer by simulating the program.
2. In Listing 9.4, set the gate delay to 8 ns. Simulate the adder with the
new gate delay and measure the total delay. Analytically justify the delay
that you measured.
3. In Listing 9.7, we wrote the Verilog module as behavioral description.
Repeat Example 9.5, but use Verilog gate-level description instead of
behavioral description. Verify your description by simulation.
492 • HDL WITH DIGITAL DESIGN
4. In Listing 9.13, HDL code was written to instantiate the Verilog com-
mand casex in a VHDL module. Repeat the same steps to instantiate
casez in a VHDL module. The truth table for casez is as shown in
Table 9.3.
TABLE 9.3 Truth Table for casez
Input Output
a b
zzz1 1
zz10 2
z100 4
1000 8
Others 0
5. In Example 9.12, a low-pass RC filter was simulated. Repeat the same
steps for a high-pass RC filter.
6. Add another output Y1bar in the VHDL code in Example 9.13. Y1bar is
the invert of Y1. Write the mixed code and simulate.
9.7 Reference
Reed, M., and R. Rohrer, Applied Introductory Circuit Analysis for Electrical
and Computer Engineers, Prentice Hall, Upper Saddle River, New Jersey,
1999.
CHAPTER
10
SYNTHESIS BASICS
Chapter Objectives
O Understand the concept of synthesis
O Learn how to map behavioral statements into logical gates and
components
O Learn how to verify your synthesis
O Review and understand the fundamentals of digital-logic design for
digital systems, such as adders, multiplexers, decoders, compara-
tors, encoders, latches, flip-flops, counters, and memory cells
O Understand the concept of sequential finite-state machines
Facts
Q Synthesis maps the simulation (software) domain into the hardware
domain.
494 • HDL WITH DIGITAL DESIGN
Step 6: Use CAD tools to download the gates and components of Step 4
into the electronic chip, usually a FPGA chip.
Step 7: Test the chip by inputting signals to the input pins of the chip and
observe the output from the output pins. This step is similar to the
verification done in Step 5, except the test here is on real, physical
signals.
a s
y
s
t d
e
M
b 1
System2 also has two one-bit input signals and one one-bit output sig-
nal. However, because the type is std_logic, each signal can take 0 (low),
1 (high), or high impedance (open).
Consider the entity shown in Listing 10.3.
4
a s
y
s
8
t d
e
4 m
b 3
System4 has two four-bit signals and one eight-bit signal. The input
signals are binary; the output signal can be binary or high impedance.
Consider the entity shown in Listing 10.5.
System6 has two four-bit input signals and one five-bit output signal.
In the hardware domain, the integer is represented by binary, so five bits
is adequate for representing d. Figure 10.4 illustrates the information ex-
tracted from Listing 10.6.
a 4
s
y
s 5
t d
e
m
4 6
b
Because N = 4 and M = 3, system7 has two five-bit input signals and one
four-bit output signal. All signals are binary. N and M have no explicit hard-
ware mapping. Figure 10.5 illustrates the synthesis information extracted
from the code of Listing 10.7.
SYNTHESIS BASICS • 499
5
a s
y
s
4
t d
e
5
m
b 7
entity ALUS2 is
port (a, b : in std_logic_vector (3 downto 0);
cin : in std_logic; opc : in op;
z : out std_logic_vector (7 downto 0);
cout : out std_logic; err : out Boolean);
end ALUS2;
The package codes defines type op. Signal opc is of type op. In
our digital hardware domain, there are only zeros and ones. Packages and
libraries have no explicit mapping into the hardware domain; they are simu-
lation tools. To map the signal opc into the hardware domain, the signal is
decoded. Because the signal can take one of four values (add, mul, divide,
or none), it is decoded into two bits. A possible decoding is shown in Table
10.1. Better decoding could be used; choose the one that yields the mini-
mum number of components after minimization.
TABLE 10.1 Decoding of Signal opc
Figure 10.6 illustrates the information extracted from the Listing 10.8.
As shown, entity ALUS2 has two input signals, a and b, each of four bits, one
input signal cin of one bit, one input signal opc of two bits, one output sig-
nal z of eight bits, one output signal cout of one bit, and one output signal
err of one bit. The Boolean type is mapped to binary 0 or 1.
opc 2 err
4
a
A
L
8 z
U
S
2
4
b
cin cout
FIGURE 10.6 Synthesis information extracted from Listing 10.8.
Consider the entity and package shown in Listing 10.9.
entity array1 is
generic (N : integer := 4; M : integer := 3);
Port (a : in strng; z : out std_logic_vector (M downto 0));
end array1;
SYNTHESIS BASICS • 501
From the package, type strng is an array of five elements, and each ele-
ment is four bits wide, so entity array1 has five input signals, each of four
bits. The output of array1 is a four-bit signal. Figure 10.7 illustrates the
synthesis information extracted from the code of Listing 10.9.
4
a(0)
4
a(1) a
r
4 r 4
a(2) z
a
4 y
a(3) 1
4
a(4)
W
E 2
A out_cond
T
H
3
E 7
Day_in R out_temperature
|
F
R 3
C out_day
S
T
package state_machine is
Type machine is (state0, state1, state2, state3);
Type st_machine is
record
state : machine;
weight : natural range 3 to 16;
Measr : std_logic_vector (5 downto 0);
end record;
end package state_machine;
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
use work.state_machine.all ;
entity Procs_Mchn is
port (S : in machine; Y : in st_machine;
Z : out integer range -5 to 5);
end Procs_Mchn;
The entity Procs_Mchn has two inputs, S and Y, and one output, Z. Input
S is of type machine; this type has four elements, so input S is mapped to
two bits. Input Y is of type st_machine; this type is record (a collection of
different types). The record includes type state, which is mapped to a
two-bit signal, type weight, which is mapped to a five-bit signal, and type
Measr, which is mapped to a six-bit signal. So, signal Y is mapped to six
bits (the largest out of two, five, and six). Output Z is mapped to a four-bit
signal. Figure 10.9 shows the synthesis information extracted from the code
of Listing 10.11.
504 • HDL WITH DIGITAL DESIGN
2 P
S
r
o
c
s 4
Z
|
M
c
6 h
Y
h
From Listing 10.12, system1v has two input signals, a and b, each of one
bit, and one output signal d of one bit. All signals can take 0, 1, or high
impedance. Figure 10.10 shows the synthesis information extracted from
Listing 10.12.
a
s
y
s
t
d
e
m
1
b
v
Listing 10.13 describes system2v with two input signals, X and Y, each of
four bits, and one output signal, Z, of eight bits. The statement reg [7:0]
Z; does not convey any additional information to the hardware domain;
its use is solely for simulation. Figure 10.11 illustrates the information ex-
tracted from Listing 10.13.
4
X
s
y
s
t 7
Z
e
m
2
4 v
Y
Module system3v has two input signals, a and b, and one output signal
c. Input a is a five-bit signal, input b is one bit, and output c is a four-bit sig-
nal. Parameter has no explicit mapping in the hardware domain; it is just a
simulation tool to instantiate N and M. Figure 10.12 illustrates the synthesis
information extracted from Listing 10.14.
5
a
s
y
s
t 4
c
e
m
3
b v
FIGURE 10.12 Synthesis information extracted from Listing 10.14.
Consider the code shown in Listing 10.15.
Module array1v has one one-bit input signal (start) and one four-bit out-
put signal (grtst). The register a is an array of five elements, each of four
bits. This register is mapped to five signals, each of four bits. Figure 10.13
illustrates the synthesis information extracted from Listing 10.15.
SYNTHESIS BASICS • 507
a
r
r 4
start a grtst
4
y a[0]
1 4
a[1]
v 4
a[2]
4
a[3]
4
a[4]
FIGURE 10.13 Synthesis information extracted from Listing 10.15.
entity SIGNA_ASSN is
port (X : in bit; Y : out bit);
end SIGNA_ASSN;
Y <= X;
end process P1;
end BEHAVIOR;
508 • HDL WITH DIGITAL DESIGN
The code in Listing 10.16 describes a one-bit input signal X and a one-bit
output signal Y (see Figure 10.14a). In VHDL Listing 10.16a, the entity
is bound to architecture BEHAVIOR. The process has X as the sensitivity
list. The signal-assignment statement states that Y = X. In the hardware
domain, this statement is mapped to a buffer. Other statements such as
begin, end, and architecture have no hardware mapping. The same ap-
plies for Listing 10.16b; the hardware is a buffer. Figure 10.14b shows this
mapping: if X changes, Y is updated. This mimics the process activation in
Listing 10.16 when an event occurs on X.
S
I
G
N
A
X Y
|
A
S X Y
S
N
FIGURE 10.14 Gate-level synthesis of Listing 10.16. a) Logic symbol. b) Gate-level logic diagram.
Consider the entity (module) shown in Listing 10.17.
entity sign_assn2 is
port (X : in unsigned (1 downto 0);
Y : out unsigned (3 downto 0));
end ASSN2;
architecture BEHAVIOR of sign_assn2 is
begin
P1 : process (X)
begin
Y <= 2 X + 3;
end process P1;
end BEHAVIOR;
Input X Output Y
X1 X0 Y3 Y2 Y1 Y0
0 0 0 0 1 1
0 1 0 1 0 1
1 0 0 1 1 1
1 1 1 0 0 1
510 • HDL WITH DIGITAL DESIGN
Y(0) = 1
Y(1) = X (0)
S
I 1 Y(0)
G
N X(0) Y(1)
2
A 4
X | Y X(1)
Y(2)
A
S
S Y(3)
N
2
(a) (b)
FIGURE 10.15 Gate-level synthesis of Listing 10.17. a) Logic symbol. b) Gate-level logic diagram.
To verify the synthesis, write the structural code for the logic diagram
shown in Figure 10.15b and then simulate it. If the simulation waveform
is the same as the simulation waveform in Listing 10.17, then the synthesis
is correct. The simulation waveform for Listing 10.17 is shown in Figure
10.16. The Verilog structural code is shown in Listing 10.18.
LISTING 10.18 Structural Verilog Code for the Logic Diagram in Figure 10.15b.
module sign_struc(X, Y);
input [1:0] X;
output [3:0] Y;
reg [3:0] Y;
always @ (X)
begin
Y[0] = 1'b1;
Y[1] = ~ X[0];
Y[2] = X[0] ^ X[1];
SYNTHESIS BASICS • 511
X(0)
X(1)
Y(0)
Y(1)
Y(2)
Y(3)
FIGURE 10.16 Simulation waveform for Listing 10.17.
entity parity_even is
port (x : in std_logic_vector (3 downto 0);
C : out std_logic);
end parity_even;
P1 : process (x)
512 • HDL WITH DIGITAL DESIGN
variable c1 : std_logic;
begin
c1 := (x(0) xor x(1)) xor (x(2) xor x(3));
C <= c1;
end process P1;
end behav_prti;
Listing 10.19 shows an entity with one four-bit input and one one-bit out-
put (see Figure 10.17a). The architecture behav_prti is bound to the entity
and consists of one process (P1). The process contains one variable declara-
tion, variable c1 : std_logic; and two assignment statements. One of
the assignment statements is a signal, C <= c1;, and the other is a variable
assignment:
c1 := (x(0) xor x(1)) xor (x(2) xor x(3));
p
a
r X(0)
i
X(1)
4 t
X y c c
|
X(2)
e
v X(3)
e
n
(a) (b)
FIGURE 10.17 Gate-level synthesis of Listing 10.19. a) Logic symbol. b) Gate-level logic diagram.
entity decod_var is
port (a : in std_logic_vector (1 downto 0);
D : out std_logic_vector (3 downto 0));
end decod_var;
begin
dec : process (a)
variable a0bar, a1bar : std_logic;
begin
a0bar := not a(0);
a1bar := not a(1);
D(0) <= not (a0bar and a1bar);
D(1) <= not (a0bar and a(1));
D(2) <= not (a(0) and a1bar);
D(3) <= not (a(0) and a(1));
end process dec;
end Behavioral;
input [1:0] a;
output [3:0] D;
reg a0bar, a1bar;
reg [3:0] D;
always @ (a)
begin
a0bar = ~ a[0];
a1bar = ~ a[1];
D[0] = ~ (a0bar & a1bar);
D[1] = ~ (a0bar & a[1]);
D[2] = ~ (a[0] & a1bar);
D[3] = ~ (a[0] & a[1]);
end
endmodule
The statements
a0bar := not a(0); -- VHDL
a0bar = ~ a[0]; // Verilog
represent an inverter. The input to the inverter is the least significant bit of
the input a. The statements
D[3] = ~ (a[0] & a[1]); -- VHDL
D(3) <= not (a(0) and a(1)); // Verilog
represent a two-input NAND gate. The input is a, and the output is the
most significant bit of D.
Figure 10.18 shows the synthesis of the code in Listing 10.20.
a(0)
D(0)
d a(1)
e
c
2 o 4 D(1)
a d D
|
v
a D(2)
r
D(3)
(a) (b)
FIGURE 10.18 Gate-level synthesis of Listing 10.20. a) Logic symbol. b) Gate-level logic diagram.
SYNTHESIS BASICS • 515
X
Y
a
FIGURE 10.19 Gate-level synthesis of Listing 10.21.
Now, consider the IF statement shown in Listing 10.22.
else
Y <= X1;
end if;
end process;
a Y
X1
FIGURE 10.20 Gate-level synthesis of Listing 10.22.
Consider the IF statement shown in Listing 10.23.
entity IF_st is
port (a : in std_logic_vector (2 downto 0);
Y : out Boolean);
end IF_st;
Input a Output Y
a2 a1 a0 Y
0 0 0 1
0 0 1 1
0 1 0 1
0 1 1 1
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 0
518 • HDL WITH DIGITAL DESIGN
Figure 10.21 shows the K-map of Listing 10.23. From the figure, the Bool-
ean function of Y is:
Y = a(2) a(1) a(0)
a1a0 00 01 11 10
a2
0 1 1 1 1
1 1 0 0 0
Y
FIGURE 10.21 K-map for Listing 10.23.
From the Boolean function, draw the gate-level synthesis for Listing 10.22
as shown in Figure 10.22.
a(0)
a(1) Y
a(2)
FIGURE 10.22 Gate-level synthesis of Listing 10.23.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity elseif is
port (BP : in natural range 0 to 7;
ADH : out natural range 0 to 15);
end;
SYNTHESIS BASICS • 519
begin
ADHP : process(BP)
variable resADH : natural := 0;
begin
if BP <= 2 then resADH := 15;
elsif BP >= 5 then resADH := 0;
else
resADH := BP (-5) + 25;
end if;
BP ADH
bit210 bit3210
000 1111
001 1111
010 1111
011 1010
520 • HDL WITH DIGITAL DESIGN
BP ADH
bit210 bit3210
100 0101
101 0000
110 0000
111 0000
From Table 10.7, construct K-maps to find ADH (see Figure 10.23).
Bp1Bp0 Bp1Bp0
00 01 11 10 00 01 11 10
Bp2 Bp2
0 1 1 0 1 0 1 1 1 1
1 1 0 0 0 1 0 0 0 0
ADH(0) ADH(1)
FIGURE 10.23 K-maps of Table 10.7.
Bp(0)
ADH(0)
ADH(2)
Bp(1)
Bp(2)
ADH(1)
ADH(3)
entity If_store is
port (a, X : in std_logic; Y : out std_logic);
end If_store;
begin
process (a, X)
begin
if (a = ‘1’) then
Y <= X;
end if;
end process;
end If_store;
store signals in the hardware domain, latches or flip-flops are used. In List-
ing 10.25, signal a is implemented as a clock to a D-latch; the input to the
latch is the signal X. If a = 0, then the output of the latch stays the same. If
a = 1, then the output follows the input X. Figure 10.25 shows the mapping
of Listing 10.25 to the hardware domain.
X D Q Y
clk Q
a
FIGURE 10.25 Synthesis of Listing 10.25.
library ieee;
use ieee.std_logic_1164.all;
use work.weather_fcst.all;
entity weather is
port (a : in unit; tempr : in integer range 0 to 15;
z : out integer range 0 to 15);
end weather;
begin
T : process (a, tempr)
variable z_tem : integer range 0 to 15;
begin
if ((tempr <= 7) and (a = cent)) then
z_tem := tempr;
SYNTHESIS BASICS • 523
else
z_tem := 15;
end if;
z <= z_tem;
end process T;
end weather;
a tempr z
00 (cent) 0–7 z = tempr
01 (offset) 0–7 z = tempr + 4
10 (half) 0–7 z = tempr/2
11 xx z = 15
xx >7 z = 15
If we want to construct a truth table, it will be a (2 + 4 = 6) six-bit input
and four-bit output; this table will be huge and cannot be analyzed easily.
Accordingly, the code in Listing 10.26 is analyzed logically. Input a can be
the select lines of a multiplexer. The multiplexer has four inputs; each input
is a four-bit signal representing one of the four values tempr, tempr+4,
tempr/2, or the constant 15. Figure 10.26 shows this analysis using register
transfer level (RTL) logic.
524 • HDL WITH DIGITAL DESIGN
4
tempr 0
4
tempr Logic 1 tempr+4 1
Four
4
4x1 z
Logic 2
4 MUX
tempr/2 2
4
15 3
2
Select
FIGURE 10.26 RTL synthesis of Listing 10.26.
tempr tempr +4
bit3210 bit3210
0000 0100
0001 0101
0010 0110
0011 0111
0100 1000
0101 1001
0110 1010
0111 1011
1000–1111 dddd
Inspecting Table 10.8, tempr +4 can be written as:
tempr tempr/2
bit3210 bit3210
0000 0000
0001 0000
0010 0001
0011 0001
0100 0010
0101 0010
0110 0011
0111 0011
1000-1111 dddd
After inspecting Table 10.10:
tempr/2(0) = tempr (1)
tempr /2(1) = tempr (2)
tempr /2(2) = 0
tempr /2(3) = 0
For the select in Figure 10.26 to satisfy the condition temp 7, tempr (3)
must be equal to 0. Accommodating the values of a, construct a truth table
as shown in Table 10.11.
TABLE 10.11 Truth Table for Figure 10.26 Select
a(1)a(0) a(1)a(0)
00 01 11 10 00 01 11 10
tempr(3) tempr(3)
0 0 1 1 0 0 0 0 1 1
1 1 1 1 1 1 1 1 1 1
4
tempr 0
4 4
tempr Logic 1 tempr+4 1
Four
4
4x1 z
Logic 2
4 MUX
tempr/2 2
4
15 3
2
Select
tempr(0) tempr+4(0)
tempr(1) tempr+4(1)
Select (0)
tempr(2) tempr+4(2)
tempr(3)
tempr+4(3) a(0)
Select (1)
a(1)
tempr(1) tempr/2(0)
tempr(2) tempr/2(1)
0 tempr/2(2)
0 tempr/2(3)
FIGURE 10.28 Synthesis of Listing 10.26.
SYNTHESIS BASICS • 527
1’b1 : d = a - b;
endcase
end
endmodule
To synthesize the above code, construct a truth table. This table would
have (4 + 4 +1 = 9) nine bits input for a, b, and ct, and five bits for the
output d. This table would yield a minimum number of gates for the code
in Listing 10.27; however, the table would be very large and hard to ana-
lyze. Another approach is to logically analyze the code using RTL blocks.
Listing 10.27 includes two operations: four-bit addition and four-bit sub-
traction. The result is expressed in a five-bit output, d. Signal ct selects
whether to add or subtract. To add, use four one-bit ripple-carry adders.
To subtract, use four one-bit subtractors, but the number of components
can be reduced by noticing that the full adder can be used as a subtractor,
as shown below:
d = a – b = a + (–b) = a + b + 1
Figure 10.29 shows the RTL synthesis of Listing 10.27. The XOR gate is
implemented to generate the complement of signal b.
528 • HDL WITH DIGITAL DESIGN
ct a
b
4
4 4
Adder/subtractor
d
FIGURE 10.29 RTL synthesis of Listing 10.27.
endmodule
SYNTHESIS BASICS • 529
4 5 Q 5
a D d
Four-bit
adder
4
b
Five
D-Latches
E Q
ct
FIGURE 10.30 RTL synthesis of Listing 10.28.
Input Output
IR RA
xxx1 0001
xx10 0010
x100 0100
1000 1000
Others 0000
Notice the input IR has explicit value for all of its entries, so synthesis does
not need storage. By inspecting Table 10.12, the Boolean function of the
output can be written as:
RA(0) = IR(0)
RA(1) = IR(0) IR(1)
RA(2) = IR(0) IR(1) IR(2)
RA(3) = IR(0) IR(1) IR(2) IR(3)
Figure 10.31 shows the logic diagram of Listing 10.29.
IR(0) RA(0)
IR(0)
RA(1)
IR(1)
IR(0)
IR(1) RA(2)
IR(2)
IR(0)
IR(1) RA(3)
IR(3)
IR(2)
FIGURE 10.31 Logic diagram of Listing 10.29.
Now consider the code shown in Listing 10.30. This code is slightly differ-
ent from that of Listing 7.9 (see Chapter 7).
SYNTHESIS BASICS • 531
use IEEE.STD_LOGIC_1164.ALL;
use work.types.all;
entity state_machine is
port (A, clk : in std_logic; pres_st : buffer states;
Z : out std_logic);
end state_machine;
begin
Z <= '0';
end if;
In order to know to which state to go, we need to know the present state.
For example, if the present state is state0, then the next state can be
state1 or state0. The code implies that the current state must be remem-
bered, so, accordingly, storage elements are needed to synthesize the code.
The best approach here is to follow the same steps covered in Chapter 4 for
analyzing state machines. Write the excitation table of the machine and use
D flip-flops. Table 10.13 shows the excitation table for Listing 10.30.
TABLE 10.13 Excitation Table for Listing 10.30
Q1Q0 Q1Q0
00 01 11 10 00 01 11 10
A A
0 0 1 0 0 0 0 1 1 0
1 1 0 0 1 1 0 1 0 1
D0 D1
Q1Q0
00 01 11 10
A
0 1 0 1 1
1 0 0 1 1
Z
FIGURE 10.32 K-maps for Table 10.13.
534 • HDL WITH DIGITAL DESIGN
D0 Q0
Q0
clk
s1 s0
s5
A Z
D1 Q1
Q1
clk
s4 s3 s2 Clock
D0 = A Q1 Q0 + A Q0
D1 = Q0 Q1 + A Q0 + AQ1 Q0
Z = Q1 + A Q0
From the Boolean function, the logic diagram of the system is drawn. Fig-
ure 10.33 shows the logic diagram of Listing 10.30.
result := 0;
536 • HDL WITH DIGITAL DESIGN
The code in Listing 10.32 describes a system with one four-bit input a,
one integer input c, and a four-bit output b. In the hardware domain, there
are only bits, so the integer c (because its range is from 0 to 15), is repre-
sented by four bits. If you are using a vendor’s synthesizer, be sure to spec-
ify the integer range; otherwise, the synthesizer, because it does not know
the range, will allocate more than 32 bits for the integer. Figure 10.34
summarizes the information retrieved from the entity.
4 L
a
I
S
T
I 4
b
N
G
10
4 |
c
32
c 7 7 7 7 7 7
FIGURE 10.35 Simulation output of Listing 10.32.
The code in Listing 10.32 included a process labeled shfl. The process
has an IF statement and three For-Loops: lop1, lop2, and lop3. The
first For-Loop, lop1, converts the std_logic_vector a to an integer. This
conversion is ignored by the hardware domain; the main goal of this conver-
sion is to be able to compare a with the integer c. The hardware views the
variable result and a as the same signal. The IF statement that starts with
if result > c then
is complete; if result > c, then loop lop2 is executed. Otherwise, loop
lop3 is executed. Accordingly, latches are not needed to synthesize this IF
statement. For loop lop2, expand the loop as shown in Table 10.14.
TABLE 10.14 Expanding the Loop lop2
i j temp(j) = a(i)
0 2 temp(2) = a(0)
1 3 temp(3) = a(1)
2 0 temp(0) = a(2)
3 1 temp(1) = a(3)
Notice from Listing 10.32 that the variable temp is identical to signal b;
the hardware domain views b and temp as the same signal. For loop lop2,
expand the loop as shown in Table 10.15.
TABLE 10.15 Expanding Loop lop3
i j temp(j) = a(i)
0 1 temp(1) = a(0)
1 2 temp(2) = a(1)
2 3 temp(3) = a(2)
3 0 temp(0) = a(3)
538 • HDL WITH DIGITAL DESIGN
From Tables 10.14 and 10.15, the logic diagram of the system consists
of a four-bit magnitude comparator and four 2x1 multiplexers (see Fig-
ure 10.36). The four-bit comparator can be built from four-bit adders (see
Chapter 4).
C(0)
C(1)
C(2)
a<c
C(3)
4x4-bit a=c
Comparator
a(0)
a>c
a(1)
a(2)
a(3)
Select
a(3) 0
2X1 b(0)
a(2) 1 MUX
a(0) 0
2X1 b(1)
a(3) 1 MUX
a(1) 0
2X1 b(2)
a(0) 1 MUX
a(2) 0 2X1
b(3)
MUX
a(1) 1
in Listing 10.33.
task xor_synth;
output d;
input a, b;
begin
d = a ^ b;
end
endtask
endmodule
d1 = a1 Å b1
The synthesis of this module is shown in Figure 10.37.
a1
d1
b1
FIGURE 10.37 Synthesis of Listing 10.33.
Now consider the code shown in Listing 10.34.
entity Int_Bin is
generic (N : integer := 3);
port (X_bin : out std_logic_vector (N downto 0);
Y_int : in integer;
flag_even : out std_logic);
end Int_Bin;
begin
if (int MOD 2 = 0) then
flag <= ‘1’;
else
flag <= ‘0’;
end if;
for i in 0 to N loop
int := int / 2;
end loop;
end itb;
begin
process (Y_int)
variable tem : std_logic_vector (N downto 0);
variable tem_int : integer;
begin
tem_int := Y_int;
itb (tem, flag_even, N, tem_int);
X_bin <= tem;
end process;
end convert;
SYNTHESIS BASICS • 541
Let’s analyze the procedure itb. This procedure has two outputs (flag
and bin), one input (N) and one inout (int). In the hardware domain, there
is no distinction between variables and signals: all are signals. Also, type inte-
ger has to be converted to binary. The signal flag checks to see if signal int is
divisible by two (even) or not (odd). This is done by the statements:
if (int MOD 2 = 0) then
flag <= ‘1’;
else
flag <= ‘0’;
end if;
int := int / 2;
end loop;
The loop is converting type integer int to binary bin. This conversion
is not mapped to the hardware domain. As mentioned above, all signals in
the hardware domain are binary; we cannot have an integer signal in the
hardware domain. So, for our synthesis, the procedure is performing a test
to see whether the signal is even or odd.
Now let’s analyze the entity Int_Bin. The entity has two outputs: a
four-bit signal X_bin (because N = 3) and a one-bit signal flag_even. The
entity has one input of type integer, Y_int. The entity has one process:
process (Y_int)
variable tem : std_logic_vector (N downto 0);
variable tem_int : integer;
begin
tem_int := Y_int;
itb (tem, flag_even, N, tem_int);
X_bin <= tem;
end process;
542 • HDL WITH DIGITAL DESIGN
The process is calling the procedure itb, the integer Y_int is con-
verted to binary X_bin, and flag_even is assigned a value of 1 if Y_int is
even or 0 if it is odd. To find the hardware logic of flag_even, notice that if
a binary number is even, its least significant bit is 0. Otherwise, the num-
ber is odd. So, flag_even = X_bin(0) . That is all there is to the synthesis of
Listing 10.34. Figure 10.38 shows the synthesis of Listing 10.34; it is just a
single inverter.
X_bin(0) Flag_even
FIGURE 10.38 Synthesis of Listing 10.34.
function andopr;
input a, b;
begin
andopr = a ^ b;
end
endfunction
endmodule
is being called. For example, in Listing 10.35, the function andopr is per-
forming an AND logical operation on two operands. The result is a single
operand. In the module Func_synth, this function is called to perform an
AND operation on the two inputs of the module, a1 and b1; the result is
stored in the output of the module d1. Listing 10.35 is synthesized as shown
in Figure 10.39; it has an AND gate with two one-bit inputs, a1 and b1, and
a one-bit output, d1.
input [2:0] x;
output [3:0] y;
reg [3:0] y;
always @ (x)
begin
y = fn (x);
end
if (a <= 4)
fn = 2 a + 5;
end
endfunction
endmodule
The function in Listing 10.36 has one three-bit input a and one four-bit
output fn. If the value of the input is less than or equal to four, the output
is calculated as fn = 2 a + 5. If the input is greater than four, the func-
tion does not change the previous value of the output. Incorporating the
function into the module Function_Synth2, we summarize the module as
544 • HDL WITH DIGITAL DESIGN
representing a system with one three-bit input x and one four-bit output
y. If x is less than or equal to four, y = 2 a + 5. If x is greater than four,
y retains its previous value. This means that latches must be used to retain
the previous value.
Figure 10.40 shows the simulation output of the module Function_
Synth2. As is shown, if x is greater than four, y retains its previous value.
To synthesize this module, we use four high-level triggered D-latches be-
cause output y is four bits. If x is from zero to four, these latches should be
transparent; if x is from five to seven, these latches should be inactive. We
design a signal clk connected to the clock of the latches; if x is from zero to
four, the clk is high; otherwise, it is low. Table 10.16 shows the truth table
of signal clk.
1 D0 y(0)
D1 y(1)
X(0)
X(1)
X(2)
D2 y(2)
clk
D3 y(3)
LISTING 10.37 (same as Listing 8.15) Verilog Code 2x1 Multiplexer with
Active-Low Enable Using Combinational User-Defined Primitive
module Mux2x1Prmtv(A, B, SEL, Gbar,Y);
input A,B,SEL,Gbar;
output Y;
endmodule
primitive multiplexer (mux, enable, control, dataA, dataB) ;
output mux;
input enable, control, dataA, dataB;
table
// enable control dataA dataB mux
1 ? ? ? : 0;
0 0 1 ? : 1;
0 0 0 ? : 0;
0 1 ? 1 : 1;
0 1 ? 0 : 0;
0 x 0 0 : 0;
0 x 1 1 : 1;
endtable
endprimitive
“don’t care” operator x. Table 10.18 shows the truth table of representing
the module in the hardware domain.
TABLE 10.18 Truth Table for Listing 10.37
Gbar SEL A B Y
1 x x x 0
0 0 1 x 1
0 0 0 x 0
0 1 x 1 1
0 1 x 0 0
0 x 0 0 0
0 x 1 1 1
Table 10.18 is the same as Table 2.4, and the logic diagram of Listing 10.37
is the same as Figure 2.9.
10.4 Summary
This chapter covered the fundamentals of hardware synthesis. We
looked at synthesis as reverse engineering; HDL code was synthesized it
into gates and latches. The steps of synthesizing any system can be sum-
marized as follows:
such as IF, case, and For-Loop. Any signal that needs to retain a value must
be mapped using latches. Procedures, tasks, functions, and user-defined
primitives are simulation tools; they do not have explicit hardware map-
pings. The operations they perform should be incorporated in the entity or
in the module to be synthesized. Integers should be declared, if possible,
with a range. This reduces the number of bits the synthesizer allocates for
the integer. If the range is not specified, the synthesizer allocates at least 32
bits for integers.
10.5 Exercises
1. Synthesize the code in Listing 10.38, simulate it, write the structural
description, and verify it.
LISTING 10.38 Code for Exercise 10.1
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity IF_sgned is
port (a : in signed (3 downto 0); Y : out Boolean);
end IF_sgned;
begin
IfB : process (a)
variable tem : Boolean;
begin
if (a < “1100”) then
tem := true;
else
tem := false;
end if;
Y <= tem;
end process;
end IF_sgned;
2. Synthesize the code in Listing 10.39. Simulate it, write the structural
description, and verify it.
SYNTHESIS BASICS • 549
Synthesize the new code using multiplexers, gates, and flip-flops (if
needed).
5. Simulate the VHDL behavioral code of Listing 10.30. Write the VHDL
structural description of the logic diagram shown in Figure 10.33 and
simulate it. Verify that the two simulations are identical.
6. Synthesize the behavioral code shown in Listing 10.40 using RTL.
LISTING 10.40 Code for Exercise 10.6
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity exercise is
550 • HDL WITH DIGITAL DESIGN
result := 0;
lop1 : for i in 0 to 3 loop
if a(i) = ‘1’ then
result := result + 2i;
end if;
end loop;
if result > c then
lop2 : for i in 0 to 3 loop
j := (i + 3) mod 4;
temp (j) := a(i);
end loop;
end if;
b <= temp;
end process shfl;
end exercise;
7. For Figure 10.41, write the structural code for the logic shown in the fig-
ure, simulate it, and verify that the figure is the synthesis of Listing 10.36.
8. We want to realize Figure 10.41 on a programmable device such as a
FPGA. Use the synthesis tools (provided in most cases with the HDL
package) to synthesize the code of Listing 10.36. Compare the outcome
of the synthesizer with Figure 10.41 and report the differences. Now,
use the tools provided in your HDL package to download the design
into a FPGA or compatible chip. Use the same test signals to compare
the software’s and hardware’s simulation. Report the differences and
suggest how to minimize these differences.
9. In Listing 10.36, if the statement inside function fn is written as:
function [3:0] fn;
SYNTHESIS BASICS • 551
input [2:0] a;
begin
if (a <= 4)
fn = 2 a + 5;
end
endfunction
endmodule
then it is likely that the code is intended to say that if a is greater than four,
the value of fn is unimportant. If this is true, can you modify the function’s
code to avoid using the four latches? Redraw the synthesis of your code.
10. Synthesize the code in Listing 8.18. Hint: use RTL, use a register to
synthesize the cpu address, and use a memory or group of registers to
synthesize the cache. After synhesizing, write the Verilog code of the
synthesis and verify it.
APPENDIX
A
CREATING A VHDL OR VERILOG
PROJECT USING CAD SOFTWARE
PACKAGE
In this appendix, the necessary steps to create a new project using Xilinx
ISE 13.1 or 14.1 software are covered. The steps include the source code
and its test bench code. Although these steps are for ISE 13.1, the same
concepts can be applied to other versions or to other vendors’ products.
These steps are for beginners. To find out more about these CAD packages,
visit the homepage of the vendor.
Step 1: Double click on the Xilinx Project Navigator icon. From the tool-
bar, select File ® New Project. A dialog box will open (see Figure A.1).
Step 2: In the new-project dialog box, type the desired location in the
“Project Location” field or browse to the directory under which you want
to create your new project directory using the browse button next to the
“Project Location” field.
554 • HDL WITH DIGITAL DESIGN
Step 3: Enter the name of the project. In Figure A.1, the name entered is
“AppndxDemo.”
Step 4: Click “Next,” and Figure A.2 appears. Enter the appropriate in-
formation as shown in Figure A.2. The device is the chip where the HDL
program, if desired, is downloaded after synthesis. The device in Figure A.2
is selected to be from the Spartan3E chip family.
Step 5: Click “Next” until you see the screen depicted in Figure A.3. This
window summarizes the properties of the new project.
Step 6: Click “Finish” (see Figure A.4). The screen now shows the name
of the project and the device.
CREATING VHDL OR VERILOG PROJECT USING CAD SOFTWARE PACKAGE • 555
Step 7: Attach the HDL module to your project. Click “Project” and select
“New Source” (see Figure A.5).
Step 10: Enter the VHDL code for full adder. The VHDL module here
is the VHDL code for the full adder that was discussed in Chapter 2 (see
Figure 2.5). The copy, cut, and paste tools can be accessed via the “Edit”
menu on the toolbar. After finishing writing the module, click “Save.” The
screen will display the code along with tools for testing and simulating the
code (see Figure A.7).
Step 11: Check the syntax of the VHDL program. This checking can be
done using various tools; one of these tools is the behavioral check syntax,
which appeared on the screen entitled “Processes,” as shown in Figure A.7.
To check the syntax, select the file “Demofulladder” and click on “Behav-
ioral Check Syntax.” The results of syntax checking, with detected errors (if
any), appear on the screen entitled “Console” at the bottom of Figure A.7.
If there are no errors, the VHDL code has been compiled successfully.
Step 12: After compiling the code, we need to simulate and test it. There
are several ways to simulate and test. Here, we use a test bench to simulate
and test the code. A test bench is a user-written code that assigns values
or wave forms to the input signals of the code being tested. To build a test
bench (see Figure A.8), select the file “Demofulladder” and click “Project-
CREATING VHDL OR VERILOG PROJECT USING CAD SOFTWARE PACKAGE • 557
New Source-VHDL Test Bench” and enter a name of the test bench. Here,
we assign the name “fulladTstBnch” as the name of our test bench.
Keep clicking “Next” and then “Finish.” Figure A.9 shows the partial screen
after clicking “Finish.” Start cleaning up the template by deleting the com-
ments if wanted.
describe a process that generates a clock with a period of 20 ns. The state-
ment a <= not a; inverts signal a continuously; if a is 0, it will be inverted
to 1 and vice versa. The statement wait for period; will delay the inver-
sion of signal a for 10 ns because the period was declared to be 10 ns. This
delay and the inversion generate a clock with a period of 20 ns.
FIGURE A.10 The test-bench code.
Step 13: After checking that the test-bench code has no errors, select the
test-bench module and click on “Simulate Behavioral Model.” On the simu-
lation screen, adjust the scale to 10ns/division and click on “Run the Simu-
lation.” Figure A.11, which is a copy of Figure 2.7, shows the waveform that
should appear on the screen.
a
b
Sum
Carryout
FIGURE A.11 Waveform output for full adder.