Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
248 views

Verilog

The document discusses hierarchical modeling concepts in Verilog, including: 1. It describes top-down and bottom-up design methodologies, modules and module instances, and four levels of abstraction - behavioral, data flow, gate level, and switch level. 2. It explains the differences between modules and module instances, and provides an example of a 4-bit ripple carry counter to illustrate hierarchical modeling. 3. It discusses the different levels of abstraction in Verilog - behavioral, data flow, gate level, and switch level - and how the level of abstraction impacts the flexibility and technology dependence of a design.

Uploaded by

manju
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
248 views

Verilog

The document discusses hierarchical modeling concepts in Verilog, including: 1. It describes top-down and bottom-up design methodologies, modules and module instances, and four levels of abstraction - behavioral, data flow, gate level, and switch level. 2. It explains the differences between modules and module instances, and provides an example of a 4-bit ripple carry counter to illustrate hierarchical modeling. 3. It discusses the different levels of abstraction in Verilog - behavioral, data flow, gate level, and switch level - and how the level of abstraction impacts the flexibility and technology dependence of a design.

Uploaded by

manju
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 338

Module 1: Hierarchical Modeling

Concepts
Learning Objectives:
• Understand top-down and bottom-up design methodologies
for digital design.
• Explain differences between modules and module instances
in Verilog.
• Describe four levels of abstraction? behavioral, data flow,
gate level, and switch level? to represent the same module.
• Describe components required for the simulation of a digital
design.
•Define a stimulus block and a design block. Explain two
methods of applying stimulus.(Not being covered new!)
Design Methodologies

Top-down Design Methodology:


Bottom-up Design Methodology
Example for Hirarchical Modelling
4 –bit Ripple Carry Counter
T_ FF
Design Hierarchy:
Modules :
(Structure of verilog program)
module <module_name> (<module_terminal_list>);
...
<module internals>
...
...
endmodule

Ex. of T-FF:
module T_FF (q, clock, reset);
.
.
<functionality of T-flipflop>
.
.
endmodule
Levels of Abstraction:
1. Behavioral or algorithmic level
• This is the highest level of abstraction provided by Verilog HDL.
• 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.
2. Dataflow level
• At this level, the module is designed by specifying the data
flow.
• Here the designer is aware of how data flows between
hardware registers and how the data is processed in the
design.
3. Gate level (Structural)
• 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.
4. Switch level
• This is the lowest level of abstraction
provided by Verilog.
• A module can be implemented in terms of
switches, storage nodes, and the interconnections
between them.
• Design at this level requires knowledge of
switch-level(transistor) implementation details.
Flexibility of Abstraction Levels
• 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.

Ex:
The analogy with C programming and assembly language
programming.
• It is easier to program in a higher-level language
such as C. The program can be easily ported to any machine.
• However, if you design at the assembly level, the program is
specific for that machine and cannot be easily ported
Instances and Instantiation
Module Instantiation
// Define the top-level module called ripple carry
// counter. It instantiates 4 T-flipflops.
module ripple_carry_counter(q, clk, reset);
output [3:0] q;
input clk, reset;
//Four instances of the module T_FF are created. Each has a unique
//name.Each instance is passed a set of signals. Notice, that
//each instance is a copy of the module T_FF.
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 D-flipflop is defined elsewhere in the design.
module T_FF(q, clk, reset);
//Declarations to be explained later
output q;
input clk, reset;
wire d;
D_FF dff0(q, d, clk, reset); // Instantiate D_FF. Call it dff0.
not n1(d, q); // not gate is a Verilog primitive.
endmodule
Illegal Module Nesting
• One module definition cannot contain another
module definition within the module and
endmodule statements.
• Instead, a module definition can incorporate
copies of other modules by instantiating
them.
• It is important not to confuse module
definitions and instances of a module
Example of Illegal Module Nesting

/*Define the top-level module called ripple carry counter.


It is illegal to define the module T_FF inside this module.*/
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

Applying Stimulus or writing a test bench


would be covered later!!!!????
Chapter 3. Basic Concepts
Topic Learning Objectives:
• Understand lexical conventions for operators,
comments, whitespace, numbers, strings, and
identifiers.
• Define the logic value set and data types such as nets,
registers, vectors, numbers, simulation time, arrays,
parameters, memories, and strings.
• Identify useful system tasks for displaying and
monitoring information, and for stopping and finishing
the simulation.
• Learn basic compiler directives to define macros and
include files.
Lexical Conventions
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.
Lexical Conventions
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.
• A multiple-line comment starts with "/*" and ends with
"*/".
• Multiple-line comments cannot be nested.
• However, one-line comments can be embedded in
multiple-line comments.
Lexical Conventions
Example of comments:
1. a = b && c; // This is a one-line comment
2. /* This is a multiple line comment, which can be
Used to give comments in more than one line */
3. /* This is /* an illegal */ comment */
4. /* This is //a legal comment */
Lexical Conventions
Operators:
• There are of three types: unary, binary, and ternary.
• Unary operators precede the operand.
• Binary operators appear between two operands.
• Ternary operators have two separate operators that
separate three operands.
Example of operators:
1. a = ~ b; // ~ is a unary operator. b is the operand
2. a = b && c; // && is a binary operator. b and c are operands
3. a = b ? c : d; // ? : is a ternary operator. b, c and d are
operands
Lexical Conventions
Number Specification

1. 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.
• <base format> can be 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.
• Uppercase letters are legal for number specification.
Lexical Conventions
Examples of Sized numbers:

1. 4'b1111
// This is a 4-bit binary number
2. 12'habc
// This is a 12-bit hexadecimal number
3. 16'd255
// This is a 16-bit decimal number.
Lexical Conventions
2. Unsized numbers
• 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 of unsized numbers:
1. 23456 // This is a 32-bit decimal number by default
2. 'hc3 // This is a 32-bit hexadecimal number
3. 'o21 // This is a 32-bit octal number
Lexical Conventions
X or Z values:
• Verilog has two symbols for unknown and high
impedance values along with 0 and 1.
• These values are very important for modeling
real circuits.
• An unknown value is denoted by an X.
• A high impedance value is denoted by Z.
Lexical Conventions
Examples for X and Z
• 12'h13x // This is a 12-bit hex number; 4 least significant
bits unknown
• 6'hx // This is a 6-bit hex number
• 32'bz // This is a 32-bit high impedance number
Lexical Conventions
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.
Lexical Conventions
Examples of Negative numbers:
• -6'd3 // 8-bit negative number stored as 2's
complement of 3
• -6'sd3 // note the sign specifier, which is optional
• 4'd-2 // Illegal specification
Lexical Conventions
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.
Lexical Conventions
• A question mark "?" is the Verilog HDL
alternative for z in the context of numbers.
Examples:
• 12'b1111_0000_1010 // Use of underline
characters for readability
• 4'b10?? // Equivalent of a 4'b10zz
Lexical Conventions
Strings
• A string is a sequence of characters that are enclosed
by double quotes.
• The restriction on a string is that it 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 Verilog World" // is a string
• "a / b" // is a string
Lexical Conventions
Identifiers and Keywords
• Keywords are special identifiers reserved to
define the language constructs. Keywords are
in lowercase.
• Identifiers are names given to objects so that
they can be referenced in the design.
• Identifiers are made up of alphanumeric
(Alphabets and Numbers) characters, the
underscore ( _ ), or the dollar sign ( $ ).
Lexical Conventions
• 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).
Examples:
• reg value; // reg is a keyword; value is an identifier
• input clk; // input is a keyword, clk is an identifier
Lexical Conventions
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.
Examples:
• \a+b-c
• \**my_name**
Data Types
Value Set
• Verilog supports four values and eight strengths
to model the functionality of real hardware.
• In addition to logic values, strength levels are often used to
resolve conflicts between drivers of different strengths in
digital circuits.
• Value levels 0 and 1 can have the strength levels listed in Table .
Data Types
Strength Levels:
• If two signals of unequal strengths are driven on a
wire, the stronger signal prevails.
Ex: 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.
Ex: If two signals of strength strong1 and strong0
conflict, the result is an X.
Data Types
• 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.
Data Types
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.
•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 computed as b & c.
Data Types
Nets (Contd…)
• Net is not a keyword but represents a class of
data types such as wire, wand,wor, tri, triand,
trior, trireg, etc.
• 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.
Data Types
Nets (Contd…)

Examples:
• wire a; // Declare net a
• wire b; // Declare net b
• Wire a,b; // declare two nets a and b in the same line
• wire d = 1'b0; /* Net d is fixed to logic value 0 at
declaration.*/
Data Types
Registers
• Registers represent data storage elements.
• Registers retain value until another value is
placed onto them.
• In Verilog, the term register merely means a
variable that can hold a value and not a
hardware register.
Data Types
Example of data types:
• reg reset; // declare a variable reset that can hold its value

Registers can also be signed and can be used for


signed arithmatic
• reg signed [63:0] m; // 64 bit signed value
• integer i; // 32 bit signed value
Data Types
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).
Data Types
Vectors (Contd…)
Examples:
• wire a; // scalar net variable, default 1-bit
• wire [7:0] bus; // 8-bit bus
• wire [31:0] busA, busB, busC; // 3 buses of 32-
bit width.
• reg clock; // scalar register, default 1- bit
• reg [0:40] virtual_addr; // Vector register,
virtual address 41 bits wide
Data Types
Vectors (Contd…)

• Vectors can be declared at [high# : low#] or


[low# : high#]
• The left number in the squared brackets is
always the most significant bit of the vector.
Data Types
Vectors (Contd…)
Vector Part Select
• A part of the vectors can also be selected.
Consider the vector declaration wire [7:0] bus;
• busA[7] // bit # 7 of vector busA
• bus[2:0] // Three least significant bits of vector
bus,
• using bus[0:2] is illegal because the significant bit
should always be on the left of a range
specification
Data Types
Vectors (Contd…)
Consider Another example:

reg [0:40] virtual_addr;

• virtual_addr[0:1] // Two most significant bits


of vector virtual_addr
Data Types
Vectors (Contd…)
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.
Data Types
Vectors (Contd…)
There are two special part-select operators:
1. [<starting_bit>+:width] - part-select
increments from starting bit
2. [<starting_bit>-:width] - part-select
decrements from starting bit
Data Types
Vectors (Contd…)
Consider
• reg [255:0] data1; //Little endian notation
• reg [7:0] byte;
1. byte = data1[31-:8]; //starting bit = 31, width =8
=> data[31:24]
2. byte = data1[24+:8]; //starting bit = 24, width =8 =>
data[31:24]
Data Types
Vectors (Contd…)
Consider
reg [0:255] data2; //Big endian notation
reg [7:0] byte;

• byte = data2[31-:8]; //starting bit = 31, width=8 =>


data[24:31]
• byte = data2[24+:8]; //starting bit = 24, width=8=>
data[24:31]
Integer , Real, and Time Register Data
Types
Integer
• An integer is a general purpose register data
type used for manipulating quantities.
• Integers are declared by the keyword integer.
• Although it is possible to use integer as a
general-purpose variable, it is more
convenient to declare an integer variable for
purposes such as counting.
Integer , Real, and Time Register Data
Types
• 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 (e.g.,
3.14) or in scientific notation (e.g., 3e6,
which is 3 x 106 ).
• 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.
Examples of real numbers:
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.
Examples of time:
time save_sim_time; // Define a time variable
save_sim_time
initial
save_sim_time = $time; // Save the current
simulation time
• Simulation time is measured in terms of simulation
seconds.
• The unit is denoted by s, the same as real time.
• However, the relationship between real time in the
digital circuit and simulation time is left to the user.
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.
Examples of Arrays:
• 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
Examples of Arrays (Contd…)
• 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
• It is important not to confuse arrays with net
or register vectors.
• A vector is a single element that is n-bits wide.
• On the other hand, arrays are multiple
elements that are 1-bit or n-bits wide.
Examples of assignments to elements of
arrays discussed above are shown below:

• 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.
• port_id = 0; // Illegal syntax - Attempt to write the
entire array
Memories
• In digital simulation, one often needs to model register
files, RAMs, and ROMs.
• 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.
• It is important to differentiate between n 1-bit
registers and one n-bit register.
• A particular word in memory is obtained by using the
address as a memory array subscript.
Examples of memory:
• reg mem1bit[0:1023]; // Memory mem1bit
with 1024 1-bit words
• reg [7:0] membyte[0:1023]; // Memory
membyte with 1024 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.
• This allows the module instances to be
customized.
Examples of Parameters
• 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;
// declaring a vector WITDH with 16 bit signed
elements
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.
Example of a string:
• reg [8*20:1] string_value;
// Declare a variable that is 20 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.
System Tasks and Compiler Directives
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.
System Tasks
Displaying information
• $display is the main system task for displaying values of
variables or strings or expressions.
• This is one of the most useful tasks in Verilog.

Usage:
$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.
System Tasks

Displaying information (Contd…)


• A $display inserts a newline at the end of the
string by default.
• A $display without any arguments produces a
newline.
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
String Format Specifications(Contd…)
Format Display
• %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
Some examples of using $display
//Display the string in quotes
• $display("Hello Verilog World");
-- Hello Verilog World

//Display value of current simulation time 230


• $display($time);
-- 230
//Display 44-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
//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
//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
//Display the hierarchical name of instance p1
instantiated under the highest-level module
called top. No argument is required. This is a
useful feature
• $display("This string is displayed from %m level
of hierarchy");
• -- This string is displayed from top.p1 level of
hierarchy
Special Characters
//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.
Ex.:$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.
• Unlike $display, $monitor needs to be invoked only
once.
• 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.
Usage:
$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 Monitor Statement
//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
Output:
-- 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 designer can then debug the design from the
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:
// Stop at time 100 in the simulation and examine the results
// Finish the simulation at time 1000.
initial // to be explained later. time = 0
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
• Compiler directives are provided in Verilog.
• All compiler directives are defined by using
the format `<keyword>.
`define
• The `define directive is used to define text macros
in Verilog.
• The Verilog compiler substitutes the text of the
macro wherever it encounters a `<macro_name>.
• This is similar to the #define construct in C.
• The defined constants or text macros are used in
the Verilog code by preceding them with a
` (back tick).
Examples:
//define a text macro that defines default word size
//Used as 'WORD_SIZE in the code
'define WORD_SIZE 32

//define an alias. A $stop will be substituted wherever 'S appears


'define S $stop;
Examples (Contd…):
//define a frequently used text string
• 'define WORD_REG reg [31:0]
• // you can then define a 32-bit register as
'WORD_REG reg32;
`include
• 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 the file header.v, which contains declarations in the
// main verilog file design.v.
'include header.v
...
...
<Verilog code in file design.v>
...
...
Two other directives, `ifdef and `timescale, are
used frequently.
Summary
• Verilog is similar in syntax to the C programming
language . Hardware designers with previous C
programming experience will find Verilog easy to
learn.
• Lexical conventions for operators, comments,
whitespace, numbers, strings, and identifiers were
discussed.
• There are four logic values, each with different
strength levels. Available data types include nets,
registers, vectors, numbers, simulation time,
arrays, memories, parameters, and strings.
• Verilog provides useful system tasks to do
functions like displaying, monitoring,
suspending, and finishing a simulation.
• Compiler directive `define is used to define text
macros, and `include is used to include other
Verilog files.
Chapter 4: Modules and Ports
Learning Objectives:
• Identify the components of a Verilog module
definition, such as module names, port lists,
parameters, variable declarations, dataflow
statements, behavioral statements,
instantiation of other modules, and tasks or
functions.
• Understand how to define the port list for a
module and declare it in Verilog.
Learning Objectives:
• Identify the components of a Verilog module
definition, such as module names, port lists,
parameters, variable declarations, dataflow
statements, behavioral statements,
instantiation of other modules, and tasks or
functions.
• Understand how to define the port list for a
module and declare it in Verilog.
Learning Objectives:
• Describe the port connection rules in a module
instantiation.
• Understand how to define the port list for a
module and declare it in Verilog.
• Explain hierarchical name referencing of Verilog
identifiers
Modules
• In this section, we analyze the internals of the
module in greater detail.
A module in Verilog consists of distinct parts,
• 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.
n2

Consider the above SR latch to understand the


components,
// This example illustrates the different components of a
module
// Module name and port list
// SR_latch module
module SR_latch(Q, Qbar, Sbar, Rbar);
//Port declarations
output Q, Qbar;
input Sbar, Rbar; n2

// Instantiate lower-level modules


// In this case, instantiate Verilog primitive nand gates
// Note, how the wires are connected in a cross-coupled fashion.
nand n1(Q, Sbar, Qbar);
nand n2(Qbar, Rbar, Q);
// endmodule statement
endmodule
Notice the following characteristics about the modules
defined above:
• In the SR latch definition above , notice that all
components described in Figure 4-1 need not be
present in a module. We do not find variable
declarations, dataflow (assign) statements, or
behavioral blocks (always or initial).
• However, the stimulus block for the SR latch contains
module name, wire, reg, and variable declarations,
instantiation of lower level modules, behavioral block
(initial), and endmodule statement but does not contain
port list, port declarations, and data flow (assign)
statements.
• Thus, all parts except module, module name, and
endmodule are optional and can be mixed and matched
as per design needs.
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.
I/O Ports List for Top and Full Adder

•The module Top is a top-level module. 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.
• The module names and port lists for both module
declarations in Verilog are as shown

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:

• Each port in the port list is defined as input,


output, or inout, based on the direction of the
port signal.
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
• Note that 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.
• That is why in behavioral description of flip
flops output is declared as reg.
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.
ANSI C style of port declaration
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 declarations can be declared using an ANSI
C style syntax to specify the ports of that
module. Each declared port provides the
complete information about the port.
• This syntax avoids the duplication of naming
the ports in both the module definition
statement and the module port list definitions.
• If a port is declared but no data type is
specified, then, under specific circumstances,
the signal will default to a wire data type.
Port Connection Rules
• A port consists 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.
• However, a warning is typically issued that the
widths do not match.
Unconnected ports
• Verilog allows ports to remain unconnected.
• For example, certain output ports might be
simply for debugging, and you might not be
interested in connecting them to the external
signals.
• You can let a port remain unconnected by
instantiating a module as shown
fulladd4 fa0(SUM, , A, B, C_IN);
// Output port c_out is unconnected
Example of illegal port connection
module Top;
//Declare connection variables
reg [3:0]A_top,B_top;
reg C_IN_top;
reg [3:0] SUM_top;
wire C_OUT_top;
//Instantiate fulladd4, call it fa4_0.
//Signals are connected to ports in order (by position)
fulladd4 fa4_0 (SUM_top, C_OUT_top, A_top, B_top, C_IN_top);
...
<stimulus>
...
endmodule

This problem is rectified if the variable SUM_top is declared as a net (wire).


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
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.
1. Connecting by ordered list
2. Connecting ports by name
Connecting by ordered list
• Connecting by ordered list is the most intuitive
method for most beginners.
• 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.
• As an example consider the instantiation of
fulladd4 in top level module top.
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
module Top;
//Declare connection variables
reg [3:0]A_top,B_top;
reg C_IN_top;
wire [3:0] SUM_top;
wire C_OUT_top;
//Instantiate fulladd4, call it fa_ordered.
//Signals are connected to ports in order (by position)
fulladd4 fa_ordered (SUM_top, C_OUT_top, A_top,
B_top, C_IN_top);
...
<stimulus>
...
endmodule
• Notice that the external signals SUM_top,
C_OUT_top, A_top, B_top and C_IN_top
appear in exactly the same order as the ports
sum, c_out, a, b, and c_in in module definition
of fulladd4.
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.
• Note that you can specify the port connections
in any order as long as the port name in the
module definition correctly matches the
external signal.
// Instantiate module fa_byname and connect signals to
ports by name
fulladd4 fa_byname (.c_out(C_OUT_top),
.sum(SUM_top), .b(B_top),
.c_in(C_IN_top),.a(A_top),);
• Note that only those ports that are to be
connected to external signals must be specified
in port connection by name. Unconnected ports
can be dropped.
• For example, if the port c_out were to be kept
unconnected, the instantiation of fulladd4 would look
as follows.
// Instantiate module fa_byname and connect signals to
ports by name
fulladd4 fa_byname(.sum(SUM_top),
.b(B_top), .c_in(C_IN_top), .a(A_top),);

• The port c_out is simply dropped from the port


list.
• 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
• Verilog supports a hierarchical design methodology.
• 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.
Stimulus( Root module)

m1 (SR Latch)

n2
Design Hierarchy for SR Latch Simulation
• Stimulus, the top-level module is not instantiated
anywhere, it is called the root 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.
Examples of 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.
//Display the hierarchical name of instance p1
instantiated under the highest-level module called
top. No argument is required. This is a useful
feature
• $display("This string is displayed from %m level of
hierarchy");
• -- This string is displayed from top.p1 level of
hierarchy
Chapter 5. Gate-Level Modeling
Learning Objectives
• Identify logic gate primitives provided in Verilog.
• Understand instantiation of gates, gate symbols, and
truth tables for and/or and buf/not type gates.
• Understand how to construct a Verilog description from
the logic diagram of the circuit.
• Describe rise, fall, and turn-off delays in the gate-level
design.
• Explain min, max, and typ delays in the gate-level
design.
Gate Types
• A logic circuit can be designed by use of logic
gates.
• Verilog supports basic logic gates as predefined
primitives.
• These primitives are instantiated like modules
except that they are predefined in Verilog and do
not need a module definition.
• All logic circuits can be designed by using basic
gates.
• There are two classes of basic gates: and/or gates
and buf/not gates.
And/Or Gates
• And/or gates have one scalar output and multiple
scalar inputs.
• The first terminal in the list of gate terminals is an
output and the other terminals are inputs.
• The output of a gate is evaluated as soon as one
of the inputs changes.
• The and/or gates available in Verilog are
and or xor
nand nor xnor
Basic Gates
• These gates are instantiated to build logic circuits in
Verilog.
• For all instances, OUT is connected to the output out,
and IN1 and IN2 are connected to the two inputs i1 and
i2 of the gate primitives.
• Note that the instance name does not need to be
specified for primitives.
• This lets the designer instantiate hundreds of gates
without giving them a name.
• More than two inputs can be specified in a gate
instantiation.
• Gates with more than two inputs are instantiated by
simply adding more input ports in the gate instantiation.
• Verilog automatically instantiates the appropriate gate.
Gate Instantiation of And/Or Gates
wire OUT, IN1, IN2;
// basic gate instantiations.
and a1(OUT, IN1, IN2);
nand na1(OUT, IN1, IN2);
or or1(OUT, IN1, IN2);
nor nor1(OUT, IN1, IN2);
xor x1(OUT, IN1, IN2);
xnor nx1(OUT, IN1, IN2);
// More than two inputs; 3 input nand gate
nand na1_3inp(OUT, IN1, IN2, IN3);
// gate instantiation without instance name
and (OUT, IN1, IN2); // legal gate instantiation
Truth Tables for And/Or
Buf/Not Gates
• Buf/not gates have one scalar input and one
or more scalar outputs.
• The last terminal in the port list is connected
to the input.
• Other terminals are connected to the outputs.
• Two basic buf/not gate primitives are provided
in Verilog.
buf not
Notice that these gates can have multiple outputs
but exactly one input

Gate Instantiations of Buf/Not Gates


// basic gate instantiations.
buf b1(OUT1, IN);
not n1(OUT1, IN);
// More than two outputs
buf b1_2out(OUT1, OUT2, IN);
// gate instantiation without instance name
not (OUT1, IN); // legal gate instantiation
Truth Tables for Buf/Not Gates
Bufif/notif
• Gates with an additional control signal on buf
and not gates are also available.
bufif1 notif1
bufif0 notif0
• These gates propagate only if their control
signal is asserted.
• They propagate z if their control signal is
deasserted.
• These gates are used when a signal is to be driven
only when the control signal is asserted.
• Such a situation is applicable when multiple
drivers drive the signal.
Gate Instantiations of Bufif/Notif Gates
//Instantiation of bufif gates.
bufif1 b1 (out, in, ctrl);
bufif0 b0 (out, in, ctrl);
//Instantiation of notif gates
notif1 n1 (out, in, ctrl);
notif0 n0 (out, in, ctrl);
Array of Instances
• There are many situations when repetitive
instances
• To simplify specification of such instances,
Verilog HDL allows an array of primitive
instances to be defined are required.
wire [7:0] OUT, IN1, IN2;
// basic gate instantiations.
nand n_gate[7:0](OUT, IN1, IN2);
// This is equivalent to the following 8 instantiations

nand n_gate0(OUT[0], IN1[0], IN2[0]);


nand n_gate1(OUT[1], IN1[1], IN2[1]);
nand n_gate2(OUT[2], IN1[2], IN2[2]);
nand n_gate3(OUT[3], IN1[3], IN2[3]);
nand n_gate4(OUT[4], IN1[4], IN2[4]);
nand n_gate5(OUT[5], IN1[5], IN2[5]);
nand n_gate6(OUT[6], IN1[6], IN2[6]);
nand n_gate7(OUT[7], IN1[7], IN2[7]);
4:1 Multiplexer
// Module 4-to-1 multiplexer. Port list is taken exactly from
// the I/O diagram.
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram
output out;
input i0, i1, i2, i3;
input s1, s0;
// Internal wire declarations
wire s1n, s0n;
wire y0, y1, y2, y3;
// Gate instantiations
// Create s1n and s0n signals.
not (s1n, s1);
not (s0n, s0);
// 3-input and gates instantiated
and (y0, i0, s1n, s0n);
and (y1, i1, s1n, s0);
and (y2, i2, s1, s0n);
and (y3, i3, s1, s0);
// 4-input or gate instantiated
or (out, y0, y1, y2, y3);
Endmodule

This can be tested by writing a STIMULUS


Stimulus for Multiplexer
// Define the stimulus module (no ports)
module stimulus;
// Declare variables to be connected
// to inputs
reg IN0, IN1, IN2, IN3;
reg S1, S0;
// Declare output wire
wire OUTPUT;
// Instantiate the multiplexer
mux4_to_1 mymux(OUTPUT, IN0, IN1, IN2, IN3, S1,
S0);
// Stimulate the inputs
// Define the stimulus module (no ports)
initial
begin
// set input lines
IN0 = 1; IN1 = 0; IN2 = 1; IN3 = 0;
#1 $display("IN0= %b, IN1= %b, IN2= %b, IN3= %b\n",IN0,IN1,IN2,IN3);
// choose IN0
S1 = 0; S0 = 0;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
// choose IN1
S1 = 0; S0 = 1;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n", S1, S0, OUTPUT);
// choose IN2
S1 = 1; S0 = 0;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n",
S1, S0, OUTPUT);
// choose IN3
S1 = 1; S0 = 1;
#1 $display("S1 = %b, S0 = %b, OUTPUT = %b \n",
S1, S0, OUTPUT);
end
endmodule
The output of the simulation is shown below.
Each combination of the select signals is tested.

IN0= 1, IN1= 0, IN2= 1, IN3= 0


S1 = 0, S0 = 0, OUTPUT = 1
S1 = 0, S0 = 1, OUTPUT = 0
S1 = 1, S0 = 0, OUTPUT = 1
S1 = 1, S0 = 1, OUTPUT = 0
Gate Delays
1. Rise delay

The rise delay is associated with a gate output


transition to a 1 from another value.
2. Fall delay
• The fall delay is associated with a gate
output transition to a 0 from another
value.
Turn-off delay
• The turn-off delay is associated with a gate
output transition to the high impedance value
(z) from another value.
• If the value changes to x, the minimum of the
three delays is considered.
Three types of delay specifications are allowed.
• If only one delay is specified, this value is used
for all transitions.
Ex: // Delay of delay_time for all transitions
and #(delay_time) a1(out, i1, i2);
• If two delays are specified, they refer to the rise
and fall delay values. The turn-off delay is the
minimum of the two delays.
Ex: // Rise and Fall Delay Specification.
and #(rise_val, fall_val) a2(out, i1, i2);
• If all three delays are specified, they refer to rise,
fall, and turn-off delay values.
Ex: // Rise, Fall, and Turn-off Delay Specification
bufif0 #(rise_val, fall_val, turnoff_val) b1 (out, in,
control);
• If no delays are specified, the default value is
zero.
Some examples:
• and #(5) a1(out, i1, i2);
//Delay of 5 for all transitions
• and #(4,6) a2(out, i1, i2);
// Rise = 4, Fall = 6
• bufif0 #(3,4,5) b1 (out, in, control);
// Rise = 3, Fall = 4, Turn-off= 5
Min/Typ/Max Values
• Verilog provides an additional level of control for
each type of delay
• Delay rise, fall, and turn-off three values, min,
typ, and max, can be specified.
• Any one value can be chosen at the start of the
simulation.
• Min/typ/max values are used to model devices
whose delays vary within a minimum and
maximum range because of the IC fabrication
process variations.
Min value
• The min value is the minimum delay value that
the designer expects the gate to have.
Typ val
• The typ value is the typical delay value that the
designer expects the gate to have.
Max value
• The max value is the maximum delay value that
the designer expects the gate to have.
• Min, typ, or max values can be chosen at
Verilog run time.
• Method of choosing a min/typ/max value may
vary for different simulators or operating
systems.
• This helps the designer to experiment with
delay values without modifying the design.
• Example 5-11 Min, Max, and Typical Delay
Values
// One delay
// if +mindelays, delay= 4
// if +typdelays, delay= 5
// if +maxdelays, delay= 6
• and #(4:5:6) a1(out, i1, i2);
// Two delays
// if +mindelays, rise= 3, fall= 5,
// if +typdelays, rise= 4, fall= 6, turn-off = min(4,6)
// if +maxdelays, rise= 5, fall= 7, turn-off = min(5,7)
• and #(3:4:5, 5:6:7) a2(out, i1, i2);

• turn-off = min(rise,fall)
// Three delays
// if +mindelays, rise= 2 fall= 3 turn-off = 4
// if +typdelays, rise= 3 fall= 4 turn-off = 5
// if +maxdelays, rise= 4 fall= 5 turn-off = 6

• and #(2:3:4, 3:4:5, 4:5:6) a3(out, i1,i2);


Delay Example

• Consider the above module called D


• The gate-level implementation is shown in
Module D
• module contains two gates with delays of 5
and 4 time units.
Verilog Definition for Module D with Delay
// Define a simple combination module called D
module D (out, a, b, c);
// I/O port declarations
output out;
input a,b,c;
// Internal nets
wire e;
// Instantiate primitive gates to build the circuit
and #(5) a1(e, a, b); //Delay of 5 on gate a1
or #(4) o1(out, e,c); //Delay of 4 on gate o1
endmodule
Stimulus for Module D with Delay
// Stimulus (top-level module)
module stimulus;
// Declare variables
reg A, B, C;
wire OUT;
// Instantiate the module D
D d1( OUT, A, B, C);
// Stimulate the inputs. Finish the simulation at 40 time units.
initial
begin
A= 1'b0; B= 1'b0; C= 1'b0;
#10 A= 1'b1; B= 1'b1; C= 1'b1;
#10 A= 1'b1; B= 1'b0; C= 1'b0;
#20 $finish;
end
endmodule
Input output waveforms
Simple Array of Primitive Instances
wire [7:0] OUT, IN1, IN2;

// basic gate instantiations.


nand n_gate[7:0](OUT, IN1, IN2);

// This is equivalent to the following 8 instantiations


nand n_gate0(OUT[0], IN1[0], IN2[0]);
nand n_gate1(OUT[1], IN1[1], IN2[1]);
nand n_gate2(OUT[2], IN1[2], IN2[2]);
nand n_gate3(OUT[3], IN1[3], IN2[3]);
nand n_gate4(OUT[4], IN1[4], IN2[4]);
nand n_gate5(OUT[5], IN1[5], IN2[5]);
nand n_gate6(OUT[6], IN1[6], IN2[6]);
nand n_gate7(OUT[7], IN1[7], IN2[7]);
Chapter 6. Dataflow Modeling
Learning Objectives
• Describe the continuous assignment (assign) statement,
restrictions on the assign statement, and the implicit
continuous assignment statement.
• Explain assignment delay, implicit assignment delay, and net
declaration delay for continuous assignment statements.
• Define expressions, operators, and operands.
• List operator types for all possible operations : arithmetic,
logical, relational, equality, bitwise, reduction, shift,
concatenation, and conditional.
• Use dataflow constructs to model practical digital circuits in
Verilog.
Continuous Assignments
• A continuous assignment is the most basic
statement in dataflow modeling, used to drive
a value onto a net.
• This assignment replaces gates in the
description of the circuit and describes the
circuit at a higher level of abstraction.
• The assignment statement starts with the
keyword assign.
The syntax of an assign statement :
continuous_assign :
assign [drive_strength] [delay3] List_of_ net _assignments ;
• drive strength is optional and can be specified in terms of
strength levels .
• The default value for drive strength is strong1 and strong0.
• The delay value is also optional and can be used to specify
delay on the assign statement.
• This is like specifying delays for gates.
Charecteristics of Continueous assgnment
statement :
1. The left hand side of an assignment must always be a
scalar or vector net or a concatenation of scalar and
vector nets. It cannot be a scalar or vector register.
2. Continuous assignments are always active. The
assignment expression is evaluated as soon as one of
the right-hand-side operands changes and the value is
assigned to the left-hand-side net.
3. The operands on the right-hand side can be registers
or nets or function calls.
4. Registers or nets can be scalars or vectors.
5. Delay values can be specified for assignments in terms
of time units.
Examples of Continuous Assignment:
1. assign out = i1 & i2;
// Continuous assign. out is a net. i1 and i2 are nets.
2. assign addr[15:0] = addr1_bits[15:0] ^ addr2_bits[15:0];
// Continuous assign for vector nets. addr is a 16-bit vector net
// addr1 and addr2 are 16-bit vector registers.
3. assign {c_out, sum[3:0]} = a[3:0] + b[3:0] + c_in;
// Concatenation. Left-hand side is a concatenation of a scalar
// net and a vector net.
Implicit Continuous Assignment:

• Instead of declaring a wire in one line and


assigning in another line as shown below,
wire out;
assign out = in1 & in2;
declaration of a net and assignment can be
done in the same line as shown below
wire out = in1 & in2;
This is called Implicit Continuous Assignment
Implicit Net Declaration:
Consider the following example:
wire i1, i2;
assign out = i1 & i2;
• Here i1 and i2 are declared as wires but “out” on the
left hand side of the equation is not declared as wire.
• Even then the simulator treats “out” as wire by
default (implicitly).
• This is referred to as implicit wire declaration.
Delays
• Delay values control the time between the
change in a right-hand-side operand and when
the new value is assigned to the left-hand
side.
• Three ways of specifying delays in continuous
assignment statements are
i. regular assignment delay,
ii. implicit continuous assignment delay, and
iii. net declaration delay.
1.Regular Assignment Delay:
assign #10 out = in1 & in2; // Delay in a continuous assign

• The delay value is specified after the keyword assign.


• Any change in values of in1 or in2 will result in a delay
of 10 time units before recomputation of the
expression in1 & in2, and the assignment to out.
• If in1 or in2 changes value again before 10 time units
when the result propagates to out, the values of in1
and in2 at the time of recomputation are considered.
• This property is called inertial delay.
• An input pulse that is shorter than the delay of the
assignment statement does not propagate to the
output.
assign #10 out = in1 & in2; // Delay in a continuous assign

1. When signals in1 and in2 go high at time 20, out goes to a high
10 time units later (time = 30).
2. When in1 goes low at 60, out changes to low at 70.
3. However, in1 changes to high at 80, but it goes down to low
before 10 time units have elapsed.
4. Hence, at the time of recomputation, 10 units after time 80,
in1 is 0. Thus, out gets the value 0. A pulse of width less than
the specified assignment delay is not propagated to the output.
2.Implicit Continuous Assignment Delay:
• An equivalent method is to use an implicit
continuous assignment to specify both a delay
and an assignment on the net.
Example:
//implicit continuous assignment delay
wire #10 out = in1 & in2;
• The declaration above has the same effect as
defining a wire out and declaring a continuous
assignment on out as shown below.
wire out;
assign #10 out = in1 & in2;
3.Net Declaration Delay:
• A delay can be specified on a net when it is declared
without putting a continuous assignment on the net.
• If a delay is specified on a net out, then any value change
applied to the net out is delayed accordingly.

//Net Delays
wire # 10 out;
assign out = in1 & in2;
//The above statement has the same effect as the following.
wire out;
assign #10 out = in1 & in2;
Expressions, Operators, and Operands
Expressions
• Expressions are constructs that combine
operators and operands to produce a result.
Examples of expressions:
1. a ^ b
2. addr1[20:17] + addr2[20:17]
3. in1 | in2
Operands:
• Operands can be constants, integers, real numbers, nets,
registers, times, bit-select (one bit of vector net or a
vector register), part-select (selected bits of the vector
net or register vector), and memories or function calls
Examples:
1. integer count, final_count;
final_count = count + 1;
//count is an integer operand

2. real a, b, c;
c = a - b;
//a and b are real operands
3. reg [15:0] reg1, reg2;
reg [3:0] reg_out;
reg_out = reg1[3:0] ^ reg2[3:0];
//reg1[3:0] and reg2[3:0]
//are part-select register operands
4. reg ret_value;
ret_value = calculate_parity(A,
B);//calculate_parity is a
//function type operand
Operators:
• Operators act on the operands to produce
desired results
Examples:
1. d1 && d2 // && is an operator on operands d1 and d2
2. !a[0] // ! is an operator on operand a[0]
3. B >> 1 // >> is an operator on operands B and 1
Operator Types:
Arithmetic Operators
• There are two types of arithmetic operators:
binary and unary.
Binary operators
• Binary arithmetic operators are multiply (*),
divide (/), add (+), subtract (-), power (**), and
modulus (%).
• Binary operators take two operands.
Examples:
A = 4'b0011; B = 4'b0100; // A and B are register
vectors
D = 6; E = 4; F=2// D and E are integers
1. A * B // Multiply A and B. Evaluates to 4'b1100
2. D / E // Divide D by E. Evaluates to 1. Truncates any
fractional part.
3. A + B // Add A and B. Evaluates to 4'b0111
4. B - A // Subtract A from B. Evaluates to 4'b0001
5. F = E ** F; //E to the power F, yields 16
• If any operand bit has a value x, then the
result of the entire expression is x.
• This seems intuitive because if an operand
value is not known precisely, the result should
be an unknown.
Example:
in1 = 4'b101x;
in2 = 4'b1010;
sum = in1 + in2; // sum will be evaluated to the value 4'bx
• Modulus operators produce the remainder
from the division of two numbers.
1. 13 % 3 // Evaluates to 1
2. 16 % 4 // Evaluates to 0
3. -7 % 2 // Evaluates to -1, takes sign of the first operand
4. 7 % -2 // Evaluates to +1, takes sign of the first operand
Unary operators:
• The operators + and - can also work as unary operators.
• They are used to specify the positive or negative sign of
the operand.
1. -4 // Negative 4
2. +5 // Positive 5
• Negative numbers are represented as 2's complement
internally in Verilog.
• It is advisable to use negative numbers only if the type
integer or real in expressions.
• Designers should avoid negative numbers of the type
<sss> '<base> <nnn> in expressions because they are
• converted to unsigned 2's complement numbers and
hence yield unexpected results.
1. //Advisable to use integer or real numbers
-10 / 5// Evaluates to -2

2. //Do not use numbers of type <sss> '<base> <nnn>


-'d10 / 5// Is equivalent (2's complement of 10)/5
// This evaluates to an incorrect and unexpected result
Logical Operators
• Logical operators are logical-and (&&), logical-or (||) and
logical-not (!). Operators && and || are binary operators.
Operator ! is a unary operator.
1. Logical operators always evaluate to a 1-bit value, 0 (false),
1 (true), or x (ambiguous).
2. If an operand is not equal to zero, it is equivalent to a logical
1 (true condition).
If it is 01, it is equivalent to a logical 0 (false condition). If
any operand bit is x or z, it is equivalent to x (ambiguous
condition) and is normally treated by simulators as a false
condition.
3. Logical operators take variables or expressions as operands.
• Use of parentheses to group logical operations is
highly recommended to improve readability.
• Also, the user does not have to remember the
precedence of operators.
Examples:
A = 3; B = 0;
A && B // Evaluates to 0. Equivalent to (logical-1 && logical-0)
A || B // Evaluates to 1. Equivalent to (logical-1 || logical-0)
!A// Evaluates to 0. Equivalent to not(logical-1)
!B// Evaluates to 1. Equivalent to not(logical-0)
// Unknowns
A = 2'b0x; B = 2'b10;
A && B // Evaluates to x. Equivalent to (x && logical 1)
// Expressions
(a == 2) && (b == 3) // Evaluates to 1 if both a == 2 and b
== 3 are true.
// Evaluates to 0 if either is false.
Relational Operators
// A = 4, B = 3
// X = 4'b1010, Y = 4'b1101, Z = 4'b1xxx
1. A <= B // Evaluates to a logical 0
2. A > B // Evaluates to a logical 1
3. Y >= X // Evaluates to a logical 1
4. Y < Z // Evaluates to an x
Equality Operators

•The logical equality operators (==, !=) will yield an x


if either operand has x or z in its bits.
• However, the case equality operators ( ===, !==
) compare both operands bit by bit and
compare all bits, including x and z. The result is
1 if the operands match exactly, including x and
z bits.
• The result is 0 if the operands do not match
exactly.
• Case equality operators never result in an x.
// A = 4, B = 3
// X = 4'b1010, Y = 4'b1101
// Z = 4'b1xxz, M = 4'b1xxz, N = 4'b1xxx
A == B // Results in logical 0
X != Y // Results in logical 1
X == Z // Results in x
Z === M // Results in logical 1 (all bits match, including x and z)
Z === N // Results in logical 0 (least significant bit does not
match)
M !== N // Results in logical 1
Bitwise Operators
• Bitwise operators are negation (~), and(&), or (|),
xor (^), xnor (~^)
• Bitwise operators perform a bit-by-bit operation
on two operands.
• They take each bit in one operand and perform
the operation with the corresponding bit in the
other operand.
• If one operand is shorter than the other, it will be
bit-extended with zeros to match the length of
the longer operand.
• A z is treated as an x in a bitwise operation.
• The exception is the unary negation operator
(~), which takes only one operand and
operates on the bits of the single operand.
Examples of bitwise operators
// X = 4'b1010, Y = 4'b1101
// Z = 4'b10x1
~X // Negation. Result is 4'b0101
X & Y // Bitwise and. Result is 4'b1000
X | Y // Bitwise or. Result is 4'b1111
X ^ Y // Bitwise xor. Result is 4'b0111
~(X ^ Y ) // Bitwise xnor. Result is 4'b1000
X & Z // Result is 4'b10x0
• It is important to distinguish bitwise operators
~, &, and | from logical operators !, &&, ||.
• Logical operators always yield a logical value 0,
1, x, whereas bitwise operators yield a bit-by-
bit value.
• Logical operators perform a logical operation,
not a bit-by-bit operation.
// X = 4'b1010, Y = 4'b0000
X | Y // bitwise operation. Result is 4'b1010
X || Y // logical operation. Equivalent to 1 || 0. Result is 1.
Reduction Operators
• Reduction operators are and (&), nand (~&), or (|), nor
(~|), xor (^), and xnor (~^, ^~).
• Reduction operators take only one operand.
• Reduction operators perform a bitwise operation on a
single vector operand and yield a 1-bit result.
• The difference is that bitwise operations are on bits from
two different operands, whereas reduction operations
are on the bits of the same operand.
• Reduction operators work bit by bit from right to left.
• Reduction nand, reduction nor, and reduction xnor are
computed by inverting
• the result of the reduction and, reduction or, and
reduction xor, respectively.
// X = 4'b1010
&X //Equivalent to 1 & 0 & 1 & 0. Results in 1'b0
|X//Equivalent to 1 | 0 | 1 | 0. Results in 1'b1
^X//Equivalent to 1 ^ 0 ^ 1 ^ 0. Results in 1'b0

• A reduction xor or xnor can be used for even or odd


parity generation of a vector.
Shift Operators
// X = 4'b1100
Y = X >> 1;
//Y is 4'b0110. Shift right 1 bit. 0 filled in MSB position.
Y = X << 1;
//Y is 4'b1000. Shift left 1 bit. 0 filled in LSB position.
Y = X << 2;
//Y is 4'b0000. Shift left 2 bits.
integer a, b, c; //Signed data types
a = 0;
b = -10; // 00111...10110 binary
c = a + (b >>> 3); //Results in -2 decimal, due to arithmetic
shift
Concatenation Operator
// A = 1'b1, B = 2'b00, C = 2'b10, D = 3'b110
Y = {B , C}
// Result Y is 4'b0010
Y = {A , B , C , D , 3'b001}
// Result Y is 11'b10010110001
Y = {A , B[0], C[1]}
// Result Y is 3'b101
Replication Operator
• Repetitive concatenation of the same number
can be expressed by using a replication
constant.
• A replication constant specifies how many
times to replicate the number inside the
brackets ( { } ).
reg A;
reg [1:0] B, C;
reg [2:0] D;
A = 1'b1; B = 2'b00; C = 2'b10; D = 3'b110;
Y = { 4{A} }
// Result Y is 4'b1111
Y = { 4{A} , 2{B} }
// Result Y is 8'b11110000
Y = { 4{A} , 2{B} , C }
// Result Y is 8'b1111000010
Conditional Operator
• The conditional operator(?:) takes three
operands.
Usage:
condition_expr ? true_expr : false_expr ;
• The condition expression (condition_expr) is first
evaluated.
• If the result is true (logical 1), then the true_expr
is evaluated. If the result is false (logical 0), then
the false_expr is evaluated.
• The action of a conditional operator is similar
to a multiplexer.
• Alternately, it can be compared to the if-else
expression.

//model functionality of a 2-to-1 mux


assign out = codition_expr ? true_expr : false_expr;
//model functionality of a 2-to-1 mux
assign out = (sel==1)? in1 : in0;

• Conditional operators are frequently used in


dataflow modeling to model conditional
assignments.
• The conditional expression acts as a switching
control.
//model functionality of a tristate buffer
assign addr_bus = drive_enable ? addr_out : 36'bz;

Nested Conditional operators:


• Conditional operations can be nested.
• Each true_expr or false_expr can itself be a
conditional operation.
Consider,
assign out = (A == 3) ? ( control ? x : y ): ( control ? m : n) ;
Operator Precedence
4-to-1 Multiplexer
Method 1: Using logic equation
// Module 4-to-1 multiplexer using data flow. logic equation
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram
output out;
input i0, i1, i2, i3;
input s1, s0;
//Logic equation for out
assign out = (~s1 & ~s0 & i0)| (~s1 & s0 & i1) |
(s1 & ~s0 & i2) |(s1 & s0 & i3) ;
endmodule
Method 2: Using Conditional operator
// Module 4-to-1 multiplexer using data flow. Conditional
operator.
module multiplexer4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram
output out;
input i0, i1, i2, i3;
input s1, s0;
// Use nested conditional operator
assign out = (s1==1) ?((s0==1)?i3:i2) :
((s0==1)?i1:io);
endmodule
4-bit Full Adder
Method 1: dataflow operators

// Define a 4-bit full adder by using dataflow statements.


module fulladd4(sum, c_out, a, b, c_in);
// I/O port declarations
output [3:0] sum;
output c_out;
input[3:0] a, b;
input c_in;
// Specify the function of a full adder
assign {c_out, sum} = a + b + c_in;
endmodule
4-bit Full Adder with Carry Lookahead
module fulladd4(sum, c_out, a, b, c_in);
// Inputs and outputs
output [3:0] sum;
output c_out;
input [3:0] a,b;
input c_in;
// Internal wires
wire p0,g0, p1,g1, p2,g2, p3,g3;
wire c4, c3, c2, c1;
// compute the p for each stage
assign p0 = a[0] ^ b[0],
p1 = a[1] ^ b[1],
// compute the p for each stage
assign p0 = a[0] ^ b[0],
p1 = a[1] ^ b[1],
p2 = a[2] ^ b[2],
p3 = a[3] ^ b[3];
// compute the g for each stage
assign g0 = a[0] & b[0],
g1 = a[1] & b[1],
g2 = a[2] & b[2],
g3 = a[3] & b[3];
// compute the carry for each stage
// Note that c_in is equivalent c0 in the arithmetic
equation for
// carry lookahead computation
assign c1 = g0 | (p0 & c_in),
c2 = g1 | (p1 & g0) | (p1 & p0 & c_in),
c3 = g2 | (p2 & g1) | (p2 & p1 & g0) | (p2 &
p1 & p0 & c_in),
c4 = g3 | (p3 & g2) | (p3 & p2 & g1) | (p3 &
p2 & p1 & g0) |(p3 & p2 & p1 & p0 &c_in);
// Compute Sum
assign sum[0] = p0 ^ c_in,
sum[1] = p1 ^ c1,
sum[2] = p2 ^ c2,
sum[3] = p3 ^ c3;
// Assign carry output
assign c_out = c4;
endmodule
Chapter 7. Behavioral Modeling
Learning Objectives
• Explain the significance of structured procedures always and
initial in behavioral modeling.
• Define blocking and nonblocking procedural assignments.
• Understand delay-based timing control mechanism in
behavioral modeling.
• Use regular delays, intra-assignment delays, and zero delays.
• Describe event-based timing control mechanism in behavioral
modeling.
• Use regular event control, named event control, and event OR
control.
• Use level-sensitive timing control mechanism in behavioral
modeling.
• Explain conditional statements using if and else.
• Describe multiway branching, using case, casex, and casez
statements.
• Understand looping statements such as while, for, repeat, and
forever.
Structured Procedures
• There are two structured procedure
statements in Verilog: always and initial.
• These statements are the two most basic
statements in behavioral modeling.
• All other behavioral statements can appear
only inside these structured procedure
statements.
• Verilog is a concurrent programming language
unlike the C programming language, which is
sequential in nature.
initial Statement
• All statements inside an initial statement constitute an initial
block.
• An initial block starts at time 0, executes exactly once during a
simulation, and then does not execute again.
• If there are multiple initial blocks, each block starts to execute
concurrently at time 0.
• Each block finishes execution independently of other blocks.
• Multiple behavioral statements must be grouped, typically
using the keywords begin and end.
• If there is only one behavioral statement, grouping is not
necessary.
• This is similar to the begin-end blocks in Pascal programming
language or the { } grouping in the C programming language.
Example of initial Statement
module stimulus;
reg x,y, a,b, m;

initial
m = 1'b0; //single statement; does not need to be
grouped

initial
begin
#5 a = 1'b1; //multiple statements; need to be grouped
#25 b = 1'b0;
end
initial
begin
#10 x = 1'b0;
#25 y = 1'b1;
end

Initial
#50 $finish;
endmodule
• The three initial statements start to execute in parallel
at time 0.
• If a delay #<delay> is seen before a statement, the
statement is executed <delay> time units after the
current simulation time.
Time statement executed
0 m = 1'b0;
5 a = 1'b1;
10 x = 1'b0;
30 b = 1'b0;
35 y = 1'b1;
50 $finish;

• The initial blocks are typically processes that must be


executed only once during the entire simulation run.
Combined Variable Declaration and
Initialization
• Variables can be initialized when they are
declared.
Initial Value Assignment
Instead of declaring a clock in one line and
initializing it in another line as shown in Ex1.,
it can be done in the same line as in Ex2.
Ex1:reg clock;
initial clock = 0;
Ex2: reg clock = 0;
Combined Port/Data Declaration and
Variable Initialization
module adder (sum, co, a, b, ci);
output reg [7:0] sum = 0; //Initialize 8 bit output
sum
output reg co = 0; //Initialize 1 bit output co
input [7:0] a, b;
input ci;
--
--
endmodule
Combined ANSI C Port Declaration and Variable
Initialization
module adder (output reg [7:0] sum = 0, //Initialize
8 bit output
output reg co = 0, //Initialize 1 bit output co
input [7:0] a, b,
input ci
);
--
--
endmodule
always Statement
• All behavioral statements inside an always
statement constitute an always block.
• The always statement starts at time 0 and
executes the statements in the always block
continuously in a looping fashion.
• This statement is used to model a block of
activity that is repeated continuously in a
digital circuit.
• An example is a clock generator module that
toggles the clock signal every half cycle.
• In real circuits, the clock generator is active
from time 0 to as long as the circuit is
powered on.
The following example illustrates one method to model
a clock generator in Verilog.

module clock_gen (output reg clock);


//Initialize clock at time zero
//executed just once during simulation
Initial
clock = 1'b0;
//Toggle clock every half-cycle
always
#10 clock = ~clock; //clock time period = 20 time units
initial
#1000 $finish;
endmodule
• The always statement starts at time 0 and
executes the statement clock = ~clock every 10
time units.
• Notice that the initialization of clock has to be
done inside a separate initial statement.
• If we put the initialization of clock inside the
always block, clock will be initialized every time
the always is entered.
• Also, the simulation must be halted inside an
initial statement.
• If there is no $stop or $finish statement to halt
the simulation, the clock generator will run
forever.
Procedural Assignments
• Procedural assignments update values of reg,
integer, real, or time variables.
• The value placed on a variable will remain
unchanged until another procedural
assignment updates the variable with a
different value.
The syntax for the simplest form of procedural assignment is
shown below.
assignment :
variable_lvalue = [ delay_or_event_control ] expression
Or
[ delay ] variable_lvalue = expression

The left-hand side of a procedural assignment <lvalue> can


be one of the following:
• A reg, integer, real, or time register variable or a memory element
• A bit select of these variables (e.g., addr[0])
• A part select of these variables (e.g., addr[31:16])
• A concatenation of any of the above
The right-hand side can be any expression that evaluates to a value.
Examples: i) reg1 <= #1 in1;
ii) reg2 <= @(negedge clock) in2 ^ in3;
iii) #15 reg_a[2] = 1'b1;
There are two types of procedural assignment
statements: blocking and nonblocking.
Blocking Assignments
• Blocking assignment statements are those
which use = as the assignment operator.
• Blocking assignment statements are executed
in a sequential manner one after the other in
the top to down order.
• A blocking assignment will not block execution
of statements that follow in a parallel block.
Example of Blocking Statements
reg x, y, z;
reg [15:0] reg_a, reg_b;
integer count;
//All behavioral statements must be inside an initial or always block
initial
begin
x = 0; y = 1; z = 1; //Scalar assignments
count = 0; //Assignment to integer variables
reg_a = 16'b0;
reg_b = reg_a; //initialize vectors
#15 reg_a[2] = 1'b1; //Bit select assignment with delay
#10 reg_b[15:13] = {x, y, z} //Assign result of concatenation to
// part select of a vector
count = count + 1; //Assignment to an integer (increment)
end
• the statement y = 1 is executed only after x = 0 is
executed.
• Similarly all statements starting from x = 0 to
count = count + 1 get executed one after the
other
• The statement count = count+ 1 is executed last.
• if the right-hand side has more bits than the
register variable, the right-hand side is truncated
to match the width of the register variable. The
least significant bits are selected and the most
significant bits are discarded.
• If the right-hand side has fewer bits, zeros are
filled in the most significant bits of the register
variable.
The simulation times at which the statements
are executed are as follows:
• All statements starting from x = 0 to reg_b =
reg_a start getting executed at time 0
• Statement reg_a[2] = 0 at time = 15
• Statement reg_b[15:13] = {x, y, z} at time = 25
• Statement count = count + 1 at time = 25
• Since there is a delay of 15 and 10 in the
preceding statements, count = count + 1 will
be executed at time = 25 units
Nonblocking Assignments
• A <= operator is used to specify nonblocking
assignments.
• <= is relational operator in a comparative
statement like if-then-else
• <= is an assignment operator in the context of a
nonblocking assignment.
• To illustrate the behavior of nonblocking
statements and its difference from blocking
statements, let us consider an Example, where
we convert some blocking assignments to
nonblocking assignments, and observe the
behavior.
Example of Nonblocking Assignments
reg x, y, z;
reg [15:0] reg_a, reg_b;
integer count;
//All behavioral statements must be inside an initial or always block
initial
begin
x = 0; y = 1; z = 1; //Scalar assignments
count = 0; //Assignment to integer variables
reg_a = 16'b0; reg_b = reg_a; //Initialize vectors
reg_a[2] <= #15 1'b1; //Bit select assignment with delay
reg_b[15:13] <= #10 {x, y, z}; //Assign result of concatenation
//to part select of a vector
count <= count + 1; //Assignment to an integer (increment)
end
• In this example, the statements x = 0 through reg_b = reg_a are
executed sequentially at time 0.
• Then the three nonblocking assignments are processed at the same
simulation time.
1. reg_a[2] <= #15 1'b1; //Bit select assignment with delay
2. reg_b[15:13] <= #10 {x, y, z}; //Assign result of concatenation
3. count <= count + 1; //Assignment to an integer (increment)
• reg_a[2] <= 0 is scheduled to execute after 15 units (i.e., time = 15)
• reg_b[15:13] <= {x, y, z} is scheduled to execute after 10 time units
(i.e., time = 10)
• count <= count + 1 is scheduled to be executed without any delay
(i.e., time = 0)
• First the variables on the RHS are read and then the expressions are
evaluated and the result is stored in the temporary variable, which is
then followed by the write operation to the LHS
• Thus, the simulator schedules a nonblocking
assignment statement to execute and
continues to the next statement in the block
without waiting for the nonblocking statement
to complete execution.
• In the example considered both blocking and
nonblocking assignments are mixed to
illustrate their behavior.
• However, it is recommended that blocking and
nonblocking assignments not be mixed in the
same always block.
Application of nonblocking assignments
• They are used as a method to model several concurrent data transfers that
take place after a common event.
• Consider the following example where three concurrent data transfers take
place at the positive edge of clock.
always @(posedge clock)
begin
reg1 <= #1 in1;
reg2 <= @(negedge clock) in2 ^ in3;
reg3 <= #1 reg1; //The old value of reg1
end
• Here reading in1, in2, in3 and reg1 happens at rising edge of
clock.
• The write operations to the left-hand-side variables are scheduled
to be executed at the time specified by the intra-assignment
delay in each assignment
• Assignment to reg2 is at the next negative edge of clock.
• reg3 is assigned the old value of reg1 that was stored before the
assignment of new value in1 after 1 delay unit.
Nonblocking Statements to Eliminate Race Conditions
Illustration 1: Two concurrent always blocks with blocking statements
always @(posedge clock)
a = b;
always @(posedge clock)
b = a;
• there is a race condition when blocking statements are
used.
• Either a = b would be executed before b = a, or vice versa,
depending on the simulator implementation.
• Thus, values of registers a and b will not be swapped.
• This race condition can be eliminated and swapping of
registers a and b can be implemented using non-blcking
statements as shown in illustartion 2.
Illustration 2: Two concurrent always blocks with
nonblocking statements
always @(posedge clock)
a <= b;
always @(posedge clock)
b <= a;
• At the positive edge of clock, the values of all right-
hand-side variables are "read," and the right-hand-side
expressions are evaluated and stored in temporary
variables.
• During the write operation, the values stored in the
temporary variables are assigned to the left-handside
variables.
• Separating the read and write operations ensures that
the values of registers a and b are swapped correctly.
Implementing Nonblocking Assignments using Blocking
Assignments
//Emulate the behavior of nonblocking assignments by
//using temporary variables and blocking assignments
reg temp_a,temp_b;
always @(posedge clock)
begin
//Read operation
//store values of right-hand-side expressions in temporary variables
temp_a = a;
temp_b = b;
//Write operation
//Assign values of temporary variables to left-hand-side variables
a = temp_b;
b = temp_a;
end
• For digital design, use of nonblocking assignments in
place of blocking assignments is highly recommended
in places where concurrent data transfers take place
after a common event.
• In such cases, blocking assignments can potentially
cause race conditions because the final result depends
on the order in which the assignments are evaluated.
Applications of non-blocking statement:
• Typical applications of nonblocking assignments
include pipeline modeling and modeling of several
mutually exclusive data transfers.
Disadvantages of non-blocking statement:
• On the downside, nonblocking assignments can
potentially cause a degradation in the simulator
performance and increase in memory usage.
Timing Controls
• Timing controls provide a way to specify the
simulation time at which procedural
statements will execute.
• There are three methods of timing control:
i. delay-based timing control,
ii. event-based timing control, and
iii. level-sensitive timing control.
Delay-Based Timing Control
• Delay-based timing control in an expression
specifies the time duration between when the
statement is encountered and when it is
executed.
• Delays are specified by the symbol #.
• Syntax for the delay-based timing control
statement is shown below.
# delay_value out = expression
• Delay_value is specified by a number,
identifier, or a mintypmax_expression.
• There are three types of delay control for
procedural assignments: regular delay control,
intra-assignment delay control, and zero delay
control.
Regular delay control:
• Regular delay control is used when a non-zero
delay is specified to the left of a procedural
assignment.
Example of Regular Delay Control
//define parameters
parameter latency = 20;
parameter delta = 2;
//define register variables
reg x, y, z, p, q;
initial
begin
x = 0; // no delay control
#10 y = 1; // delay control with a number. Delay execution of y = 1 by 10 units
#latency z = 0; // Delay control with identifier. Delay of 20 units
#(latency + delta) p = 1; // Delay control with expression
#y x = x + 1; // Delay control with identifier. Take value of y.
#(4:5:6) q = 0; // Minimum, typical and maximum delay values.
end
Intra-assignment delay control
• Instead of specifying delay control to the left
of the assignment, it is possible to assign a
delay to the right of the assignment operator.
• Such delay specification alters the flow of
activity in a different manner.
• The following example shows the contrast
between intra-assignment delays and regular
delays.
//define register variables
reg x, y, z;
//intra assignment delays
initial
begin
x = 0; z = 0;
y = #5 x + z;
//Take value of x and z at the time=0, evaluate x + z and then wait 5
time units to assign value to y.
end
//Equivalent method with temporary variables and regular delay
control is as following
initial
begin
x = 0; z = 0;
temp_xz = x + z;
#5 y = temp_xz;
/*Take value of x + z at the current time and store it in a
temporary variable. Even though x and z might change
between 0 and 5, the value assigned to y at time 5 is
unaffected. */
end
• Intra-assignment delays compute the right-
hand- side expression at the current time and
defer the assignment of the computed value
to the left-hand-side variable.
• Intra-assignment delays are like using regular
delays with a temporary variable to store the
current value of a right-hand-side expression.
Zero delay control:
• The order of execution of Procedural
statements in different always-initial blocks is
nondeterministic.
• Zero delay control is a method to ensure that
a statement is executed last, after all other
statements in that simulation time are
executed.
• This is used to eliminate race conditions.
• However, if there are multiple zero delay
statements, the order between them is
nondeterministic.
Example Zero Delay Control:
initial
begin
x = 0;
y = 0;
end
initial
begin
#0 x = 1; //zero delay control
#0 y = 1;
end
• In the Example, four statements x = 0, y = 0, x
= 1, y = 1 are to be executed at simulation
time 0.
• However, since x = 1 and y = 1 have #0, they
will be executed last.
• Thus, at the end of time 0, x will have value 1
and y will have value 1.
• The order in which x = 1 and y = 1 are
executed is not deterministic.
• The example was used as an illustration.
However, using #0 is not a recommended
practice.
Event-Based Timing Control
• An event is the change in the value on a
register or a net.
• Events can be utilized to trigger execution of a
statement or a block of statements.
• There are four types of event-based timing
control: regular event control, named event
control, event OR control, and level sensitive
timing control.
Regular event control:
• The @ symbol is used to specify an event
control.
• Statements can be executed on changes in
signal value or at a positive or negative
transition of the signal value.
• The keyword posedge is used for a positive
transition, as shown in the Example shown.
Example Regular Event Control
@(clock) q = d;
/*q = d is executed whenever signal clock changes value*/
@(posedge clock) q = d;
/*q = d is executed whenever signal clock does a positive
transition ( 0 to 1,x or z, x to 1, z to 1 )*/
@(negedge clock) q = d;
/*q = d is executed whenever signal clock does a negative
transition ( 1 to 0,x or z, x to 0, z to 0)*/
q = @(posedge clock) d; /*d is evaluated immediately
and assigned to q at the positive edge of clock*/
Named event control
• Verilog provides the capability to declare an
event and then trigger and recognize the
occurrence of that event .
• The event does not hold any data.
• A named event is declared by the keyword
event.
• An event is triggered by the symbol ->.
• The triggering of the event is recognized by
the symbol @.
Example of Named Event Control:
This is an example of a data buffer storing data after the
last packet of data has arrived.

event received_data; //Define an event called received_data


always @(posedge clock) //check at each positive clock edge
begin
if(last_data_packet) //If this is the last data packet
->received_data; //trigger the event received_data
end
always @(received_data)
/* Await triggering of event received_data .When event is
triggered, store all four packets of received data in data
buffer. use concatenation operator { } */
data_buf = {data_pkt[0], data_pkt[1], data_pkt[2], data_pkt[3]};
Event OR Control:
• Sometimes a transition on any one of multiple
signals or events can trigger the execution of a
statement or a block of statements.
• This is expressed as an OR of events or signals.
• The list of events or signals expressed as an
OR is also known as a sensitivity list.
• The keyword or is used to specify multiple
triggers, as shown in the following example.
Example of Event OR Control (Sensitivity List)
//A level-sensitive latch with asynchronous reset
always @( reset or clock or d)
//Wait for reset or clock or d to change
begin
if (reset) //if reset signal is high, set q to 0.
q = 1'b0;
else if(clock) //if clock is high, latch input
q = d;
end
• Sensitivity lists can also be specified using the
"," (comma) operator instead of the or
operator.
• Example shows how the above example can
be rewritten using the comma operator.
• Comma operators can also be applied to
sensitivity lists that have edge-sensitive
triggers.
Sensitivity List with Comma Operator
//A level-sensitive latch with asynchronous reset
always @( reset, clock, d)
//Wait for reset or clock or d to change
begin
if (reset) //if reset signal is high, set q to 0.
q = 1'b0;
else if(clock) //if clock is high, latch input
q = d;
end
A positive edge triggered D flipflop with
asynchronous falling reset
always @(posedge clk, negedge reset)
//Note use of comma operator
if(!reset)
q <=0;
else
q <=d;
• When the number of input variables to a
combination logic block are very large, sensitivity
lists can become very cumbersome to write.
• Moreover, if an input variable is missed from the
sensitivity list, the block will not behave like a
combinational logic block.
• To solve this problem, Verilog HDL contains two
special symbols: @* and @(*).
• Both symbols exhibit identical behavior.
• These special symbols are sensitive to a change
on any signal that may be read by the statement
group that follows this symbol
Example of Use of @* Operator
//Combination logic block using the or operator
//Cumbersome to write and it is easy to miss one input to the block
always @(a or b or c or d or e or f or g or h or p or m)
begin
out1 = a ? b+c : d+e;
out2 = f ? g+h : p+m;
end
//Instead of the above method, use @(*) symbol
//Alternately, the @* symbol can be used
//All input variables are automatically included in the
//sensitivity list.
always @(*)
begin
out1 = a ? b+c : d+e;
out2 = f ? g+h : p+m;
end
Level-Sensitive Timing Control
• Event control discussed earlier waited for the change of
a signal value or the triggering of an event.
• The symbol @ provided edge-sensitive control.
• Verilog also allows level sensitive timing control, that
is, the ability to wait for a certain condition to be true
before a statement or a block of statements is
executed.
• The keyword wait is used for level sensitive constructs.
always
wait (count_enable) #20 count = count + 1;
• In the example, the value of count_enable is
monitored continuously.
• If count_enable is 0, the statement is not
entered.
• If it is logical 1, the statement count =count +
1 is executed after 20 time units.
• If count_enable stays at 1, count will be
incremented every 20 time units.
Conditional Statements
• Conditional statements are used for making
decisions based upon certain conditions.
• These conditions are used to decide whether
or not a statement should be executed.
• Keywords if and else are used for conditional
statements. There are three types of
conditional statements.
Type 1 conditional statement:
• No else statement.
• Statement executes or does not execute.
Ex: if (<expression>) true_statement ;
Type 2 conditional statement:
One else statement
• Either true_statement or false_statement is
evaluated
Ex: if (<expression>) true_statement ;
else false_statement ;
Type 3 conditional statement:
• Nested if-else-if.
• Choice of multiple statements.
• Only one is executed.
Ex: if (<expression1>) true_statement1 ;
else if (<expression2>) true_statement2 ;
else if (<expression3>) true_statement3 ;
else default_statement ;
• The <expression> is evaluated, If it is true (1 or
a non-zero value), the true_statement is
executed.
• However, if it is false (zero) or ambiguous (x),
the false_statement is executed.
• Each true_statement or false_statement can
be a single statement or a block of multiple
statements.
• A block must be grouped, typically by using
keywords begin and end.
• A single statement need not be grouped.
Conditional Statement Examples

//Type 1 statements
if(!lock) buffer = data; //if lock=0 assign data to buffer
if(enable) out = in;//if enable=1 assign in to out

//Type 2 statements
if (number_queued < MAX_Q_DEPTH)
begin
data_queue = data;
number_queued = number_queued + 1;
end
else
$display("Queue Full. Try again");
//Type 3 statements
//Execute statements based on ALU control signal.
if (alu_control == 0)
y = x + z;
else if(alu_control == 1)
y = x - z;
else if(alu_control == 2)
y = x * z;
else
$display("Invalid ALU control signal");
Multiway Branching

• In type 3 conditional statement, Conditional


Statements, there were many alternatives, from
which one was chosen.
• The nested if-else-if can become unwieldy if there are
too many alternatives. A shortcut to achieve the
same result is to use the case statement.
Case Statement:
• The keywords case, endcase, and default are used
in the case statement..
case (expression)
alternative1: begin statement1; statement11; end
alternative2: statement2;
alternative3: statement3;
...
...
default: default statement;
endcase
• Each of statement1, statement2 , default_statement
can be a single statement or a block of multiple
statements.
• A block of multiple statements must be grouped by
keywords begin and end.
• The expression is compared to the alternatives in the
order they are written.
• For the first alternative that matches, the
corresponding statement or block is executed.
• If none of the alternatives matches, the
default_statement is executed.
• The default_statement is optional. Placing of multiple
default statements in one case statement is not
allowed.
• The case statements can be nested.
//Execute statements based on the ALU control signal
reg [1:0] alu_control;
...
...
case (alu_control)
2'd0 : y = x + z;
2'd1 : y = x - z;
2'd2 : y = x * z;
default : $display("Invalid ALU control signal");
endcase
• The case statement can also act like a many-
to-one multiplexer.
• To understand this, let us model the 4-to-1
multiplexer
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
// Port declarations from the I/O diagram
output out;
input i0, i1, i2, i3;
input s1, s0;
reg out;
always @(s1 or s0 or i0 or i1 or i2 or i3) //always@(*)
//always @(s1,s0 ,i0, i1,i2 , i3)
case ({s1, s0}) //Switch based on concatenation of control signals
2'd0 : out = i0;
2'd1 : out = i1;
2'd2 : out = i2;
2'd3 : out = i3;
default: $display("Invalid control signals");
endcase
endmodule
Case Statement with x and z
module demultiplexer1_to_4 (out0, out1, out2, out3, in, s1, s0);
// Port declarations from the I/O diagram
output out0, out1, out2, out3;
reg out0, out1, out2, out3;
input in;
input s1, s0;
always @(s1 or s0 or in)
begin
case ({s1, s0}) //Switch based on control signals
2'b00 : begin out0 = in; out1 = 1'bz; out2 = 1'bz; out3 =1'bz; end
2'b01 : begin out0 = 1'bz; out1 = in; out2 = 1'bz; out3 =1'bz; end
2'b10 : begin out0 = 1'bz; out1 = 1'bz; out2 = in; out3 =1'bz; end
2'b11 : begin out0 = 1'bz; out1 = 1'bz; out2 = 1'bz; out3 =in; end
default: $display("Unspecified control signals");
endcase
end
endmodule
casex, casez Keywords
• There are two variations of the case
statement.
• casex and casez.
• casez treats all z values in the case alternatives
or the case expression as don't cares.
• All bit positions with z can also represented by
? in that position.
• casex treats all x and z values in the case item
or the case expression as don't cares
Example for usage of casex
reg [3:0] encoding;
integer state;
casex (encoding) //logic value x represents a don't care bit.
4'b1xxx : next_state = 3;
4'b01xx : next_state = 2;
4'b001x : next_state = 1;
4'b0001 : next_state = 0;
default : next_state = 0;
endcase
• Thus, an input encoding = 4'b10xz would cause
next_state = 3 to be executed.
Loops
While Loop:
• The while loop executes until the while
expression is not true.
• If the loop is entered when the while-
expression is not true, the loop is not
executed at all.
Illustration 1: Increment count from 0 to 127. Exit at
count 128.
integer count;
initial
begin
count = 0;
while (count < 128) //Execute loop till count is 127.
//exit at count 128
begin
$display("Count = %d", count);
count = count + 1;
end
end
Illustration 2: Find the first bit with a value 1 in
flag (vector variable)
'define TRUE 1'b1';
'define FALSE 1'b0;
reg [15:0] flag;
integer i; //integer to keep count
reg continue;
initial
begin
flag = 16'b 0010_0000_0000_0000;
i = 0;
continue = 'TRUE;
while((i < 16) && continue ) //Multiple conditions using
operators.
begin
if (flag[i])
begin
$display("Encountered a TRUE bit at element number
%d", i);
continue = 'FALSE;
end
i = i + 1;
end
end
For Loop
The keyword for is used to specify this loop. The for
loop contains three parts:
• An initial condition
• A check to see if the terminating condition is true.
• A procedural assignment to change value of the
control variable.
Ex:
integer count;
initial
for ( count=0; count < 128; count = count + 1)
$display("Count = %d", count);
• for loops can also be used to initialize an array or
memory, as shown below.
'define MAX_STATES 32
//define and initialise MAX_STATES as 32
integer state [0: 'MAX_STATES-1];
//definining 32 elements array with each element
as integer
integer i;
initial
begin
for(i = 0; i < 32; i = i + 2)
state[i] = 0; //initialize all even locations with 0
for(i = 1; i < 32; i = i + 2) //initialize all odd
locations with 1
state[i] = 1;
end
• for loops are generally used when there is a
fixed beginning and end to the loop.
• If the loop is simply looping on a certain
condition, it is better to use the while loop.
Repeat Loop

• The keyword repeat is used for this loop.


• The repeat construct executes the loop a fixed number
of times.
• A repeat construct cannot be used to loop on a general
logical expression.
• A while loop is used for that purpose.
• A repeat construct must contain a number, which can
be a constant, a variable or a signal value.
• However, if the number is a variable or signal value, it
is evaluated only when the loop starts and not during
the loop execution.
Illustration 1 : increment and display count from 0 to 127
integer count;
initial
begin
count = 0;
repeat(128)
begin
$display("Count = %d", count);
count = count + 1;
end
end
Illustration 2 : Data buffer module example.
After it receives a data_start signal, reads data
for next 8 cycles.
module data_buffer(data_start, data, clock);
parameter cycles = 8;
input data_start;
input [15:0] data;
input clock;
reg [15:0] buffer [0:7];
integer i;
always @(posedge clock)
begin
if(data_start) //data start signal is true
begin
i = 0;
repeat(cycles) //Store data at the posedge of next 8 clock cycles
begin
@(posedge clock) buffer[i] = data;
//waits till next posedge to latch data
i = i + 1;
end
end
end
endmodule
Repeat Loop

• The repeat construct executes the loop a fixed


number of times.
• A repeat construct cannot be used to loop on
a general logical expression.
• A while loop is used for that purpose. A repeat
construct must contain a number, which can
be a constant, a variable or a signal value.
Illustration : Increment and display count from 0 to 127
integer count;
initial
begin
count = 0;
repeat(128)
begin
$display("Count = %d", count);
count = count + 1;
end
end
Forever loop

• The loop does not contain any expression and


executes forever until the $finish task is
encountered.
• The loop is equivalent to a while loop with an
expression that always evaluates to true
Example 1: Clock generation
reg clock;
initial
begin
clock = 1'b0;
forever #10 clock = ~clock; //Clock with period of 20 units
end
Example 2: Synchronize two register values at every
positive edge of clock
reg clock;
reg x, y;
initial
forever @(posedge clock) x = y;
Block Types
Sequential blocks
• The keywords begin and end are used to group statements
into sequential blocks.
• Sequential blocks have the following characteristics:
• The statements in a sequential block are processed in the
order they are specified.
• A statement is executed only after its preceding statement
completes execution (except for nonblocking assignments
with intra-assignment timing control).
• If delay or event control is specified, it is relative to the
simulation time when the previous statement in the block
completed execution.
Illustration 1: Sequential block without delay
reg x, y;
reg [1:0] z, w;
initial
begin
x = 1'b0;
y = 1'b1;
z = {x, y};
w = {y, x};
//Illustration 2: Sequential blocks with delay.
reg x, y;
reg [1:0] z, w;
initial
begin
x = 1'b0; //completes at simulation time 0
#5 y = 1'b1; //completes at simulation time 5
#10 z = {x, y}; //completes at simulation time 15
#20 w = {y, x}; //completes at simulation time 35
end
Parallel blocks
• Parallel blocks, specified by keywords fork and
join, provide interesting simulation features.
• Parallel blocks have the following characteristics:
Statements in a parallel block are executed
concurrently.
The order of the statements with in the block is not
important
Ordering of statements is controlled by the delay or
event control assigned to each statement.
• If delay or event control is specified, it is relative
to the time the block was entered.
Example 1: Parallel blocks with delay.
reg x, y;
reg [1:0] z, w;
initial
fork
x = 1'b0; //completes at simulation time 0
#5 y = 1'b1; //completes at simulation time 5
#10 z = {x, y}; //completes at simulation time 10
#20 w = {y, x}; //completes at simulation time 20
join
Parallel blocks with deliberate race condition
reg x, y;
reg [1:0] z, w;
initial
fork
x = 1'b0;
y = 1'b1;
z = {x, y};
w = {y, x};
join
• The keyword fork can be viewed as splitting a single flow
into independent flows. The
• keyword join can be seen as joining the independent flows
back into a single flow.
• Independent flows operate concurrently.
Special Features of Blocks
Nested blocks
• Blocks can be nested.
• Sequential and parallel blocks can be mixed, as shown in
Example
Example for Nested Blocks
initial
begin
x = 1'b0;
fork
#5 y = 1'b1;
#10 z = {x, y};
join
#20 w = {y, x};
end
Named blocks
• Blocks can be given names.
• Local variables can be declared for the named
block.
• Named blocks are a part of the design
hierarchy.
• Variables in a named block can be accessed by
using hierarchical name referencing.
• Named blocks can be disabled, i.e., their
execution can be stopped.
Example for Named Blocks
module top;
initial
begin: block1 //sequential block named block1
integer i;
/*integer i is static and local to block1
can be accessed by hierarchical name, top.block1.i */
...
...
end
initial
fork: block2 //parallel block named block2
reg i;
/* register i is static and local to block2
can be accessed by hierarchical name, top.block2.i */
...
...
join
Disabling named blocks:
• The keyword disable provides a way to terminate the
execution of a named block.
• disable can be used to get out of loops, handle error
conditions, or control execution of pieces of code,
based on a control signal.
• Disabling a block causes the execution control to be
passed to the statement immediately succeeding the
block.
• For C programmers, this is very similar to the break
statement used to exit a loop.
• The difference is that a break statement can break the
current loop only, whereas the keyword disable allows
disabling of any named block in the design.
Find a bit with a value 1 in flag and display a true bit is found
along with its location
reg [15:0] flag;
integer i; //integer to keep count
initial
begin
flag = 16'b 0010_0000_0000_0000;
i = 0;
begin: block1 //The main block inside while is named block1
while(i < 16)
begin
if (flag[i])
begin
$display("Encountered a TRUE bit at element number %d", i);
disable block1; //disable block1 because you found true bit.
end
i = i + 1;
end
end
end
4-to-1 Multiplexer
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
output out;
input i0, i1, i2, i3;
input s1, s0;
reg out;
always @(s1 or s0 or i0 or i1 or i2 or i3)
begin
case ({s1, s0})
2'b00: out = i0;
2'b01: out = i1;
2'b10: out = i2;
2'b11: out = i3;
default: out = 1'bx;
endcase
end
endmodule
4-bit Counter
module counter(Q , clock, clear);
output [3:0] Q;
input clock, clear;
reg [3:0] Q;
always @( posedge clear or negedge clock)
begin
if (clear) //if clear =1
Q <= 4'd0; //Nonblocking assignments are recommended
//for creating sequential logic such as flipflops
else
Q <= Q + 1;// Modulo 16 is not necessary because Q is a
// 4-bit value and wraps around.
end
endmodule
Typical Design Flow in IC Fabrication
• A typical design flow for designing VLSI IC
circuits is shown in Figure.
• Unshaded blocks show the level of design
representation;
• shaded blocks show processes in the design
flow
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
Example for 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
Example 2-5 Flipflop D_F
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
module stimulus;
reg clk;
reg reset;
wire[3:0] q;
// instantiate the design block
ripple_carry_counter r1(q, clk, reset);
// Control the clk signal that drives the design block. Cycle time = 10
initial
clk = 1'b0; //set clk to 0
always
#5 clk = ~clk; //toggle clk every 5 time units
// Control the reset signal that drives the design block
// reset is asserted from 0 to 20 and from 200 to 220.
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
0 Output q = 0
Output: 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

You might also like