0% found this document useful (0 votes)
139 views48 pages

Module 1: Overview of Digital Design With Verilog HDL

This document provides an overview of the evolution of digital circuit design and the role of hardware description languages (HDLs) like Verilog. It describes how digital design has progressed from manual transistor-level design to using HDLs at higher levels of abstraction. HDLs allow designers to describe circuits functionally in terms of data flow and let synthesis tools implement the design using gates. This cuts down design time and improves verification. Verilog has become a dominant HDL standard for its features and support by EDA tools. Modern design flows typically involve specifying a design behaviorally in HDL, synthesizing to optimize it, and simulating the resulting gate-level netlist.

Uploaded by

GranTorino
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)
139 views48 pages

Module 1: Overview of Digital Design With Verilog HDL

This document provides an overview of the evolution of digital circuit design and the role of hardware description languages (HDLs) like Verilog. It describes how digital design has progressed from manual transistor-level design to using HDLs at higher levels of abstraction. HDLs allow designers to describe circuits functionally in terms of data flow and let synthesis tools implement the design using gates. This cuts down design time and improves verification. Verilog has become a dominant HDL standard for its features and support by EDA tools. Modern design flows typically involve specifying a design behaviorally in HDL, synthesizing to optimize it, and simulating the resulting gate-level netlist.

Uploaded by

GranTorino
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/ 48

Module 1: Overview of Digital Design with Verilog HDL

Evolution of Computer-Aided Digital Design:

Digital circuit design has evolved rapidly over the last 25 years. The earliest digital circuits
were designed with vacuum tubes and transistors. Integrated circuits were then invented
where logic gates were placed on a single chip. The first integrated circuit (IC) chips were
SSI (Small Scale Integration) chips where the gate count was very small. As technologies
became sophisticated, designers were able to place circuits with hundreds of gates on a chip.
These chips were called MSI (Medium Scale Integration) chips. With the advent of LSI
(Large Scale Integration), designers could put thousands of gates on a single chip. At this
point, design processes started getting very complicated, and designers felt the need to
automate these processes.

Electronic Design Automation (EDA)techniques began to evolve. Chip designers began to


use circuit and logic simulation techniques to verify the functionality of building blocks of
the order of about 100 transistors. The circuits were still tested on the breadboard, and the
layout was done on paper or by hand on a graphic computer terminal.

The term Computer-Aided Design (CAD) tools refers to back-end tools that perform
functions related to place and route, and layout of the chip . The term Computer-Aided
Engineering (CAE) tools refers to tools that are used for front-end processes such HDL
simulation, logic synthesis, and timing analysis. Designers used the terms CAD and CAE
interchangeably. Today, the term Electronic Design Automation is used for both CAD and
CAE.

With the advent of VLSI (Very Large Scale Integration) technology, designers could design
single chips with more than 100,000 transistors. Because of the complexity of these circuits,
it was not possible to verify these circuits on a breadboard. Computer aided techniques
became critical for verification and design of VLSI digital circuits. Computer programs to do
automatic placement and routing of circuit layouts also became popular. The designers were
now building gate-level digital circuits manually on graphic terminals. They would build
small building blocks and then derive higher-level blocks from them. This process would
continue until they had built the top-level block. Logic simulators came into existence to
verify the functionality of these circuits before they were fabricated on chip. As designs got
larger and more complex, logic simulation assumed an important role in the design process.

Emergence of HDLs:
For a long time, programming languages such as FORTRAN, Pascal, and C were being used
to describe computer programs that were sequential in nature. Similarly, in the digital design
field, designers felt the need for a standard language to describe digital circuits. Thus,
Hardware Description Languages (HDLs) came into existence.

HDLs allows the designers to model the concurrency of processes found in hardware
elements. Hardware description languages such as Verilog HDL and VHDL became popular.

Verilog HDL originated in 1983 at Gateway Design Automation.

Later, VHDL was developed under contract from DARPA. Both Verilog and VHDL
simulators to simulate large digital circuits quickly gained acceptance from designers.

Even though HDLs were popular for logic verification, designers had to manually translate
the HDL-based design into a schematic circuit with interconnections between gates.

The advent of logic synthesis in the late 1980s changed the design methodology radically.
Digital circuits could be described at a register transfer level (RTL) by use of an HDL. Thus,
the designer had to specify how the data flows between registers and how the design
processes the data. The details of gates and their interconnections to implement the circuit
were automatically extracted by logic synthesis tools from the RTL description.

Thus, logic synthesis pushed the HDLs into the forefront of digital design. Designers could
describe complex circuits at an abstract level in terms of functionality and data flow by
designing those circuits in HDLs. Logic synthesis tools would implement the specified
functionality in terms of gates and gate interconnections.

HDLs also began to be used for system-level design. HDLs were used for simulation of
system boards, interconnect buses, FPGAs (Field Programmable Gate Arrays), and PALs
(Programmable Array Logic). A common approach is to design IC chip, using an HDL, and
then verify system functionality via simulation.

Verilog HDL is an accepted IEEE standard. In 1995, the original standard IEEE
1364-1995 was approved.

IEEE 1364-2001 is the latest Verilog HDL standard that made significant improvements to
the original standard.

Typical Design Flow:


A typical design flow for designing VLSI IC circuits is shown in figure below.

.
Unshaded blocks show the level of design representation;
shaded blocks show processes in the design flow

Figure: Typical Design Flow

In any design, specifications are written first. Specifications describe abstract of the
functionality, interface, and overall architecture of the digital circuit to be designed.

A behavioural description is then created to analyze the design in terms of functionality,


performance, compliance to standards, and other high-level issues. Behavioural descriptions
are written with HDLs.
.
The behavioural description is converted to an RTL description in an HDL. The designer has
to describe the data flow that will implement the desired digital circuit.
Logic synthesis tools convert the RTL description to a gate-level netlist. A gate-level netlist
is a description of the circuit in terms of gates and connections between them. Logic synthesis
tools ensure that the gate-level netlist meets timing, area, and power specifications. The gate-
level netlist is input to an Automatic Place and Route tool, which creates a layout. The layout
is verified and then fabricated on a chip.

Thus, most digital design activity is concentrated on manually optimizing the RTL
description of the circuit. After the RTL description is frozen, EDA tools are available to
assist the designer in further processes.

Importance of HDLs:
HDLs have many advantages compared to traditional schematic-based design.
➢ Designs can be described at a very abstract level by use of HDLs. Designers can write
their RTL description without choosing a specific fabrication technology. Logic
synthesis tools can automatically convert the design to any fabrication technology. If
a new technology emerges, designers do not need to redesign their circuit. They
simply input the RTL description to the logic synthesis tool and create a new gate-
level netlist, using the new fabrication technology. The logic synthesis tool will
optimize the circuit in area and timing for the new technology.

➢ By describing designs in HDLs, functional verification of the design can be done


early in the design cycle. Since designers work at the RTL level, they can optimize
and modify the RTL description until it meets the desired functionality. Most design
bugs are eliminated at this point. This cuts down design cycle time significantly
because the probability of hitting a functional bug at a later time in the gate-level
netlist or physical layout is minimized.

➢ Designing with HDLs is analogous to computer programming. A textual description


with comments is an easier way to develop and debug circuits. This also provides a
concise representation of the design, compared to gate-level schematics. Gate-level
schematics are almost incomprehensible for very complex designs.

➢ With rapidly increasing complexities of digital circuits and increasingly sophisticated


EDA tools, HDLs are now the dominant method for large digital designs. No digital
circuit designer can afford to ignore HDL-based design.

➢ New tools and languages focused on verification have emerged in the past few years.
These languages are better suited for functional verification. However, for logic
design, HDLs continue as the preferred choice.

Popularity of Verilog HDL:

Verilog HDL has evolved as a standard hardware description language. Verilog HDL
offers many useful features
➢ Verilog HDL is a general-purpose hardware description language that is easy to learn
and easy to use. It is similar in syntax to the C programming language.

➢ Verilog HDL allows different levels of abstraction to be mixed in the same model.
Thus, a designer can define a hardware model in terms of switches, gates, RTL, or
behavioural code. Also, a designer needs to learn only one language for stimulus and
hierarchical design.

➢ Most popular logic synthesis tools support Verilog HDL. This makes it the language
of choice for designers.

➢ All fabrication vendors provide Verilog HDL libraries for postlogic synthesis
simulation. Thus, designing a chip in Verilog HDL allows the widest choice of
vendors.

➢ The Programming Language Interface (PLI) is a powerful feature that allows the user
to write custom C code to interact with the internal data structures of Verilog.
Designers can customize a Verilog HDL simulator to their needs with the PLI.
Trends in HDLs:
The speed and complexity of digital circuits have increased rapidly. Designers have
responded by designing at higher levels of abstraction. Designers have to think only in terms
of functionality. EDA tools take care of the implementation details. With designer assistance,
EDA tools have become sophisticated enough to achieve a close-to-optimum implementation.

The most popular trend currently is to design in HDL at an RTL level, because logic
synthesis tools can create gate-level netlists from RTL level design. Behavioral synthesis
allowed engineers to design directly in terms of algorithms and the behavior of the circuit,
and then use EDA tools to do the translation and optimization in each phase of the design.

Formal verification and assertion checking techniques have emerged. Formal verification
applies formal mathematical techniques to verify the correctness of Verilog HDL descriptions
and to establish equivalency between RTL and gate-level netlists. However, the need to
describe a design in Verilog HDL will not go away. Assertion checkers allow checking to be
embedded in the RTL code. This is a convenient way to do checking in the most important
parts of a design.
New verification languages have also gained rapid acceptance. These languages combine
the parallelism and hardware constructs from HDLs with the object oriented nature of C++.
These languages also provide support for automatic stimulus creation, checking, and
coverage. However, these languages do not replace Verilog HDL. They simply boost the
productivity of the verification process. Verilog HDL is still needed to describe the
design.

For very high-speed and timing-critical circuits like microprocessors, the gate-level netlist
provided by logic synthesis tools is not optimal. In such cases, designers often mix gate-level
description directly into the RTL description to achieve optimum results. This practice is
opposite to the high-level design paradigm, yet it is frequently used for high speed designs
because designers need to squeeze the last bit of timing out of circuits, and EDA tools
sometimes prove to be insufficient to achieve the desired results.

Another technique that is used for system-level design is a mixed bottom-up methodology
where the designers use either existing Verilog HDL modules, basic building blocks, or
vendor-supplied core blocks to quickly bring up their system simulation. This is done to
reduce development costs and compress design schedules.
For example, consider a system that has a CPU, graphics chip, I/O chip, and a system bus.
The CPU designers would build the next-generation CPU themselves at an RTL level, but
they would use behavioral models for the graphics chip and the I/O chip and would buy a
vendor-supplied model for the system bus. Thus, the system-level simulation for the CPU
could be up and running very quickly and long before the RTL descriptions for the
graphics chip and the I/O chip are completed.

Hierarchical Modeling Concepts:

Design Methodologies
There are two basic types of digital design methodologies:
✓ Top-down design methodology
✓ Bottom-up design methodology.

In a top-down design methodology:


✓ First define the top-level block
✓ Identify the sub-blocks necessary to build the top-level block.
✓ Then subdivide the sub-blocks until leaf cells are reached, which are the cells that
cannot further be divided.

Figure: Top-down Design Methodology

In a bottom-up design methodology:


✓ First identify the building blocks that are available to us.
✓ Build bigger cells, using these building blocks.
✓ These cells are then used for higher-level blocks until we build the top-level block in
the design.
Figure : Bottom-up Design Methodology

Typically, a combination of top-down and bottom-up flows is used. Design architects define
the specifications of the top-level block. Logic designers decide how the design should be
structured by breaking up the functionality into blocks and sub-blocks. At the same time,
circuit designers are designing optimized circuits for leaf-level cells. They build higher-level
cells by using these leaf cells. The flow meets at an intermediate point where the switch-level
circuit designers have created a library of leaf cells by using switches, and the logic level
designers have designed from top-down until all modules are defined in terms of leaf cells.

Example: 4-bit Ripple Carry Counter:


The ripple carry counter shown in figure is made up of negative edge-triggered toggle flip
flops (T_FF). Each of the T_FFs can be made up from negative edge-triggered D-flip flops
(D_FF) and inverters (assuming q_bar output is not available on the D_FF).
.

Figure : Ripple Carry Counter


Figure :T-flip flop

Figure : Design Hierarchy

In a top-down design methodology, we first have to specify the functionality of the ripple
carry counter, which is the top-level block. Then, we implement the counter with T_FFs.
We build the T_FFs from the D_FF and an additional inverter gate. Thus, we break bigger
blocks into smaller building sub-blocks until we decide that we cannot break up the blocks
any further.
A bottom-up methodology flows in the opposite direction. We combine small building blocks
and build bigger blocks; e.g., we could build D_FF from and & or gates, or we could build a
custom D_FF from transistors. Thus, the bottom-up flow meets the top-down flow at the level
of the D_FF.
Modules:
Verilog provides the concept of a module. A module is the basic building block in Verilog. A
module can be an element or a collection of lower-level design blocks. Typically, elements
are grouped into modules to provide common functionality that is used at many places in the
design.
A module provides the necessary functionality to the higher-level block through its port
interface (inputs, outputs and inouts ), but hides the internal implementation. This allows the
designer to modify module internals without affecting the rest of the design.

In the example of ripple carry counter, T_FF, D_FF are examples of modules.

In Verilog, a module is declared by the keyword module. A corresponding keyword


endmodule must appear at the end of the module definition. Each module must have a
module_name, which is the identifier for the module, and a module_terminal_list, which
describes the input and output terminals of the module

module <module_name> (<module_terminal_list>);


...
<module internals>
...
...
endmodule

Example: Module T-flipflop is defined as follows:

module T_FF (q, clock, reset);


.
.
<functionality of T-flipflop>
.
.
endmodule
Verilog is both a behavioral and a structural language. Internals of each module can be
defined at four levels of abstraction, depending on the needs of the design. The module
behaves identically with the external environment irrespective of the level of abstraction
at which the module is described. The internals of the module are hidden from the
environment. Thus, the level of abstraction to describe a module can be changed without
any change in the environment.

Different levels of abstraction

✓ Behavioral or algorithmic level


✓ Dataflow level
✓ Gate level
✓ Switch level
✓ Mixed level

Behavioral or algorithmic level: This is the highest level of abstraction provided by Verilog
HDL. The behavioral description describes the system by showing how the output behaves
according to the changes in the input. A module can be implemented in terms of the desired
design algorithm without concern for the hardware implementation details. Designing at this
level is very similar to C
programming.

Dataflow level: At this level, the module is designed by specifying how the data flow from
system inputs to system outputs. The designer is aware of how data flows between hardware
registers and how the data is processed in the design.

Gate level: The module is implemented in terms of logic gates and interconnections between
these gates. Design at this level is similar to describing a design in terms of a gate-level logic
diagram.

Switch level: This is the lowest level of abstraction provided by Verilog. A module can be
implemented in terms of switches or transistors, storage nodes, and the interconnections
between them. Design at this level requires knowledge of switch-level implementation details
Mixed Level: This type of description uses more than one type of description mentioned
earlier

If a design contains four modules, Verilog allows each of the modules to be written at a
different level of abstraction. As the design matures, most modules are replaced with gate-
level implementations. Normally, the higher the level of abstraction, the more flexible and
technology independent the design. As one goes lower toward switch-level design, the design
becomes technology-dependent and inflexible. A small modification can cause a significant
number of changes in the design.

Instances:
• A module provides a template from which you can create actual objects.
• When a module is invoked, Verilog creates a unique object from the template.
• Each object has its own name, variables, parameters, and I/O interface.
• The process of creating objects from a module template is called instantiation, and the
objects are called instances.

In the ripple carry counter example


• The top-level block creates four instances from the T-flipflop (T_FF) template.
• Each T_FF instantiates a D_FF and an inverter gate.
• Each instance must be given a unique name.

Example : Module Instantiation

// top-level module called ripple carry counter. It instantiates 4 T-flip flops.

module ripple_carry_counter(q, clk, reset);


output [3:0] q; //output signals and vector declarations
input clk, reset; //Input signals declarations

//Four instances of the module T_FF are created, each has unique name
// Each instance is passed a set of signals
T_FF tff0(q[0],clk, reset);
T_FF tff1(q[1],q[0], reset);
T_FF tff2(q[2],q[1], reset);
T_FF tff3(q[3],q[2], reset);

endmodule

// Define the module T_FF. It instantiates a D-flipflop.

module T_FF(q, clk, reset);


output q;
input clk, reset;
wire d;

D_FF dff0(q, d, clk, reset); // Instantiate D_FF.


not n1(d, q); // not gate is a Verilog primitive

endmodule

In Verilog, it is illegal to nest modules.


One module definition cannot contain another module definition within the module and
endmodule statements.
Module definitions simply specify how the module will work, its internals, and its interface.
Modules must be instantiated for use in the design.

Example : Illegal Module Nesting

module ripple_carry_counter(q, clk, reset);


output [3:0] q;
input clk, reset;
module T_FF(q, clock, reset); // ILLEGAL MODULE NESTING
...
<module T_FF internals>
...
endmodule // END OF ILLEGAL MODULE NESTING
endmodule

Components of a Simulation:
Once a design block is completed, it must be tested. The functionality of the design block
can be tested by applying stimulus and checking results. keep the stimulus and design blocks
separate. The stimulus block can be written in Verilog. The stimulus block is also commonly
called a test bench. Different test benches can be used to thoroughly test the design block.

Two styles of stimulus application are possible:


✓ The stimulus block instantiates the design block and directly drives the signals in the
design block. The stimulus block becomes the top-level block. It manipulates signals
clk and reset, and it checks and displays output signal q.

Figure: Stimulus Block Instantiates Design Block

✓ Instantiate both the stimulus and design blocks in a top-level dummy module. The
stimulus block interacts with the design block only through the interface. The
stimulus module drives the signals d_clk and d_reset, which are connected to the
signals clk and reset in the design block. It also checks and displays signal c_q, which
is connected to the signal q in the design block. The function of top-level block is
simply to instantiate the design and stimulus blocks.
Figure: Stimulus and Design Blocks Instantiated in a Dummy Top-Level Module

Example
Design Block
use a top-down design methodology. First, write the Verilog description of the top-level
design block which is the ripple carry counter

Ripple Carry Counter Top Block

module ripple_carry_counter(q, clk, reset);


output [3:0] q;
input clk, reset;
//4 instances of the module T_FF are created.
T_FF tff0(q[0],clk, reset);
T_FF tff1(q[1],q[0], reset);
T_FF tff2(q[2],q[1], reset);
T_FF tff3(q[3],q[2], reset);
endmodule

In the above module, four instances of the module T_FF (T-flipflop) are used. Therefore,
define the internals of the module T_FF

Example : Flipflop T_FF


module T_FF(q, clk, reset);
output q;
input clk, reset;
wire d;
D_FF dff0(q, d, clk, reset);
not n1(d, q); // not is a Verilog-provided primitive. case sensitive
endmodule

Since T_FF instantiates D_FF, define the internals of module D_FF. We assume
asynchronous reset for the D_FFF.

Example: Flipflop D_F

// module D_FF with synchronous reset

module D_FF(q, d, clk, reset);


output q;
input d, clk, reset;
reg q;
always @(posedge reset or negedge clk)
if (reset)
q <= 1'b0;
else
q <= d;
endmodule

All modules have been defined down to the lowest-level leaf cells in the design
methodology. The design block is now complete.

Stimulus Block
Write the stimulus block to check if the ripple carry counter design is functioning correctly.
In this case, we must control the signals clk and reset so that the regular function of the ripple
carry counter and the asynchronous reset mechanism are both tested.

The cycle time for clk is 10 units;


the reset signal stays up from time 0 to 15 and then goes up again from time 195 to 205.
Output q counts from 0 to 15.
Figure : Stimulus and Output Waveforms

Example : Stimulus Block

module stimulus;
reg clk;
reg reset;
wire[3:0] q;
ripple_carry_counter r1(q, clk, reset); // instantiate the design block
initial
clk = 1'b0; //set clk to 0
always
#5 clk = ~clk; //toggle clk every 5 time units

initial
begin
reset = 1'b1;
#15 reset = 1'b0;
#180 reset = 1'b1;
#10 reset = 1'b0;
#20 $finish; //terminate the simulation
end
// Monitor the outputs
initial
$monitor($time, " Output q = %d", q);
endmodule
Example : Output of the Simulation
0 Output q = 0
20 Output q = 1
30 Output q = 2
40 Output q = 3
50 Output q = 4
60 Output q = 5
70 Output q = 6
80 Output q = 7
90 Output q = 8
100 Output q = 9
110 Output q = 10
120 Output q = 11
130 Output q = 12
140 Output q = 13
150 Output q = 14
160 Output q = 15
170 Output q = 0
180 Output q = 1
190 Output q = 2
195 Output q = 0
210 Output q = 1
220 Output q = 2
Module 2:Basic Concepts

Lexical Conventions: The basic lexical conventions used by Verilog HDL are similar to
those in the C programming language.

Verilog contains a stream of tokens. Tokens can be comments, delimiters, numbers, strings,
identifiers, and keywords. Verilog HDL is a case-sensitive language. All keywords are in
lowercase.

Whitespace: Blank spaces (\b) , tabs (\t) and newlines (\n) comprise the whitespace.
Whitespace is ignored by Verilog except when it separates tokens. Whitespace is not ignored
in strings.

Comments: Comments can be inserted in the code for readability and documentation.
There are two ways to write comments.
• A one-line comment starts with "//". Verilog skips from that point to the end of line.
Example: a = b && c; // This is a one-line comment

• A multiple-line comment starts with "/*" and ends with "*/".


Example: /* This is a multiple line
comment */

• Multiple-line comments cannot be nested.


Example: /* This is /* an illegal */ comment */

• One-line comments can be embedded in multiple-line comments.


Example: /* This is //a legal comment */

Operators : Operators are of three types: unary, binary, and ternary.


• Unary operators precede the operand and operates on single operand
Example: a = ~ b; // ~ is a unary operator. b is the operand

• Binary operators appear between two operands.


example: a = b && c; // && is a binary operator. b and c are operands
• Ternary operators have two separate operators that separate three operands.
Example: a = b ? c : d; // ?: is a ternary operator. b, c and d are
operands

Number Specification: There are two types of number specification in Verilog: sized and
unsized.

Sized numbers: Sized numbers are represented as <size> '<base format> <number>
✓ <size> is written only in decimal and specifies the number of bits in the number.
✓ Legal base formats are decimal ('d or 'D), hexadecimal ('h or 'H), binary ('b or 'B) and
octal ('o or 'O).
✓ The number is specified as consecutive digits from 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b,
c, d, e, f. Only a subset of these digits is legal for a particular base. Uppercase letters
are legal for number specification

Examples: 4'b1001 // This is a 4-bit binary number


12'habc // This is a 12-bit hexadecimal number
16'd215 // This is a 16-bit decimal number

Unsized numbers: Numbers that are written without a <size> specification.


✓ Numbers that are specified without a <base format> specification are decimal
numbers by default.
✓ Numbers that are written without a <size> specification have a default number of bits
that is simulator- and machine-specific (must be at least 32).
Examples: 23456 // This is a 32-bit decimal number by default
'hc3 // This is a 32-bit hexadecimal number
'o21 // This is a 32-bit octal number

X or Z values: Verilog has two symbols for unknown and high impedance values. These
values are very important for modeling real circuits.
✓ An unknown value is denoted by an x.
12'h13x // This is a 12-bit hex number; 4 least significant bits unknown

6'hx // This is a 6-bit hex number


✓ A high impedance value is denoted by z.
32'bz // This is a 32-bit high impedance number

• An x or z sets four bits for a number in the hexadecimal base, three bits for a number
in the octal base, and one bit for a number in the binary base.

• If the most significant bit of a number is 0, x, or z, the number is automatically


extended to fill the most significant bits, respectively, with 0, x, or z.

• This makes it easy to assign x or z to whole vector. If the most significant digit is 1,
then it is also zero extended.

Negative numbers: Negative numbers can be specified by putting a minus sign before the
size for a constant number.
✓ Size constants are always positive.
✓ It is illegal to have a minus sign between <base format> and <number>. An optional
signed specifier can be added for signed arithmetic.
Examples: -6'd3 // 8-bit negative number stored as 2's complement of 3
-6'sd3 // Used for performing signed integer math
4'd-2 // Illegal specification

Underscore characters and question marks:


An underscore character "_" is allowed anywhere in a number except the first character.
Underscore characters are allowed only to improve readability of numbers and are ignored by
Verilog.
Example: 12'b1111_0000_1010 // Use of underline characters for readability

A question mark "?" is the Verilog HDL alternative for z in the context of numbers. The ? is
used to enhance readability in the casex and casez statements.
Example: 4'b10?? // Equivalent of a 4'b10zz

Strings: A string is a sequence of characters that are enclosed by double quotes.


✓ A string must be contained on a single line, that is, without a carriage return.
✓ It cannot be on multiple lines.
✓ Strings are treated as a sequence of one-byte ASCII values.
Examples: "Hello SJCIT" // is a string
"a / b" // is a string

Identifiers and Keywords: Identifiers are user-defined words for variables, function names,
module names, block names and instance names. Identifiers begin with a letter or underscore
and can include any number of letters, digits and underscores.

Keywords are special identifiers reserved to define the language constructs. Keywords are in
lowercase. A list of all keywords in Verilog

always ifnone rnmos


and incdir rpmos
assign include rtran
automatic initial rtranif0
begin inout rtranif1
buf input scalared
bufif0 instance showcancelled
bufif1 integer signed
case join small
casex large specify
casez liblist specparam
cell library strong0
cmos localparam strong1
config macromodule supply0
deassign medium supply1
default module table
defparam nand task
design negedge time
disable nmos tran
edge nor tranif0
else noshowcancelled tranif1
end not tri
endcase notif0 tri0
endconfig notif1 tri1
endfunction or triand
endgenerate output trior
endmodule parameter trireg
endprimitive pmos unsigned
endspecify posedge use
endtable primitive vectored
endtask pull0 wait
event pull1 wand
for pulldown weak0
force pullup weak1
forever pulsestyle_onevent while
fork pulsestyle_ondetect wire
function rcmos wor
generate real xnor
genvar realtime xor
highz0 reg
highz1 release
if repeat
List of keywords frequently used by Verilog simulators for names of system tasks and
Functions
$bitstoreal $countdrivers $display $fclose
$fdisplay $fmonitor $fopen $fstrobe
$fwrite $finish $getpattern $history
$incsave $input $itor $key
$list $log $monitor $monitoroff
$monitoron $nokey

List of keywords frequently used by Verilog simulators for specifying compiler directives

'accelerate 'autoexpand_vectornets 'celldefine


'default_nettype 'define 'define
'else 'elsif 'endcelldefine
'endif 'endprotect 'endprotected
'expand_vectornets 'ifdef 'ifndef
'include 'noaccelerate 'noexpand_vectornets
'noremove_gatenames 'nounconnected_drive 'protect
'protected 'remove_gatenames 'remove_netnames
'resetall 'timescale 'unconnected_drive

Identifiers are names given to objects so that they can be referenced in the design.
✓ Identifiers are made up of alphanumeric characters, the underscore ( _ ), or the dollar
sign ( $ ).
✓ Identifiers are case sensitive.
✓ Identifiers start with an alphabetic character or an underscore.
✓ They cannot start with a digit or a $ sign (The $ sign as the first character is reserved
for system tasks)
Example: reg value; // reg is a keyword; value is an identifier
input clk; // input is a keyword, clk is an identifier

Escaped Identifiers: Escaped identifiers begin with the backslash ( \ ) character and end with
whitespace (space, tab, or newline).
✓ All characters between backslash and whitespace are processed literally.
✓ Any printable ASCII character can be included in escaped identifiers.
✓ Neither the backslash nor the terminating whitespace is considered to be a part of the
identifier.

Example: \a+b-c
\**my_name**

Escaped characters Character displayed


\n Newline
\t tab
%% %
\\ \
\" "
\ooo Characters written in 123 octal digits

Verilog Data Types:


Value Set: Verilog supports four values and eight strengths to model the functionality of real
hardware.

The four value levels are


Value Level Condition in Hardware
Circuits
0 Logic zero, false condition
1 Logic one, true condition
x Unknown logic value
z High impedance, floating state
The four Strength Levels are
Strength Level Type Degree
supply Driving strongest
strong Driving
pull Driving
large Storage
weak Driving
medium Storage
small Storage
highz High Impedance weakest

If two signals of unequal strengths are driven on a wire, the stronger signal prevails.
• if two signals of strength strong1 and weak0 contend, the result is resolved as a
strong1.
• If two signals of equal strengths are driven on a wire, the result is unknown.
• If two signals of strength strong1 and strong0 conflict, the result is an x.
• Strength levels are particularly useful for accurate modeling of signal contention,
MOS devices, dynamic MOS, and other low-level devices.
• Only trireg nets can have storage strengths large, medium, and small.

Nets:
• Nets represent connections between hardware elements.
• Just as in real circuits, nets have values continuously driven on them by the outputs of
devices that they are connected to.
• Nets are declared primarily with the keyword wire.
• Nets are one-bit values by default unless they are declared explicitly as vectors.
• The default value of a net is z (except the trireg net, which defaults to x).
• Nets get the output value of their drivers. If a net has no driver, it gets the value z.

In the above figure net a is connected to the output of and gate g1. Net a will continuously
assume the value computed at the output of gate g1, which is b & c.
Examples:
wire a; // Declares net a for the above circuit
wire b,c; // Declares two nets/wires b,c for the above circuit
wire d = 1'b0; // Net d is fixed to logic value 0 at declaration.

Registers:
• Registers represent data storage elements.
• Registers retain value until another value is placed onto them.
• In Verilog, the term register means a variable that can hold a value.
• Unlike a net, a register does not need a driver.
• Verilog registers do not need a clock as hardware registers do.
• Values of registers can be changed anytime in a simulation by assigning a new value
to the register.
• Register data types are commonly declared by the keyword reg.
• The default value for a reg data type is x.

Examples:
reg reset; // declare a variable reset that can hold its value
initial
begin
reset = 1'b1; //initialize reset to 1 to reset the digital circuit.
#100 reset = 1'b0; // after 100 time units reset is deasserted.
end

Registers can also be declared as signed variables. Such registers can be used for signed
arithmetic.
Example : Signed Register Declaration
reg signed [63:0] m; // 64 bit signed value

Vectors:
• Nets or reg data types can be declared as vectors (multiple bit widths).
• If bit width is not specified, the default is scalar (1-bit).
• Vectors can be declared at [high# : low#] or [low# : high#], but the left number in the
squared brackets is always the most significant bit of the vector

Examples:
wire a; // scalar net variable, default
wire [7:0] bus; // 8-bit bus
wire [31:0] busA, busB, busC; // 3 buses of 32-bit width.
reg clock; // scalar register, default
reg [0:40] virtual_addr; // Vector register, virtual address 41 bits wide

Vector Part Select:

In a vector, it is possible to address bits or parts of vectors.


Example: wire [7:0] Abus;
For the vector Abus we can select bit 7 and bit positions 2 to 0 by using the following
statements
Abus[7] // bit # 7 of vector Abus
Abus[2:0] // Three least significant bits of vector Abus
Bit 7 6 5 4 3 2 1 0
positions
Abus 1 0 0 0 1 1 0 1

Abus[7] Abus[2:0]

Variable Vector Part Select:

Another ability provided in Verilog HDL is to have variable part selects of a vector. This
allows part selects to be put in for loops to select various parts of the vector.

There are two special part-select operators:

[<starting_bit>+:width] // part-select increments from starting bit

[<starting_bit>-:width] //- part-select decrements from starting bit

The starting bit of the part select can be varied, but the width has to be constant.
The following example shows the use of variable vector part select:
reg [255:0] data1; //Little endian notation
reg [0:255] data2; //Big endian notation
reg [7:0] byte;

byte = data1[31-:8]; //starting bit = 31, width =8 => data[31:24]


byte = data1[24+:8]; //starting bit = 24, width =8 => data[31:24]
byte = data2[31-:8]; //starting bit = 31, width =8 => data[24:31]
byte = data2[24+:8]; //starting bit = 24, width =8 => data[24:31]

for (j=0; j<=31; j=j+1)


byte = data1[(j*8)+:8]; //Sequence is [7:0], [15:8]... [255:248]

//Can initialize a part of the vector


data1[(byteNum*8)+:8] = 8'b0; //If byteNum = 1, clear 8 bits [15:8]

Integer:
• An integer is a general purpose register data type used for manipulating quantities.
• Integers are declared by the keyword integer.
• The default width for an integer is the host-machine word size, which is
implementation-specific but is at least 32 bits.
• Registers declared as data type reg store values as unsigned quantities, whereas
integers store values as signed quantities.

Examples: integer counter; // general purpose variable used as a counter.


initial
counter = -1; // A negative one is stored in the counter

Real :
• Real number constants and real register data types are declared with the keyword real.
• They can be specified in decimal notation or in scientific notation
• Real numbers cannot have a range declaration, and their default value is 0.
• When a real value is assigned to an integer, the real number is rounded off to the
nearest integer.

real delta; // Define a real variable called delta


initial
begin
delta = 4e10; // delta is assigned in scientific notation
delta = 2.13; // delta is assigned a value 2.13
end
integer i; // Define an integer i
initial
i = delta; // i gets the value 2 (rounded value of 2.13)

Time
Verilog simulation is done with respect to simulation time. A special time register data type is
used in Verilog to store simulation time. A time variable is declared with the keyword time.
The width for time register data types is implementation-specific but is at least 64 bits.The
system function $time is invoked to get the current simulation time. Simulation time is
measured in terms of simulation seconds

Example:
time save_sim_time; // Define a time variable save_sim_time
initial
save_sim_time = $time; // Save the current simulation time

Arrays:
• Arrays are allowed in Verilog for reg, integer, time, real, realtime and vector register
data types.
• Multi-dimensional arrays can also be declared with any number of dimensions.
• Arrays of nets can also be used to connect ports of generated instances.
• Each element of the array can be used in the same fashion as a scalar or vector net.
• Arrays are accessed by <array_name>[<subscript>].
• For multi-dimensional arrays, indexes need to be provided for each dimension.

Example array declaration statements:

integer count[0:7]; // An array of 8 count variables


reg bool[31:0]; // Array of 32 one-bit boolean register variables
time chk_point[1:100]; // Array of 100 time checkpoint variables
reg [4:0] port_id[0:7]; // Array of 8 port_ids; each port_id is 5 bits wide
integer matrix[4:0][0:255]; // Two dimensional array of integers
reg [63:0] array_4d [15:0][7:0][7:0][255:0]; //Four dimensional array
wire [7:0] w_array2 [5:0]; // Declare an array of 8 bit vector wire
wire w_array1[7:0][5:0]; // Declare an array of single bit wires

Examples of assignments to elements of arrays:

count[5] = 0; // Reset 5th element of array of count variables


chk_point[100] = 0; // Reset 100th time check point value
port_id[3] = 0; // Reset 3rd element (a 5-bit value) of port_id array.
matrix[1][0] = 33559; // Set value of element indexed by [1][0] to 33559
array_4d[0][0][0][0][15:0] = 0; //Clear bits 15:0 of the register accessed by indices
[0][0][0][0]
port_id = 0; // Illegal syntax - Attempt to write the entire array
matrix [1] = 0; // Illegal syntax - Attempt to write [1][0]..[1][255]

Note: A vector is a single element that is n-bits wide.


Arrays are multiple elements

Memories: Memories are modeled in Verilog simply as a one-dimensional array of registers.


Each element of the array is known as an element or word and is addressed by a single array
index. Each word can be one or more bits.

reg mem1bit[0:1023]; // Memory mem1bit with 1K 1-bit words


reg [7:0] membyte[0:1023]; // Memory membyte with 1K 8-bit words(bytes)
membyte[511]; // Fetches 1 byte word whose address is 511.

Parameters:
Verilog allows constants to be defined in a module by the keyword parameter. Parameters
cannot be used as variables. Parameter values for each module instance can be overridden
individually at compile time.

Examples:
parameter port_id = 5; // Defines a constant port_id
parameter cache_line_width = 256; // Constant defines width of cache line
parameter signed [15:0] WIDTH; // Fixed sign and range for parameter WIDTH
parameter signed N=4; // Defines a constant N=4

Verilog HDL local parameters (defined using keyword localparam -) are identical to
parameters except that they cannot be directly modified with the defparam statement or by
the ordered or named parameter value assignment. The localparam keyword is used to define
parameters when their values should not be changed.

Examples:
localparam state1 = 4'b0001,
state2 = 4'b0010,
state3 = 4'b0100,
state4 = 4'b1000;

Strings:
• Strings can be stored in reg.
• The width of the register variables must be large enough to hold the string.
• Each character in the string takes up 8 bits (1 byte).
• If the width of the register is greater than the size of the string, Verilog fills bits to the
left of the string with zeros.
• If the register width is smaller than the string width, Verilog truncates the leftmost
bits of the string.
• It is always safe to declare a string that is slightly wider than necessary.

Examples:
reg [8*18:1] string_value; // Declare a variable that is 18 bytes wide initial
string_value = "Hello Verilog World"; // String can be stored in variable

Special characters serve a special purpose in displaying strings, such as newline, tabs, and
displaying argument values. Special characters can be displayed in strings only when they are
preceded by escape characters
Table :Special Characters
Escaped characters Character displayed
\n Newline
\t tab
%% %
\\ \
\" "
\ooo Characters written in 123 octal digits

System Tasks
• Verilog provides standard system tasks for certain routine operations.
• All system tasks appear in the form $<keyword>.
• Operations such as displaying on the screen, monitoring values of nets, stopping, and
finishing are done by system tasks.

Displaying information: $display is the main system task for displaying values of variables
or strings or expressions.

Example: $display(p1, p2, p3,....., pn);

p1, p2, p3,..., pn can be quoted strings or variables or expressions.


The format of $display is very similar to printf in C.
A $display inserts a newline at the end of the string by default.

Table: String Format Specifications


Format Display
%d or %D Display variable in decimal
%b or %B Display variable in binary
%s or %S Display string
%h or %H Display variable in hex
%c or %C Display ASCII character
%m or %M Display hierarchical name (no argument required)
%v or %V Display strength
%o or %O Display variable in octal
%t or %T Display in current time format
%e or %E Display real number in scientific format (e.g., 3e10)
%f or %F Display real number in decimal format (e.g., 2.13)
%g or %G Display real number in scientific or decimal, whichever is
shorter

Examples of the $display task


Example1:Display the string in quotes
$display("Hello Verilog World");
-- Hello Verilog World

Example2:Display value of current simulation time 230


$display($time);
-- 230

Example3:Display value of 41-bit virtual address 1fe0000001c at time 200


reg [0:40] virtual_addr;
$display("At time %d virtual address is %h", $time, virtual_addr);
-- At time 200 virtual address is 1fe0000001c

Example4:Display value of port_id 5 in binary


reg [4:0] port_id;
$display("ID of the port is %b", port_id);
-- ID of the port is 00101

Example5:Display x characters, Display value of 4-bit bus 10xx (signal contention) in binary
reg [3:0] bus;
$display("Bus value is %b", bus);
-- Bus value is 10xx

Example6:Display the hierarchical name of instance p1 instantiated under the highest-level


module called top. No argument is required.
$display("This string is displayed from %m level of hierarchy");
-- This string is displayed from top.p1 level of hierarchy
Example6:Display special characters, newline and %
$display("This is a \n multiline string with a %% sign");
-- This is a
-- multiline string with a % sign

Monitoring information
Verilog provides a mechanism to monitor a signal when its value changes. This facility is
provided by the $monitor task.

example: $monitor(p1,p2,p3,....,pn);
The parameters p1, p2, ... , pn can be variables, signal names, or quoted strings. A format
similar to the $display task is used in the $monitor task.
• $monitor continuously monitors the values of the variables or signals specified in the
parameter list and displays all parameters in the list whenever the value of any one
variable or signal changes
• Only one monitoring list can be active at a time.
• If there is more than one $monitor statement in your simulation, the last $monitor
statement will be the active statement. The earlier $monitor statements will be
overridden.

Two tasks are used to switch monitoring on and off.


$monitoron;
$monitoroff;

• The $monitoron tasks enables monitoring, and the $monitoroff task disables
monitoring during a simulation.
• Monitoring is turned on by default at the beginning of the simulation and can be
controlled during the simulation with the $monitoron and $monitoroff tasks

Examples of monitoring statements:


Example1: Monitor time and value of the signals clock and reset.Clock toggles
every 5 time units and reset goes down at 10 time units

initial
begin
$monitor($time," Value of signals clock = %b reset = %b", clock,reset);
end

Partial output of the above monitor statement:


-- 0 Value of signals clock = 0 reset = 1
-- 5 Value of signals clock = 1 reset = 1
-- 10 Value of signals clock = 0 reset = 0

Stopping and finishing in a simulation

The task $stop is provided to stop during a simulation.

Usage: $stop;
• The $stop task puts the simulation in an interactive mode.
• The $stop task is used whenever the designer wants to suspend the simulation and
examine the values of signals in the design.

The $finish task terminates the simulation.


usage: $finish;

Examples of $stop and $finish

Example: Stop at time 100 in the simulation and examine the results.
Finish the simulation at time 1000.

initial
begin
clock = 0;
reset = 1;
#100 $stop; // This will suspend the simulation at time = 100
#900 $finish; // This will terminate the simulation at time = 1000
end

Compiler Directives: All compiler directives are defined by using the `<keyword>
construct.
`define Directive:The `define directive is used to define text macros in Verilog . Verilog
compiler substitutes the text of the macro wherever it encounters a `<macro_name>. This is
similar to the #define construct in C.

Example of `define Directive

Example 1: Define a text macro that defines default word size

'define WORD_SIZE 32

Example 2: Define an alias. A $stop will be substituted wherever 'S appears

'define S $stop;

Example 3:define a frequently used text string

'define WORD_REG reg [31:0]


`include Directive:The `include directive allows you to include entire contents of a Verilog
source file in another Verilog file during compilation. This works similarly to the #include in
the C programming language. This directive is typically used to include header files, which
typically contain global or commonly used definitions

Example : `include Directive


Include the file header.v, which contains declarations in the main verilog file design.v.

'include header.v
...
...
<Verilog code in file design.v>
Modules and Ports

A module in Verilog consists of distinct parts, as shown in figure

• A module definition always begins with the keyword module.


• The module name, port list, port declarations, and optional parameters must come first
in a module definition .
• Port list and port declarations are present only if the module has any ports to interact
with the external environment.
• The five components within a module are: variable declarations, dataflow statements,
instantiation of lower modules, behavioral blocks, and tasks or functions.
• These components can be in any order and at any place in the module definition.
• The endmodule statement must always come last in a module definition.
• All components except module, module name, and endmodule are optional and can be
mixed and matched as per design needs.
• Verilog allows multiple modules to be defined in a single file. The modules can be
defined in any order in the file.

Example of an SR latch:

Design Module:
module SR_latch(Q, Qbar, Sbar, Rbar);
output Q, Qbar; //Port declarations
input Sbar, Rbar;
nand n1(Q, Sbar, Qbar); // Instantiate lower-level modules
nand n2(Qbar, Rbar, Q);
endmodule // endmodule statement

Stimulus module
module Top;
wire q, qbar;
reg set, reset;
// Feed inverted set and reset signals to the SR latch
SR_latch m1(q, qbar, ~set, ~reset);
initial // Behavioral block, initial

begin
$monitor($time, " set = %b, reset= %b, q= %b\n",set,reset,q);
set = 0; reset = 0;
#5 reset = 1;
#5 reset = 0;
#5 set = 1;
end
endmodule

Ports: Ports provide the interface by which a module can communicate with its environment.
For example, the input/output pins of an IC chip are its ports.

• The environment can interact with the module only through its ports.
• The internals of the module are not visible to the environment.
• This provides a very powerful flexibility to the designer.
• The internals of the module can be changed without affecting the environment as long
as the interface is not modified.
• Ports are also referred to as terminals.

List of Ports: A module definition contains an optional list of ports. If the module does not
exchange any signals with the environment, there are no ports in the list.

Consider a 4-bit full adder that is instantiated inside a top-level module Top

• The module fulladd4 is instantiated below Top.


• The module fulladd4 takes input on ports a, b, and c_in and produces an output on
ports sum and c_out. Thus, module fulladd4 performs an addition for its environment.
• The module Top is a top-level module in the simulation and does not need to pass
signals to or receive signals from the environment. Thus, it does not have a list of
ports

Example : List of Ports


module fulladd4(sum, c_out, a, b, c_in); //Module with a list of ports
module Top; // No list of ports, top-level module in simulation

Port Declaration:All ports in the list of ports must be declared in the module. Ports can be
declared as follows:
Verilog Type of Port
Keyword
input Input port
output Output port
inout Bidirectional port
Each port in the port list is defined as input, output, or inout, based on the direction of the
port signal.

Example : Port Declarations


module fulladd4(sum, c_out, a, b, c_in);
//Begin port declarations section
output[3:0] sum;
output c_cout;
input [3:0] a, b;
input c_in;
//End port declarations section
...
<module internals>
...
endmodule

• All port declarations are implicitly declared as wire in Verilog. Thus, if a port is
intended to be a wire, it is sufficient to declare it as output, input, or inout.
• Input or inout ports are normally declared as wires.
• However, if output ports hold their value, they must be declared as reg.
Example : Port Declarations for DFF
module DFF(q, d, clk, reset);
output q;
reg q; // Output port q holds value; therefore it is declared as reg.
input d, clk, reset;
...
...
endmodule

• Ports of the type input and inout cannot be declared as reg because reg variables store
values and input ports should not store values but simply reflect the changes in the
external signals they are connected to.

Example :ANSI C Style Port Declaration Syntax


module fulladd4(output reg [3:0] sum,
output reg c_out,
input [3:0] a, b, //wire by default
input c_in); //wire by default
...
<module internals>
...
endmodule

Port Connection Rules: A port as consisting of two units, one unit that is internal to the
module and another that is external to the module. The internal and external units are
connected. There are rules governing port connections when modules are instantiated within
other modules. The Verilog simulator complains if any port connection rules are violated.
Inputs:
• Internally, input ports must always be of the type net.
• Externally, the inputs can be connected to a variable which is a reg or a net.

Outputs:
• Internally, outputs ports can be of the type reg or net.
• Externally, outputs must always be connected to a net. They cannot be connected to a
reg.

Inouts:
• Internally, inout ports must always be of the type net.
• Externally, inout ports must always be connected to a net.
Width matching:
• It is legal to connect internal and external items of different sizes when making
intermodule port connections.

Unconnected ports:
• Verilog allows ports to remain unconnected
fulladd4 fa0(SUM, , A, B, C_IN); // Output port c_out is unconnected

Example : Illegal Port Connection


module Top;
reg [3:0]A,B;
reg C_IN;
reg [3:0] SUM;
wire C_OUT;
fulladd4 fa0(SUM, C_OUT, A, B, C_IN); //Instantiate fulladd4, call it fa0

//Illegal connection because output port sum in module fulladd4


//is connected to a register variable SUM in module Top.
.
.
<stimulus>
.
.
endmodule

Connecting Ports to External Signals: There are two methods of making connections
between signals specified in the module instantiation and the ports in a module definition.

Connecting by ordered list: The signals to be connected must appear in the module
instantiation in the same order as the ports in the port list in the module definition

Example : Connection by Ordered List


module Top;
reg [3:0]A,B;
reg C_IN;
wire [3:0] SUM;
wire C_OUT;
fulladd4 fa_ordered(SUM, C_OUT, A, B, C_IN); /*Signals are connected to ports
in order (by position)*/

...
<stimulus>
...
endmodule
module fulladd4(sum, c_out, a, b, c_in);
output[3:0] sum;
output c_cout;
input [3:0] a, b;
input c_in;
...
<module internals>
...
endmodule

Connecting ports by name: For large designs where modules have, say, 50 ports,
remembering the order of the ports in the module definition is impractical and error-prone.
Verilog provides the capability to connect external signals to ports by the port names, rather
than by position.

Example: Instantiate module fa_byname and connect signals to ports by name


fulladd4 fa_byname(.c_out(C_OUT), .sum(SUM), .b(B), .c_in(C_IN),.a(A),);

Example, To unconnect any port, simply port name is dropped from the list.
The port c_out is simply dropped from the port list.

fulladd4 fa_byname(.sum(SUM), .b(B), .c_in(C_IN), .a(A),);

Another advantage of connecting ports by name is that as long as the port name is not
changed, the order of ports in the port list of a module can be rearranged without changing
the port connections in module instantiations

Hierarchical Names
• Every module instance, signal, or variable is defined with an identifier.
• A particular identifier has a unique place in the design hierarchy.
• Hierarchical name referencing allows us to denote every identifier in the design
hierarchy with a unique name.
• A hierarchical name is a list of identifiers separated by dots (".") for each level of
hierarchy. Thus, any identifier can be addressed from any place in the design by
simply specifying the complete hierarchical name of that identifier.
• The top-level module is called the root module because it is not instantiated
anywhere. It is the starting point.
• To assign a unique name to an identifier, start from the top-level module and trace the
path along the design hierarchy to the desired identifier.

Figure : Design Hierarchy for SR Latch Simulation

For the simulation of SR latch, stimulus is the top-level module. The identifiers defined in
this module are q, qbar, set, and reset. The root module instantiates m1, which is a module of
type SR_latch. The module m1 instantiates nand gates n1 and n2. Q, Qbar, S, and R are port
signals in instance m1. Hierarchical name referencing assigns a unique name to each
identifier. To assign hierarchical names, use the module name for root module and instance
names for all module instances below the root module.

Hierarchical Names
stimulus stimulus.q
stimulus.qbar stimulus.set
stimulus.reset stimulus.m1
stimulus.m1.Q stimulus.m1.Qbar
stimulus.m1.S stimulus.m1.R
stimulus.n1 stimulus.n2
Each identifier in the design is uniquely specified by its hierarchical path name. To display
the level of hierarchy, use the special character %m in the $display task.

You might also like