0% found this document useful (0 votes)
2 views100 pages

Verilog Module

The document introduces Verilog, a hardware description language used for designing and simulating digital systems, highlighting its evolution from early integration technologies to modern VLSI and ULSI. It discusses the significance of computer-aided design (CAD) tools and the design flow process, which includes problem formulation, design entry, simulation, and synthesis. Additionally, it compares Verilog with VHDL and outlines the learning process for mastering Verilog, emphasizing its syntactic similarities to C.

Uploaded by

Abhi ATM
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views100 pages

Verilog Module

The document introduces Verilog, a hardware description language used for designing and simulating digital systems, highlighting its evolution from early integration technologies to modern VLSI and ULSI. It discusses the significance of computer-aided design (CAD) tools and the design flow process, which includes problem formulation, design entry, simulation, and synthesis. Additionally, it compares Verilog with VHDL and outlines the learning process for mastering Verilog, emphasizing its syntactic similarities to C.

Uploaded by

Abhi ATM
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 100

CHAPTER

Introduction to Verilog®
2

As integrated circuit technology has improved to allow more and more components
on a chip, digital systems have continued to grow in complexity. While putting a few
transistors on an integrated circuit (IC) was a miracle when it happened, technology
improvements have advanced the VLSI (very large scale integration) field contin-
ually. The early integrated circuits belonged to SSI (small-scale integration), MSI
(medium-scale integration), or LSI (large-scale integration) categories depending
on the density of integration. SSI referred to ICs with 1 to 20 gates, MSI referred
to ICs with 20 to 200 gates, and LSI referred to devices with 200 to a few thousand
gates. Many popular building blocks such as adders, multiplexers, decoders, regis-
ters, and counters are available as MSI standard parts. When the term VLSI was
coined, devices with 10,000 gates were called VLSI chips. The boundaries between
the different categories are fuzzy today. Many modern microprocessors contain
more than 100 million transistors. Compared to what was referred to as VLSI in its
initial days, modern integration capability could be described as ULSI (ultra large
scale integration). Despite the changes in integration ability and the fuzzy defini-
tion, the term VLSI remains popular.
As digital systems have become more complex, detailed design of the sys-­
tems at the gate and flip-flop level has become very tedious and time-consuming.
Two or three decades ago, digital systems were created using hand-drawn
schematics, bread-boards, and wires, which were connected to the bread-board.
Now, hardware design often involves no-hands-on tasks with bread-boards and
wires.
In this chapter, first we present an introduction to computer-aided design. Then,
an introduction to hardware description languages is presented. Basic features of
Verilog® are presented, and examples are provided to illustrate how digital hard-
ware is described, simulated, and synthesized using Verilog. Advanced features of
Verilog are presented later in Chapter 8.
2.1 Computer-Aided Design 59

2.1 Computer-Aided Design


Computer-aided design (CAD) tools have advanced significantly during the past
decade, and nowadays digital design is performed using a variety of software tools.
Prototypes or even final designs can be created without discrete components and
interconnection wires.
Figure 2-1 illustrates the steps in modern digital system design. Like any engi-
neering design, the first step in the design flow is formulating the problem, stating
the design requirements, and arriving at the design specification. The next step is to
formulate the design at a conceptual level, either at a block diagram level or at an
algorithmic level.

FIGURE 2-1: Design Flow


Requirements
in Modern Digital System
Design
Design specifications

Design formulation

Design entry
VHDL, Verilog, schematic capture

Simulation

Logic synthesis

Post synthesis simulation

Mapping, placement, routing

FPGA programming unit

ASIC masks Configured FPGAs

Design entry is the next step in the design flow. Previously, this would have been
a hand-drawn schematic or blueprint. Now with CAD tools, the design conceptu-
alized in the previous step needs to be entered into the CAD system in an appro-
priate manner. Designs can be entered in multiple forms. A few years ago, CAD
tools used to provide a graphical method to enter designs. This was called schematic
capture. The schematic editors typically were supplemented with a library of
standard digital building blocks such as gates, flip-flops, multiplexers, decoders,
60 Chapter 2 Introduction to Verilog

counters, registers, and so forth. ORCAD (a company that produced design auto-
mation tools) provided a very popular schematic editor. Nowadays, hardware
description languages (HDLs) are used to enter designs in textual form. Two
popular HDLs are VHDL and Verilog.
A hardware description language (HDL) allows a digital system to be designed
and debugged at a higher level of abstraction than schematic capture. In sche-
matic capture, a designer inputs a schematic with gates, flip-flops, and standard
MSI building blocks. However, with HDLs, the details of the gates and flip-flops
do not need to be handled during early phases of design. A design can be entered
in what is called a behavioral description of the design. In a behavioral HDL
description, one specifies only the general working of the design at a flow-chart or
algorithmic level without associating to any specific physical parts, components,
or implementations. Another method to enter a design in VHDL and Verilog is
the structural description entry. In structural design, specific components or spe-
cific implementations of components are associated with the design. A structural
VHDL or Verilog model of a design can be considered as a textual description
of a schematic diagram that you would have drawn interconnecting specific gates,
flip-flops, and other modules.
Once the design has been entered, it is important to simulate it to confirm that
the conceptualized design does function correctly. Initially, one should perform the
simulation at the high-level behavioral model. This early simulation unveils prob-
lems in the initial design. If problems are discovered, the designer goes back and
alters the design to meet the requirements.
Once the functionality of the design has been verified through simulation, the
next step is synthesis. Synthesis means conversion of the higher-level abstract
description of the design to actual components at the gate and flip-flop levels. Use
of computer-aided design tools to do this conversion, also called synthesis, is stan-
dard practice in the industry now. The output of the synthesis tool, consisting of a
list of gates and a list of interconnections, specifying how to interconnect them, is
often referred to as a netlist. Synthesis is analogous to writing software programs
in a high-level language such as C and then using a compiler to convert the pro-
grams to machine language. Just as a C compiler can generate optimized or unop-
timized machine code, a synthesis tool can generate optimized or unoptimized
hardware. The synthesis software generates different hardware implementations,
depending on algorithms embedded in the software to perform the translation and
optimization. A synthesis tool is nothing but a compiler to convert design descrip-
tions to hardware, and it is not unusual to name synthesis packages with phrases
such as “design compiler,” “silicon compiler,” and the like.
The next step in the design flow is post-synthesis simulation. The earlier sim-
ulation at a higher level of abstraction does not take into account specific imple-
mentations of the hardware components that the design is using. If post-synthesis
simulation unveils problems, one should go back and modify the design to meet
timing requirements. Arriving at a proper design implementation is an iterative
process.
Next, a designer moves into specific realizations of the design. A design can be
implemented in several different target technologies. It could be a completely cus-
tom IC, or it could be implemented in a standard part that is easily available from
2.1 Computer-Aided Design 61
FIGURE 2-2: Spectrum of
Design Technologies
Custom ASIC

Mask
programmable gate
arrays (MPGAs)

Cost Design-Time Performance


Field
programmable gate
arrays (FPGAs)

Complex PLDS
(CPLDs)

PALs, PLAs, PLDs

Off-the-shelf gates,
flip-flops, and standard
logic elements

Density and degree of customization

a vendor. The target technologies that are commonly available now are illustrated
in Figure 2-2.
At the lowest level of sophistication and density is an old-fashioned printed
circuit board with off-the-shelf gates, flip-flops, and other standard logic-building
blocks. Slightly higher in density are programmable logic arrays (PLAs), pro-
grammable array logic (PALs), and simple programmable logic devices (SPLDs).
PLDs with higher density and gate count are called complex programmable logic
devices (CPLDs). In addition, there are the popular field programmable gate arrays
(FPGAs) and mask programmable gate arrays (MPGAs), or simply gate arrays.
The highest level of density and performance is a fully custom application-specific
integrated circuit (ASIC).
Two most common target technologies currently are FPGAs and ASICs.
The initial steps in the design flow are largely the same for either realization.
Towards the final stages in the design flow, different operations are performed
depending on the target technology. This is indicated in Figure 2-1. The design
is mapped into specific target technology and placed into specific parts in the
target ASIC or FPGA. The paths taken by the connections between components
are decided during the routing. If an ASIC is being designed, the routed design
is used to generate a photomask that will be used in the integrated circuit (IC)
manufacturing process. If a design is to be implemented in an FPGA, the design
is translated to a format specifying what is to be done to various programmable
points in the FPGA. In modern FPGAs, programming simply involves writing a
sequence of 0s and 1s into the programmable cells in the FPGA, and no specific
programming unit other than a personal computer (PC) is required to program
an FPGA.
62 Chapter 2 Introduction to Verilog

2.2 Hardware Description Languages


Hardware description languages (HDLs) are a popular mode of design entry for
digital circuits and systems. There are two popular HDLs—VHDL and Verilog.
Before the advent of HDLs, designers used graphical schematics and schematic
capture tools to document and simulate digital circuits. A need was felt to create
a textual method of documenting circuits and feeding them into simulators in the
textual form as opposed to a graphic form. This book uses the Verilog language for
illustrating principles of modern digital system design. Those interested in VHDL
can find the equivalent material in Roth and John, Digital Systems Design Using
VHDL, 2nd ed. (Cengage Learning, 2008).
Verilog is a hardware description language used to describe the behavior and/
or structure of digital systems. Verilog is a general-purpose hardware description
language that can be used to describe and simulate the operation of a wide variety
of digital systems, ranging in complexity from a few gates to an interconnection of
many complex integrated circuits. While the competing language VHDL was orig-
inally developed under funding from the Department of Defense (DoD), Verilog
was developed by the industry. It was initially developed as a proprietary language
by a company called Gateway Design Automation around 1984.
In 1990, Cadence acquired Gateway Design Automation and became the owner
of Verilog. Cadence marketed it as a language and as a simulator, but it remained pro-
prietary. At this time, Synopsis was promoting the concept of top-down design using
Verilog. Cadence realized that it needed to make Verilog open in order to prevent the
industry from shifting to VHDL and hence opened up the language. An organization
called Open Verilog International (OVI) was formed, which helped to create a ven-
dor-independent language specification for Verilog, clarifying many of the confusions
around the proprietary specification. This was followed by an effort to create an IEEE
standard for Verilog. The first Verilog IEEE Standard was created in 1995, which was
revised in 2001 and 2005. Synopsis created synthesis tools for Verilog around 1988.
HDLs can describe a digital system at several different levels—behavioral, data
flow, and structural. For example, a binary adder could be described at the behav-
ioral level in terms of its function of adding two binary numbers without giving any
implementation details. The same adder could be described at the data flow level
by giving the logic equations for the adder. Finally, the adder could be described
at the structural level by specifying the gates and the interconnections between the
gates that comprise the adder.
HDLs lead naturally to a top-down design methodology, in which the system
is first specified at a high level and tested using a simulator. After the system is
debugged at this level, the design can gradually be refined, eventually leading to a
structural description closely related to the actual hardware implementation. HDLs
are designed to be technology independent. If a design is described in HDL and
implemented in today’s technology, the same HDL description could be used as a
starting point for a design in some future technology.
Verilog has its syntactic roots in C whereas VHDL has its syntactic roots in
ADA. Some find Verilog easier or less intimidating to learn due to its similarity
2.2 Hardware Description Languages 63
with C, while many find VHDL to be excellent for supporting design and documen-
tation of large systems. VHDL and Verilog enjoy approximately 50/50 global market
share. Both languages can accomplish most requirements for digital design rather
easily. But Verilog is touted by many to be slightly more supportive for synthesis and
VHDL is touted to be slightly more elegant for simulation of very large systems at
a higher level of abstraction. Often design companies continue to use what they are
used to; hence, Verilog users continue to use Verilog and VHDL users continue to
use VHDL. If one knows one of these languages, it is not difficult to transition to the
other. VHDL has more conceptual elegance for the higher-level abstractions, while
Verilog has enjoyed its popularity from its syntactic similarity to C.
More recently, there also have been efforts in system design languages such as
System C, Handel-C, and System Verilog. System C is created as an extension to
C11; hence, some who are more comfortable with general-purpose software find it
less intimidating. These languages are primarily targeted at describing large digital
systems at a higher level of abstraction. They are primarily used for verification and
validation. When different parts of a large system are designed by different teams,
one team can use a system-level behavioral description of the block being designed
by the other team during the initial design process. Problems that might otherwise
become obvious only during system integration may become evident in early stages,
reducing the design cycle time for large systems. System-level simulation languages
are used during the design of large systems. Efforts to synthesize hardware from high
level-languages are steadily progressing, and tools to convert models written in lan-
guages such as C11 to hardware are emerging.
Learning a Language
There are several challenges when you learn a new language, whether it be a
language for common communication (English, Spanish, French, etc.), a computer
language such as C, or a special-purpose language such as Verilog. If it is not your
first language, you typically have a tendency to compare it with a language you
know. In the case of Verilog, if you already know another hardware description
language, it is good to compare it with Verilog, but you should be careful when
comparing it with languages such as C. VHDL and Verilog have a very different
purpose from languages such as C, and a comparison with C is not a meaningful
activity. We will be describing the language assuming it is your first HDL; however,
we will assume basic knowledge of computer languages such as C and the basic
compilation and execution flow.
When one learns a new language, one needs to study the alphabet of the new
language, its vocabulary, grammar, syntax rules, and semantics of language descrip-
tions. The process of learning Verilog is not much different. One needs to learn
the alphabet, vocabulary or lexical elements of the language, syntax (grammar and
rules), and semantics (meaning of descriptions). The lexical elements of the lan-
guage include various identifiers, reserved words, special symbols, and literals. We
have listed these in Appendix B. The syntax or grammar determines what combina-
tions of lexical elements can be combined to make valid Verilog descriptions. These
are the rules that govern the use of different Verilog constructs. Then one needs
to understand the semantics or meaning of Verilog descriptions. It is here that one
understands what descriptions represent combinational hardware versus sequential
64 Chapter 2 Introduction to Verilog

hardware. And just as fluency in a natural language comes by speaking, reading, and
writing the language, mastery of Verilog comes by repeated use of the language to
create models for various digital systems.
Since Verilog is a hardware description language, it differs from an ordinary pro-
gramming language in several ways. Most importantly, Verilog has statements that
execute concurrently since they must model real hardware in which the components
are all in operation at the same time. It is popularly used for the purposes of describ-
ing, documenting, simulating, and automatically generating hardware. Hence, its
constructs are tailored for these purposes. We will present the various methods to
model different kinds of digital hardware using examples in the following sections.

Common Abbreviations
VHDL: VHSIC hardware description language
VHSIC: very-high-speed integrated circuit
HDL: hardware description language
CAD: computer-aided design
EDA: electronic design automation
LSI: large-scale integration
MSI: medium-scale integration
SSI: small-scale integration
VLSI: very-large-scale integration
ULSI: ultra-large-scale integration
ASCII: American standard code for information interchange
ISO: International Standards Organization
ASIC: application-specific integrated circuit
FPGA: field-programmable gate array
PLA: programmable logic array
PAL: programmable array logic
PLD: programmable logic device
CPLD: complex programmable logic device
STA: static timing analysis

2.3 Verilog Description of Combinational


Circuits
The biggest difficulty in modeling hardware using a general-purpose computer lan-
guage is representing concurrently operating hardware. Computer programs that
you are normally accustomed to are sequences of instructions with a well-defined
order. At any point of time during execution, the program is at a specific point in
its flow, and it encounters and executes different parts of the program sequentially.
In order to model combinational circuits that have several gates (all of which are
always working simultaneously), one needs to be able to “simulate” the execution
of several parts of the circuit at the same time.
2.3 Verilog Description of Combinational Circuits 65
Verilog models combinational circuits by what are called concurrent state-
ments or continuous assignments. Concurrent statements (continuous assign-
ments) are statements that are always ready to execute. These are statements that
are evaluated any time and every time a signal on the right side of the statement
changes.
We will start by describing a simple gate circuit in Verilog. If each gate in the
circuit of Figure 2-3 has a 5 ns propagation delay, the circuit can be described by
two Verilog statements as shown, where A, B, C, D, and E are signals. A signal
in Verilog usually corresponds to a signal in a physical system. The symbol “&&”
represents the AND gate and the symbol “||” represents the OR. The #5 indicates a
delay symbol of 5 ns. The symbol “5” is the signal assignment operator, which indi-
cates that the value computed on the right side is assigned to the signal on the left
side. The assign statement is used to assign a value, as shown in Figure 2-3. When
the statements in Figure 2-3 are simulated, the first statement will be evaluated any
time A or B changes, and the second statement will be evaluated any time C or D
changes. Suppose that initially A 5 1 and B 5 C 5 D 5 E 5 0. If B changes to 1
at time 0, C will change to 1 at time 5 5 ns. Then E will change to 1 at time 5 10 ns
(assuming timescale is 1 ns).

FIGURE 2-3: A Simple A C


Gate Circuit B
D
E assign #5 C = A && B;
assign #5 E = C || D;

Verilog signal assignment statements like the ones in the foregoing example
are examples of concurrent statements or continuous assignments. The Verilog
simulator monitors the right side of each concurrent statement, and any time a
signal changes, the expression on the right side is immediately reevaluated. The
new value is assigned to the signal on the left side after an appropriate delay.
This is exactly the way the hardware works. Any time a gate input changes, the
gate output is recomputed by the hardware and the output changes after the gate
delay.
Unlike a sequential program, the order of the above concurrent statements is
unimportant. If we write
assign #5 E = C || D;
assign #5 C = A && B;

the simulation results would be exactly the same as before. In general, a signal
assignment statement has the form

assign [#delay] signal_name = expression;

The expression is evaluated when the statement is executed, and the signal on
the left side is scheduled to change after delay. The square brackets indicate that
#delay is optional; they are not part of the statement. If #delay is omitted, then the
signal is updated immediately. Unlike in VHDL, Verilog simulators do not display
delta delays for continuous assign statements. The delta delay is an infinitesimally
66 Chapter 2 Introduction to Verilog

small delay used to maintain/indicate sequentiality between dependent events hap-


pening at the same time. Note that the time at which the statement executes and the
time at which the signal is updated are not the same if delay is specified.
Even if a Verilog program has no explicit loops, concurrent statements execute
repeatedly as if they were in a loop. Figure 2-4 shows an inverter with the output
connected back to the input. If the output is 0, then this 0 feeds back to the input
and the inverter output changes to 1 after the inverter delay, which is assumed to
be 10 ns. Then the 1 feeds back to the input, and the output changes to 0 after the
inverter delay. The signal CLK will continue to oscillate between 0 and 1 as shown
in the waveform. The corresponding concurrent Verilog statement will produce the
same result. If CLK is initialized to 0 the statement executes and CLK changes to
1 after 10 ns. Since CLK has changed, the statement executes again, and CLK will
change back to 0 after another 10 ns. This process will continue indefinitely.

FIGURE 2-4: Inverter with CLK


Feedback assign #10 CLK = ~CLK;

CLK

10 20 30 40 50 60

The statement in Figure 2-4 generates a clock waveform with a half period of 10 ns.
On the other hand, if the concurrent statement
assign CLK = ~CLK;

is used, time will never advance to 1 ns.


In general, Verilog is case sensitive; that is, capital and lower-case letters are
treated as different by the compiler and by the simulator. Thus, the statements
assign #10 Clk = ~Clk;

and
assign #10 CLK = ~CLK;

would result in two different clocks. Signal names and other Verilog identifiers may
contain letters, numbers, the underscore character (_), and the dollar sign ($). An
identifier must start with a letter or underscore character, and it cannot start with a
number or a $ sign. The dollar sign ($) is reserved as the first character for system
tasks. The following are valid identifiers:
adder
Mux_input
_error_code
Index_bit
vector_sz
_$five
Count
XOR
2.3 Verilog Description of Combinational Circuits 67
The following are invalid identifiers:
4bitadder
$error_code

Every Verilog statement must be terminated with a semicolon. Spaces, tabs, and
carriage returns are treated in the same way. This means that a Verilog statement
can be continued over several lines, or several statements can be placed on one
line. In a line of Verilog code, anything following a double slash (//) is treated as a
comment to the end of the line. Comments for more than one line start with “/*”
and end with “*/”. Words such as and, or, and always are reserved words (or key-
words) that have a special meaning to the Verilog compiler. In this text, we will put
all reserved words in boldface type. Verilog reserved words (keywords) are shown
in Appendix B.
Figure 2-5 shows three gates that have the signal A as a common input and the
corresponding Verilog code. The three concurrent statements execute simultane-
ously whenever A changes, just as the three gates start processing the signal change
at the same time. However, if the gates have different delays, the gate outputs can
change at different times. If the gates have delays of 2 ns, 1 ns, and 3 ns, respectively,
and A changes at time 5 ns, then the gate outputs D, E, and F can change at times
7 ns, 6 ns, and 8 ns, respectively. The Verilog statements work in the same way. Even
though the statements execute simultaneously at 5 ns, the signals D, E, and F are
updated at times 7 ns, 6 ns, and 8 ns.

FIGURE 2-5: Three Gates B


with a Common Input D
// when A changes, these concurrent
and Different Delays // statements all execute at the
// same time
A E
assign #2 D = A && B;

F assign #1 E = ~A;
C
assign #3 F = A || C;

In the foregoing examples, every signal is of type wire (or net), and it generally has a
value of 0 or 1 (or 1’b0, 1’b1). In general, the net values in Verilog are represented as
<number of bits>’<base><value>. The values on nets can be represented as binary,
decimal, or hexadecimal indicated by b, d, and h respectively.
In digital design, we often need to perform the same operation on a group of
signals. A one-dimensional array of bit signals is referred to as a vector. If a 4-bit
vector named B has an index range 0 through 3, then the 4 elements of the wire or
reg data types are designated B[0], B[1], B[2], and B[3]. One can declare a multiple
bit wire using a statement such as

wire B[3:0];

The statement B = 4'b1100 assigns 1 to B[3], 1 to B[2], 0 to B[1], and 0


to B[0].
68 Chapter 2 Introduction to Verilog

Figure 2-6 shows an array of four AND gates. The inputs are represented by
4-bit vectors A and B, and the output by 4-bit vector C, where the && (logical
AND operator) is used. Although we can write four Verilog statements to represent
the four gates, it is much more efficient to write a single Verilog statement that
performs the & (bitwise AND operator) operation on the vectors A and B. When
applied to vectors, the & operator performs the bitwise AND operation on corre-
sponding pairs of elements.

FIGURE 2-6: Array of A(3)


C(3)
AND Gates B(3) // the hard way
assign C[3] = A[3] && B[3];
A(2)
C(2) assign C[2] = A[2] && B[2];
B(2)
assign C[1] = A[1] && B[1];
A(1) assign C[0] = A[0] && B[0];
C(1)
B(1)

A(0)
C(0)
B(0)
// the easy way assuming C, A and
// B are 4-bit vectors
assign C = A & B;

2.4 Verilog Modules


The general structure of a Verilog code is a module description. A module is a basic
building block that declares the input and output signals and specifies the internal
operation of the module. As an example, consider Figure 2-7. The module declara-
tion has the name two_gates and specifies the inputs and outputs. A, B, and D are
input signals, and E is an output signal. The signal C is declared within the module
as a wire since it is an internal signal. The two concurrent statements that describe
the gates are placed and the module ends with endmodule. All the input and output
signals are listed in the module statement without specifying whether they are input
or output.

FIGURE 2-7: Verilog


Module with Two Gates A C module two_gates (A, B, D, E);
B E
output E;
D
input A, B, D;
wire C;
assign C 5 A && B; // concurrent
assign E 5 C || D; // statements
endmodule
2.4 Verilog Modules 69
The module I/O declaration part can be considered as the black box picture of
the module being designed and its external interface; that is, it represents the inter-
connections from this module to the external world as in Figure 2-8.

FIGURE 2-8: Black Box


View of the 2-Gate A
Module
B E

Just as in this simple example, when we describe a system in Verilog, we must


specify input and output signals and also specify the functionalities of the module
that are part of the system (see Figure 2-9). Each module declaration includes a list
of interface signals that can be used to connect to other modules or to the outside
world. We will use module declarations of the form:

module module-name (module interface list);


[list-of-interface-ports]
...
[port-declarations]
...
[functional-specification-of-module]
...
endmodule

The items enclosed in square brackets are optional. The list-of-interface-


ports normally has the following form:

type-of-port list-of-interface-signals
{; type-of-port list-of-interface-signals};

The curly brackets indicate zero or more repetitions of the enclosed clause.
Type-of-port indicates the direction of information; whether information is flowing
into the port or out of it. Input port signals are of keyword input, output port signals
are of keyword output, and bidirectional signals are of keyword inout. Also, list-of-
ports can be combined with the module interface list.

FIGURE 2-9: Verilog


Program Structure Module

Module_1 Module_2 Module_N


instantiation instantiation instantiation
70 Chapter 2 Introduction to Verilog

In the port-declarations section, we can declare internal signals that are used
within the module. The module contains other module instances that describe the
operation of the module.
Next, we will write a Verilog module for a full adder. A full adder adds two bit
inputs and a carry input to generate a sum bit and a carry output bit. As shown in
Figure 2-10, the port declaration specifies that X, Y, and Cin are input signals of type
bit and that Cout and Sum are output signals of type bit.
FIGURE 2-10: Verilog
Module for a Full Adder module FullAdder(X, Y, Cin, Cout, Sum);
output Cout, Sum;
X
Full Cout input X, Y, Cin;
Y
adder Sum assign #10 Sum 5 X ^ Y ^ Cin;
Cin
assign #10 Cout 5 (X && Y) || (X && Cin) || (X && Cin);
endmodule

In this example, the Verilog assignment statements for Sum and Cout represent the
logic equations for the full adder. The specified equations are
Sum = X ! Y ! Cin
Cout = XY ! YCin + XCin

Several other architectural descriptions such as a truth table or an interconnec-


tion of gates could have been used instead. In the Cout equation, parentheses are
required around (X && Y) since Verilog does not specify an order of precedence for
the logic operators except the NOT operator.

Four-Bit Full Adder


Next, we will show how to use the FullAdder module defined previously as a
module in a system, which consists of four full adders connected to form a 4-bit
binary adder (see Figure 2-11). We first declare the 4-bit adder as another module
(see Figure 2-12). Since the inputs and the sum output are four bits wide, we declare
them as a 4-bit vector and they are dimensioned [3:0]. (We could have used a
range [1:4] instead).
FIGURE 2-11: 4-Bit Binary S3 S2 S1 S0
Adder

Full C3 Full C2 Full C1 Full


Co Ci
adder adder adder adder

A3 B3 A2 B2 A1 B1 A0 B0

Next, we instantiate the FullAdder module within the module of Adder4


(Figure 2-12).
Following the I/O port declaration, we declare a 3-bit internal carry signal
C as a data type wire. After that, we create several instances of the FullAdder
2.4 Verilog Modules 71
component. (In CAD jargon, we “instantiate” four copies of the FullAdder.) Each
copy of FullAdder has a port map. The port map corresponds one-to-one with the
signals in the component port. Thus, A[0], B[0], and Ci correspond to the inputs
X, Y, and Cin, respectively. C[1] and S[0] correspond to the Cout and Sum outputs of
the adder for least significant bit. Unconnected ports can be omitted. In case the sig-
nals are not connected to the ports by name, the order of the signals in the port map
must be the same as the order of the signals in the port of the module declaration.
In this example, we use the ports in order, a method called positional association.
The other method called named association is described in Chapter 8. Note that the
order of the signals in named association can be in any order as long as the signals
in the module are connected to the ports by name.

FIGURE 2-12: Structural Description of a 4-Bit Adder

module Adder4 (S, Co, A, B, Ci);


output [3:0] S;
output Co;
input [3:0] A, B;
input Ci;

wire [3:1] C; // C is an internal signal

// instantiate four copies of the FullAdder

FullAdder FA0 (A[0], B[0], Ci, C[1], S[0]);


FullAdder FA1 (A[1], B[1], C[1], C[2], S[1]);
FullAdder FA2 (A[2], B[2], C[2], C[3], S[2]);
FullAdder FA3 (A[3], B[3], C[3], Co, S[3]);

endmodule

In preparation for simulation, we can place the modules for the FullAdder and for
Adder4 together in one project and compile. Some tools may require them to be in
the same file.
All of the simulation examples in this text use the ModelSim Verilog
simulator from Mentor Graphics. Most other Verilog simulators use similar com-
mand files and can produce output in a similar format. The simulator command
file is usually called the do file. We will use the following simulator commands
to test Adder4:
add list A B Co C Ci S // put these signals on the output list
force A 1111 // set the A inputs to 1111
force B 0001 // set the B inputs to 0001
force Ci 1 // set Ci to 1
run 50 ns // run the simulation for 50 ns
force Ci 0
force A 0101
force B 1110
run 50 ns
72 Chapter 2 Introduction to Verilog

We have chosen to run the simulation for 50 ns for each input set, since this is
more than enough time for the carry to propagate through all of the full adders. The
simulation results for the above command list are:

ns delta a b co c ci s
0 10 1111 0001 x xxx 1 xxxx
10 10 1111 0001 x xx1 1 xxx1
20 10 1111 0001 x x11 1 xx01
30 10 1111 0001 x 111 1 x001
40 10 1111 0001 1 111 1 0001
50 10 0101 1110 1 111 0 0001
60 10 0101 1110 1 110 0 0101
70 10 0101 1110 1 100 0 0111
80 10 0101 1110 1 100 0 0011

The listing shows how the carry propagates one position every 10 ns. The x values
can be avoided by initializing the S, C, and Co values to 0. Under that condition,
the simulation progresses as follows
0 0 0 0
Time = D
0 0 0 0 1
FA3 FA2 FA1 FA0

1 0 1 0 1 0 1 1

The sum and carry are computed by each FA and appear at the FA outputs 10 ns
later:
1 1 1 1
Time = 10
0 0 0 1 1
FA3 FA2 FA1 FA0

1 0 1 0 1 0 1 1

Since the inputs to FA1 have changed, the outputs change 10 ns later:
1 1 0 1
Time = 20
0 0 1 1 1
FA3 FA2 FA1 FA0

1 0 1 0 1 0 1 1

The final simulation results are:

1111 1 0001 1 1 5 0001 with a carry of 1 (at time 5 40 ns) and


0101 1 1110 1 0 5 0011 with a carry of 1 (at time 5 80 ns).
The simulation stops at 80 ns since no further changes occur after that time.

Use of “Inout” Mode


Let us consider the example in Figure 2-13. Assume that all variables are 0 @ 0 ns,
but A changes to 1 @ 10 ns.
2.5 Verilog Assignments 73
FIGURE 2-13: Verilog Code Illustrating Use of Output as an Input Signal

module gates (A, B, C, D, E);


input A, B, C;
output D, E;
assign #5 D = A || B; // statement 1
assign #5 E = C || D; // statement 2 uses D as an input
endmodule
The code in Figure 2-13 will actually compile, simulate, or synthesize in most
tools even though D is declared only as an output. Statement 2 uses D as an input.
In VHDL, D should be strictly in either in or inout mode, but Verilog is not that
strict in compilation. The output mode can also be used as an input in a statement
inside the same module, but inout has to be used as in Figure 2-14 if D has to be
used as input and output by other modules.

FIGURE 2-14: Verilog Code Illustrating Use of Mode Inout

module gates (A, B, C, D, E);


input A, B, C;
output E;
inout D;
assign #5 D = A || B; // statement 1
assign #5 E = C || D; // statement 2
endmodule

All signals remain at 0 until time 10 ns. The change in A at 10 ns results in


statement 1 reevaluating. The value of D becomes 1 at time equal to 15 ns. The
change in D at time 15 ns results in statement 2 reevaluating. Signal E changes to
1 at time 20 ns. The description represents TWO gates, each with a delay of 5 ns.

2.5 Verilog Assignments


There are two types of assignment in the Verilog: continuous assignments and proce-
dural assignments. Continuous assignments are used to assign values for combinational
logic circuits. The assign keyword can be used after the net is separately declared,
which is referred to as explicit continuous assignments. Implicit continuous assign-
ments assign the value in declaration without using the assign keyword. The following
examples show the difference between explicit and implicit continuous assignments.

wire C;
assign C = A || B; // explicit continuous assignment
wire D = E && F; // implicit continuous assignment
74 Chapter 2 Introduction to Verilog

Procedural assignments are used to model registers and finite state machines using
the always keyword. More details on procedural assignment are explained in the
following section.

2.6 Procedural Assignments


The concurrent statements from the previous section are useful in modeling combi-
national logic. Combinational logic constantly reacts to input changes. In contrast,
synchronous sequential logic responds to changes dependent on the clock. Many
input changes might be ignored since output and state changes occur only at valid
conditions of the clock. Modeling sequential logic requires primitives to model selec-
tive activity conditional on clock, edge-triggered devices, sequence of operations,
and so forth. There are two types of procedural assignments in Verilog. Initial blocks
execute only once at time zero, whereas always blocks loop to execute over and over
again. In other words, the initial block execution and always block execution starts
at time 0. Always block waits for the event, whereas initial block just executes all the
statements without waiting. Verilog also has a procedural assign statement that can
be used inside the always block, but we do not use them in this book.
In this unit, we will learn initial and always statements, which help to model
sequential logic. Initial blocks are useful in simulation and verification, but only
always blocks are synthesized.

Initial Statements
An initial statement has the following basic form:
initial
begin
sequential-statements
end

Always Statements
An always statement has the following basic form:
always @(sensitivity-list)
begin
sequential-statements
end

When an always statement is used, the statements between the begin and the end
are executed sequentially rather than concurrently. The expression in parentheses
after the word always is called a sensitivity list, and the process executes whenever
any signal in the sensitivity list changes. The symbol “@” should be used before the
sensitivity list. For example, if the always statement has the sensitivity list @(A, B, C),
then it executes whenever any one of A, B, or C changes. Whenever one of the
signals in the sensitivity list changes, the sequential statements in the always block
are executed in sequence one time. In earlier versions of Verilog, “or” is used to
specify more than one element in the sensitivity list. In Verilog 2001, comma (,) is
2.6 Procedural Assignments 75
also used in the sensitivity list. Starting with Verilog 2001, an always statement can
be used with a * in the sensitivity list to cause the always block to execute whenever
any signal changes. When a process finishes executing, it goes back to the beginning
and waits for a signal on the sensitivity list to change again.
The variables on the left-hand side element of an 5 or ,5 in an always block
should be defined as reg data type. Any other data type including wire is illegal.
The assignment operator “5” indicates concurrent execution when used outside
an always block. When the statements
C = A && B; // concurrent statements
E = C || D; // when used outside always block

are used outside an always block, the order of the statements does not matter. But
when used in an always block, they become sequential statements executed in the
order they are written.

Blocking and Non-Blocking Assignments


Sequential statements can be evaluated in two different ways in Verilog—blocking
assignments and non-blocking assignments. A blocking statement must complete
the evaluation of the right-hand side of a statement before the next statements in a
sequential block are executed. Operator “5” is used for representing the blocking
assignment. The meaning of “blocking” is that a blocking assignment has to com-
plete before the next statement starts execution (i.e., it blocks the next assignment
in the sequential block from starting evaluation). A non-blocking statement allows
assignment evaluation without blocking the sequential flow. In other words, several
assignments can be evaluated at the same time. Operator “,5” is used for repre-
senting the non-blocking assignment.
For instance, consider the situation if they are in an always block, as shown here:
always @(A, B, D)
begin
C = A && B; // Blocking operator is used
E = C || D; // Statements execute sequentially
end

The block executes once when any of the signals A, B, or D changes. The first state-
ment updates the value of C before the second statement starts execution; hence,
the second statement uses the new value of C as input. If C or E changes when the
block executes, then the always block will not execute a second time because C is
not on the sensitivity list. Operator “5” is used for representing what Verilog calls
the blocking assignment, which blocks the next assignment in the sequential block.
It should be noticed that the assignment operator “5” has a blocking nature inside
the always block but a non-blocking or concurrent nature outside the always block.
The operator “<5” is to evaluate several assignments at the same time without
blocking the sequential flow. Consider the following code:
always @(A, B, D)
begin
C <= A && B; // Statements execute simultaneously because
E <= C || D; // non-blocking operator is used
end
76 Chapter 2 Introduction to Verilog

The block executes once when any of the signals A, B, or D changes. Both state-
ments execute simultaneously with the values of A, B, C, and D at the beginning
of the always block. The first statement does not update the value of C before the
second statement starts execution; hence, the second statement uses the old value
of C as input. If C changes when the block executes, then the always block will not
execute a second time because C is not on the sensitivity list. Operator “,5” is used
for representing what Verilog calls the non-blocking assignment inside an always
statement. It should be noticed that the concurrent operations occur with “5” out-
side the always block, but with “,5” inside the always block. C and E should be
defined as reg data type since reg is the only legal type on the left-hand side element
of an 5 or ,5 in an always block.
Figure 2-15 shows a comparison of blocking assignments and non-blocking
assignments. The posedge keyword of Verilog is used for an edge-triggered func-
tionality in the sensitivity list. Signals A and B are used for a blocking statement,
and C and D are applied for a non-blocking statement. Assume the initial values of
input signals are A5C51’b1 and B5D51’b0. In the case of blocking assignments,
both A and B will become 1’b0. Since the second assignment will not be evaluated
until the completion of the first assignment, the newly evaluated A signal will be
assigned to B in the second assignment. On the other hand, non-blocking assign-
ments will start evaluating all statements in a sequential block at the same time;
the result will be independent of the assignment order. Therefore, the result of
non-blocking assignments will be C51’b0 and D51’b1. So the signals swap in the
case of C and D, but not in the case of A and B.
Always statements can be used for modeling combinational logic and sequen-
tial logic; however, always statements are not necessary for modeling combina-
tional logic. They are, however, required for modeling sequential logic. One should
be very careful when using always statements to represent combinational logic. If

FIGURE 2-15: Blocking and Non-Blocking Assignments

module sequential_module (A, B, C, D, clk);


input clk;
output A, B, C, D;
reg A, B, C, D;

always @(posedge clk)


begin
A = B; // blocking statement 1
B = A; // blocking statement 2
end

always @(posedge clk)


begin
C <= D; // non-blocking statement 1
D <= C; // non-blocking statement 2
end

endmodule
2.6 Procedural Assignments 77
any of the input signals are accidentally omitted from the sensitivity list, there can
be mismatches between synthesis and simulation and a lot of confusion. Hence, the
common practice starting with Verilog 2001 of using the always @* statement if a
combinational circuit is desired, which avoids accidental errors such as these. If the
sensitivity list is “*” then the block will get triggered for any input signal changes.
Consider the code in Figure 2-16, where an always statement is used to model
two cascaded gates. D and E should be defined as reg since reg is the only legal type
on the left-hand side element of an 5 or ,5 in an always block. Also, D should be
defined as output if the output of the first gate is desired externally. If inout is used
for D, you will have a compile error, since D is of reg type. Normally, input and
inout ports can be only net (or wire) data type. The statement order is important
here because blocking assignment is used.

FIGURE 2-16: Verilog Code for Combinational Logic with Blocking Assignments in an Always Block

module two_gates (A, B, C, D, E);


input A, B, C;
output D, E;

reg D, E;

always @(*)
begin
#5 D = A || B; // blocking statement 1
#5 E = C || D; // blocking statement 2
end

endmodule

Let us assume that all variables are 0 @ 0 ns. Then, A changes to 1 @ 10 ns. That
causes the module to execute. The statements inside the always statement execute
once sequentially. D becomes 1 @ 15 ns, and E becomes 1 @ 20 ns.
Section 2.14 has additional examples illustrating the distinction between block-
ing and non-blocking operators inside always statements. While sequential logic
can be modeled using the blocking operator “5,” it is generally advised not to do
so. A good coding practice while writing synthesizable code is to use non-blocking
assignments (i.e., “<5”) in always blocks intended to create sequential logic and
the blocking operator “5” in always blocks intended to create combinational logic.
Another rule to remember is not to mix blocking and non-blocking assignments
in the same always block. When each always block is written, think whether you
want sequential logic or combinational logic and then use blocking assignments if
combinational logic is desired.

Sensitivity List
Both combinatorial always blocks and sequential always blocks have a sensitivity list
that includes a list of events. An always block will be activated if one of the events
occurs. In the combinatorial logic, the sensitivity list includes all signals that are used
in the condition statement and all signals on the right-hand side of the assignment.
78 Chapter 2 Introduction to Verilog

On the other hand, the sensitivity list in sequential circuit contains three kinds of
edge-triggered events: clock, reset, and set signal event. The sensitivity list can be
specified using @(*) if a combinational circuit is desired, indicating that the block
must be triggered for any input signal changes. If sensitivity list is omitted at the
always keyword, delays or time-controlled events must be specified inside the always
block. More details on this form of always block are presented in Section 2.8.
Wire and Reg
The two Verilog data types that we have used so far are wire and reg (more on data
types is presented in Section 2.11). The wire acts as real wires in circuit designs. The
reg is similar to wires, but can store information just like registers. The declarations
for wire and reg signals should be done inside a module but outside any initial or
always block. The initial value of a wire is z (high impedance), and the initial value
of a reg is x (unknown).
The wires are either single bit or multiple bits in Verilog. The wires cannot store
any information. They can be used only in modeling combinational logic and must
be driven by something. The wires are a data type that can be used on the left-hand
side of an assign statement but cannot be used on the left-hand side of 5 or <5 in
an always @ block.
The data type reg is used where the assigned data needs to be stored until the
next assignment. If you want to assign your output in sequential code (within an
always block), you should declare it as a reg. Otherwise, it should be a wire by
default. One can use reg to model both combinational and sequential logic. Data
type reg is the only legal type on the left-hand side element of an 5 or <5 in an
always block or initial block (normally used in test benches). It cannot be used on
the left-hand side of an assign statement. Section 2.11 presents more on data types.
The default Verilog HDL data value set is a 4-value system consisting of four
basic values:
0 represents a logic zero, or a false condition.
1 represents a logic one, or a true condition.
x represents an unknown logic value.
z represents a high-impedance state (often called the tristated value).
The 4-valued logic is described in more detail in Chapter 8.
For better understanding of sequential statements and operation of always
statements, several more examples will be presented. In the following section, we
explain how simple flip-flops can be modeled using always statements, and then we
explain the basics of the Verilog simulation process.

2.7 Modeling Flip-Flops Using Always Block


A flip-flop can change state either on the rising or on the falling edge of the clock
input. This type of behavior is modeled in Verilog by an always block. For a simple
D flip-flop with a Q output that changes on the rising edge of CLK, the correspond-
ing code is given in Figure 2-17.
2.7 Modeling Flip-Flops Using Always Block 79
FIGURE 2-17: Verilog Q
Code for a Simple always @ (posedge CLK)
D ­Flip-Flop begin
DFF Q <= D;
end

CLK D

In Figure 2-17, on the rising edge of CLK, the always block executes once
through and then waits at the start of the block until CLK changes again. The
sensitivity list of the always block tests for a rising edge of the clock, and Q is set
equal to D when a rising edge occurs. The expression posedge (or negedge)
is used to accomplish the functionality of an edge-triggered device. If CLK is
changed from 0 to 1 it is a rising edge. If CLK changes from 1 to 0, it indi-
cates a falling edge.
If the flip-flop has a delay of 5 ns between the rising edge of the clock and the
change in the Q output, we would replace the statement Q <= D; with Q <= #5 D;
in the foregoing always block.
The statements between begin and end in an always block operate as sequential
statements. In the previous example, Q <= D; is a sequential statement that executes
only following the rising edge of CLK. In contrast, the concurrent statement assign
Q 5 D; executes whenever D changes. If we synthesize the foregoing code, the synthe-
sizer infers that Q must be a flip-flop since it changes only on the rising edge of CLK. If we
synthesize the concurrent statement assign Q 5 D; the synthesizer will simply connect
D to Q with a wire or a buffer.
In Figure 2-17, note that D is not on the sensitivity list because changing D
will not cause the flip-flop to change state. Figure 2-18 shows a transparent latch
and its Verilog representation. Both G and D are on the sensitivity list since if
G 5 1, a change in D causes Q to change. If G changes to 0, the always block
executes, but Q does not change. For the sensitivity list, both (G or D) and (G, D)
are acceptable.

FIGURE 2-18: Verilog


Code for a Transparent D Q
always @ (G or D)
Latch begin
G
if (G)
Q <= D;
end

If a flip-flop has an active-low asynchronous clear input (ClrN) that resets the
flip-flop independently of the clock, then we must modify the code of Figure 2-17 so
that it executes when either CLK or ClrN changes. To do this, we add ClrN to the
sensitivity list. The Verilog code for a D flip-flop with asynchronous clear is given in
Figure 2-19. Since the asynchronous ClrN signal overrides CLK, ClrN is tested first
and the flip-flop is cleared if ClrN is 0. Otherwise, CLK is tested, and Q is updated
if a rising edge has occurred.
80 Chapter 2 Introduction to Verilog

FIGURE 2-19: Verilog Q


Code for a D Flip-Flop always @ (posedge CLK or negedge ClrN)
with Asynchronous Clear begin
if (~ClrN)
DFF ClrN
Q <= 0;
else
Q <= D;
end

CLK D

In the foregoing examples, we have used two types of sequential statement: sig-
nal assignment statements and if statements. The basic if statement has the form
if (condition)
sequential statements1
else
sequential statements2
The condition is a Boolean expression that evaluates to TRUE or FALSE. If
it is TRUE, sequential statements1 are executed; otherwise, sequential
statements2 are executed.
Verilog if statements are sequential statements that can be used within an
always block (or an initial block), but they cannot be used as concurrent statements
outside of an always block. The most general form of the if statement is
if (condition)
sequential statements
// 0 or more else if clauses may be included
else if (condition)
sequential statements}
[else sequential statements]
The curly brackets indicate that any number of else if clauses may be included,
and the square brackets indicate that the else clause is optional. The example of
Figure 2-20 shows how a flow chart can be represented using nested ifs or the
FIGURE 2-20: Equivalent
Representations of a if (C1)
Flow Chart Using Nested T F begin
C1
Ifs and Else Ifs S1; S2;
T F end
S1; S2; C2 else if (C2)
begin
T F S3; S4;
S3; S4; C3
end
else if (C3)
S5; S6; S7; S8; begin
S5; S6;
end
else
begin
S7; S8;
end
2.7 Modeling Flip-Flops Using Always Block 81
FIGURE 2-21: J-K Flip-Flop QN Q

RN JKFF SN

K CLK J

equivalent using else ifs. In this example, C1, C2, and C3 represent conditions
that can be true or false, and S1, S2, . . . , S8 represent sequential statements. If more
than one statement needs to be in an if block, begin and end should be used.
Next, we will write a Verilog module for a J-K flip-flop (Figure 2-21). This flip-flop
has active-low asynchronous preset (SN) and clear (RN) inputs. State changes
related to J and K occur on the falling edge of the clock. In this chapter, we use
a suffix N to indicate an active-low (negative-logic) signal. For simplicity, we will
assume that the condition SN 5 RN 5 0 does not occur.
The Verilog code for the J-K flip-flop is given in Figure 2-22. The input and output
signals are listed after the module statement. We define a reg Qint as an internal signal
that represents the state of the flip-flop internal to the module. The two concurrent
statements, statement4 and statement5, transmit this internal signal to the Q and QN
outputs of the flip-flop. Because the flip-flop can change state in response to changes
in SN, RN, and CLK, these three signals are in the sensitivity list of the always state-
ment. Both RN and SN are active low signals. If RN 5 0, the flip-flop is reset, and if
SN 5 0, the flip-slop is set. Since RN and SN, reset and set the flip-flop independently
of the clock, they are tested first. If RN and SN are both 1, we test for the falling
edge of the clock. In the if statement, both (~RN) and (RN 55 1’b0) are acceptable.

FIGURE 2-22: J-K Flip-Flop Model

module JKFF (SN, RN, J, K, CLK, Q, QN);


input SN, RN, J, K, CLK;
output Q, QN;
reg Qint;
always @(negedge CLK or RN or SN)
begin
if (~RN)
#8 Qint <= 0; // statement1
else if (~SN)
#8 Qint <= 1; // statement2
else
Qint <= #10 ((J && ~Qint) || (~K && Qint)); // statement3
end
assign Q = Qint; // statement4
assign QN = ~Qint; // statement5
endmodule
82 Chapter 2 Introduction to Verilog

The condition (negedge CLK) is TRUE only if CLK has just changed from 1 to 0.
The next state of the flip-flop is determined by its characteristic equation:
Q1 5 JQ9 1 K9Q
The 8 ns delay represents the time it takes to set or clear the flip-flop output after
SN or RN changes to 0. The 10 ns delay represents the time it takes for Q to change
after the falling edge of the clock.

2.8 Always Blocks Using Event Control


Statements
An alternative form for an always block uses wait or event control statements instead
of a sensitivity list. If a sensitivity list is omitted at the always keyword, delays or time-
controlled events must be specified inside the always block. For example,
always
begin
#10 clk <= ~clk;
end

will work as long as non-zero delay is specified.


An always block cannot have both wait statements and a sensitivity list. An
always block with wait statements may have the form

always
begin
sequential-statements
wait-statement
sequential-statements
wait-statement
. . .
end

Such an always block could look like

always
begin
rst = 1; // sequential statements
@(posedge CLK); //wait until posedge CLK
// more sequential statements
end

This always block will execute the sequential-statements until a wait (event
control) statement is encountered. Then it will wait until the specified condition is
satisfied. It will then execute the next set of sequential-statements until another
wait is encountered. It will continue in this manner until the end of the always block
is reached. Then it will start over again at the beginning of the block.
2.8 Always Blocks Using Event Control Statements 83
The wait statement is used as a level-sensitive event control. The general syntax
of the wait statement is

wait (Boolean-expression)

A procedural statement waits when the Boolean expression is FALSE. When


the expression is TRUE, the statement is executed. The logic values 0, ‘x’, and ‘z’
are treated as FALSE. Logic 1 is TRUE. The following example will block the
flow of the procedural block when the condition of the wait statement is FALSE.
The wait statement can also be used to handshake or synchronize two concurrent
processes, as illustrated in the following sequence:

always
begin
wait (WR)
MEM = DATA_IN;
wait (~WR)
DATA_OUT = MEM;
end

When the WR signal becomes true, DATA_IN gets written into MEM but as
soon as the WR signal becomes false, the MEM value becomes available on
DATA_OUT.

For a half adder, sum and carry can be found using the equations sum = x XOR y ; carry = x
Example AND y. What is wrong with the following code for a half adder that must add if add signal
equals 1?

always @(*)
begin
if (add == 1)
   sum = x ^ y;
   carry = x & y;
end

(a) It will compile but not simulate correctly


(b) It will compile and simulate correctly but not synthesize correctly
(c) It will work correctly in simulation and synthesis
(d) It will not even compile

Answer: (a). This code will compile but will not simulate correctly. The if statement is missing
begin and end. Currently only the sum is part of the if statement. The carry statement will
get executed regardless of the add signal. This can be corrected by adding begin and end for
the if statement. That will result in correct simulation. It can still lead to latches in synthesis.
Latches can be avoided by adding else clause or by initializing sum and carry to 0 at the
beginning of the always statement.
84 Chapter 2 Introduction to Verilog

What is wrong with the following code for a half adder that must add if add signal equals 1?
Example
always @(*)
begin
if (add == 1)
   sum = x ^ y;
   carry = x & y;
else
   sum = 0;
   carry = 0;
end

(a) It will compile but not simulate correctly


(b) It will compile and simulate correctly but not synthesize correctly
(c) It will work correctly in simulation and synthesis
(d) It will not even compile

Answer: (d). This code will not even compile due to the missing begin and end inside the if
statement. When the compiler gets to the else, it finds that the corresponding if statement is
missing. Both if and else clauses need begin and end. Once that is corrected, both simulation
and synthesis will work correctly.

2.9 Delays in Verilog


In one of the initial examples in this chapter, we used the statement
assign #5 D = A && B;

to model an AND gate with a propagation delay of 5 ns (assuming its time unit is
ns). The foregoing statement will model the AND gate’s delay; however, it also
introduces some complication, which many readers will not normally expect. If you
simulate this AND gate with inputs that change very often in comparison to the gate
delay (e.g., at 1 ns, 2 ns, 3 ns, etc.), the simulation output will not show the changes.
This is due to the way Verilog delays work.
Basically, delays in Verilog can be categorized into two models: inertial delay
and transport delay. The inertial delay for combinational blocks can be expressed
in the following three ways:

// explicit continuous assignment


wire D;
assign #5 D = A && B;

// implicit continuous assignment


wire #5 D = A && B;

// net declaration
wire #5 D;
assign D = A && B;
2.9 Delays in Verilog 85
Any changes in A and B will result in a delay of 5 ns before the change in output
is visible. If values in A or B are changed 5 ns before the evaluation of D output, the
change in values will be propagated. However, an input pulse that is shorter than
the delay of the assignment does not propagate to the output. This feature is called
inertial delay. Inertial delay is intended to model gates and other devices that do not
propagate short pulses from the input to the output. If a gate has an ideal inertial
delay T, in addition to delaying the input signals by time T, any pulse with a width
less than T is rejected. For example, if a gate has an inertial delay of 5 ns, a pulse
of width 5 ns would pass through, but a pulse of width 4.999 ns would be rejected.
Transport delay is intended to model the delay introduced by wiring; it simply
delays an input signal by the specified delay time. In order to model this delay, a
delay value must be specified on the right-hand side of the statement. Figure 2-23
illustrates transport delay and inertial delay in Verilog. Consider the following code:

always @ (X)
begin
Z1 <= #10 (X);    // transport delay
end
assign #10 Z2 = X;  // inertial delay

FIGURE 2-23: Inertial and 10ns 3ns 5ns


Transport Delays
10ns
X
2ns

Z1
X X X XX XX

Z2
X X X XX X X

0 10 20 30 40 50

The first statement has transport delay while the second one has inertial delay.
As shown in Figure 2-23, if the delay is shorter than 10 ns, the input signal will not
be propagated to the output in the second statement. Only one pulse (between
10 ns and 20 ns) on input X is propagated to the output Z2, since it has 10 ns pulse
width. All other pulses are not propagated to the output Z2. But Z1 has transport
delay and hence propagates all pulses. It is assumed that the output Z1 and Z2
are initialized to 0 at 0 ns. The delay in the statement Z1 <= #10 X; is called
intra-assignment delay. The expression on the right hand side is evaluated but
not assigned to Z1 until the delay has elapsed (also called delayed assignment).
However, in a statement like #10 Z1 <= X; the delay of #10 elapses first and then
the expression is evaluated and assigned to Z1 (also called delayed evaluation).
The placement of the delay on the right-hand side cannot be done with contin-
uous assign statements. Hence the following statement is illegal. It will produce a
compile-time error.
86 Chapter 2 Introduction to Verilog

assign a = #10 b;

Verilog also has a type of delay called net delay. Consider the code

wire C1;
wire #10 C2; // net delay on wire C2

assign #30 C1 = A || B; // statement 1 – inertial delay


assign #20 C2 = A || B; // 
statement 2 – inertial delay
will be
// added to net delay before being
// assigned to wire C2

The wire C2 has a net delay of 10 ns associated with it, specified in its declara-
tion whereas C1 has no such net delay. Net delay refers to the time it takes from
any driver on the net to change value to the time when the net value is updated
and propagated further. There are inertial delays of 30 ns for C1 in statement 1 and
20 ns for C2 in statement 2, typically representative of gate delays. After statement
2 processes its delay of 20 ns, the net delay of 10 ns is added to it. Figure 2-24(a)
indicates the difference between C1 and C2. C1 rejects all narrow pulses less than
30 ns, whereas C2 rejects only pulses less than 20 units.

FIGURE 2-24: Example of 3ns 20ns 30ns


Net Delays
A

B
30ns
C1
XXXXXXXXXXXXXXXXXXXXXXXXXXXX
60ns
C2
XXXXXXXXXXXXXXXX

0 10 20 30 40 60 70 80 100
(a)

10ns 3ns 5ns

10ns
Y
2ns

D
XXXXXXX

E
XXXXXXX

0 10 20 30 40 50
(b)
2.10 Compilation, Simulation, and Synthesis of Verilog Code 87
Now consider the following two statement pairs with the Y waveform as shown
in Figure 2-24(b).
wire #3 D; // net delay on wire D
assign #7 D 5 Y; // statement 1 – inertial delay

wire #7 E; // net delay on wire E


assign #3 E 5 Y; // statement 1 – inertial delay

The assign statement for D works with a 7 ns inertial delay and rejects any
pulse below 7 ns. Hence D rejects the 3 ns, 2 ns and 5 ns pulses in Y. The 3 ns net
delay from the wire statement is added to the signal that comes out from the assign
statement. In the case of E, pulses below 3 ns are rejected. Hence the 3 ns pulse in
Y passes through the assign statement for E, the 2 ns pulse is rejected and the 5 ns
pulse is accepted. Hence the 3 ns and 5 ns pulses get combined in the absence of the
2 ns pulse to yield output on E appears as a big 10 ns pulse. The 7 ns net delay from
the wire statement is added to the signal that comes out from the assign statement.
If any pulses less than 7 ns are encountered at the net delay phase, they will be
rejected. Figure 2-24(b) illustrates the waveforms for D and E.
Note that these delays are relevant only for simulation. Understanding how iner-
tial delay works can remove a lot of frustration in your initial experience with Verilog
simulation. The pulse rejection associated with inertial delay can inhibit many output
changes. In simulations with basic gates and simple circuits, one should make sure that
test sequences that you apply are wider than the inertial delays of the modeled devices.
The focus of this book is synthesizeable Verilog where all specified delays are ignored.
Hence we do not further dwell on simulator behavior for delays.

2.10 Compilation, Simulation, and Synthesis


of Verilog Code
After describing a digital system in Verilog, simulation of the Verilog code is impor-
tant for two reasons. First, we need to verify that the Verilog code correctly imple-
ments the intended design, and second, we need to verify that the design meets its
specifications. We first simulate the design and then synthesize it to the target tech-
nology (FPGA or custom ASIC). In this section, first we describe steps in simulation
and then introduce synthesis. As illustrated in Figure 2-25, there are three phases in
the simulation of Verilog code: analysis (compilation), elaboration, and simulation.

FIGURE 2-25: Compilation, Resource Simulator


Elaboration, and libraries commands
Simulation of Verilog
Code
VHDL
Compiler Intermediate Working Simulation
source Elaborator Simulator
(analyzer) library
code code Data
structure
Simulator
output
88 Chapter 2 Introduction to Verilog

Before the Verilog model of a digital system can be simulated, the Verilog code
must first be compiled. The Verilog compiler, also called an analyzer, first checks
the Verilog source code to see that it conforms to the syntax and semantic rules of
Verilog. If there is a syntax error, such as a missing semicolon, or if there is a seman-
tic error, such as trying to add two signals of incompatible types, the compiler will
output an error message. The compiler also checks to see that references to libraries
are correct. If the Verilog code conforms to all of the rules, the compiler generates
intermediate code, which can be used by a simulator or by a synthesizer.
After a Verilog design has been parsed but before simulation begins, the design
must have the modules being instantiated linked to the modules being defined, the
parameters propagated among the various modules, and hierarchical references
resolved. This phase in understanding a Verilog description is referred to as elabo-
ration. During elaboration, a driver is created for each signal. Each driver holds the
current value of a signal and a queue of future signal values. Each time a signal is
scheduled to change in the future, the new value is placed in the queue along with
the time at which the change is scheduled. In addition, memory storage is allocated
for the required signals; the interconnections among the port signals are ­specified;
and a mechanism is established for executing the Verilog statements in the proper
sequence. The resulting data structure represents the digital system being s­ imulated.
The simulation process consists of an initialization phase and actual simulation.
The simulator accepts simulation commands, which control the simulation of the
digital system and which specify the desired simulator output. Verilog simulation
uses what is known as discrete event simulation. The passage of time is simulated in
discrete steps in this method of simulation. The initialization phase is used to give an
initial value to the signal. To facilitate correct initialization, the initial value can be
specified in the Verilog model. In the absence of any specifications of the initial val-
ues, some simulator packages may assign an initial value depending on the type of the
signal. Please note that this initialization is only for simulation and not for synthesis.
A design consists of connected threads of execution or processes. Processes are
objects that can be evaluated, that may have state, and that can respond to changes
on their inputs to produce outputs. Processes include modules, initial and always
procedural blocks, continuous assignments, procedural assignment statements, sys-
tem tasks, and so forth.
Every change in value of a net or variable in the circuit being simulated is con-
sidered an update event. Processes are sensitive to update events. When an update
event is executed, all the processes that are sensitive to that event are evaluated in an
arbitrary order. The evaluation of a process is also an event, known as an evaluation
event. The term simulation time is used to refer to the time value maintained by the
simulator to model the actual time it would take for the circuit being simulated.
Events can occur at different times. In order to keep track of the events and
to make sure they are processed in the correct order, the events are kept on an
event queue, ordered by simulation time. Putting an event on the queue is called
scheduling an event.
The Verilog event queue is logically segmented into five different regions:
i. Active event region: Events that occur at the current simulation time are in this
region. Events can be added to any of the five regions but can be removed only
2.10 Compilation, Simulation, and Synthesisof Verilog Code 89
from this region (i.e., the active region). Events can be processed in any order
from within this region. (This freedom to choose any active event for immedi-
ate processing is an essential source of non-determinism in the Verilog HDL.)
ii. Inactive event region: Events that occur at the current simulation time but that
shall be processed after all the active events are processed are in this region.
Blocking assignments with zero delays are in this region until they get moved
later to the active region.
iii. Non-blocking assign update region: Events that have been evaluated during
some previous simulation time but that shall be assigned at this simulation time
after all the active and inactive events are processed are in this region.
iv. Monitor event region: Events that shall be processed after all the active, inac-
tive, and non-blocking assign update events are processed are in this region.
These are the monitor events.
v. Future event region: Events that occur at some future simulation time are in
this region. These are the future events. Future events are divided into future
inactive events and future non-blocking assignment update events.
When each Verilog statement is processed, events are added to the various
queue regions according to the following convention for each type of statement:
i. Continuous assignment—evaluate RHS and add to active region as an active
update event.
ii. Procedural continuous assign—evaluate RHS and add to active region as an
update event.
iii. Blocking assignment with delay—compute RHS and put into future event
region for time after delay.
iv. Blocking assignment with no delay—compute RHS and put into inactive region
for current time.
v. Non-blocking assignment with no delay—compute RHS and schedule as
non-blocking assign update event for current time if zero delay.
vi. Non-blocking assignment with delay—compute RHS and schedule as non-
blocking assign update event for future time if zero delay.
vii. $monitor and $strobe system tasks—create monitor events for these system
tasks. (These events are continuously reenabled in every successive time step.)
The processing of all the active events is called a simulation cycle.
For each simulation time, the following actions are performed in order:
i. Process all active update events. (Whenever there is an active update event, the
corresponding object is modified and new events are added to the various event
queue regions for other processes sensitive to this update.)
ii. Then activate all inactive events for that time (and process them because now
they are active).
iii. Then activate all non-blocking assign update events and process them.
iv. Then activate all monitor events and process them.
v. Advance time to the next event time and repeat from step i.
All of these five steps happen at the same time, but the events occur in the order
active, inactive, non-blocking update, and monitor events.
90 Chapter 2 Introduction to Verilog

VHDL uses the concept of an infinitesimal delay called delta (∆) delay to
explicitly indicate the various update times within the same simulation time,
however the Verilog Language Reference Model (LRM) does not mention
delta delays. In the Verilog simulators we experimented with, there is a delta
delay indicated in non-blocking procedural assignments with zero delay, but
no delta delays were observed in blocking or continuous assign statements
with zero delay. However, implicitly the simulation uses the ordering between
the aforementioned 5 event queue regions to yield the correct ordering.
Blocking assignments with zero delay are in the inactive queue first, and hap-
pen after continuous assignments but no delta delay is shown to indicate the
delay. Non-determinism is usually avoided except that the freedom to choose
any active event for immediate processing from the active queue region con-
tributes to some non-determinism in the Verilog HDL.

Basically, the simulator works as follows with “,5”: whenever a component


input changes, the output is scheduled to change after the specified delay or after D
if no delay is specified. When all events for the current time have been processed,
simulated time is advanced to the next time at which an event is specified. When
time is advanced by a finite amount (1 ns for example), the D counter is reset and
simulation resumes. Real time does not advance again until all events associated
with the current simulation time have been processed.
If two non-blocking updates are made to the same variable in the same time
step, the second one dominates by the end of the time step. For example, in
Figure 2-26(a) events are added to the event queue in source code order because of

FIGURE 2-26: Illustration of Non-Determinism


The IEEE 1364 Standard Verilog Language
module determinate;
Reference Manual (LRM) [1] provides def-
reg a;
initions and interpretations for the various
initial a = 0; Verilog constructs, which all compliant simula-
always begin tors shall implement. However, there is a great
a <= #5 0; deal of choice in the definitions, and some
a <= #5 1; differences in the details of execution are to be
end expected between different simulators.
// The assigned value of a is deterministic Those who are accustomed to the elegant
// because of ordering from begin to end delta delay conventions in VHDL may be
endmodule disappointed with Verilog simulation out-
(a) puts. Verilog was created primarily with cir-
module nondeterminate; cuit synthesis in mind and Verilog simulation
reg a;
may not clearly indicate the precise ordering
initial a = 0;
of multiple events happening at the same
always a <= #5 0; simulation time. The IEEE 1364 Standard
always a <= #5 1; Verilog Language Reference Manual (LRM)
// The assigned value of a is non-deterministic does not even use the word ‘delta’ in it.
Endmodule
2.10 Compilation, Simulation, and Synthesisof Verilog Code 91
the begin . . . end, and the two updates are performed in source order as well. Hence,
the variable a will be assigned 0 first and then 1 in that order. There is no non-
determinism in this code. However, for the code in Figure 2-26(b), the two always
blocks are concurrent with respect to each other and there is no ordering between
them. Hence the assigned value of a is non-deterministic.

2.10.1 Simulation with Multiple Processes


(Initial or Always Blocks)
If a model contains more than one process, all processes execute concurrently with
other processes. If there are concurrent statements outside always statements, they
also execute concurrently. Statements inside of each always block execute sequen-
tially. A process takes no time to execute unless it has wait statements in it. As an
example of simulation of multiple processes, we trace execution of the Verilog code
shown in Figure 2-27.

FIGURE 2-27: Verilog Code to Illustrate Process Simulation

module twoprocess
reg A,B;
initial
begin
A = 0;
B = 0;
end
// process P1
always @(B)
begin
A <= 1;
A <= #5 0;
end
// process P2
always @(A)
begin
if (A)
B <= #10 ~B;
end

Figure 2-28 shows the drivers for the signals A and B as the simulation pro-
gresses. In the absence of an initial block, each driver would hold x, since this is
the default initial value for a signal. When simulation begins, initialization takes
place and each driver holds 0 since an initial block is included in the provided
code. Both always statements wait until a signal on the sensitivity list changes. With
the initial block here, the signal changes from initialization lead to the execution
of the always statements. In the absence of the initial block, one can force input
changes using simulation commands. When process P1 executes at zero time, two
changes in A are scheduled (A changes to 1 at time D and back to 0 at time 5
5 ns). Meanwhile, process P2 executes at zero time, but no change in B occurs since
92 Chapter 2 Introduction to Verilog

FIGURE 2-28: Signal Queued Current


Drivers for Simulation values value
Example

After initialization: 0@5 1@D 0 A

time = 0 0 B

Simulation step: 0@5 1 A

time = D 1 @ 10 0 B

0 A
time = 5
1 @ 10 0 B

0 @ 15 1 @ 10 + D 0 A
time = 10
1 B

0 @ 15 1 A
time = 10 + D
0 @ 20 1 B

0 A
time = 15
0 @ 20 1 B

A is still 0 during execution at time 0 ns. Time advances to D, and A changes to 1.


The change in A causes process P2 to execute, and since A 5 1, B is scheduled to
change to 1 at time 10 ns. The next scheduled change occurs at time 5 5 ns, when A
changes to 0. This change causes P2 to execute, but B does not change. B changes
to 1 at time 5 10 ns. The change in B causes P1 to execute, and two changes in A
are scheduled. When A changes to 1 at time 10 1 D, process P2 executes, and B is
scheduled to change at time 20 ns. Then A changes at time 15 ns, and the simulation
continues in this manner until the runtime limit is reached. It should be understood
that A changes at 15 ns and not at 15 1 D. The D delay comes into the picture only
when no time delay is specified.
Verilog simulators use event-driven simulation, as illustrated in the preceding
example. A change in a signal is referred to as an event. Each time an event occurs,
any processes that have been waiting on the event are executed in zero time, and any
resulting signal changes are queued up to occur at some future time. When all the active
processes are finished executing, simulation time is advanced to the time for which the
next event is scheduled, and the simulator processes that event. This continues until
either no more events have been scheduled or the simulation time limit is reached.
2.11 Verilog Data Types and Operators 93
Inertial delays can now be explained in the following manner. Each input
change causes the simulator to schedule a change, which is scheduled to occur after
the specified delay; however, if another input change happens before the specified
delay has elapsed, the first change is dequeued from the simulation driver queue.
Hence only pulses wider than the specified delay appear at the output.
One of the most important uses of Verilog is to synthesize or automatically
create hardware from a Verilog description. The synthesis software for Verilog
translates the Verilog code to a circuit description that specifies the needed compo-
nents and the connections between the components. The initial steps (analysis and
elaboration) in Figure 2-25 are common whether Verilog is used for simulation or
synthesis. The simulation and synthesis processes are shown in Figure 2-29.

FIGURE 2-29: Compilation, VHDL Simulator


Simulation, and Synthesis libraries commands
of Verilog Code
Intermediate
VHDL code
Compiler Simulator Simulator
code output

Synthesizer Implementer Hardware

Although synthesis can be done in parallel to simulation, practically it follows


simulation because designers would normally want to catch errors first before
attempting to synthesize. After the Verilog code for a digital system has been
simulated to verify that it works correctly, the Verilog code can be synthesized to
produce a list of required components and their interconnections, typically called
the netlist. The synthesizer output can then be used to implement the digital system
using specific hardware, such as a CPLD or an FPGA or as an ASIC. The CAD
software used for implementation generates the necessary information to program
the CPLD or FPGA hardware. Synthesis and implementation of digital logic from
Verilog code is discussed in more detail in Chapter 6.

2.11 Verilog Data Types and Operators


2.11.1 Data Types
Verilog has two main groups of data types: the variable data types and the net data
types. These two groups differ in the way that they are assigned and hold values.
They also represent different hardware structures.
The net data types can represent physical connections between structural enti-
ties, such as gates. Generally, it does not store values. Instead, its value is deter-
mined by the values of its drivers, such as a continuous assignment or a gate. A very
popular net data type is the wire. There are also several other predefined data types
94 Chapter 2 Introduction to Verilog

that are part of nets. Examples are tri (for tristate), wand (for wired and), wor (for
wired or).
The variable data type is an abstraction of a data storage element. A variable
shall store a value from one assignment to the next. An assignment statement in a
procedure acts as a trigger that changes the value in the data storage element. A very
popular variable data type is the reg. There are also several other predefined data
types that are part of variables. Examples are reg, time, integer, real, and real-time.
Unlike VHDL, all data types are predefined by the Verilog language and not by
the user. Some of the popular predefined types are

nets connections between hardware elements


(declared with keywords such as wire)
variables data storage elements that can retain values
(declared with the keywords such as reg)
integer an integer is a variable data type
(declared with the keyword integer)
real real number constants and real variable data types for fl ­ oating-point
number (declared with the keyword real)
time a special variable data type to store time information
(declared with the keyword time)
vectors wire or reg data types can be declared as vectors (multiple bits)
(vectors can be declared with [range1 : range2])
In previous versions of the Verilog standard, the term register was used to
encompass the reg, integer, time, real, and realtime types, but starting with the 2005
IEEE 1364Standard, that term is no longer used as a Verilog data type. A net or
reg declaration without a range specification shall be considered 1 bit wide and is
known as a scalar. Multiple bit net and reg data types shall be declared by specifying
a range, which is known as a vector.
While VHDL is a strongly typed language where signals and variables of differ-
ent types generally cannot be mixed in the same assignment statement, Verilog uses
weak typing, which means some mixing of related data types is allowed.

2.11.2 Verilog Operators


Verilog operators are similar to the operators used in C language. Predefined
Verilog operators can be grouped into several classes:
1. Unary sign and reduction operators:
12 Unary sign operators
&  Reduction and (unary operator to and bits in a vector and
reduce to one bit)
~& Reduction nand
| Reduction or (unary operator to or bits in a vector and reduce
to one bit)
~| Reduction nor
^ Reduction xor
2.11 Verilog Data Types and Operators 95
~^ or ^~ Reduction xnor
! Logical negation
~ Bit-wise negation
2. Arithmetic: Exponent

** Arithmetic (Power)
3. Arithmetic: Multiplying, Modulus operators:

* Multiply
/ Divide
% Modulus
4. Arithmetic: Addition:
1 Add
2 Subtract
5. Shift operators:
<< Logical left shift
>> Logical right shift
<<< Arithmetic left shift
>>> Arithmetic right shift
6. Relational operators:
> Greater than
< Less than
>5 Greater than or equal
<5 Less than or equal
7. Logical and bitwise operators: Equality and inequality
55 Logical equality
!5 Logical inequality
555 Case equality
!55 Case inequality
8. Bitwise operators:
& Bit-wise and (binary operator)
9. Logical and bitwise operators:
^ Bit-wise exclusive or (binary operator)
^~ or ~^ Bit-wise equivalence (binary operator)
| Bit-wise inclusive or (binary operator)
10. Logical and:
&& Logical and
11. Logical or:
|| Logical or
12. Conditional
?: Conditional
96 Chapter 2 Introduction to Verilog

13. Concatentation and replication


{} Concatenation
{{}} Replication
When parentheses are not used, operators in class 1 have highest precedence
and are applied first, followed by class 2, then class 3, and so forth. Class 13 oper-
ators have lowest precedence and are applied last, but if the expression with these
operators is needed in order to perform another higher-precedence operation, it
is evaluated before the other operator can be evaluated. Operators in the same
class have the same precedence and are applied from left to right in an expression.
The precedence order can be changed by using parentheses. The { } operator can
be used to concatenate two vectors (or an element and a vector, or two elements)
to form a longer vector. For example, {010, 1} is 0101 and {“ABC”, “DEF”} is
“ABCDEF”. Consider the following expression where A, B, C, and D are vectors:
({A, ~B} | C >> 2 & D) 55 110010

One must note that this is a relational expression performing an equality test; it
is not an assignment statement. To evaluate the expression inside ( ), the operator
precedence shows the highest precedence for the following three operators in order:
>>, &, |

In order to evaluate | , one of the operands of | has to be obtained by the con-


catentation, which forces the expression inside the concatenate to be evaluated and
operators ~, { }, are applied before the | can be evaluated.

A Note on Operator Precedence


Different languages have differences in the order of precedence and hence
those who program in many languages may write or interpret code errone-
ously, mixing the precedence between the different languages. Hence instead
of worrying too much about the precedence order, a good strategy is to use
parentheses and make code unambiguous.

If A 5 110, B 5 111, C 5 011000, and D 5 111011, the computation proceeds


as follows:
C >> 2 = 000110  (shift right 2
places)
C >> 2 & D = 000010 (bit-wise and)
~ B = 000 (bit-wise negate)
{A, ~ B} = 110000 (concatenation)
({A, ~ B}) | (C >> 2&D) = 110010 (bit-wise or)
[({A, ~ B} | C >> 2) & D) == 110010] = TRUE 
(the parentheses
force the equality)
test to be done
last and the
result is TRUE)
2.11 Verilog Data Types and Operators 97
The result of applying a relational operator is always a Boolean (FALSE
or TRUE). Equals (55) and not equals (!5) can be applied to almost any type.
The other relational operators can be applied to many numeric as well as to some
array types. For example, if A 5 5, B 5 4, and C 5 3, the expression (A >= B)
&& (B <= C) evaluates to FALSE. It is legal to use concatenate operator on the left
side of the assignment, For example,

{Carry, Sum} = A + B;

is legal. It adds A and B and the result goes into Sum and Carry. The most significant
bit of the result is assigned to Carry. For the logical equality and logical inequality
operators (55 and !5), if, due to unknown or high-impedance bits in the operands,
the relation is ambiguous, then the result shall be a 1-bit unknown value (x). For the
case equality and case inequality operators (555 and !55), bits that are x or z shall
be included in the comparison and shall match for the result to be considered equal.
The result of these operators shall always be a known value, either 1 or 0.
The shift operators can be applied to signed and unsigned registers. One can declare
a register to be signed in the following manner:
reg signed [7:0] A = 8'hA5; //signed register A

In contrast, the register would have been unsigned if declared as follows:


reg [7:0] B = 8'hA5; //unsigned register B

If the register is unsigned, arithmetic and logic shifts do the same operation. The
following example illustrates the difference between signed and unsigned shifts on
signed and unsigned data.
reg signed [7:0] A = 8'hA5; // A is signed 1010 0101

A >> 4 is 00001010 (shift right unsigned by 4, filled with 0).



A >>> 4 is 11111010 
(shift right signed by 4, filled with sign
bit).
A << 4 is 01010000 (shift left unsigned, filled with 0).
A <<< 4 is 01010000 
(shift left signed, filled with 0
irrespective of rightmost bit).

reg [7:0] B = 8'hA5; // B is unsigned 1010 0101


B >> 4 is 00001010  (shift right unsigned by 4, filled with 0)
B >>> 4 is 00001010 (shift right signed by 4, but B is unsigned,
filled with 0)
B << 4 is 01010000 (shift left unsigned, filled with 0)
B <<< 4 is 01010000 (shift left signed, filled with 0
irrespective of rightmost bit)

If A is declared as integer as in
integer signed A = 8'hA5;

A >>> 4 yields 00001010 (shift right signed by 4, but integer type is 32 bits and the pro-
vided number has only eight bits, which does not include the sign and hence sign bit is).
98 Chapter 2 Introduction to Verilog

But if A is initialized to 8'shA5 as in


integer A = 8'shA5;

A >>> 4 yields 11111010 (shift right signed by 4, A’s sign bit is 1). The 'sh indicates
that the value is signed hex.
However, in reg declarations, if a signed register is desired, it should be explic-
itly mentioned. For instance,
reg [7:0] A = 8'shA5

does not make the register signed. It should be declared as reg signed [7:0] A =
8'hA5
The 1 and 2 operators can be applied to any types, including integer or real
numeric operands. When types are mixed, the expression self-evaluates to a type
according to the types of the operands. If a and b are 16 bits each, (a 1 b) will evaluate
to 16 bits. However, (a 1 b 1 0) will evaluate to integer. If any operand is real, the result
is real. If any operand is unsigned, the result is unsigned, regardless of the operator.
When expressions are evaluated, if the operands are of unequal bit lengths and
if one or both operands are unsigned, the smaller operand shall be zero-extended to
the size of the larger operand. If both operands are signed, the smaller operand shall
be sign-extended to the size of the larger operand. If constants need to be extended,
signed constants are sign-extended and unsigned constants are zero-extended.
The * and / operators perform multiplication and division on integer or floating-
point operands. The ** operator raises an integer or floating-point number to an inte-
ger power. The % (modulus) operator calculates the remainder for integer operands.

According to the Verilog Language Reference Manual (LRM), the result of


the modulus operator takes the sign of the first operand. For example,
210 % 3
results in –1 because the result takes the sign of the first operand. However,
number theory books define mod m as a function from the set of integers to the
set of {0,1,2,….,m21) and hence −10 mod 3 is equal to 2. However, there is no
reason for serious concern because −1 mod 3 is 2 according to the mod m defi-
nition. Hence -1 as given by Verilog and 2 as given by their definition are in fact
the same number. VHDL has two separate operators, one for modulus and one
for remainder. The VHDL remainder is signed according to the sign of the first
operand whereas the modulus follows the mod m definition from number theory.

2.12 Simple Synthesis Examples


Synthesis tools try to infer the hardware components needed by “looking” at the
Verilog code. In order for code to synthesize correctly, certain conventions must be
followed. When writing Verilog code, you should always keep in mind that you are
2.12 Simple Synthesis Examples 99
designing hardware, not simply writing a computer program. Each Verilog state-
ment implies certain hardware requirements. Consequently, poorly written Verilog
code may result in poorly designed hardware. Even if Verilog code gives the correct
result when simulated, it may not result in hardware that works correctly when syn-
thesized. Timing problems may prevent the hardware from working properly even
though the simulation results are correct.
Consider the Verilog code in Figure 2-30. (Note that B is missing from the sen-
sitivity list in the always statement.) This code will simulate as follows. Whenever
A changes, it will cause the process to execute once. The value of C will reflect the
values of A and B when the process began. If B changes now, that will not cause
the process to execute.

FIGURE 2-30: Verilog Code Example Where Simulation and Synthesis Results in Different Outputs

module Q1 (A, B, C);


input A;
input B;
output C;

reg C;

always @(A)
C = #5 A | B;
endmodule

If this code is synthesized, most synthesizers will output an OR gate as in


Figure 2-31. The synthesizer will warn you that B is missing from the sensitivity
list in always statement, but will go ahead and synthesize the code properly. The
synthesizer will also ignore the 5 ns delay on the preceding statement. If you want
to model an exact 5 ns delay, you will have to use counters. The simulator output
will not match the synthesizer’s output since the always statement will not execute
when B changes. This is an example of where the synthesizer guessed a little more
than what you wrote; it assumed that you probably meant an OR gate and created
that circuit (accompanied by a warning). But this circuit functions differently from
what was simulated before synthesis. It is important that you always check for syn-
thesizer warnings of missing signals in the sensitivity list. Perhaps the synthesizer
helped you; perhaps it created hardware that you did not intend to.

FIGURE 2-31: Synthesize B


Output for Code in C
Figure 2-30 A
OR2

Now, consider the Verilog code in Figure 2-32. What hardware will you get if
you synthesized this code?
Let us think about the block diagram of the circuit represented by this code
without worrying about the details inside. The block diagram is as shown in
100 Chapter 2 Introduction to Verilog

FIGURE 2-32: Example Verilog Code

module Q3 (A, B, F, CLK, G);


input A;
input B;
input F;
input CLK;
output G;
reg G;
reg C;
always @(posedge CLK)
begin
C <= A & B; // statement 1
G <= C | F; // statement 2
end
endmodule

Figure 2-33. The ability to hide details and use abstractions is an important part of
good system design.

FIGURE 2-33: Block


Diagram for Verilog A G
Code in Figure 2-32 B

CLK

Note that C is an internal signal, and therefore, it does not show up in the block
diagram.
Now, let us think about the details of the circuit inside this block. This circuit is
not two cascaded gates; the signal assignment statements are in a process (an always
statement). An edge-triggered clock is implied by the use of posedge or negedge
in the clock statement preceding the signal assignment. Since the values of C and G
need to be retained after the clock edge, flip-flops are required for both C and G.
Please note that a change in the value of C from statement 1 will not be considered
during the execution of statement 2 in that pass of the process. It will be considered
only in the next pass, and the flip-flop for C makes this happen in the hardware also.
Hence the code implies hardware shown in Figure 2-34.

FIGURE 2-34: Hardware DFF


Corresponding to Verilog F
D Q G
Code in Figure 2-32 DFF
A Q
D
B C
CLK
2.12 Simple Synthesis Examples 101
We saw earlier that the following code represents a D-latch:

always @(G or D)
begin
if (G) Q <= D;
end

Let us understand why this code does not represent an AND gate with G and D
as inputs. If G 5 1, an AND gate will result in the correct output to match the if
statement. However, what happens if currently Q 5 1 and then G changes to 0?
When G changes to 0’, an AND gate would propagate that to the output; however,
the device we have modeled here should not. It is expected to make no changes to
the output if G is not equal to 1. Hence, it is clear that this device has to be a D-latch
and not an AND gate.
In order to infer flip-flops or registers that change state on the rising edge of a
clock signal, most synthesizers require that the sensitivity list in an always statement
should include an edge-triggered signal as in

always @(posedge CLK)

For every assignment statement in an always statement, a signal on the left side
of the assignment will cause creation of a register or flip-flop. The moral to this
story is that if you do not want to create unnecessary flip-flops, do not put the signal
assignments in a clocked always statement. If clock is omitted in the sensitivity list
of an always statement, the synthesizer may produce latches instead of flip-flops.
Now consider the Verilog code in Figure 2-35. If you attempt to synthesize this
code, the synthesizer will generate an empty block diagram. This is because D, the
output of the block shown in the Figure, is never assigned. The code assigns the
new value to C, which is never brought out to the outside world. It will generate
warnings that

Input <CLK> is never used.


Input <A> is never used.
Input <B> is never used.
Output <D> is never assigned.

FIGURE 2-35: Example Verilog Code That Will Not Synthesize

module no_syn (A, B, CLK, D);


input A;
input B;
input CLK;
output D;
reg C;
always @(posedge CLK)
C <= A & B;
endmodule
102 Chapter 2 Introduction to Verilog

2.13 Verilog Models for Multiplexers


A multiplexer is a combinational circuit and can be modeled using concurrent
statements only or using always statements. A conditional operator with assign
statement can be used to model a multiplexer without always statements. A case
statement or if-else statement can also be used to make a model for a multiplexer
within an always statement.

2.13.1 Using Conditional Operator


Figure 2-36 shows a 2-to-1 multiplexer (MUX) with 2 data inputs and one control
input. The MUX output is F 5 A9 ? I0 1 A ? I1. The corresponding Verilog statement is

assign F = (~A && I0) || (A && I1);

Here, the MUX can be modeled as a single concurrent signal assignment state-
ment. Alternatively, we can represent the MUX by a conditional signal assignment
statement as shown in Figure 2-36. This statement executes whenever A, I0, or I1
changes. The MUX output is I0 when A 5 0; otherwise it is I1. In the conditional
statement, I0, I1, and F can be one or more bits.

FIGURE 2-36: 2-to-1


Multiplexer // conditional signal assignment
I0 0
statement
F   assign F = (A) ? I1 : I0;
I1 1

The general form of a conditional signal assignment statement is

assign signal_name = condition ? expression_T : expression_F;

This concurrent statement is executed whenever a change occurs in a signal used


in one of the expressions or conditions. If condition is true, signal_name is set
equal to the value of expression_T. Otherwise if condition is false, signal_name
is set equal to the value of expression_F. Figure 2-37 shows how two cascaded
MUXes can be represented by a conditional signal assignment statement. The

FIGURE 2-37: Cascaded


C 0
2-to-1 MUXes Using assign F = E ? A : ( D ? B : C );
Conditional Assignment 0
// nested conditional assignment
B 1 F
A 1
D
E
2.13 Verilog Models for Multiplexers 103
output MUX selects A when the condition E is true; otherwise, it selects the output
of the first MUX, which is B when the condition D is true, or it is C.
Figure 2-38 shows a 4-to-1 multiplexer (MUX) with four data inputs and two
control inputs, A and B. The control inputs select which one of the data inputs is
transmitted to the output. The logic equation for the 4-to-1 MUX is

F 5 A9B9I0 1 A9B I1 1 A B9I2 1 A B I3

One way to model the MUX is with the Verilog statement

assign F = (~A && ~B && I0) || (~A && B && I1) ||


   
A && ~B && I2) || (A && B && I3);

Another way to model the 4-to-1 MUX is to use a conditional assignment statement:

assign F = (A) ? (B ? I3 : I2) : ( B ? I1 : I0 );

FIGURE 2-38: 4-to-1


Multiplexer I0

I1
MUX F
I2

I3

A B

2.13.2 Using If-else or Case Statement in an Always Block


If a MUX model is used inside an always statement, a concurrent statement cannot
be used. The MUX can be modeled using a case statement within an always block:
always @ (Sel or I0 or I1 or I2 or I3)
case Sel
2'b00 : F 5 I0;
2'b01 : F 5 I1;
2'b10 : F 5 I2;
2'b11 : F 5 I3;
endcase

Since this MUX has four input signals, the selection signal, Sel should be a 2-bit
signal. The selection signals are represented as 2'b00, 2'b01, 2'b10, and 2'b11
in the form of <number of bits>'<base><value>. The b represents that the base
is binary here. The case statement has the general form:
case expression
choice1 : sequential statements1
choice2 : sequential statements2
. . .
[default : sequential statements]
endcase;
104 Chapter 2 Introduction to Verilog

The expression is evaluated first. If it is equal to choice1, then sequential


statements1 are executed; if it is equal to choice2, then sequential state-
ments2 are executed; and so forth. All possible values of the expression must be
included in the choices. If all values are not explicitly given, a default clause is
required in the case statement. As an alternative, the MUX can also be modeled
using an if-else statement within an always block:
always @ (Sel or I0 or I1 or I2 or I3)
begin
if (Sel == 2'b00) F = I0;
else if (Sel == 2'b01) F = I1;
else if (Sel == 2'b10) F = I2;
else if (Sel == 2'b11) F = I3;
end

One might notice that combinational circuits can be described using concurrent or
sequential statements. Sequential circuits generally require an always statement.
Always statements can be used to make sequential or combinational circuits.
The following are important coding practices while writing synthesizeable
Verilog for combinational hardware:
(a) If possible use concurrent assignments (e.g., assign) to design combina-
tional logic.
(b) When procedural assignments (always blocks) are used for combinational
logic, use blocking assignments (e.g., “5”).
(c) If Verilog 2001 or later is used, instead of specifying contents of sensitivity
lists, use always@* to avoid accidental omission of inputs from sensitivity lists.
The accidental omission results in incorrect hardware or deviation between
simulation and synthesis.

2.14 Modeling Registers and Counters Using


Verilog Always Statements
When several flip-flops change state on the same clock edge, statements represent-
ing these flip-flops can be placed in the same clocked always statements. Figure 2-39
shows three flip-flops connected as a cyclic shift register (or a rotating shift register).
These flip-flops all change state following the rising edge of the clock. We have
assumed a 5 ns propagation delay between the clock edge and the output change.
Immediately following the clock edge, the three statements in the always statement
execute in sequence with no delay. The new values of the Qs are then scheduled to
change after 5 ns. If we omit the delay and replace the sequential statements with

Q1 <= Q3;   Q2 <= Q1;   Q3 <= Q2;

the operation is basically the same. The three statements execute in sequence in
zero time, and then the Qs values change after a delta delay. In both cases, the old
values of Q1, Q2, and Q3 are used to compute the new values. This may seem strange
2.14 Modeling Registers and Counters Using Verilog Always Statements 105
FIGURE 2-39: Cyclic Shift
Register D Q1 always @ (posedge CLK)
CLK
begin
Q1 <= #5 Q3;
Q2 <= #5 Q1;
D Q2 Q3 <= #5 Q2;
end

D Q3

at first, but that is the way the hardware works. At the rising edge of the clock, all
of the D inputs are loaded into the flip-flops, but the state change does not occur
until after a propagation delay.
The order of the statements is not important when the non-blocking assignment
operator “,5” is used. The same result is obtained even if the statements are in
reverse order as shown here.

always @ (posedge CLK)


begin
Q3 <= #5 Q2;
Q2 <= #5 Q1;
Q1 <= #5 Q3;
end

What is the hardware obtained if the following code is synthesized?


Example 1
module reg3 (Q1,Q2,Q3,A,CLK);
input A;
input CLK;
output Q1,Q2,Q3;
reg Q1,Q2,Q3;
always @(posedge CLK)
begin
Q3 = Q2; // statement 1
Q2 = Q1; // statement 2
Q1 = A; // statement 3
end
endmodule

Answer: A 3-bit shift register

Explanation: The list of statements executes from top to bottom in order. Note that the
blocking operator is used. Therefore, the first statement finishes update before the second
106 Chapter 2 Introduction to Verilog

statement is executed. Synthesis results in a 3-bit shift register with serial input A, and out-
puts Q1, Q2, and Q3.

Note: While a register can be modeled using the blocking operator “5” as in this example,
it is generally advised to not do so. As mentioned previously, a good coding practice while
writing synthesizeable code is to use non-blocking assignments (i.e., “<5”) in always blocks
intended to create sequential logic, and the blocking operator “5” in always blocks intended
to create combinational logic.

What is the hardware obtained if the following code is synthesized? Note that this is the same
Example 2 code as in the previous example, but with the statement order inside the always block reversed.

module reg31 (Q1,Q2,Q3,A,CLK);


input A;
input CLK;
output Q1,Q2,Q3;
reg Q1,Q2,Q3;
always @(posedge CLK)
begin
Q1 5 A; // statement 1
Q2 5 Q1; // statement 2
Q3 5 Q2; // statement 3
end
endmodule

Answer: A single flip-flop

Explanation: The list of statements executes from top to bottom in order. Note that the
blocking operator is used. So the first statement finishes update before the second statement
is executed. Q1 gets the value of the serial input A when statement 1 finishes. In statement 2,
the same value propagates to Q2. In statement 3, the same value propagates to Q3. In effect,
the input A has reached Q3. Modern synthesis tools will generate a single flip-flop with input
A when this code is synthesized. The outputs Q1, Q2, and Q3 can all be connected to the
output of the same flip-flop. If the synthesizer does not have good optimization algorithms,
it might generate three parallel flip-flops, each with the same input A but with outputs Q1,
Q2, and Q3, respectively. As mentioned in the Note to Example 1, it is not a good practice
to use the blocking operator “5” in always blocks intended to create sequential logic. If one
were to use non-blocking statements, the order of the statements would not have mattered.

Figure 2-40 shows a simple register that can be loaded or cleared on the rising
edge of the clock. If CLR is set to 1, the register is cleared, and if Ld 5 1, the D
inputs are loaded into the register. This register is fully synchronous so that the Q
outputs change only in response to the clock edge and not in response to a change
in Ld or CLR. In the Verilog code for the register, Q and D are 4-bit vectors
2.14 Modeling Registers and Counters Using Verilog Always Statements 107
dimensioned [3:>]. Since the register outputs can only change on the rising edge of
the clock, CLR and Ld are not on the sensitivity list. The CLR and Ld signals are
tested after the rising edge of the clock. If CLR 5 Ld 5 0, no change of Q occurs.
Since CLR is tested before Ld, if CLR 5 1, the else if prevents Ld from being
tested and CLR overrides Ld.

FIGURE 2-40: Register


with Synchronous Clear Q3 Q2 Q1 Q0 always @ (posedge CLK)
and Load Ld begin
CLR if (CLR) Q <= 4'b0000;
Register else if (Ld)   
Q <= D;
end
D3 D2 D1 D0 CLK

Next, we will model a left shift register using a Verilog always statement. The
register in Figure 2-40 is similar to that in Figure 2-41, except that we have added
a left shift control input (LS). When LS is 1, the contents of the register are shifted
left and the right-most bit is set equal to Rin. The shifting is accomplished by taking
the rightmost 3 bits of Q, Q[2:0], and concatenating them with Rin. For example, if
Q 5 1101 and Rin 5 0, then {Q[2:0], Rin} 5 1010, and this value is loaded back into
the Q register on the rising edge of CLK. The code implies that if CLR 5 Ld 5 LS 5 0,
then Q remains unchanged.

FIGURE 2-41: Left


Shift Register with Q3 Q2 Q1 Q0 always @ (posedge CLK)
Synchronous Clear and Ld
LS
begin
Load if (CLR)     
Q <= 4'b0000;
CLR Left SR Rin
else if (Ld) Q <= D;
CLK D3 D2 D1 D0 else if (LS)       
Q <= {Q[2:0], Rin};
end

Figure 2-42 shows a simple synchronous counter. On the rising edge of the clock,
the counter is cleared when ClrN 5 , and it is incremented when ClrN 5 En 5 1. In
this example, the signal Q represents the 4-bit value stored in the counter. The signal

FIGURE 2-42: Verilog Q


Code for a Simple reg Q[3:0];
Synchronous Counter
Q3 Q2 Q1 Q0 always @ (posedge CLK)
En begin
CLR ClrN
if (~ClrN) Q <= 4'b0000;
Counter else if (En) Q <= Q + 1;
end
CLK
108 Chapter 2 Introduction to Verilog

Q is declared to be of type reg with length of 4 bits. Then the statement Q <= Q+1;
increments the counter. When the counter is in state 1111, the next increment takes
it back to state 0000.
Now, let us create a Verilog model for a standard MSI counter, the 74163. It is a
4-bit fully synchronous binary counter, which is available in both TTL and CMOS
logic families. Although rarely used in new designs at present, it represents a gen-
eral type of counter that is found in many CAD libraries. In addition to performing
the counting function, it can be cleared or loaded in parallel. All operations are
synchronized by the clock, and all state changes take place following the rising
edge of the clock input. A block diagram of the counter is provided in Figure 2-43.

FIGURE 2-43: 74163


Counter Operation
Cout Q3 Q2 Q1 Q0 P
P
T T
74163
Ld LdN
D3 D2 D1 D0 Clr ClrN

Clk

Control Signals Next State


ClrN LdN PT Q3+ Q2+ Q1+ Q0+
0 X X 0 0 0 0 (clear)
1 0 X D3 D2 D1 D0 (parallel load)
1 1 0 Q3 Q2 Q1 Q0 (no change)
1 1 1 present state + 1 (increment count)

This counter has four control inputs—ClrN, LdN, P, and T. Both P and T are
used to enable the counting function. While P is an actual enable signal to the 4-bit
generic counter, T is used for a carry connection signal when cascading multiple
counters. Operation of the counter is as follows:
1. If ClrN 5 0, all flip-flops are set to 0 following the rising clock edge.
2. If ClrN 5 1 and LdN 5 0, the D inputs are transferred (loaded) in parallel
to the flip-flops following the rising clock edge.
3. If ClrN 5 LdN 5 1 and P 5 T 5 1, the count is enabled and the counter state
will be incremented by 1 following the rising clock edge.
If T 5 1, the counter generates a carry (Cout) in state 15; consequently
Cout 5 Q3 Q2 Q1 Q0 T
The truth table in Figure 2-43 summarizes the operation of the counter. Note
that ClrN overrides the load and count functions in the sense that when ClrN 5 0,
clearing occurs regardless of the values of LdN, P, and T. Similarly LdN overrides
the count function. The ClrN input on the 74163 is referred to as a synchronous
clear input because it clears the counter in synchronization with the clock, and no
clearing can occur if no clock pulse is present.
2.14 Modeling Registers and Counters Using Verilog Always Statements 109
The Verilog description of the counter is shown in Figure 2-44. Q represents
the four flip-flops that comprise the counter. The counter output, Qout, changes
whenever Q changes. The carry output is computed whenever Q or T changes.
The always statement will be executed only at the rising edge of Clk. Since clear
overrides load and count, the first if statement tests ClrN first. Since load over-
rides count, LdN is tested next. Finally, the counter is incremented if both P and
T are 1.

FIGURE 2-44: 74163 Counter Model

// 74163 FULLY SYNCHRONOUS COUNTER


module c74163(LdN, ClrN, P, T, Clk, D, Cout, Qout);
input LdN;
input ClrN;
input P;
input T;
input Clk;
input [3:0]    D;
output Cout;
output [3:0]   Qout;
reg [3:0] Q;
assign Qout = Q;
assign Cout = Q[3] & Q[2] & Q[1] & Q[0] & T;
always @(posedge Clk)
begin
if (~ClrN) Q <= 4'b0000;
else if (~LdN) Q <= D;
else if (P & T) Q <= Q 1 1;
end
endmodule

To test the counter, we have cascaded two 74163s to form an 8-bit c­ounter
(Figure 2-45). When the counter on the right is in state 1111 and T1 5 1,
Carry1 5 1. Then for the left counter, PT 5 1 if P 5 1. If PT 5 1, on the next
clock the right counter is incremented to 0000 at the same time the left counter

FIGURE 2-45: Two 74163 Qout2 Qout1


Counters Cascaded to
Form an 8-Bit Counter
Q3 Q2 Q1 Q0 P P Q3 Q2 Q1 Q0 P P
Carry2 Carry1
Cout T Cout T T1
74163 74163
Ld LdN Ld LdN
D3 D2 D1 D0 Clr ClrN D3 D2 D1 D0 Clr ClrN

Din2 Din1
Clk
110 Chapter 2 Introduction to Verilog

FIGURE 2-46: Verilog for 8-Bit Counter Using 4-Bit Counter Modules

// 8-Bit counter using two 74163 counters using the model in Fig 2-44
module eight_bit_counter(ClrN, LdN, P, T1, Clk, Din1, Din2, Count, Carry2);
input ClrN;
input LdN;
input P;
input T1;
input Clk;
input [3:0] Din1;
input [3:0] Din2;
output [7:0]   Count;
output Carry2;
wire Carry1;
wire [3:0]    
Qout1;
wire [3:0]    
Qout2;
c74163 ct1(LdN, ClrN, P, T1, Clk, Din1, Carry1, Qout1); // instance 1 (right)
c74163 ct2(LdN, ClrN, P, Carry1, Clk, Din2, Carry2, Qout2); //instance 2 (left)
assign Count 5 {Qout2, Qout1};
endmodule

is incremented. Figure 2-46 shows the Verilog code for the 8-bit counter. In this
code we have used the c74163 model from Figure 2-44 as a component and have
instantiated two copies of it. The module c74163 should be available for the module
eight_bit_counter by defining it in same file or another file. The instantiation for the
lower four bits is done using the statement

c74163 ct1(LdN, ClrN, P, T1, Clk, Din1, Carry1, Qout1);

where c74163 is the previously defined component’s module name and ct1 is the
instance name. The inputs and outputs are mapped to Din1 and Qout1 and other
control signals. VHDL uses a port-map keyword to accomplish this kind of instan-
tiation whereas in Verilog, no keyword is required. This type of instantiation is
required for structural modeling interconnecting previously defined modules. These
instances should be outside always statements.
Let us now synthesize the Verilog code for a left shift register from Figure 2-41.
Before synthesis is started, we must specify a target device (e.g., a particular
FPGA or CPLD) so that the synthesizer knows what components are available.
Let us assume that the target is a CPLD or FPGA that has D flip-flops with clock
enable (D-CE flip-flops). Q and D are of length four bits. Because updates to
Q follow on rising edge of the CLK, this suggests that Q must be a register composed
of four flip-flops, which we will label Q3, Q2, Q1, and Q0. Since the flip-flops can
change state when Clr, Ld, or Ls is 1, we connect the clock enables to an OR gate
whose output is Clr 1 Ld 1 Ls. Then we connect gates to the D inputs to select
the data to be loaded into the flip-flops. If Clr 5 and Ld 5 1, D is loaded into the
2.14 Modeling Registers and Counters Using Verilog Always Statements 111
register on the rising clock edge. If Clr 5 Ld 5 0 and Ls 5 1, then Q2 is loaded into
Q3, Q1 is loaded into Q2, and so forth. Figure 2-47 shows the logic circuit for the
first two flip-flops. If Clr 5 1, the D flip-flop inputs are 0 and the register is cleared.

FIGURE 2-47: Synthesis Q3 Q2


of Verilog Code for
Left Shift Register from CE D CE D
Figure 2-41
Clr CLK CLK
Ld
Ls

Clr9 Ld D3 Clr9 Ld9 Ls Q2 Clr9 Ld D2 Clr9 Ld9 Ls Q1

A Verilog synthesizer cannot synthesize delays. Clauses of the form “# time”


will be ignored by most synthesizers, but some synthesizers may even require
that the clauses be removed.
Similarly, initial blocks are usually ignored by synthesis tools. Also,
although initial values for signals may be specified in port and signal decla-
rations, these initial values are usually ignored by the synthesizer. A reset
signal should be provided if the hardware must be set to a specific initial
state. Otherwise, the initial state of the hardware may be unknown and the
hardware may malfunction. The only exception to this is that some synthesis
tools for FPGAs may utilize the initial blocks and initial values in the initial
bit stream that is downloaded into the FPGA. But for synthesis into custom
hardware, initial values and initial blocks are typically ignored.

Avoiding Unwanted Latches


Verilog signals retain their current values until they are changed. This can result in
the creation of unwanted latches when the Verilog code is synthesized. For exam-
ple, in a combinational always block created using the statements

always @ (Sel or I0 or I1 or I2)


begin
if (Sel == 2'b00) F = I0;
else if   
(Sel == 2'b01) F = I 1;
else if   
(Sel == 2'b10) F = I2;
end

there would be latches to hold the value of F when Sel changes to 2'b11. Someone
probably wrote this code intending a MUX. Circuits with latches are not combi-
national hardware any more. The latch creates a variety of timing problems and
unexpected behavior. Instead of being 1 bit wide, if F is 8 bits wide, eight latches
would be created.
112 Chapter 2 Introduction to Verilog

One can avoid unwanted latches by assigning a value to combinational signals in


every possible execution path in an always block intended to create combinational
hardware. Hence one should include an else clause in every if statement or explic-
itly include all possible cases of the inputs. For example, the code
always @ (Sel or I0 or I1 or I2 or I3)
begin
if (Sel == 2'b00) F = I0;
else if   
(Sel == 2'b01) F = I1;
else if    (Sel == 2'b10) F = I2;
else if   
(Sel
   == 2'b11) F = 0;
end

would not create any latches but would create a MUX. For if then else statements
and case statements, it is important to have all cases specified.
Another method to avoid latches is by initializing at the beginning of the always
statement. For instance, the following code is latch free, even though only three of
the four possible cases are specified.
always @ (Sel or I0 or I1 or I2 or I3)
F = 0;
begin
if    
(Sel == 2'b00) F = I0;
else if (Sel == 2'b01) F = I1;
else if (Sel == 2'b10) F = I2;
end

The following are important coding practices while writing synthesizable


Verilog for sequential hardware:
(a) Use an edge-triggered clock in the sensitivity list using the posedge or
negedge keywords.
(b) Use non-blocking assignments—that is, “<5” inside always blocks although it is
possible to get sequential hardware by certain uses of the blocking “5” operator.
(c) Do not mix blocking and non-blocking statements in an always block.
(d) Do not make assignments to the same variable from more than one always
block. This is not a compile-time error and hence may go unnoticed.
(e) Avoid unwanted latches by assigning a value to combinational output signals in
every possible execution path in the always block. This can be done by
i. including else clauses for if statements,
ii. specifying all cases for case statements or have a default clause at the end, or
iii. unconditionally assigning default values to all combinational output signals
at the beginning of the always block.

2.15 Behavioral and Structural Verilog


Any circuit or device can be represented in multiple forms of abstraction. Consider
the different representations for a NAND gate, as illustrated in Figure 2-48. When
one hears the term NAND, different designers, depending on their domain of
2.15 Behavioral and Structural Verilog 113
FIGURE 2-48: Different
NOT AND
Levels of Abstraction of a
NAND Device
(a) Behavior
C <= not(A and B)

CMOS 7400
1
2 & 3
4 SSI Gates
(b) 5 & 6
12 &
13 11
9 &
10 8

A
(c) C Logic
B

Vdd
A B
(d) C Transistor
A
B

(e) Layout

expertise, think of these different representations of the same NAND device.


Some would think of just a block representing the behavior of a NAND operator,
as illustrated in Fig 2-48(a). Some others might think of the four gates in a CMOS
7400 chip, as in Figure 2-48(b). Designers who work at the logic level think of the
logic symbol for a NAND gate, as in Figure 2-48(c). Transistor-level circuit design-
ers think of the transistor-level circuit to achieve the NAND functionality, as in
Figure 2-48(d). What passes through the mind of a physical-level designer is the
layout of a NAND gate, as in Figure 2-48(e). All of the figures represent the same
device, but they differ in the amount of detail provided in the description.
Just as a NAND gate can be described in different ways, any logic circuit can be
described with different levels of detail. Figure 2-49 indicates a behavioral level rep-
resentation of the logic function F 5 ab 1 bc, whereas Figures 2-50(a) and 2-50(b)
illustrate two equivalent structural representations. The functionality specified in
the abstract description in Figure 2-49 can be achieved in different ways, two exam-
ples of which are by using two AND gates and one OR gate or three NAND gates.
114 Chapter 2 Introduction to Verilog

A structural description gives different descriptions for Figures 2-50(a) and 2-50(b),
whereas the same behavioral description could result in either of these two repre-
sentations. A structural description specifies more details, whereas the behavioral
level description specifies only the behavior at a higher level of abstraction.

FIGURE 2-49: A Block


Diagram with A, B, C as A
Inputs and F 5 AB 1 BC
B F = AB + BC
as Output
C

FIGURE 2-50: Two A A


Implementations of B B
F 5 AB 1 BC

C C
(a) using AND-OR (b) using NAND

You probably noticed that the same circuit can be described in different ways.
Similarly, Verilog allows you to create design descriptions at multiple levels of
abstraction. The most common ones are behavioral models, data flow (RTL) models,
and structural models. Behavioral Verilog models describe the circuit or system at
a high level of abstraction without implying any particular structure or technology.
Only the overall behavior is specified. In contrast, in structural models, the compo-
nents used and the structure of the interconnection between the components are
clearly specified. Structural models may be detailed enough to specify use of particu-
lar gates and flip-flops. The structural Verilog model is at a low level of abstraction.
Verilog code can be written at an intermediate level of abstraction, at the data flow
level or the RTL level, in addition to the pure behavioral level or structural level.
RTL stands for Register Transfer Language. Register Transfer Languages have been
used for decades to describe the behavior of synchronous systems where a system is
viewed as registers plus the control logic required to perform loading and manipula-
tion of registers. In the data flow model, data path and control signals are specified.
The working of the system is described in terms of the data transfer between registers.
If designs are specified at higher levels of abstraction, they need to be converted to
the lower levels in order to be implemented. In the early days of design automation,
there were not enough automatic software tools to perform this conversion; hence,
designs needed to be specified at the lower levels of abstraction. Designs were entered
using schematic capture or lower levels of abstraction. Nowadays, synthesis tools
perform very efficient conversion of behavioral level designs into target technologies.
Behavioral and structural design techniques are often combined. Different parts
of the design are often done with different techniques. State-of-the-art design auto-
mation tools generate efficient hardware for logic and arithmetic circuits; hence,
a large part of those designs are done at the behavioral level. However, memory
structures often need manual optimizations and are done by custom design, as
opposed to automatic synthesis.
2.15 Behavioral and Structural Verilog 115

2.15.1 Modeling a Sequential Machine


In this section, we discuss several ways of writing Verilog descriptions for sequential
machines. Let us assume that we have to write a behavioral model for a Mealy sequential
circuit represented by the state table in Figure 2-51 (one may note that this is the BCD to
Excess-3 code converter designed in Chapter 1). A block diagram of this state machine is
also shown in Figure 2-51. This view of the circuit can be used to write its entity descrip-
tion. Please note that the current state and next state are not visible externally.

FIGURE 2-51: State Table


and Block Diagram of NS Z
Sequential Machine PS X=0 X=1 X=0 X=1
X Combinational Z
circuit NS
S0 S1 S2 1 0 State
S1 S3 S4 1 0 register
S2 S4 S4 0 1 CLK
S3 S5 S5 0 1
S4 S5 S6 1 0 PS
S5 S0 S0 0 1
S6 S0 — 1 —

There are several ways to model this sequential machine. One approach would be
to use two always blocks to represent the two parts of the circuit. One always block
models the combinational part of the circuit and generates the next state information
and outputs. The other always block models the state register and updates the state at
the appropriate edge of the clock. Figure 2-52 illustrates such a model for this Mealy
machine. The first always block represents the combinational circuit. At the behav-
ioral level, we will represent the state and next state of the circuit by integer signals
initialized to 0. Please remember that this initialization is meaningful only for simula-
tions. Since the circuit outputs, Z and Nextstate, can change when either the State or
X changes, the sensitivity list includes both State and X. The case statement tests the
value of State, and depending on the value of X, Z and Nextstate are assigned new val-
ues. The second always block represents the state register. Whenever the rising edge
of the clock occurs, State is updated to the value of Nextstate, so CLK appears in the
sensitivity list. The second always block will simulate correctly if written as
always @ (CLK) // State Register
begin // rising edge of clock (simulation)
State <= Nextstate;
end

but in order to synthesize with edge-triggered flip-flops, the event expression


(posedge) or negedge must be used, as in

always @ (posedge CLK) // State Register


begin // (synthesis)
State <= Nextstate; // rising edge of clock
end

In Figure 2-52, State is defined as 3-bit register. If State is defined as an integer,


some synthesis tools may synthesize it to be a 32-bit register, but most modern syn-
thesis tools will figure out that only values less than 7 are used and will synthesize it
to a 3-bit register. The statement default is not actually needed when the outputs
116 Chapter 2 Introduction to Verilog

FIGURE 2-52: Behavioral Model for Excess-3 Code Converter

// This is a behavioral model of a Mealy state machine (Figure 2-51)


// based on its state table. The output (Z) and next state are
// computed before the active edge of the clock. The state change
// occurs on the rising edge of the clock.
module Code_Converter(X, CLK, Z);
input X, CLK;
output Z;
reg Z;
reg [2:0] State;
reg [2:0] Nextstate;
initial
begin
State = 0;
Nextstate = 0;
end

always @(State or X)
begin // Combinational Circuit
case(State)
0 : begin
if(X == 1’b0)
begin
    Z = 1’b1;
    Nextstate = 1;
end
else
begin
    Z = 1’b0;
    Nextstate = 2;
end
end
1 : begin
if(X == 1’b0)
   begin
   Z = 1’b1;
   Nextstate = 3;
end
else
begin
   Z = 1’b0;
   Nextstate = 4;
end
end
2 : begin
if(X == 1’b0)
  begin
    Z = 1’b0;
2.15 Behavioral and Structural Verilog 117
   Nextstate = 4;
end
  
else
begin
   
Z = 1’b1;
   Nextstate = 4;
end
end
3 : begin
if(X == 1’b0)
begin
    Z = 1’b0;
    Nextstate = 5;
end
else
begin
    Z = 1’b1;
    Nextstate = 5;
end
end
4 : begin
if(X == 1’b0)
   begin
   
Z = 1’b1;
    Nextstate = 5;
end
  else
  begin
   Z = 1’b0;
    Nextstate = 6;
   end
end
5 : begin
  if(X == 1’b0)
  begin
   Z = 1’b0;
    Nextstate = 0;
  end
   else
  begin
    Z = 1’b1;
    Nextstate = 0;
   end
end
6 : begin
   if(X == 1’b0)
  begin
    Z = 1’b1;
    Nextstate = 0;
   end
   else
118 Chapter 2 Introduction to Verilog

  begin
    Z = 1’b0;
    Nextstate = 0;
   end
end
default : begin
// should not occur
end
endcase
end
always @(posedge CLK) // State Register
begin      // rising edge of clock
State <= Nextstate;
end
endmodule
and next states of all possible values of State are explicitly specified. In this case,
however, it should be included because one of the eight states is not specified as a
case. The empty statement implies no action, which is appropriate, since the other
values of State should never occur. In case statements, the State variable should be
bound to a specific number of bits, or results will be unpredictable.
A simulator command file that can be used to test Figure 2-52 is as follows:
add wave CLK X State Nextstate Z
force CLK 0 0, 1 100 -repeat 200
force X 0 0, 1 350, 0 550, 1 750, 0 950, 1 1350
run 1600

The first command specifies the signals that are to be included in the waveform
output. The next command defines a clock with a period of 200 ns. CLK is 0 at time
0 ns, is 1 at time 100 ns, and repeats every 200 ns. In a command of the form
force signal_name v1 t1, v2 t2, ...

signal_name gets the value v1 at time t1, the value v2 at time t2, and so forth. X
is 0 at time 0 ns, changes to 1 at time 350 ns, changes to 0 at time 550 ns, and so on.
The X input corresponds to the sequence 0010 1001, and only the times at which
X changes are specified. Execution of the preceding command file produces the
waveforms shown in Figure 2-53.
FIGURE 2-53: Simulator /clk
Output for Excess-3 Code
Converter /x
/state 0 1 3 5 0 2 4 5 0

/nextstate 1 3 5 0 1 2 4 5 0 2

/z
0 ns 500 ns 1000 ns 1500 ns

In Chapter 1, we manually designed this state machine (Figure 1-26). This


circuitry contained three flip-flops, four 3-input NAND gates, two 3-input NAND
gates, and one inverter. The behavioral model of Figure 2-52 may not result in
exactly that circuit. In fact, when we synthesized it using Xilinx ISE tools, we
2.15 Behavioral and Structural Verilog 119
obtained a circuit that contains seven D-flip-flops, fifteen 2-input AND gates, three
2-input OR gates, and one 7-input OR gate. Apparently, the Xilinx synthesis tool
may be using one-hot design by default, instead of encoded design. One-hot design
is a popular approach for FPGAs, where flip-flops are abundant.
Figure 2-54 shows an alternative behavioral model for the code converter that
uses a single always block instead of two always blocks. The next state is not com-
puted explicitly, but instead the state register is updated directly to the proper next
state value on the rising edge of the clock. Since Z can change whenever State or X
changes, Z should not be computed in the clocked block. Instead, we have used a
conditional assignment statement to compute Z. If Z were updated in the clocked
block, then a flip-flop would be created to store Z and Z would be updated at the
wrong time. In general, the two always block model for a state machine is preferable

FIGURE 2-54: Behavioral Model for Code Converter Using a Single Process

// This is a behavioral model of the Mealy state machine for BCD to


// Excess-3 Code Converter based on its state table. The state change
// occurs on the rising edge of the clock. The output is computed by a
// conditional assignment statement whenever State or Z changes.
module Code_Converter(X, CLK, Z);
input X, CLK;
output Z;
wire X; // Redundant declaration of X, CLK and Z.
wire CLK; // Input and output signals are wire data
wire Z; // type by default
reg [2:0] State;
initial
begin
State = 0;
end
always @(posedge CLK) begin
case(State)
0 : begin
if(X == 1'b0)
State <= 1;
else
State <= 2;
end
1 : begin
if(X == 1'b0)
State <= 3;
else
State <= 4;
end
2 :
State <= 4;
3 :
State <= 5;
4 : begin
120 Chapter 2 Introduction to Verilog

if(X == 1’b0)
State <= 5;
else
State <= 6;
end
5 :
State <= 0;
6 :
State <= 0;
default : begin
end
endcase
end
assign Z 5 (State == 0 && X == 1’b0) || (State == 1 && X == 1’b0) ||

(State == 2 && X == 1’b1) || (State == 3 && X == 1’b1) ||
(State == 4 && X == 1’b0) || (State == 5 && X == 1’b1) ||
State == 6 ? 1’b1 : 1’b0;
endmodule
to the one always block model, since the former corresponds more closely to the
hardware implementation which uses a combinational circuit and a state register.
Another way to model this Mealy machine is using the data flow approach (i.e.,
using equations). The data flow Verilog model of Figure 2-55 is based on the next
state and output equations, which are derived in Chapter 1 (Figure 1-25). The flip-
flops are updated in an always block that is sensitive to CLK. When the rising edge of
the clock occurs, Q1, Q2, and Q3 are all assigned new values. A 10 ns delay is included

FIGURE 2-55: Sequential Machine Model Using Equations

// The following is a description of the sequential machine of


// the BCD to Excess-3 code converter in terms of its next state
// equations obtained as in Figure 1-25. The following state assignment was
// used: S0-->0; S1-->4; S2-->5; S3-->7; S4-->6; S5-->3; S6-->2
module Code_Converter(X, CLK, Z);
input X;
input CLK;
output Z;
reg Q1;
reg Q2;
reg Q3;
always @(posedge CLK)
begin
Q1 <= #10 (~Q2);
Q2 <= #10 Q1;

Q3 <= #10 (Q1 & Q2 & Q3) | ((~X) & Q1 & (~Q3)) |
(X & (~Q1) & (~Q2));
end
assign #20 Z = ((~X) & (~Q3)) | (X & Q3);
endmodule
2.15 Behavioral and Structural Verilog 121
to represent the propagation delay between the active edge of the clock and the
change of the flip-flop outputs. Even though the statements in the always block are
executed sequentially, Q1, Q2, and Q3 are all scheduled to be updated at the same
time, T 1 Δ, where T is the time at which the rising edge of the clock occurred. Thus,
the old value of Q1 is used to compute Q1 2
, and the old values of Q1, Q2, and Q3 are
used to compute Q1 3
. The concurrent assignment statement for Z causes Z to be
updated whenever a change in X or Q3 occurs. The 20 ns delay represents two gate
delays. One may note that in order to do Verilog modeling at this level, one needs to
perform state assignments, derive next-state equations, etc. In contrast, at the behav-
ioral level, the state table was sufficient to create the Verilog model.
Yet another approach to creating a Verilog model of the foregoing Mealy machine
is to create a structural model describing the gates and flip-flops in the circuit. Figure
2-58 shows a structural Verilog representation of the circuit of Figure 1-26. One should
note that the designer had to manually perform the design and obtain the gate level
circuitry here in order to create a model as in Figure 2-58. Seven NAND gates, three
D flip-flops, and one inverter are used in the design presented in Figure 1-26. When
primitive components like gates and flip-flops are required, each of these components
can be defined in a separate Verilog module. One could also use the built-in primitives
predefined in Verilog. In this chapter, we are going to build our own building blocks.
Predefined built-in primitives are described in Section 8.4. Depending on which CAD
tools are used, the component modules must be included in the same file as the main
Verilog description, or they must be inserted as separate files in a Verilog project. The
code in Figure 2-58 requires component modules DFF, Nand3, Nand2, and Inverter.
CAD tools might include modules with similar components. If such modules are used,
one should use the exact component names and port-map statements that match the
input-output signals of the component. The DFF module is as follows:
FIGURE 2-56: D Flipflop

// D Flip-Flop
module DFF(D, CLK, Q, QN);
input D;
input CLK;
output Q;
output QN;
reg Q;
reg QN;
initial
begin
Q = 1’b0;
QN = 1’b1;
end
always @(posedge CLK)
begin
Q <= #10 D;
QN <= #10 (~D);
end
endmodule
122 Chapter 2 Introduction to Verilog

The Nand3 module is as follows:

FIGURE 2-57: 3-Input NAND Gate

// 3 input NAND gate


module Nand3(A1, A2, A3, Z);
input A1;
input A2;
input A3;
output Z;
assign #10 Z = (~(A1 & A2 & A3));
endmodule

The Nand2 and Inverter modules are similar except for the number of inputs. We
have assumed a 10-ns delay in each component, and this can easily be changed to
reflect the actual delays in the hardware being used.

FIGURE 2-58: Structural Model of Sequential Machine

// The following is a STRUCTURAL Verilog description of


// the circuit to realize the BCD to Excess-3 code Converter.
// This circuit was illustrated in Figure 1-26.
// Uses components NAND3, NAND2, INVERTER and DFF
// The component modules can be included in the same file
// or they can be inserted as separate files.

module Code_Converter(X, CLK, Z);


input X, CLK;
output Z;
wire X;
wire CLK;
wire Z;
wire A1;
wire A2;
wire A3;
wire A5;
wire A6;
wire D3;
wire Q1;
wire Q2;
wire Q3;
wire Q1N;
wire Q2N;
wire Q3N;
wire XN;

Inverter I1(X, XN);


Nand3 G1(Q1, Q2, Q3, A1);
2.15 Behavioral and Structural Verilog 123
Nand3 G2(Q1, Q3N, XN, A2);
Nand3 G3(X, Q1N, Q2N, A3);
Nand3 G4(A1, A2, A3, D3);
DFF FF1(Q2N, CLK, Q1, Q1N);
DFF FF2(Q1, CLK, Q2, Q2N);
DFF FF3(D3, CLK, Q3, Q3N);
Nand2 G5(X, Q3, A5);
Nand2 G6(XN, Q3N, A6);
Nand2 G7(A5, A6, Z);

endmodule

Since Q1, Q2, and Q3 are initialized to 0, the complementary flip-flop outputs
(Q1N, Q2N, and Q3N) are initialized to 1. G1 is a 3-input NAND gate with inputs
Q1, Q2, Q3, and output A1. FF1 is a D flip-flop with the D input connected to
Q2N. Executing the simulator command file given below produces the waveforms
of Figure 2-59, which are very similar to Figure 1-39.
add wave CLK X Q1 Q2 Q3 Z
force CLK 0 0, 1 100 -repeat 200
force X 0 0, 1 350, 0 550, 1 750, 0 950, 1 1350
run 1600

FIGURE 2-59: Waveforms /CLK


for Code Converter /X
/Q1
/Q2
/Q3
/Z
0 500 1000 1500

If you synthesize this structural description, you will certainly get exactly the same
circuit that you had in mind. Now the circuit includes only three D-flip-flops, three
2-input NAND gates, and four 3-input NAND gates. Compare it with the seven D-flip-
flops, fifteen 2-input AND gates, three 2-input OR gates, and one 7-input OR gate
generated when Figure 2-52 was synthesized. When the designer specified all compo-
nents and their interconnections, the synthesizer tool did not have to infer or “guess.”

Synthesis with integers: Integers are generally treated as 32-bit quantities. While
writing synthesizeable code, it is a good idea to use the appropriate number of
bits for your variables as needed as opposed to using integers. One should use
integers only where they are not explicitly synthesized, eg: looping variables.
If integers are used for state variables in the state machine design presented in
these pages, the synthesis tools we used could figure out that the state variable
is actually only 3-bits long. However, some tools may generate 32-bit registers.

Those who have developed C code with assembly inlining may feel some
similarity to the phenomenon occurring here. By inlining the assembly code, one
can precisely describe what microprocessor instruction sequence you want to be
124 Chapter 2 Introduction to Verilog

used, and the compiler gives you that. In a similar way, the synthesizer does not
actually have to translate any structural descriptions that the designer wrote; it
simply gives the hardware that the designer specified in a structural fashion. Some
optimizing tools are capable of optimizing imperfect circuits that you might have
specified. In general, you have more control over the generated circuitry when
you use structural coding. However, it takes a lot more effort to produce a struc-
tural model, because one needs to perform state assignments, derive next state
equations, and so forth. Time to market is an important criterion for success in the
IC market; hence, designers often use behavioral design in order to achieve quick
time to market. Additionally, CAD tools have matured significantly during the
past decade, and most modern synthesis tools are capable of producing efficient
hardware for arithmetic and logic circuits.

2.16 Constants
Verilog provides constants in addition to variables and nets. Verilog provides three
different ways to define constant values, one of which is using `define as in

`define constant_name constant_value

The `define is one of the compiler directives in Verilog and is used to define a
number or an expression for a meaningful string. The ` in `define is called grave
accent (ASCII 0x60). It is different from the character (‘), which is the apostrophe
character (ASCII 0x27). More on compiler directives can be found in Chapter 8.
The `define compiler directive replaces 'constant_name with constant_
value. For example:

`define wordsize 16
reg [1:`wordsize] data;

causes the string wordsize to be replaced by 16. It then shows how data is declared
to be a reg of width wordsize.
Another method to create constants is to use the parameter keyword as follows:
parameter constant_name = constant_value;

For example,
parameter msb = 15; // defines msb as a constant value 15
parameter [31:0] decim = 1'b1; // value converted to 32 bits

Another method to make constants is using localparam.


localparam constant_name = constant_value;

The localparam is similar to the parameter, but it cannot be directly changed. The
localparam can be used to define constants that should not be changed.
Verilog can define constant values in a module using the parameter. The param-
eter can be used to customize the module instances. Typical uses of parameters are
to specify delays and width of variables.
2.17 Arrays 125
Verilog HDL parameters do not belong to either the variable or the net group.
Parameters are not variables; they are constants. Since parameters represent con-
stants, it is illegal to modify their values at run time. However, module parameters
can be modified at compilation time to have values that are different from those
specified in the declaration assignment. This allows customization of module
instances. The parameter values can be changed at module instantiation or by using
defparam statement. These are described in Chapter 8.

2.17 Arrays
A key feature of VLSI circuits is the repeated use of similar structures. Arrays in
Verilog can be used while modeling the repetition. Digital systems often use memory
arrays. Verilog arrays can be used to create memory arrays and specify the values
to be stored in these arrays. In order to use an array in Verilog, we must declare the
array upper and lower bound. There are two positions to declare the array bounds:
In one option, the array bounds are declared between the variable type (reg or net)
and the variable name, and the array bound means the number of bits for the declared
variable. If the array bound is defined as [7:0] as shown in the following example,
reg [7:0] eight_bit_register;

the register variable eight_bit_register can store one byte (eight bits) of infor-
mation. The 8-bit register can be initialized to hold the value 00000001 using the
following statement:
eight_bit_register 5 8'b00000001;

As a second option, array bounds can be declared after the name of the array. In the
declaration that follows, rega is an array of n 1-bit registers while regb is a single
n-bit register.
reg rega [1:n]; // This is an array of n 1-bit registers
reg [1:n] regb; // This is an n-bit register

We can define multiple 8-bit registers in one array declaration. In this case,
additional upper and lower bound(s) must be declared after the name of the array.
In the example that follows, 16 registers are declared; each register can store one-
byte (8-bit) vector information.
reg [7:0] eight_bit_register_array [15:0];

The foregoing declaration means that each of the 16 variables in the array can have
8-bit vector information. This array can be initialized as follows:
eight_bit_register_array[15] 5 8'b00001100;
eight_bit_register_array[14] 5 8'b00000000;

. . . . . . . .
eight_bit_register_array[1] 5 8'b11001100;
eight_bit_register_array[0] 5 8'b00010001;
126 Chapter 2 Introduction to Verilog

Arrays can be created of various data types. Arrays of wires and integers can
be declared as follows:
wire wire_array[5:0]; // declares an array of 6 wires
integer inta[1:64]; // declares an array of 64 integer values

Matrices
Multidimensional array types may also be defined with two or more dimensions.
The following example defines a 2-dimensional array variable in an initial statement,
which is a matrix of integers with four rows and three columns with 8-bit elements:
reg [7:0] matrixA [0:3][0:2] = { { 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9},
{10, 11, 12}};

The array element matrixA[3][1] references the element in the fourth row and
second column, which has a value of 11.

Look-Up Table Method Using Arrays and Parameters


The array construct together with parameter can be used to create look-up tables
which can be used to create combinational circuits using the ROM or Look-up
Table (LUT) method.

Parity bits are often used in digital communication for error detection and correction. The
Example simplest of these involve transmitting one additional bit with the data, a parity bit. Use
Verilog arrays to represent a parity generator that generates a 5-bit-odd-parity generation
for a 4-bit input number using the look-up table (LUT) method.

Answer: The input word is a 4-bit binary number. A 5-bit odd-parity representation will
contain exactly an odd number of 1s in the output word. This can be accomplished by the
ROM or LUT method using a look-up table of size 16 entries × 5 bits. The look-up table is
indicated in Figure 2-60.

FIGURE 2-60: LUT Input (LUT Address) Output (LUT Data)


Contents for a Parity A B C D P Q R S T
Code Generator 0 0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0 0
0 0 1 1 0 0 1 1 1
0 1 0 0 0 1 0 0 0
0 1 0 1 0 1 0 1 1
0 1 1 0 0 1 1 0 1
0 1 1 1 0 1 1 1 0
1 0 0 0 1 0 0 0 0
1 0 0 1 1 0 0 1 1
1 0 1 0 1 0 1 0 1
1 0 1 1 1 0 1 1 0
1 1 0 0 1 1 0 0 1
1 1 0 1 1 1 0 1 0
1 1 1 0 1 1 1 0 0
1 1 1 1 1 1 1 1 1
2.18 Loops in Verilog 127
The Verilog code for the parity generator is illustrated in Figure 2-61. The first
4 bits of the output are identical to the input. Hence, instead of storing all 5 bits
of the output, one might store only the parity bit and then concatenate it to the
input bits. The parameter construct is used to define the ParityBit which is 1-bit
constant, and the 4-bit input data and 1-bit ParityBit are concatenated to make a
parity code as an output.

FIGURE 2-61: Parity Code Generator Using the LUT Method

module parity_gen(X, Y);


input [3:0] X;
output [4:0] Y;
wire ParityBit;
parameter [0:15] OT = {1'b1, 1'b0, 1'b0, 1'b1, 1'b0, 1'b1, 1'b1, 1'b0, 1'b0, 1'b1,
1'b1, 1'b0, 1'b1, 1'b0, 1'b0, 1'b1};
assign ParityBit = OT[X];
assign Y = {X, ParityBit};
endmodule

2.18 Loops in Verilog


Often, one has systems where some activity is happening in a repetitive fashion.
Verilog loop statements can be used to express this behavior. A loop statement is
a sequential statement. Verilog has several kinds of loop statements including for
loops and while loops. There is also a repeat loop.

Forever Loop (Infinite Loop)


Infinite loops are undesirable in common computer languages, but they can be use-
ful in hardware modeling where a device works continuously and continues to work
until the power is off. Below is an example for a forever loop:

begin
clk = 1'b0;
forever #10 clk = ~clk;
end

For Loop
One way to augment the basic loop is to use the for loop, where the number of
invocations of the loop can be specified. Syntax is similar to C language except
that begin and end are used instead of { } for more than one statement. Note that,
unlike C language, we do not have the operators 11 and 2 in Verilog. Instead of
using those operators as in C language, we need to use its full operational state-
ment, i = i + 1. The general form of a for loop is as follows:
128 Chapter 2 Introduction to Verilog

for (initial_statement; expression; incremental_statement)


begin

sequential statement(s);

end

The following example is of initializing an array variable, eight_bit_register_


array, using a for loop.

reg [7:0] eight_bit_register_array [15:0];

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


begin

register A[i] = 8'b00000000;

end

One could use this type of loop in behavioral models. The following excerpt
models a 4-bit adder. The loop index (i) will be initialized to 0 when the for loop is
entered, and the sequential statements will be executed. Execution will be repeated
for i 5 1, i 5 2, and i 5 3; then the loop will terminate. The carry out from one iter-
ation (Cout) is copied to the carry in (cin) before the end of the loop. Since variables
are used for the sum and carry bits, the update of carry out happens instantaneously.
Code like this often appears in Verilog tasks and functions (described in Chapter 8).
for (i=0; i<4; i=i+1)
begin

Cout = (A[i] && B[i]) || (A[i] && Cin) || (B[i] && Cin);
sum[i] = A[i] ^ B[i] ^ Cin;
Cin = Cout;

end

You could also use the for loop to create multiple copies of a basic cell. When the
foregoing code is synthesized, the synthesizer typically provides four copies of a 1-bit
adder connected in a ripple carry fashion. If you actually desire to create just one copy
of the cell and simply use it multiple times as a serial adder, then you have to design a
sequential circuit. The loop construct will not synthesize into that behavior.

While Loop
As in while loops in most languages, a condition is tested before each iteration. The
loop is terminated if the condition is false. The general form of a while loop is
while condition
begin

sequential statements;

end
2.19 Testing a Verilog Model 129
A while loop is used primarily for simulation.
Figure 2-62 illustrates a while loop that models a down counter. We use the
while statement to continue the decrementing process until the stop is encountered
or the counter reaches 0. The counter is decremented on every rising edge of clk
until either the count is 0 or stop is 1.

FIGURE 2-62: Use of While Loop

`define MAX 100


module counter_100;
integer count;
initial begin
count = 0;
while (count < `MAX) begin
count = count + 1;
end // while
$display("number = %d ", count);
end // initial begin
endmodule

Repeat Loop
The repeat loop repeats the sequential statement(s) for specified times. The num-
ber of repetitions is set by a constant value or a logical expression.

repeat( 8 )
begin

x = x + 1;
y = y + 2;

end

2.19 Testing a Verilog Model


Once a Verilog model for a system has been made, the next step is to test it. A
model has to be tested and validated before it can be successfully used.
A test bench is a piece of Verilog code that can provide input combinations
to test a Verilog model for the system under test. It provides stimuli to the sys-
tem or circuit under test. Test benches are frequently used during simulation to
provide sequences of inputs to the circuit or Verilog model under test. Figure
2-63 shows a test bench for testing the 4-bit binary adder that we created earlier
in this chapter. The adder we are testing will be treated as a component and will
be embedded in the test-bench program. The signals generated within the test
130 Chapter 2 Introduction to Verilog

bench are interfaced to the adder, as shown in Figure 2-63. The module on the
right side is the module under test.

FIGURE 2-63: Interfacing Addend


A
of Signals While Using a Augend
B
Test Bench to Test a 4-Bit Test Carry in 4-Bit
Adder Cin
bench Sum adder
S
Carry out Co

Figure 2-64 shows an example of a test bench for a 4-bit adder without using
assertion monitors.
Assertion statements available in languages such as System Verilog provide an
easy mechanism to specify properties that the design must adhere to and to verify
them. Verilog does not have assertion statements. Hence in this test bench, we sim-
ply provide test inputs and check whether the module outputs match the expected
outputs. It may be noticed that the test bench module does not have external inputs
and outputs; hence, the port list is empty in the module declaration in statement 1.
One can see use of Verilog parameter construct in statement 2.

FIGURE 2-64: Test Bench for 4-Bit Adder

module TestAdder_v2; //Statement 1


parameter N = 11; //Statement 2
reg [3:0] addend;
reg [3:0] augend;
reg    
cin;
wire [3:0] sum;
wire    
cout;
reg [3:0] addend_array[1:N];
reg [1:N] cin_array;
reg [3:0] augend_array[1:N];
reg [3:0] sum_array[1:N];
reg [1:N] cout_array;
initial
begin
//initialization of addend_array
addend_array[1] = 4’b0111;
addend_array[2] = 4’b1101;
addend_array[3] = 4’b0101;
addend_array[4] = 4’b1101;
addend_array[5] = 4’b0111;
addend_array[6] = 4’b1000;
addend_array[7] = 4’b0111;
addend_array[8] = 4’b1000;
addend_array[9] = 4’b0000;
addend_array[10] = 4’b1111;
addend_array[11] = 4’b0000;
2.19 Testing a Verilog Model 131
//initialization of cin_array
cin_array[1] = 1’b0;
cin_array[2] = 1’b0;
cin_array[3] = 1’b0;
cin_array[4] = 1’b0;
cin_array[5] = 1’b1;
cin_array[6] = 1’b0;
cin_array[7] = 1’b0;
cin_array[8] = 1’b0;
cin_array[9] = 1’b1;
cin_array[10] = 1’b1;
cin_array[11] = 1’b0;
//initialization of augend_array
augend_array[1] = 4’b0101;
augend_array[2] = 4’b0101;
augend_array[3] = 4’b1101;
augend_array[4] = 4’b1101;
augend_array[5] = 4’b0111;
augend_array[6] = 4’b0111;
augend_array[7] = 4’b1000;
augend_array[8] = 4’b1000;
augend_array[9] = 4’b1101;
augend_array[10] = 4’b1111;
augend_array[11] = 4’b0000;
//initialization of sum_array (expected sum outputs)
sum_array[1] = 4’b1100;
sum_array[2] = 4’b0010;
sum_array[3] = 4’b0010;
sum_array[4] = 4’b1010;
sum_array[5] = 4’b1111;
sum_array[6] = 4’b1111;
sum_array[7] = 4’b1111;
sum_array[8] = 4’b0000;
sum_array[9] = 4’b1110;
sum_array[10] = 4’b1111;
sum_array[11] = 4’b0000;

//initialization of cout_array (expected carry output)


cout_array[1] = 1'b0;
cout_array[2] = 1'b1;
cout_array[3] = 1'b1;
cout_array[4] = 1'b1;
cout_array[5] = 1'b0;
cout_array[6] = 1'b0;
cout_array[7] = 1'b0;
cout_array[8] = 1'b1;
cout_array[9] = 1'b0;
cout_array[10] = 1'b1;
cout_array[11] = 1'b0;
end
132 Chapter 2 Introduction to Verilog

integer i;
always
begin
for(i = 1 ; i <= N ; i = i + 1)
begin
$display(i);
addend <= addend_array[i];//apply an addend test vector
augend <= augend_array[i];//apply an augend test vector
cin <= cin_array[i];//apply a carry in
#(40);//adder expected to take 40 time units

if(!(sum == sum_array[i] & cout == cout_array[i]))


begin
$write("ERROR: ");
$display("Wrong Answer ");
end
else begin
$display("Correct!!");
end
end
$display(“Test Finished”);
end
Adder4 add1(addend, augend, cin, sum, cout); //module under test instantiated
endmodule

Input and output vectors are hard-coded into the test bench. An exhaustive
test of the adder module requires 512 tests, since there are 9 input bits (4 addend;
4 augend and 1 carryin). We have a random set of 11 tests.
The $display and $write statements are used to print test results. The two sets
of tasks are identical except that $display automatically adds a new line character
to the end of its output, whereas the $write task does not. In Verilog, a name fol-
lowing the $ is interpreted as a system task or a system function. The dollar sign
($) essentially introduces a language construct that enables the development of
user-defined system tasks and functions. These system tasks are not design seman-
tics, but refer to simulator functionality.
The test module has to be instantiated into the test bench outside the always
statement. In this example, Adder4 is the adder module from Figure 2-12. It is
instantiated into the test bench and the inputs mapped to test vectors. Use of
appropriate delays becomes important in test benches. A #(40) delay is specified
after applying a set of inputs so that the simulation model has time to evaluate the
results. This delay value is computed based on the fact that each bit of the ripple
carry adder takes 10 ns in the model in Figure 2-10. Use of incorrect values of delays
may give misleading test results. An improperly created test bench may incorrectly
indicate that a properly working circuit is faulty.
Similar to $display, there are several other Verilog statements to observe
outputs—for example, $strobe, and $monitor. The format string is like that in
C/C11 and may contain format characters, as in the following:
2.20 A Few Things to Remember 133

$display ("Value is %d", para1);


$strobe ("Value is %d", para1);
$monitor ("Value is %d", para1);

The $display and $strobe display once every time they are executed (i.e., every
time the statement is encountered), whereas $monitor displays every time one of
its parameters changes. The difference between $display and $strobe is that $strobe
displays the parameters at the very end of the current simulation time unit whereas
$display outputs them exactly where it is executed.

2.20 A Few Things to Remember


Verilog has different kinds of signal assignments and constructs. Which construct is
to be used depends on the purpose of the Verilog model being created. Verilog is
typically written for the following three reasons:
i. to design hardware (i.e., to model and synthesize hardware)
ii. to model hardware (i.e., to create simulation models that are not necessarily
synthesizeable)
iii. to verify hardware (i.e., to test designs)
The following are illegal in all models:

assign a <= b; // statement 1


assign a <= #10 b; // statement 2
assign a = #10 b; // statement 3

The assign statement is to be used with ‘5’, not with ‘<5’. Hence the first two state-
ments are illegal. Statement 3 uses delayed assignment, which cannot be done with
the assign statement. No delay can be specified on the right side of a continuous
assign statement. Hence statement 3 is illegal.
The following are legal.

assign a = b; \\ Statement 4
assign #10 a = b; \\ Statement 5

Statement 4 is a concurrent statement. It executes concurrently to all other con-


current assign statements and always blocks. Statement 5 behaves with the inertial
type of delay.
How we use assign, blocking, and non-blocking concepts depends on what we
are trying to write Verilog for. Some strategies can be followed to result in appro-
priate models for each purpose.
1. To design hardware (i.e., to model and synthesize hardware) This is a major use
of Verilog, and the following guidelines are important
(a) Do not use initial blocks. Initial blocks are usually ignored during synthesis,
except in some FPGA synthesis tools.
134 Chapter 2 Introduction to Verilog

(b) Do not use delays (either delayed assignment or delayed evaluation).


Delays are ignored during synthesis.
(c) If possible, use concurrent assignments (assign) to design combinational
logic.
(d) It is possible to use procedural assignments (always blocks) to design either
combinational logic or sequential logic.
(e) When procedural assignments (always blocks) are used for combinational
logic, use blocking assignments (e.g., ‘5’). In Verilog 2001 or later, use
always@* to avoid accidental omission of signals from sensitivity lists.
(f) When procedural assignments (always block) are used for sequential logic,
use non-blocking assignments (e.g., ‘<5’).
(g) Do not mix blocking and non-blocking statements in an always block.
(h) Do not make assignments to the same variable from more than one always
block. This is not a compile-time error, but it leads to timing problems,
which are very difficult to debug.
(i) Avoid unwanted latches by assigning a value to combinational output
signals in every possible execution path in the always block. This can be
done by
i. including else clauses for if statements,
ii. specifying all cases for case statements or have a default clause at the
end, or
iii. unconditionally assigning default values to all combinational outputs at
the beginning of the always block.
2. To model hardware (i.e., to create simulation models which are not necessarily
synthesizable) There are several choices in the types of statements used when
synthesis is not required. The following are important points to remember:
(a) If delays are not to be modeled, use blocking assignments (e.g., A 5 B)
for combinational logic and non-blocking assignments (e.g., A <5 B) for
sequential logic.
(b) In blocking assignments with no delay specification (e.g., A 5 B), the new
values are assigned immediately without any delta delays. However, in non-
blocking assignments with no delay specification (e.g., A <5 B), the change
is scheduled to occur after a delta time.
(c) To model combinational logic with inertial delays, use delayed evaluation
blocking statements (e.g., #10 A 5 B;)
(d) To model combinational logic with transport delays, use delayed assign-
ment non-blocking assignments (e.g., A <5 #10 B;). This has to be inside
an always statement, because non-blocking assignments cannot be outside
always statements.
(e) To model sequential logic with delays, use delayed assignment non-
blocking assignments (e.g., A <5 #10 B;). This has to be inside an always
statement because non-blocking assignments cannot be outside always
statements.
(f) Use inertial delays if pulse-rejection behavior is required. If inertial delays
are used, remember this fact when checking simulation outputs. If input
pulses are narrower than the inertial delay values, output changes will not
2.20 A Few Things to Remember 135
occur and not paying attention to this fact may make a designer think that
the model is wrong, even when the model is fine.
(g) Do not make assignments to the same variable from more than one always
block. Since this is not a compile-time error, it can lead to hard debugging
challenges. It may appear that the circuit is working at times and not work-
ing at times.
Verilog Language Reference Model (LRM) outlines the possibility of race
conditions during the simulation since execution of expression evaluation and net
update events may be intermingled. For instance, consider the following code:
assign p = q;
initial begin
q = 1;
#1 q = 0;
$display(p);
end

The Verilog LRM mentions that a simulator is correct in displaying either a 1 or a 0.


The assignment of 0 to q enables an update event for p. The simulator may either
continue and execute the $display task or execute the update for p, followed by the
$display task.
3. To verify hardware. Verification models and test benches mostly use initial
blocks with blocking assignments and delayed assignments (see Figure 2-64
for an example). All types of assignment statements can be used in verification
models. Delays are often used to create test stimuli arrive to unit under test at
precise times and results are compared against expected results after the delays
for the circuit to work. Good strategies for simulation apply here as well, but
the following are especially important:
(a) Although all types of assignment statements can be used in verification
models, use blocking assignments if possible.
(b) When delays are used, pay attention to inertial behavior.
(c) Use initial blocks to hard code test stimulus values.
(d) Use parameters for creating constants so test benches can easily be modified.
(e) Be aware of the differences between $display, $strobe and $monitor so that
wrong conclusions are not made about correctly working circuits.
i. $monitor displays every time one of its parameters changes.
ii. $strobe displays at the very end of the current simulation time unit.
iii. $display outputs values exactly where it is executed.
In this chapter, we have covered the basics of Verilog. We have shown how to
use Verilog to model combinational logic and sequential machines. Since Verilog is
a hardware description language, it differs from an ordinary programming language
in several ways. Most importantly, Verilog statements execute concurrently, since
they must model real hardware in which the components are all in operation at the
same time. Statements within an always block execute sequentially, but the always
blocks themselves operate concurrently. We will cover more advanced features of
Verilog in Chapter 8.
136 Chapter 2 Introduction to Verilog

Problems
2.1 (a) What do the acronyms HDL and FPGA stand for?
(b) How does a hardware description language like Verilog differ from an ordinary
programming language?
(c) What are the advantages of using a hardware description language as compared
with schematic capture in the design process?

2.2 (a) Which of the following are legalVerilog identifiers? 123A, A_123, _A123, $A123_,
c1__c2, and, and1
(b) Which of the following Verilog identifiers are equivalent? aBC, ABC, Abc, abc

2.3 Given the concurrent Verilog statements:


assign #3 B = A && C;
assign #2 C = !B;

(a) Draw the circuit the statements represent.


(b) Draw a timing diagram if initially A 5 B 5 0 and C 5 1, and A changes to 1 at
time 5 ns.

2.4 Write a Verilog description of the following combinational circuit using concurrent
statements. Each gate has a 5-ns delay, excluding the inverter, which has a 2-ns delay.
A
B E
C
D
A
F Z
B
C

2.5 (a) Write Verilog code for a full subtracter using logic equations.
(b) Write Verilog code for a 4-bit subtracter using the module defined in (a) as a
component.

2.6 Write Verilog code for the following circuit. Assume that the gate delays arenegligible.
(a) Using concurrent statements.
(b) Using an always block with sequential statements. No latches should be generated.

A
E
B
F
C
G
D

2.7 In the following Verilog code, A, B, C, and D are 0 at time 10 ns. If D changes to 1 at
20 ns, specify the times at which A, B, and C will change and the values they will take.
Problems 137
(a)
always @(D)
begin
#5 A <= 1;
B <= A + 1;
#10 C <= B;
end
(b)
always @(D)
begin
A <= #5 1;
B <= A + 1;
C <= #10 B;
end

2.8 (a) What device does the following Verilog code represent?
always @(CLK, Clr, Set)
begin
if(Clr == 1'b1)
Q <= 1'b0;
else if(Set == 1'b1)
Q <= 1'b1;
else if(CLK == 1'b0)
Q <= D;
else begin
end
end

(b) What happens if Clr 5 Set 5 1 in the device in part a?

2.9 Write a Verilog description of an S-R latch using an always block.

2.10 An M-N flip-flop responds to the falling clock edge as follows:


If M 5 N 5 0, the flip-flop changes state.
If M 5 0 and N 5 1, the flip-flop output is set to 1.
If M 5 1 and N 5 0, the flip-flop output is set to 0.
If M 5 N 5 1, no change of flip-flop state occurs.
The flip-flop is cleared asynchronously if CLRn 5 0.
Write a complete Verilog module that implements an M-N flip-flop.

2.11 A DD flip-flop is similar to a D flip-flop, except that the flip-flop can change
state (Q1 5 D) on both the rising edge and the falling edge of the clock input.
The flip-flop has a direct reset input, R, and R 5 0 resets the flip-flop to
Q 5 0 independent of the clock. Similarly, it has a direct set input, S, that sets
the flip-flop to 1 independent of the clock. Write a Verilog description of a DD
flip-flop.
138 Chapter 2 Introduction to Verilog

2.12 An inhibited toggle flip-flop has inputs I0, I1, T, and Reset and outputs Q and QN.
Reset is active high and overrides the action of the other inputs. The flip-flop works
as follows: If I0 5 1, the flip-flop changes state on the rising edge of T; if I1 5 1, the
flip-flop changes state on the falling edge of T. If I0 5 I1 5 0, no state change occurs
(except on reset). Assume the propagation delay from T to output is 8 ns and from
reset to output is 5 ns.
(a) Write a complete Verilog description of this flip-flop.
(b) Write a sequence of simulator commands that will test the flip-flop for the input
sequence I1 5 1, toggle T twice, I1 5 0, I0 5 1, toggle T twice.

2.13 In the following Verilog process A, B, C, and D are all registers that have a value of 0
at time 5 10 ns. If E changes from 0 to 1 at time 5 20 ns, specify the time(s) at which
each signal will change and the value to which it will change. List these changes in
chronological order.
always
begin
wait(E);
A <= #5 1;
B <= A + 1;
C <= #10 B;
D <= #3 B;
A <= #15 A + 5;
B <= B + 7;
end

2.14 In the following Verilog process A, B, C, and D are all registers that have a value of 0
at time 5 10 ns. If E changes from 0 to 1 at time 5 20 ns, specify the time(s) at which
each signal will change and the value to which it will change. List these changes in
chronological order.
always @(E)
begin
A <= #5 1;
B <= A + 1;
C <= #10 B;

D <= #3 B;
A <= #15 A + 5;
B <= B 1 7;
end

2.15 Given
wire a = 1'b1;
wire [1:0] b = 2'b10;
wire [2:0] c = 3'b101;

evaluate
i. {b, c}
ii. {a, b, c, 2'b01}
iii. {a, b[0], c[1]}
Problems 139
2.16 Given
wire a = 1'b0;
wire [1:0] b = 2'b10;
wire [2:0] c = 3'b101;

evaluate
i. { 4{a} }
ii. { 4{a}, 2{b} }
iii. { 4{a}, c}

2.17 Given
reg [7:0] C;
reg signed [7:0] D;
reg signed [7:0] A = 8'hD5;

evaluate
i. C = A >> 4
ii. C = A >>> 4
iii. C = A << 4
iv. C = A <<< 4
v. D = A >> 4
vi. D = A >>> 4
vii. D = A << 4
viii. D = A <<< 4

2.18 Evaluate
A >> 4
A >>> 4
A << 4
A <<< 4
given
(a) reg signed [7:0] A 5 89hC7;
(b) reg [7:0] A 5 89hA5;
(c) reg signed [7:0] A 5 89hC7;
(d) integer signed A 5 89hC7;
(e) integer A 5 89hC7;
(f) integer A 5 89shC7;
(g) integer signed A 5 89shC7;
(h) integer signed A 5 329hFFFFFFC7;

2.19 Given
reg [7:0] C;
reg signed [7:0] D;
reg [7:0] A = 8'hD5;
evaluate
i. C 5 A .. 4
ii. C 5 A ... 4
140 Chapter 2 Introduction to Verilog

iii. C 5 A ,, 4
iv. C 5 A ,,, 4
v. D 5 A .. 4
vi. D 5 A ... 4
vii. D 5 A ,, 4
viii. D 5 A ,,, 4

2.20 Given
reg [7:0] C;
reg signed [7:0] D;
reg [7:0] A = 8'shD5;

evaluate
i. C = A >> 4
ii. C = A >>> 4
iii. C = A << 4
iv. C = A <<< 4
v. D = A >> 4
vi. D = A >>> 4
vii. D = A << 4
viii. D = A <<< 4

2.21 Draw the hardware obtained if the following code is synthesized:

module reg3 (Q1,Q2,Q3,Q4, A,CLK);


input A;
input CLK;
output Q1,Q2,Q3,Q4;
reg Q1,Q2,Q3,Q4;
always @(posedge CLK)
begin
Q4 = Q3;
Q3 = Q2;
Q2 = Q1;
Q1 = A;
end
endmodule

2.22 Draw the hardware obtained if the following code is synthesized:

module reg3 (Q1,Q2,Q3,Q4, A,CLK);


input A;
input CLK;
output Q1,Q2,Q3,Q4;
reg Q1,Q2,Q3,Q4;
always @(posedge CLK)
begin
Problems 141
Q1 = A;
Q2 = Q1;
Q3 = Q2;
Q4 = Q3;
end
endmodule

2.23 Draw the hardware obtained if the following two modules are synthesized and
describe the differences.

module reg3 (Q1,Q2,Q3,Q4,A,CLK);


input A;
input CLK;
output Q1,Q2,Q3,Q4;
reg Q1,Q2,Q3,Q4;
// first
always @(posedge CLK)
begin
Q1 <= A;
Q2 <= Q1;
Q3 <= Q2;
Q4 <= Q3;
end

endmodule

module reg3 (Q1,Q2,Q3,Q4,A,CLK);


input A;
input CLK;
output Q1,Q2,Q3,Q4;

reg Q1,Q2,Q3,Q4;

// first -> second


always @(posedge CLK)
begin
Q4 <= Q3;
Q3 <= Q2;
Q2 <= Q1;
Q1 <= A;
end

endmodule

2.24 (a) Assume D150, D255, and D1 changes to 1 at time510 ns. What are the values
of D1 and D2 after the following code has been executed once? Do the values
of D1 and D2 swap?
142 Chapter 2 Introduction to Verilog

always @ (D1)
begin
D2 <= D1;
D1 <= D2;
End

(b) Assume D150, D255, and D1 changes to 1 at time510 ns. What are the values
of D1 and D2 after the following code has been executed once? Do the values
of D1 and D2 swap?
     always @ (D1)
begin
D2 = D1;
D1 = D2;
end

(c) How many latches will result when the following code is synthesized? Assume
B is 3 bits long.

always @ (State) begin


case(State)
2'b00: B = 5;
2'b01: B = 3;
2'b10: B = 0;
endcase
end

Circle the correct choice:

i. 1 latch because 1 case is missing


ii. 2 latches because state is 2 bits
iii. 3 latches because B is 3 bits
iv. 5 latches because B is 3 bits and state is 2 bits
v. None of the above. But it results in latches.
2.25 What is wrong with the following code for a half adder that must add if add signal
equals 1?

always @(x)
begin
  if (add == 1)
  begin
     sum = x ^ y;
     carry = x & y;
  end
  else
  begin
     sum = 0;
     carry = 0;
  end
end
Problems 143
(a) It will compile but will not simulate correctly.
(b) It will compile and simulate correctly but will not synthesize correctly.
(c) It will work correctly in simulation and in synthesis.
(d) It will not even compile.

2.26 For the following Verilog code, assume that D changes to 1 at time 5 ns. Give
the values of A, B, C, D, E, and F each time a change occurs. That is, give the
values at time 5 ns, 5 1 D, 5 1 2D, and so forth. Carry this out until 20 steps have
occurred, until no further change occurs, or until a repetitive pattern emerges.
module prob(D);
inout D;
wire A, C;
reg B,E,F,temp_D;

initial
begin
B = 1'b0;
E = 1'b0;
F = 1'b0;
temp_D = 1'b0;
end

assign C = A;
assign A = (B & !E) | D;
assign D = temp_D;
always @(A)
begin
B = A;
end

always
begin
wait(A)
E <= #5 B;
temp_D <= 1'b0;
F <= E;
end
endmodule

2.27 Assuming B is driven by the simulator command:


force B 0 0, 1 10, 0 15, 1 20, 0 30, 1 35

Draw a timing diagram illustrating A, B, and C if the following concurrent state-


ments are executed:

always @(B)
begin
A = #5 B;
end
assign #8 C = B;
144 Chapter 2 Introduction to Verilog

2.28 Assuming B is driven by the simulator command:


force B 0 0, 1 4, 0 10, 1 15, 0 20, 1 30, 0 40

Draw a timing diagram illustrating A, B, and C if the following concurrent state-


ments are executed:
always @(B)
begin
A <= #5 B;
end
assign #5 C <= B;

2.29 Assuming B is driven by the simulator command:


force B 0 0, 1 4, 0 10, 1 15, 0 20, 1 30, 0 40

Draw a timing diagram illustrating A, B, and C if the following statement is executed:


(a) always @(A,B)
begin
#5 C <= A && B;
end

(b) always @(A,B)


begin
#5 C = A && B;
end

(c) always @(A,B)


begin
C <= #5 A && B;
end

(d) always @(A,B)


begin
C = #5 A && B;
end

2.30 Given the following timing waveform for Y, draw D and E.

10ns 3ns 5ns

10ns
Y
2ns

0 10 20 30 40 50
Problems 145
wire #4 D; // net delay on wire D
assign #6 D = Y; // statement 1 2 inertial delay

wire #6 E; // net delay on wire E


assign #4 E = Y; // statement 1 - inertial delay

2.31 Given the following timing waveform for Y, draw D and E.


10ns 3ns 5ns

10ns
Y
2ns

0 10 20 30 40 50

wire #3 D; // net delay on wire D


assign #5 D = Y; // statement 1 - inertial delay

wire #5 E; // net delay on wire E


assign #3 E = Y; // statement 1 - inertial delay

2.32 In the following Verilog Code, A, B, C, and D are registers that are 0 at time 5
4 ns. If A changes to 1 at time 5 ns, make a table showing the values of A, B, C, and
D as a function of time until time 5 18 ns. Include deltas. Indicate the times at which
each process begins executing.
always @(A)
begin
B <= #5 A;
C <= #2 B;
end

always
begin
wait(B);
A <= ~B;
D <= ~A ^ B;
end

2.33 If A 5 101, B 5 011, and C 5 010, what are the values of the following statements?
Assume A, B, and C are of reg type. Assume as many bits as necessary for the result.
(a) {A,B} | {B,C}
(b) A >> 2
146 Chapter 2 Introduction to Verilog

(c) A >>> 2
(d) {A,(~B)} == 111110
(e) A | B & C

2.34 Consider the following Verilog code:


module Q3(A,B,C,F,Clk,E);
input A,B,C,F,Clk;
output reg E;
reg D,G;
initial
begin
E = 1'b0;
D = 1'b0;
G = 1'b0;
end
always @(posedge Clk)
begin
D <= A & B & C;
G <= ~A & ~B;
E <= D | G | F;
end
endmodule

(a) Draw a block diagram for the circuit (no gates and at block level only).
(b) Give the circuit generated by the preceding code (at the gate level).

2.35 Implement the following Verilog code using these components: D flip-flops with
clock enable, a multiplexer, an adder, and any necessary gates. Assume that Ad
and Ora will never be 1 at the same time and enable the flip-flops only when Ad or
Ora is 1.
module module1(A,B,Ad,Ora,clk,C);
input Ad,Ora,clk;
input [2:0]A,B;
output reg[2:0]C;
initial
begin
C = 3'd0;
end
always @(posedge clk)
begin
if(Ad == 1'b1)
C <= A + B;
if(Ora == 1'b1)
C <= A | B;
end
endmodule
Problems 147
2.36 Draw the circuit represented by the following Verilog process:
always @(clk,clr)
begin
if(clr == 1'b1)
Q <= 1'b0;
else if(clk == 1'b0 && CE == 1'b1)
begin
if(C == 1'b0)
Q <= A & B;
else
Q <= A | B;
end
end

Why is clr on the sensitivity list whereas C is not?

2.37 (a) Write a conditional signal assignment statement to represent the 4-to-1 MUX
shown subsequently. Assume that there is an inherent delay in the MUX that
causes the change in output to occur 10 ns after a change in input.
(b) Repeat (a) using an if-else statement.
(c) Repeat (a) using a case statement.
A9 I0
B I1
F
B9 I2
0 I3

C D

2.38 (a) Write at least two different Verilog modules that are equivalent to the following
pseudo code:
A = B1 when C = 1 else B2 when C = 2 else B3 when C = 3 else 0;
(b) Draw a circuit to implement the following statement,
 = B1 when C1 = 1 else B2 when C2 = 1 else B3 when C3 = 1
A
else 0;

2.39 Write a Verilog description of an SR latch.


(a) Use a conditional assignment statement (i.e., a behavioral description).
(b) Use the characteristic equation in the Verilog description.
(c) Use the logic gate level structure of an SR latch in the model.

2.40 Given
reg [3:0] A = 4'b1101;
reg [2:0] B = 3'b111;
reg signed [3:0] C = 4'b1101;
reg signed [2:0] D = 3'b111;
reg signed [7:0] S;
148 Chapter 2 Introduction to Verilog

evaluate
i. S 5 A 1 B;
ii. S 5 A 1 B 1 0;
iii. S 5 C 1 D;
iv. S 5 C 1 D 1 0;
v. S 5 A 1 D;
vi. S 5 A 1 D 1 0;

2.41 Given

integer A = 8'shA5;
integer B = 8'shB6;
integer C = 8'hA5;
integer D= 8'hB6;
reg signed [31:0] S;

evaluate

i. S 5 A 1 B;
ii. S 5 A 1 B 1 0;
iii. S 5 C 1 D;
iv. S 5 C 1 D 1 0;
v. S 5 A 1 D;
vi. S 5 A 1 D 10;

2.42 A 4-bit magnitude comparator chip (e.g., 74LS85) compares two 4-bit numbers A and
B and produces outputs to indicate whether A , B, A 5 B, or A . B. There are three
output signals to indicate each of the foregoing conditions. Note that exactly one of
the output lines will be high and the other two lines will be low at any time. The chip
is a cascadable chip and has three inputs—A.B.IN, A5B.IN, and A,B.IN—in order
to allow cascading the chip to make 8-bit or larger magnitude comparators.
(a) Draw a block diagram of a 4-bit magnitude comparator.
(b) Draw a block diagram to indicate how you can construct an 8-bit magnitude
comparator using two 4-bit magnitude comparators.
(c) Write a behavioral Verilog description for the 4-bit comparator.
(d) Write Verilog code for the 8-bit comparator using two 4-bit comparators as
components.

2.43 Write a Verilog module that describes a 16-bit serial-in, serial-out shift register with
inputs SI (serial input), EN (enable), CK (clock, shifts on rising edge), and a serial
output (SO).

2.44 A description of a 74194 4-bit bidirectional shift register follows.


The CLRb input is asynchronous and active low and overrides all the other control
inputs. All other state changes occur following the rising edge of the clock. If the
control inputs S1 5 S0 5 1, the register is loaded in parallel. If S1 5 1 and S0 5 0,
Problems 149
the register is shifted right and SDR (serial data right) is shifted into Q3. If S1 5 0
and S0 5 1, the register is shifted left and SDL is shifted into Q0. If S1 5 S0 5 0, no
action occurs.

Q3 Q2 Q1 Q0

SDR SDL
S1 74194 CLRb

S0 CLK

D3 D2 D1 D0

(a) Write a behavioral-level Verilog model for the 74194.


(b) Draw a block diagram and write a Verilog description of an 8-bit bidirectional
shift register that uses two 74194s as components. The parallel inputs and
outputs to the 8-bit register should be X([7:0]) and Y([7:0]). The serial inputs
should be RSD and LSD.

2.45 A synchronous (4-bit) up/down decade counter with output Q works as follows: All
state changes occur on the rising edge of the CLK input, except the asynchronous clear
(CLR). When CLR 5 0, the counter is reset regardless of the values of the other inputs.
If the LOAD input is 0, the data input D is loaded into the counter.
If LOAD 5 ENT 5 ENP 5 UP 5 1, the counter is incremented.
If LOAD 5 ENT 5 ENP 5 1 and UP 5 0, the counter is decremented.
If ENT 5 UP 5 1, the carry output (CO) 5 1 when the counter is in state 9.
If ENT 5 1 and UP 5 0, the carry output (CO) 5 1 when the counter is in state 0.

(a) Write a Verilog description of the counter.


(b) Draw a block diagram and write a Verilog description of a decimal counter that
uses two of the previously specified counters to form a 2-decade decimal up/
down counter that counts up from 00 to 99 or down from 99 to 00.
(c) Simulate for the following sequence: load counter with 98, increment three
times, do nothing for two clocks, decrement four times, and clear.

2.46 Write a Verilog model for a 74HC192 synchronous 4-bit up/down counter. Ignore
all timing data. Your code should contain a statement of the form always @(DOWN,
UP, CLR, LOADB).

2.47 Consider the following 8-bit bidirectional synchronous shift register with parallel
load capability. The notation used to represent the input/output pins is explained
as follows:
CLR Asynchronous Clear, which overrides all other inputs
Q(7:0) 8-bit output
D(7:0) 8-bit input
S0, S1 mode control inputs
150 Chapter 2 Introduction to Verilog

LSI serial input for left shift


RSI serial input for right shift
The mode control inputs work as follows:

S0 S1 Action
0 0 No action
0 1 Right shift
1 0 Left shift
1 1 Load parallel data (i.e., Q 5 D)

(a) Write a Verilog module for this shift register.


(b) Draw a block diagram illustrating how two of these can be connected to form a
16-bit cyclic shift register, which is controlled by signals L and R. If L 5 1 and
R 5 0, the 16-bit register is cycled left. If L 5 0 and R 5 1, the register is cycled
right. If L 5 R 5 1, the 16-bit register is loaded from X(15:0). If L 5 R 5 0, the
register is unchanged.
(c) Write a Verilog module for the module in part (b), using the module built in (a).

2.48 Complete the following Verilog code to implement a counter that counts in the
following sequence: Q 5 1000, 0111, 0110, 0101, 0100, 0011, 1000, 0111, 0110, 0101,
0100, 0011, … (repeats). The counter is synchronously loaded with 1000 when Ld8
5 1. It goes through the prescribed sequence when Enable 5 1. The counter outputs
S5 5 1 whenever it is in state 0101. Do not change the provided structure of the
following module in any way. Your code must be synthesizable.
module countQ1(clk,Ld8,Enable,S5,Q);
input clk,Ld8,Enable;
output reg S5;
output reg[3:0] Q;
.
.
.
endmodule

2.49 A synchronous 4-bit UP/DOWN binary counter has a synchronous clear signal
CLR and a synchronous load signal LD. CLR has higher priority than LD. Both
CLR and LD are active high. D is a 4-bit input to the counter, and Q is the 4-bit
output from the counter. UP is a signal that controls the direction of counting. If
CLR and LD are not active and UP 5 1, the counter increments. If CLR and LD
are not active and UP 0, the counter decrements. All changes occur on the falling
edge of the clock.
(a) Write a behavioral Verilog description of the counter.
(b) Use the foregoing UP/DOWN counter to implement a synchronous modulo 6
counter that counts from 1 to 6. This modulo 6 counter has an external reset,
which, if applied, makes the count 5 1. A count enable signal CNT makes it
count in the sequence 1, 2, 3, 4, 5, 6, 1, 2, . . ., incrementing once for each clock
pulse. You should use any necessary logic to make the counter go to count 5 1
Problems 151
after count 5 6. The modulo 6 counter counts only in the UP sequence. Provide
a textual/pictorial description of your approach.
(c) Write a behavioral Verilog description for the modulo-6 counter in part (b).

2.50 Examine the following Verilog code and answer the following questions
module Problem(X,CLK,Z1,Z2);
input X,CLK;
output Z1,Z2;
reg [1:0]State,Nextstate;
initial
begin
State = 2'b00;
Nextstate = 2'b00;
end
always @(State,X)
begin
case(State)
0:begin
if(X == 1'b0)begin
Z1 = 1'b1;
Z2 = 1'b0;
Nextstate = 2'b00;
end
else begin
Z1 = 1'b0;
Z2 = 1'b0;
Nextstate = 2'b01;
end
end
1:begin
if(X == 1'b0)begin
Z1 = 1'b0;
Z2 = 1'b1;
Nextstate = 2'b01;
end
else begin
Z1 = 1'b0;
Z2 = 1'b1;
Nextstate = 2'b10;
end
end
2:begin
if(X == 1'b0)begin
Z1 = 1'b0;
Z2 = 1'b1;
Nextstate = 2'b10;
end
else begin
Z1 = 1'b0;
152 Chapter 2 Introduction to Verilog

Z2 = 1'b1;
Nextstate = 2'b11;
end
end
3:begin
if(X == 1'b0)begin
Z1 = 1'b0;
Z2 = 1'b0;
Nextstate = 2'b00;
end
else begin
Z1 = 1'b1;
Z2 = 1'b0;
Nextstate = 2'b01;
end
end
endcase
end
always @(posedge CLK)
begin
State <= Nextstate;
end
endmodule

(a) Draw a block diagram of the circuit implemented by this code.


(b) Write the state table that is implemented by this code.

2.51 (a) Write a behavioral Verilog description of the state machine you designed in
Problem 1.13.
Assume that state changes occur on the falling edge of the clock pulse. Instead
of using if-then-else statements, represent the state table and output table by
arrays. Compile and simulate your code using the following test sequence:

X 5 1101 1110 1111


X should change 1y4 clock period after the rising edge of the clock.
(b) Write a data flow Verilog description using the next-state and output equations
to describe the state machine. Indicate on your simulation output at which
times S and V are to be read.
(c) Write a structural model of the state machine in Verilog that contains the inter-
connection of the gates and D flip-flops.

2.52 (a) Write a behavioral Verilog description of the state machine that you designed in
Problem 1.14. Assume that state changes occur on the falling edge of the clock
pulse. Use a case statement together with if-then-else statements to represent the
state table. Compile and simulate your code using the following test sequence:
X 5 1011 0111 1000
X should change 1y4 clock period after the falling edge of the clock.
Problems 153
(b) Write a data flow Verilog description using the next-state and output equations
to describe the state machine. Indicate on your simulation output at which
times D and B should be read.
(c) Write a structural model of the state machine in Verilog that contains the inter-
connection of the gates and J-K flip-flops.

2.53 A Moore sequential machine with two inputs (X1 and X2) and one output (Z) has
the following state table:

Present Next State Output


State X1X2 5 00 01 10 11 (Z )

1 1 2 2 1 0
2 2 1 2 1 1

Write Verilog code that describes the machine at the behavioral level. Assume
that state changes occur 10 ns after the falling edge of the clock and output changes
occur 10 ns after the state changes.

2.54 Write Verilog code to implement the following state table. Use two always blocks.
State changes should occur on the falling edge of the clock. Implement the Z1 and
Z2 outputs using concurrent conditional statements. Assume that the combinational
part of the sequential circuit has a propagation delay of 10 ns and the propagation
delay between the rising-edge of the clock and the state register output is 5 ns.

Present Next State Output


State (Z1Z2)
X1X2 5 00 01 11
1 3 2 1 00
2 2 1 3 10
3 1 2 3 01

2.55 In the following code, state and nextstate are integers with a range of 0 to 2.
always @(state,X)
begin
case(state)
0:begin
if(X == 1'b1)
nextstate = 2'b01;
end
1:begin
if(X == 1'b0)
nextstate = 2'b10;
end
2:begin
if(X == 1'b1)
nextstate = 2'b00;
end
endcase
end
154 Chapter 2 Introduction to Verilog

(a) Explain why a latch would be created when the code is synthesized.
(b) What signal would appear at the latch output?
(c) Make changes in the case statement that would eliminate the latch.
(d) Can you make changes outside the case statement that would eliminate the
latch? If yes, illustrate. If no, explain.
2.56 What is wrong with the following model of a 4-to-1 MUX? (It is not a syntax error.)
reg [1:0]sel;
always @(A,B,I0,I1,I2,I3)
begin
sel = 0;
if(A == 1'b1)
sel = sel + 1;
else
begin
end
if(B == 1'b1)
sel = sel + 2;
else
begin
end
case(sel)
0:begin
F = I0;
end
1:begin
F = I1;
end
2:begin
F = I2;
end
3:begin
F = I3;
end
endcase
end

2.57 When the following Verilog code is simulated, A is changed to 1 at time 5 ns. Make
a table that shows all changes in A, B, and D and the times at which they occur
through time 5 40 ns.
module Q1F00(A)
inout A;
reg B,C;
wire D;
assign #10 D = A ^ B;
always @(D)
begin
C = ~D;
if(C == 1'b1)
A <= #15 ~A;
Problems 155
B <= D;
end
endmodule

2.58 What device does the following Verilog code represent?


reg Qtmp;

always @(CLK,RST)
begin
if(RST == 1'b1)
Qtmp = 1'b0;
else if(CLK == 1'b1 && T == 1'b1)
Qtmp = ~Qtmp;
else begin
end
Q <= Qtmp;
end

2.59 (a) Write a Verilog module for a LUT with four inputs and three outputs. The
3-bit output should be a binary number equal to the number of 1s in the
LUT input.
(b) Write a Verilog module for a circuit that counts the number of 1s in a 12-bit
number. Use three of the modules from (a) along with overloaded addition
operators.
(c) Simulate your code and test it for the following data inputs:

111111111111, 010110101101, 100001011100

2.60 Implement a 3-to-8 decoder using a LUT. Give the LUT truth table and write the
Verilog code. The inputs should be A, B, and C, and the output should be an 8-bit
unsigned vector.

2.61 A is an array of 20 4-bit registers. Write Verilog code that finds the largest register
in the array,
(a) Using a for loop.
(b) Using a while loop.

2.62 Write Verilog code to test a Mealy sequential circuit with one input (X) and one
output (Z). The code should include the Mealy circuit as a component. Assume
the Mealy circuit changes state on the rising edge of CLK. Your test code should
generate a clock with a 100-ns period. The code should apply the following test
sequence:

X 5 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0
156 Chapter 2 Introduction to Verilog

X should change 10 ns after the rising edge of CLK. Your test code should read Z
at an appropriate time and should verify that the following output sequence was
generated:

Z 5 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0

Report an error if the output sequence from the Mealy circuit is incorrect; other-
wise, report “sequence correct.” Complete the following architecture for the tester:
module tester;
reg CLK;reg[11:0]X;
reg[11:0]Z;
initial
begin
X = 12'b011011011100;
Z = 12'b100110110110;
CLK = 1;
end
.
.
.
.
.
endmodule

2.63 Write a Verilog test bench that will test the Verilog code for the sequential circuit of
Figure 2-58. Your test bench should generate all 10 possible input sequences (0000, 0001,
0010, . . .,1001) and should verify that the output sequences are correct. Remember that
the components have a 10-ns delay. The input should be changed 1/4 of a clock period
after the rising edge of the clock, and the output should be read at the appropriate time.
Report “Pass” if all sequences are correct; otherwise, report “Fail.”

2.64 Write a test bench to test the counter of Problem 2.48. The test bench should
generate a clock with a 100-ns period. The counter should be loaded on the first
clock, then it should count for 5 clocks, then it should do nothing for 2 clocks, then
it should continue counting for 10 clocks. The test bench port should output the
current time (in time units, not the count) whenever S5 5 1. Use only concurrent
statements in your test bench.

2.65 Complete the following Verilog code to implement a test bench for the sequential
circuit SMQ1. Assume that the Verilog code for the SMQ1 sequential circuit module
is already available. Use a clock with a 50-ns half period. Your test bench should test
the circuit for the input sequence X 5 1, 0, 0, 1, 1. Assume that the correct output
sequence for this input sequence is 1, 1, 0, 1, 0. Use a single concurrent statement to
generate the X sequence. The test bench should read the values of output Z at the
proper times and should compare them with the correct values of Z. The correct
answer is initialized as a constant:
answer 5 11010;
Problems 157
The port signal correct should be set to TRUE if the answer is correct; otherwise, it
should be set to FALSE. Make sure that you read Z at the correct time. Use wait
statements in your test bench.
module testSMQ1(correct);
output reg correct;
reg CLK;
reg [4:0] X;
reg [4:0] Z;
reg [4:0] answer;
initial
begin
correct = 1;
X = 5'b10011;
Z = 5'b11010;
answer = 5'b11010;
end
.
.
.
.
endmodule

You might also like