0% found this document useful (0 votes)
9 views

Unit-I-VLSI Design 2023-24 Roth Book According to Syllabus

This document provides an introduction to Verilog, a hardware description language used for modeling digital systems, including combinational circuits and sequential elements like flip-flops. It covers the design flow in computer-aided design (CAD), detailing the steps from problem formulation to synthesis and post-synthesis simulation, emphasizing the use of HDLs for higher abstraction in design. Additionally, it compares Verilog with VHDL, highlighting their differences and the advantages of using Verilog for digital circuit design.

Uploaded by

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

Unit-I-VLSI Design 2023-24 Roth Book According to Syllabus

This document provides an introduction to Verilog, a hardware description language used for modeling digital systems, including combinational circuits and sequential elements like flip-flops. It covers the design flow in computer-aided design (CAD), detailing the steps from problem formulation to synthesis and post-synthesis simulation, emphasizing the use of HDLs for higher abstraction in design. Additionally, it compares Verilog with VHDL, highlighting their differences and the advantages of using Verilog for digital circuit design.

Uploaded by

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

UNIT-I

Introduction to Verilog: Computer-Aided Design, Hardware Description Languages, Verilog


Description of Combinational Circuits, Verilog Modules, Verilog Assignments, Procedural
Assignments, Modeling Flip-Flops Using Always Block, Always Blocks Using Event Control
Statements, Delays in Verilog, Compilation, Simulation, and Synthesis of Verilog Code, Verilog
Data Types and Operators, Simple Synthesis Examples, Verilog Models for Multiplexers, Modeling
Registers and Counters Using Verilog Always Statements, Behavioural and Structural Verilog,
Constants, Arrays, Loops in Verilog, Testing a Verilog Model.

1. Computer-Aided Design
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.
• 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.

• 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 conceptualized in the
previous step needs to be entered into the CAD system in an appropriate 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, counters, registers, and so forth. ORCAD (a company that produced
design automation 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 schematic 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 specific
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 problems 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 standard 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 programs to machine language. Just as a C
compiler can generate optimized or unoptimized 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 a compiler to convert design descriptions 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 simulation at a
higher level of abstraction does not take into account specific implementations
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 iterativeprocess.
• 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 custom IC, or it
could be implemented in a standard part that is easily available from 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), programmable 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.
o 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.
o 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.

2. H a r d w a r e Description L a n g u a g e s
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.
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 originally 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 proprietary. 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 vendor- 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, dataflow, and
structural. For example, a binary adder could be described at the behavioral 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 VHDL

It is a hardware description language used It is a hardware description language used to


for modeling electronic systems. describe digital and mixed-signal systems.
It is based on the C language. It is based on Ada and Pascal languages.

It is case-sensitive. It is case insensitive.

It is easier to learn. It takes work to learn.

It does not support a multidimensional array. It supports a multidimensional array.

Verilog does not allow concurrent task calls. VHDL allows concurrent procedure calls.

It is a simple datatype. It is a complex datatype.

There is no concept of the library in Verilog. The library is present in VHDL.


3. Veril og Description of Co m b i n a t i o n a l Circuits
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.
Verilog models combinational circuits by concurrent statements or continuous assignments.
Concurrent statements (continuous assignments) 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.
Consider 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 indicates 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 =1 and B = C = D = E = 0. If B changes to 1 at time 0, C will change
to 1 at time = 5 ns. Then E will change to 1 at time = 10 ns (assuming timescale is 1 ns).
Verilog signal assignment statements in the above example are 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 small delay used to maintain/indicate sequentiality between dependent events
happening 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.
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_inpu
t
_error_code
Index_bit
vector_sz
_$ 昀椀
ve
Coun
t XOR
The following are invalid identifiers:
4bita
dder
$erro
r_cod
e
• 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 keywords) that have a special
meaning to the Verilog compiler. In this text, we will put all reserved words in
boldface type.
List of Keywords (Verilog IEEE Standard 2005)
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 simultaneously 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.
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].
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
corresponding pairs of elements.

4. Veril og M o d u l e s
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 declaration 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.
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 interconnections from this module to the
external world as in Figure 2-8.

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.
The module declarations form:
m o d u l e module-name (module interface
list); [list-of-interface-ports]
...
[port-declarations]
...
[functional-speci 椀
昀 cation-of-module]
...
e nd mo d ule
The items enclosed in square brackets are optional. The list-of-interfaceports 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.

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.
Example: 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.
In this example, the Verilog assignment statements for Sum and Cout represent the logic equations
for the full adder. The specified equations are

Several other architectural descriptions such as a truth table or an interconnection 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
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).

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 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 C o u t
and S u m outputs of the adder for least significant bit. Unconnected ports can be omitted. In case
the signals 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. 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
m o d u l e Adder4 (S, Co, A, B, Ci);
o utp ut [3:0]
S; o utp ut 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]);
e nd mo d ule
All of the simulation examples use the ModelSim Verilog simulator from Mentor Graphics. Most
other Verilog simulators use similar command files and can produce output in a similar format. The
simulator command file is usually called the do file. The following simulator commands used to
test Adder4:
add list A B Co C Ci S // put these signals on the
output
force A list // set the A inputs to
1111 1111
force B // set the B inputs to
0001 0001
force Ci 1 // set Ci to 1
run 5 0 ns // run the simulation for 5 0 ns
force Ci 0
force A
0101
We have chosenforce
to runBthe simulation for 50 ns for each input set, since this is more than enough
1110
time for the carry
runto 5
propagate
0 ns through all of the full adders. The simulation results for the above
command list are:

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

The sum and carry are computed by each FA and appear at the FA outputs 10 ns later:

Since the inputs to FA1 have changed, the outputs change 10 ns later:
The final simulation results are:
1111 + 0001 +1= 0001 with a carry of 1 (at time 5 40 ns) and
0101 + 1110 + 0 = 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.

U s e of “Inout” M o d e
Let us consider the example in Figure 2-13. Assume that all variables are 0 @ 0 ns, but A changes to
1 @ 10 ns.
FIGURE 2-13: Verilog Code Illustrating Use of Output as an Input Signal
m o d u l e gates (A, B, C, D, E);
input A, B, C;
o utp ut D, E;
a s s i g n # 5 D = A // statement 1
| B; a s s i g n # 5 E // statement 2 uses D as an
= C | D; input
e nd mo d ule
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
m o d u l e gates (A, B, C, D, E);
input A, B,
C; o utp ut E;
inout D;
assign # 5 D = A // statement
| B; a s s i g n # 5 E 1
= C | D; // statement 2
e nd mo d ule
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.
5. Ver ilog A s s i g n m e n t s
There are two types of assignment in the Verilog:
continuous assignments and
procedural 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 assignments assign the value in declaration without using the
assign keyword. The following examples show the difference between explicit and implicit
continuous assignments.
wire C;
a s s i g n C = A || // explicit
continuous
B; assignment
wire D = E && // implicit continuous
F; assignment
Procedural assignments are used to model registers and finite state machines using the always
keyword.

Procedural A s s i g n m e n t s
The concurrent statements are useful in modeling combinational 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 selective
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. Initial blocks are useful in simulation
and verification, but only always blocks are synthesized.
Initial Statements
An initial statement has the following basic form:

initia
l
begi
n
seque
ntial-
state
ment
s
end

Always
Stateme
nts
An
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. 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 = or <= in an always block should be defined as
reg data type. Any other data type including wire is illegal. The assignment operator “=” indicates
concurrent execution when used outside an always block. When the statements
C = A && // concurrent statements
B; E = C ||
// when used outside always
block
D;
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 “=” is used for representing the blocking
assignment. The meaning of “blocking” is that a blocking assignment has to complete 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 “<=” is used for
representing the non-blocking assignment.
For instance, consider the situation if they are in an always block, as
shown here:
a l w ay s @(A, B,
D)
begin
// Blocking operator is
C = A && B; used
E = C || D; // Statements execute sequentially
end
The block executes once when any of the signals A, B, or D changes. The first statement 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 “=” 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 “=” has a blocking nature inside the always
block but a non-blocking or concurrent nature outside the always block.

The operator “<=” is to evaluate several assignments at the same time without blocking the
sequential flow. Consider the following code:
a l w ay s @(A, B, D)
begin
C < = A && // Statements execute
B; simultaneously
because
// non-blocking operator is
E < = C || D; used
end
The block executes once when any of the signals A, B, or D changes. Both statements 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 “<=” 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 “=” outside the always block, but with
“<=” 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 = or <= in an always block. Figure 2-15 shows a comparison
of blocking assignments and non-blocking assignments.
F I G U R E 2-15: Blocking and Non-Blocking Assignments
m o d u l e sequential_module (A, B, C, D, clk);
input clk;
o utp ut A, B, C, D;
r e g A, B, C, D;
a l w ay s @(posedge clk)
begin
A= // blocking statement
B; 1
B = // blocking statement
a l w ay s @(posedge
A; 2
clk)
end
C
b e<g=in // non-blocking statement
D; 1
D <= // non-blocking statement
C;nd mo d ule
e 2
end
The posedge keyword of Verilog is used for an edge-triggered functionality 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 A=C=1’b1 and B=D=1’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 assignments 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 C=1’b0 and D=1’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 sequential logic; however,
always statements are not necessary for modeling combinational logic. They are required for
modeling sequential logic. One should be very careful when using always statements to represent
combinational logic. If 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 =
or <= 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
m o d u l e two_gates (A, B, C, D, E);
input A, B,
C; o utp ut
D, E; r e g D,
E; a l w ay s
@(*) b e g i n
# 5 D = A || // blocking statement
B; # 5 E = C 1

|| D; // blocking statement
2
end
Let us assume that all e nd moare
variables d u0 @ 0 ns. Then, A changes to 1 @ 10 ns. That causes the module
le inside the always statement execute once sequentially. D becomes 1 @ 15
to execute. The statements
ns, and E becomes 1 @ 20 ns. While sequential logic can be modeled using the blocking operator
“=,” it is generally advised not to do so. A good coding practice while writing synthesizable code is
to use non-blocking assignments (i.e., “<=”) in always blocks intended to create sequential logic and
the blocking operator “=” 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.
The sensitivity list in sequential circuit contains three kinds of edge-
triggered events: clock, reset, and set signal event. The sensitivity list
can be speci 昀椀 ed 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 speci 椀
昀 ed inside the always block.

Wire a n d Re g
The two Verilog data types that we have used so far are wire and reg.
The wire acts as real wires in circuit designs. The r e g is similar to
wires, but can store information just like registers. The declarations for
wire and r e g 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 wire s 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 = or < = in an always @
block.
The data type r e g 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 r e g to model both
combinational and sequential logic.
Data type r e g is the only legal type on the left-hand side element of an
= or < = 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. The default Verilog HDL data value set is a 4-value system
consisting of four basic values:
1 represents a logic zero, or a false condition.
2 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).

M o d e l i n g Flip-F l ops U s i n g A l w ay s 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 corresponding code is given in Figure 2-17.
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 indicates 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 = D; executes whenever D changes. If we
synthesize the foregoing code, the synthesizer 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 = 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 = 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.

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.
In the foregoing examples, we have used two types of sequential statement: signal 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 m a y 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 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.
A Verilog module for a J-K flip-flop shown in 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 = RN = 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
statement. Both RN and SN are active low signals. If RN = 0, the flip-flop is reset, and if SN = 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 = = 1’b0) are acceptable.
F I G U R E 2-22: J-K Flip-Flop Model
m o d u l e JKFF (SN, RN, J, K, CLK, Q, QN);
input SN, RN, J, K, CLK;
o utp ut Q, QN;
r e g Qint;
a l w ay s @ ( n e g e d g e CLK or RN or SN)
begin
if
(#~8RN ) <=
Qint //
statement1
0; e ls e if
(~SN) # 8 //
statement2
Qint < = 1;
else
Qint < = # 1 0 ((J && ~Qint) || ( ~ K && Qint));

// statement3
end
a s s i g n Q = Qint; //
statement4
as s ig n QN =
//
~Qint;
statement5
The condition (negedge CLK)eisnd mo d
TRUE ule
only if CLK has just changed from 1 to 0. The next state of
the flip-flop is determined by its characteristic equation:
Q+ = JQ| + K| Q
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.

A l w ay s B l o c k s U s i n g E ven t Control S t a t e m e n t s
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 speci 昀
椀 ed
inside the always block.
For a l w ay
example:
s begin
#10
clk < =
~clk;
will work as long as non-zero delay is speci 椀
昀 ed.
end
An always block cannot have both wait statements and a sensitivity
list. An always block with wait statements m a y have the form
a l w ay
s
begin
sequential-
statements wait-
statement
sequential-
statements wait-
statement
...
end
Such an always block could look like
a l w ay s
begin
rst = 1; // sequential statements
@ ( p o s e d g e 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.
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:
a l w ay s
begin
wait
(WR)
ME
M
=
DAT
A_I
N;
wait
(~WR)
DAT
A_O
UT
=
ME
M;
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.
Example
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.
Example
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;
else
sum = 0;
carry = 0;
end
(e) It will compile but not simulate correctly
(f) It will compile and simulate correctly
but not synthesize correctly
(g) It will work correctly in simulation and
synthesis
(h) 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.
D e l ay s in Verilog
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;
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.
Trans p o rt d e l ay is intended to model the delay introduced by wiring; it
simply delays an input signal by the speci 昀
椀 ed delay time. In order to
model this delay, a delay value must be speci 椀
昀 ed on the right-hand side
of the statement. Figure 2-2 3 illustrates trans p o rt d e l ay and inertial
d e l ay in Verilog. Consider the following code:
always @
(X) begin
Z 1 < = # 1 0 (X); // transport
delay end
assign # 1 0 Z 2 = X; //
inertial delay
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 continuous assign statements. Hence the following
statement is illegal. It will produce a compile-time error.
a s s i g n a = # 1 0 b;
Verilog also has a type of delay called net delay. Consider
the code
wire C1;
wire # 1 0 C2; // net delay on wire C2
a s s i g n # 3 0 C 1 = A || B; // statement 1 – inertial delay
a s s i g n # 2 0 C 2 = 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 declaration 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.
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
a s s i g n # 7 D = Y; // statement 1 – inertial delay
wire # 7 E; // net delay on wire E
a s s i g n # 3 E = 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 1 0 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.

Compilation, Simulation, a n d S y n t h e s i s of Ver ilog


C od e

After describing a digital system in Verilog, simulation of the Verilog


code is important for two reasons.
First, need to verify that the Verilog code correctly implements
the intended design, and second, need to verify that the design
meets its speci 椀
昀 cations.
We 昀椀 rst simulate the design and then synthesize it to the target
technology (FPGA or custom ASIC). As illustrated in Figure 2-25, there
are three phases in the simulation of Verilog code: analysis
(compilation), elaboration, an d simulation.

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 semantic 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 elaboration. 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 simulated.
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 speci 椀
昀 ed in the Verilog model. In
the absence of any speci 昀
椀 cations of the initial values, 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,
system tasks, and so forth.
Every change in value of a net or variable in the circuit being
simulated is considered an u p d a t e 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 s imulat io n 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 s c h e d u l i n g a n event.

The Verilog event queue is logically segmented into 昀


椀 ve 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 昀
椀 ve regions but can be removed only from this region (i.e.,
any active event for immediate 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.
Non-blocking assign update region: Events that have been evaluated during some previous
III.
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, inactive, 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
Whennon-blocking assignment
each Verilog update events.
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 nonblocking
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:
viii.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.)
ix.Then activate all inactive events for that time (and process them because now they are active).
x. 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 椀
昀 ve steps happen at the same time, but the events occur
in the order active, inactive, non-blocking update, and monitor events.
Basically, the simulator works as follows with “ < = ” : whenever a
component input changes, the output is scheduled to change after the
speci 椀
昀 ed delay or after D if no delay is speci 椀
昀 ed. When all events for
the current time have been processed, simulated time is advanced to
the next time at which an event is speci 椀
昀 ed. When time is advanced
by a 昀椀 nite 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 the b e g i n . . . end, and the
two updates are performed in source order as well. Hence, the variable
a will be assigned 0 昀椀 rst and then 1 in that order. There is no
nondeterminism in this code. However, for the code in Figure 2-26(b), the
two a l w ay s blocks are concurrent with respect to each other and there
is no ordering between them. Hence the assigned value of a is non-
deterministic.
Ver ilog D a t a Ty p e s a n d Op er a t or s
D a t a Types
Verilog has two main groups of data types: the variable d a t a t y p e s
and the
net d a t a 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 entities, such as gates. Generally, it does not store values.
Instead, its value is determined 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 prede 椀
昀 ned data types that are part of nets. Examples are tri
(for tristate), w a n d (for wired and), wo r (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.
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)
variable data storage elements that can retain values (declared
s
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 氀

oating-point number (declared with the keyword real)
time a special variable data type to store time information
(declared with the keyword time)
vector wire or reg data types can be declared as vectors (multiple
s bits) (vectors can be declared with [range1: range2])
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.
Veril og Operat ors
Operators perform an operation on one or more operands within an
expression. An expression combines operands with appropriate
operators to produce the desired functional expression.
1. Arithmetic Op e rato rs
For the FPGA, division and multiplication are very expensive, and
sometimes we cannot synthesize division. If we use Z or X for values,
the result is unknown. The operations treat the values as unsigned.
Character Operation performed Example

+ Add b + c = 11

- Subtract b - c = 9, -b=-10

/ Divide b/a=2

* Multiply a * b = 50

% Modulus b%a=0

2. Bitwise Operators
Each bit is operated, the result is the size of the largest operand, and the smaller operand is left
extended with zeroes to the bigger operand's size.

Character Operation performed Example

~ Invert each bit ~a = 3'b010


3. Reduction Operators
& And each bit b & c = 3'b010
Thes operator
e |
Charac Or each bit
Operation a |Exampl
b = 3'b111 s
reduce vectors
the t er performed e
only one ^ Xor each bit a ^ b = 3'b011 to bit. If
are & And all &a = 1'b0, &d there
^~ or ~^ Xnor each bit
bits a ^~
= b 1'b0
= 3'b100
z t characters
the
and ~ Nand all ~&a =
can be h result
& bits 1'b1
a value. e | Or all |a = 1'b1, |c known
bits = 1'bX
x,
~| Nor all ~|a=
bits 1'b0
^ Xor all ^a =
bits 1'b1
^ ~ or Xnor all bits
VERSITY: CHIT TOOR ~^a =
1'b0
4. Relational Operators
These operators compare operands and results in a 1-bit scalar Boolean value. The case equality and
inequality operators can be used for unknown or high impedance values (z or x), and if the two
operands are unknown, the result is a 1.

Character Operation performed Example

> Greater than a > b = 1'b0

< Smaller than a < b = 1'b1

>= Greater than or equal a > = d = 1'bX

<= Smaller than or equal a < = e = 1'bX

== Equality a = = b = 1'b0

!= Inequality a ! = b = 1'b1

=== Case equality e = = = e = 1'b1

!=== Case inequality a ! = = d = 1'b1

5. Logical Operators

These operators compare operands and results in a 1-bit scalar Boolean value.

Character Operation performed Example

! Not true !(a && b) = 1'b1

&& Both expressions true a && b = 1'b0

|| One ore both expressions true a || b = 1'b1


6. Shift Operators
These operators shift operands to the right or left, the size is kept constant, shifted bits are lost, and
the vector is filled with zeroes.

Character Operation performed Example

>> Shift right b > > 1 results 4 ? b0 1 0 X

<< Shift left a < < 2 results 4 ? b1 0 0 0

7. Assignment Operators

There are three assignment operators, each of which performs different tasks, and are used with
different data types:

o assign (continuous assignment)


o < = (non-blocking assignment)
o = (blocking assignment)

8. Other Operators

These are operators used for condition testing and to create vectors.

Character Operation performed Example

?: Conditions testing test cond. ? if true do this or if not do


this
{} Concatenate c = { a , b } = 8 '1 0 1 0 1 0 x0

{{}} Replicate { 3 { 2 ' b 1 0 } } = 6'b101010

9. Operators Precedence

The order of the table tells what operation is made 椀 昀 rst. The 椀
昀 rst one
has the highest priority. The () can be used to override the default.

Operators precedence

+ , -, !, ~ (Unary)

+,- (Binary)

<<, > >


<,>,<=,>=

= =, !=

&

^ , ^ ~ or ~ ^

&&

||

?:

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.

U s i n g 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 = A’. I0 + A. I1.
The corresponding Verilog statement is
assign F = (~A && I0) || (A && I1);

This statement executes whenever A, I0, or I1 changes. The MUX output is I0 when A =0; otherwise, it
is I1. In the conditional statement, I0, I1, and F can be one or more bits.
The general form of a conditional signal assignment statement is
assign signal_name =
condition? expression_T : expression_F;
U s i n g If-e ls e or C a s e S t a t e m e n t in a n
A l w ay s Block

Since this M U X 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 < n u m b e r of b i t s > ' < b a s e > < v a l u e > .
The b represents that the base is binary here. The case statement has
the general form:

As an alternative, the MUX can also be modeled using an if-else statement within an always block:

Modeling Registers a n d Counters Using


Veril og A l w ays S t a t e m e n t s

The order of the statements is not important when the non-blocking assignment operator “<=” is
used. The same result is obtained even if the statements are in reverse order as shown here.
a l w ay s @ ( p o s e d g e
CLK)
begin
Q3 < = # 5
Q2; Q 2 < =
# 5 Q1; Q 1
< = # 5 Q3;
end
A 3-bit shift register:

simple register:
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 = 0, all flip-flops are set to 0 following the rising clock edge.
2.If ClrN = 1 and LdN = 0, the D inputs are transferred (loaded) in parallel to the flip-
flops following the rising clock edge.
3.If ClrN = LdN = 1 and P= T = 1, the count is enabled and the counter state will
be incremented by 1 following the rising clock edge.
If T = 1, the counter generates a carry (Cout) in state 15; consequently
Cout = 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.
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 overrides
count, LdN is tested next. Finally, the counter is incremented if both P and T are 1.
Behavioral a n d 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.
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 representation of the logic function
F = ab+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 examples of which are by using two AND gates and one OR gate or three NAND gates.
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 representations. A structural
description specifies more details, whereas the behavioral level description specifies only the
behavior at a higher level of abstraction.
D Flip 氀

op
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
`de 昀椀 ne constant_name
constant_value
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:
p ar am e t e r constant_name = constant_value;
For example,
p ar a m e t e r ms b = 15; // de 椀
昀 nes ms b as a constant value 15
p ar a m e t e r [31:0] decim = 1'b1; // value converted to 3 2 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 parameter can be used to customize the module instances. Typical uses of
parameters are to specify delays and width of variables.
A r r ay s
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,
r e g [7:0] eight_bit_register;
the register variable eight_bit_register can store one byte (eight bits) of information.
The 8-bit register can be initialized to hold the value 00000001 using the following statement:
eight_bit_register = 8'b00000001;
As a second option, array bounds can be declared after the name of the array. In the declaration that
follows, r e g a is an array of n 1-bit registers while r e g b is a single n-bit register.
r e g rega [1:n]; // This is an array of n 1-bit registers
r e g [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 onebyte (8-bit) vector
information.
r e g [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] =
8'b00001100;
eight_bit_register_array[14] =
8'b00000000;
........
eight_bit_register_array[1] =
8'b11001100;
eight_bit_register_array[0] =
8'b00010001;
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 6 4
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:
r e g [7:0] matrixA [0:3] [0:2] = { { 1, 2, 3},
{ 4, 5,

6},
{ 7, 8,

9},
{ 1 0 , 11, 1 2 } } ;
The array element matrixA[3][1] references the element in the fourth row and second column, which
has a value of 11.
Look- U p Table M e t h o d U s i n g Arrays a n d 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 R O M or Look-up Table (LUT) method.
Example
Parity bits are often used in digital communication for error
detection and correction. The 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.
A n s we r: The input word is a 4-bit binary number. A 5-bit odd-
parity representation will contain exactly an odd number of 1 s in the
output word. This can be accomplished by the R O M or LUT method using
a look-up table of size 16 entries × 5 bits. The look-up table is indicated in
Figure 2-60.
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.

L o o p s in Verilog
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 useful 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 # 1 0 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 ++ and --
in Verilog. Instead of using those operators as in C language, we need to use its full operational
statement, i = i + 1. The general form of a for loop is as follows:
The following example is of initializing an array variable, eight_bit_register_ array, using a for
loop.

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 = 1, i = 2, and i = 3; then the loop will terminate.
The carry out from one iteration (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.

We 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


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.

Repeat Loop
The repeat loop repeats the sequential statement(s) for specified times. The number of repetitions is
set by a constant value or a logical expression.
re p e at ( 8 )
begin
x= x+
1; y = y
+ 2;
end

You might also like