Verilog
Verilog
ENGINEERING
Verilog HDL
1
Outline
◼ Course Outline
◼ Recommended Books
◼ Prerequisites of the subject
◼ Module 1: Overview of Digital Design with
Verilog HDL
2
◼ Text Book:
◼ Samir Palnitkar, “Verilog HDL: A Guide to Digital
Design and Synthesis”, Pearson Education, Second
Edition.
◼ Reference Books:
◼ 1. Donald E. Thomas, Philip R. Moorby, “The Verilog
Hardware Description Language”, Springer, Fifth
edition.
◼ 2. Michael D. Ciletti, “Advanced Digital Design with the
Verilog HDL” Pearson (Prentice Hall), Second edition.
◼ 3. Padmanabhan, Tripura Sundari, “Design through
Verilog HDL”, Wiley, 2016 or earlier.
6
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
10
Evolution of Computer Aided Digital
Design
◼ Digital circuits were designed with
❑ Vacuum tubes
❑ Transistors
❑ Integrated circuits (ICs)
◼ SSI
◼ MSI : hundreds of gates
◼ LSI : thousands of gates
❑ CAD techniques began to evolve
❑ circuit and Logic simulation about 100 transistors
◼ VLSI : more than 100,000 transistors
◼ ULSI : Ultra Large Scale Integration
11
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
12
Emergence of HDLs
◼ Hardware Description Language (HDL)
❑ A hardware description language is the language that
describes the hardware of digital systems in textual form and
resembles a programming language, but specifically oriented
to describing hardware structures and behavior.
❑ Allowed designed to model the concurrency of processes
found in hardware elements
❑ Verilog HDL originated in 1983
13
Different Levels of Abstraction
14
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
16
Typical Design
Flow for
Designing VLSI
IC
17
Design Flow of using HDL
18
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
19
Why use the HDL ?
20
Advantages of
HDLs
◼ Advantages compared to traditional
schematic-based design
❑ Design with RTL description + logic synthesis tool
◼ Abstract level
◼ Independent to fabrication technology
◼ Reuse when fabrication technology changing
❑ Functional verification can be done early
◼ Optimized to meet the desired functionality
❑ Analogous to computer programming
◼ Textual description with comments
21
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
22
Useful Features of the Verilog HDL
◼ A general-purpose HDL
❑ Easy to learn and use
◼
powerful PLI (Programming Language Interface)
❑ Write custom C code to interact with internal data structure
25
Overview of Digital Design with Verilog
HDL
◼ Evolution of computer aided digital circuit
design
◼ Emergence of HDLs
◼ Typical design flow
◼ Importance of HDLs
◼ Popularity of Verilog HDL
◼ Trends in HDLs
26
Trends in HDLs
◼ Higher levels of abstraction
❑ Think only in terms of functionality for designers
◼ Behavioral modeling
❑ Design directly in terms of algorithms and
◼ Formal verification
◼ Supports for Mixed-level design
❑ Ex: very high speed and timing- critical circuits like μPs
◼
System-level design in a mixed bottom-up methodology
❑ Use either existing Verilog modules, basic building blocks, or IPs
27
Hierarchical Modelling 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.
28
Top Down Design Methodology
29
Bottom Up Design Methodology
30
Example : Design of 4 bit Ripple
Counter using Top Down approach
31
Ripple Counter
◼ A n-bit ripple counter can n count up to 2
states. It is also known as MOD n counter.
It is known as ripple counter because of
the way the clock pulse ripples its way
through the flip-flops. Some of the
◼
features of ripple counter are:
◼
It is an asynchronous counter.
Different flip-flops are used with a
◼
different clock pulse. All the flip-flops are
◼
used in toggle mode.
Only one flip-flop is applied with an
◼
external clock pulse and another flip-flop
clock is obtained from the output of the
previous flip-flop.
The flip-flop applied with external clock 32
T-Flip flop
33
Design Hierarchy of 4 Bit ripple
Counter
34
Verilog - Module
◼ A module is the building block in
◼ Verilog. It is declared by the
keyword module and is always
terminated by the keyword
◼
endmodule.
Each statement is terminated
with a semicolon, but there is no
semi-colon after endmodule.
35
Verilog Modules
◼ Basic building block in
Verilog
❑ Hierarchical design (top-
down vs. bottom-up)
❑ Multiple modules in a
single file
◼ Order of definition not
important
❑ Modules are:
◼ Declared
◼ Instantiated
❑ Modules declarations
cannot be nested
36
Module Representation
◼ Module
❑ A logic circuit → module
❑ Its ports: inputs and
outputs
❑ Begins with module,
ends with endmodule
◼
Module<module
name>(module terminal
list);
<Module internals>
End module
◼
Different Levels of Abstraction
Behavioural/Architectural /
Algorithmic Level
Implement a design algorithm in
high-level language constructs.
Data flow level/Register
Transfer Level
Describes the flow of data
between registers and
how a design process
these data.
Different Levels of Abstraction
Gate Level
Describe the logic gates and the
interconnections between them.
Switch (Transistor) Level
40
Module Instantiation (cont’d)
◼ General syntax
<module_name> <instance_name>(port connection list);
◼ Example:
// assuming module ripple_carry_counter(q, clk, reset);
ripple_carry_counter cntr1(wire_vec1, wire2, wire3);
41
Example Fuul Adder
module fastr(x, y, cin, sum, cout); input
x,y,cin;
output sum,cout;
wire t1,t2,t3;
ha ha1 ( x,y,t1,t2);
ha ha2 ( t1,cin,sum,t3 );
or or2 ( cout ,t3,t2);
endmodule
module ha(x, y, s, c);
input x,y;
output s,c;
assign s = x^y;
assign c = x&y;
endmodule
42
Module Instantiation
◼
Recall the Ripple-carry counter and TFF
43
Module Instances-Ripple Counter
module reg4 (q,d,clock); module dff (q,qb,data,clk);
output [3:0] q; output q, qb;
input [3:0] d; input data, clk;
input clock; //default delay parameter
wire [3:0] q, d; parameter delay = 1;
wire clock; dff_udp #(delay) (q,data,clk);
//port order connection, not (qb, q);
//2nd port not connected endmodule
dff u1 (q[0], , d[0], clock);
//port name connection,
//qb not connected
dff u2 (.clk(clock),.q(q[1]),.data(d[1]));
//explicit parameter redefine
dff u3 (q[2], ,d[2], clock);
defparam u3.delay = 3.2;
//implicit parameter redefine
dff #(2) u4 (q[3], , d[3], clock); endmodule
44
Components of Simulation
◼ The functionality of the design block can
be tested by applying stimulus and
checking results such a block is called
◼ stimulus block. Separate stimulus and
◼ design block. Stimulus block can be
written using verilog, separate language
is not required. Stimulus block is also
◼ called as Test bench.
Different test benches can be written to
test a design block
45
Stimulus Block Instantiates Design
Block(Ripple Counter)
46
Stimulus and design Blocks Instantiated
in a Dummy top level Module Design
Block
47
Example:- 4 bit Ripple Counter
◼ To illustrate the concepts discussed in the previous
sections, let us build the complete simulation of a
ripple carry counter.
◼
We will define the design block and the stimulus block.
◼
We will apply stimulus to the design block and monitor
the outputs.
◼ As we develop the Verilog models, you do not need to
understand the exact syntax of each construct at this
stage.
◼
At this point, you should simply try to understand the
design process. We discuss the syntax in much
greater detail in the later modules.
48
Example: 4 bit Ripple Counter
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
49
◼ Example 2- Ripple Carry Counter Top
Block
50
Example 3 . Flipflop D_F
◼ // module D_FF with synchronous reset module
D_FF(q, d, clk, reset);
◼ output q;
◼ input d, clk, reset;
◼ reg q;
// Lots of new constructs. Ignore the functionality of the // constructs. //
Concentrate on how the design block is built in a top-down fashion.
◼ always @(posedge reset or negedge clk)
◼ if (reset) q <= 1'b0;
◼ else q <= d;
◼ endmodule
51
Stimulus Block
◼ We need to write the stimulus block to
check if the ripple carry counter design is
◼
functioning correctly.
In this case, we must control the signals
clk and reset so that the regular function
◼
of the ripple carry counter and the
asynchronous reset mechanism are both
tested. Consider the waveforms shown in
◼
Figure 1-9 to test the design.
Waveforms for clk, reset, and 4-bit output
◼
q are shown. The cycle time for clk is 10
units;
The reset signal stays up from time 0 to
15 and then goes up again from time 195
to 205. Output q counts from 0 to 15. 52
Stimulus Block
53
Example 1-6 Stimulus Block
◼ 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
54
Example 2-7. Output of
the Simulation
◼ 0 Output q = 0 20 Output q = 1 30 Output q =
2 40 Output q = 3 50 Output q = 4 60 Output
q = 5 70 Output q = 6 80 Output q = 7 90
Output q = 8 100 Output q = 9 110 Output q =
10 120 Output q = 11 130 Output q = 12 140
Output q = 13 150 Output q = 14 160 Output
q = 15 170 Output q = 0 180 Output q = 1 190
Output q = 2 195 Output q = 0 210 Output q =
1 220 Output q = 2
55
56
Summary
◼ In this module we discussed the following concepts. Two
◼ kinds of design methodologies are used for digital design:
top-down and bottom-up. A combination of these two
methodologies is used in today's digital designs. As
designs become very complex, it is important to follow
these structured approaches to manage the design
process.
◼ Modules are the basic building blocks in Verilog. Modules
are used in a design by instantiation. An instance of a
module has a unique identity and is different from other
instances of the same module. Each instance has an
independent copy of the internals of the module. It is
important to understand the difference
between modules and instances.
57
◼ There are two distinct components in a
simulation: a design block and a stimulus
block. A stimulus block is used to test the
design block. The stimulus block is usually
the top-level block. There are two different
styles of applying stimulus to a design block.
◼ The example of the ripple carry counter
explains the step-by-step process of building
all the blocks required in a simulation.
58
Outcomes of Module-
1
◼ After completion of the module the
students are able to:
◼ Understand the importance, trends of HDL
and design flow and design methodologies
for digital design.
◼ Differentiate the modules and module
instances in Verilog with an example.
◼ Define stimulus block and design block
59
Recommended questions
◼ Discuss in brief about the evolution of CAD tools and
HDLs used in digital system design.
◼ Explain the typical VLSI IC design flow with the help of
flow chart.
◼ Discuss the trends in HDLs?
◼ Why Verilog HDL has evolved as popular HDL in digital
circuit design?
◼
Explain the advantages of using HDLs over traditional
schematic based design.
◼
Describe the digital system design using hierarchical
design methodologies with an example.
60
◼ Apply the top-down design methodology to demonstrate
the design of ripple carry counter.
◼ Apply the bottom-up design methodology to demonstrate
the design of 4-bit ripple carry adder.
◼ Write Verilog HDL program to describe the 4-bit ripple
carry counter.
◼
Define Module and an Instance. Describe 4 different
description styles of Verilog HDL.
Differentiate simulation and synthesis. What is stimulus?
◼
Write test bench to test the 4-bit ripple carry counter.
◼
Write a test bench to test the 4-bit ripple carry adder.
◼
61
Reference / Text Book Details
Sl.No Title of Book Author Publication Edition
.
1 Digital Design
Verilog HDL: Aand Synthesis
Guide to Samir Palnitkar Pearson nd
Education 2
education 2
SJB INSTITUTE OF
TECHNOLOGY
BGS Health & Education City, Kengeri , Bangalore – 60 .
DEPARTMENT OF
ELECTRONICS &
COMMUNICATION
ENGINEERING
Verilog AND
Module 2: BASIC CONCEPTS HDL MODULES AND
PORTS
[18EC56]
By:
Mrs. LATHA S
Assistant
Professor,
Dept. of ECE,
SJBIT
1
Content
◼ Basic Concepts: Lexical conventions
◼ Data types,
◼ System tasks,
◼ Compiler directives.
◼ Modules and Ports:
◼ Module definition,
◼ Port declaration,
◼ Connecting ports,
◼ Hierarchical name
◼ Referencing
Learning Objectives
◼ Understand the lexical conventions and
define the logic value set and data type.
◼ Identify useful system tasks and basic
compiler directives.
◼ Identify and understanding of components
of a Verilog module definition. Understand
◼
the port connection rules and connection
to external signals by ordered list and by
name
Lexical Conventions
◼ The basic lexical conventions used by Verilog
HDL are similar to those in the C
programming language.
◼ Verilog contains a stream of tokens. Tokens
can be comments, delimiters, numbers,
strings, identifiers, and keywords.
◼ Verilog HDL is a case-sensitive language. All
◼ keywords are in lowercase.
Whitespace
◼ Blank spaces (\b) , tabs (\t) and newlines (\n)
comprise the whitespace.
◼ Whitespace is ignored by Verilog except
when it separates tokens.
◼ Whitespace is not ignored in strings.
Comments
◼ Comments can be inserted in the code for
readability and documentation.
◼ There are two ways to write comments. A one-
line comment starts with "//".
◼
Verilog skips from that point to the end of line. 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.
Comment Syntax
◼ reg C_IN;
◼ wire C_OUT;
<stimulus>
◼ . ….
◼ endmodule
Education 2
education 2
SJB INSTITUTE OF
TECHNOLOGY
BGS Health & Education City, Kengeri , Bangalore – 60 .
DEPARTMENT OF
ELECTRONICS &
COMMUNICATION
ENGINEERING
Verilog
Module 3: Gate-Level HDL
and Data Flow Modelling
[18EC56]
By:
Mrs. LATHA S
Assistant
Professor,
Dept. of ECE,
SJBIT
1
Content
1. Basic Verilog gate primitives
5. Continuous assignments
6. Delay specification
8. Operator types
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 and Explain min, max, and type
delays in the gate-level design
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 and Define
expressions, operators, and operands.
◼ Use dataflow constructs to model practical
digital circuits in Verilog
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.
◼
The corresponding logic symbols for these
gates are shown in Figure 3-1. Consider the
◼
gates with two inputs. The output terminal is
denoted by out. Input terminals are denoted
by i1 and i2.
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 instantia tion
Truth Table
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. We will discuss gates that have
one input and one
◼
output. Two basic buf/not gate primitives are
provided in Verilog.
The symbols for these logic gates are shown in
Figure 3-2.
Example 3-2 Gate Instantiations of Buf/Not
Gates
◼ These gates are instantiated in Verilog as shown Example 3- 2.
Notice that these gates can have multiple outputs but exactly
one input, which is the last terminal in the port list.
◼ // basic gate instantiations.
◼ Truth tables for gates with one input and one output are shown
in Table 3-2.
Bufif/notif
◼ Gates with an additional control signal
on buf and not gates are also available.
◼ These gates propagate only if their
control signal is asserted. They
propagate z if their control signal is
deasserted. Symbols for bufif/notif are
shown in Figure 3-3.
Example 3-3 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 are required.
◼ These instances differ from each other only by
the index of the vector to which they are
connected.
◼ To simplify specification of such instances,
Verilog HDL allows an array of primitive
instances to be defined.
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]);
Gate-level multiplexer
Logic Diagram for Multiplexer
Example 3-5 Verilog Description of
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);
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
1-bit Full Adder
◼ Example 3-7 Verilog Description for 1-bit
Full Adder
◼ // Define a 1-bit full adder
◼ module fulladd(sum, c_out, a, b, c_in);
◼ // I/O port declarations
◼ output sum, c_out;
◼ input a, b, c_in;
◼ // Internal nets
◼ wire s1, c1, c2;
◼ // Instantiate logic gate primitives
◼ xor (s1, a, b);
◼ and (c1, a, b);
◼ xor (sum, s1, c_in);
◼ and (c2, s1, c_in);
◼ xor (c_out, c2, c1);
◼ endmodule
4-bit Ripple Carry Full Adder
◼ Example 3-8 Verilog Description for 4-bit
Ripple Carry Full Adder
◼ // Define a 4-bit full adder
◼ 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;
◼ // Internal nets
◼ wire c1, c2, c3;
◼ // Instantiate four 1-bit full adders.
◼ fulladd fa0(sum[0], c1, a[0], b[0], c_in);
◼ fulladd fa1(sum[1], c2, a[1], b[1], c1);
◼ fulladd fa2(sum[2], c3, a[2], b[2], c2);
◼ fulladd fa3(sum[3], c_out, a[3], b[3], c3);
◼ endmodule
◼ Example 3-9 Stimulus for 4-bit Ripple
Carry Full Adder
◼ // Define the stimulus (top level module)
◼ module stimulus;
◼ // Set up variables
◼ reg [3:0] A, B;
◼ reg C_IN;
◼ wire [3:0] SUM;
◼ wire C_OUT;
◼ // Instantiate the 4-bit full adder. call it FA1_4
◼ fulladd4 FA1_4(SUM, C_OUT, A, B, C_IN);
◼ // Set up the monitoring for the signal values
◼ initial
◼ begin
◼ $monitor($time," A= %b, B=%b, C_IN= %b, --
- C_OUT= %b, SUM= %b\n",
◼ A, B, C_IN, C_OUT, SUM);
◼ End
◼ // Stimulate inputs
◼ initial
◼ begin
◼ A = 4'd0; B = 4'd0; C_IN = 1'b0;
◼ #5 A = 4'd3; B = 4'd4;
◼ #5 A = 4'd2; B = 4'd5;
◼ #5 A = 4'd9; B = 4'd9;
◼ #5 A = 4'd10; B = 4'd15;
◼ #5 A = 4'd10; B = 4'd5; C_IN = 1'b1;
◼ end
◼ endmodule
◼ The output of the simulation is shown below.
◼ 0 A= 0000, B=0000, C_IN= 0, --- C_OUT= 0, SUM=
0000
◼ 5 A= 0011, B=0100, C_IN= 0, --- C_OUT= 0, SUM=
0111
◼ 10 A= 0010, B=0101, C_IN= 0, --- C_OUT= 0, SUM=
0111
◼ 15 A= 1001, B=1001, C_IN= 0, --- C_OUT= 1, SUM=
0010
◼ 20 A= 1010, B=1111, C_IN= 0, --- C_OUT= 1, SUM=
1001
◼ 25 A= 1010, B=0101, C_IN= 1,--- C_OUT= 1, SUM=
0000
Gate Delays
◼ Until now, circuits are described
without any delays (i.e., zero
delay). In real circuits, logic
◼ gates have delays associated
with them. Gate delays allow
◼
the Verilog user to specify
delays through the logic circuits.
◼ Pin-to-pin delays can also be
specified in Verilog.
There are three types of delays
from the inputs to the output of
a primitive gate : Rise, Fall,
◼ Rise delay
◼ The rise delay is associated with a gate
output transition to a 1 from another value.
◼ 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.
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.
If all three delays are specified, they refer to
◼
rise, fall, and turn-off delay values.
If no delays are specified, the default value is
zero. Examples of delay specification are
shown in Example 3- 10.
Example 3-10 Types of Delay
Specification
◼ // Delay of delay_time for all transitions
◼ and #(delay_time) a1(out, i1, i2);
◼ // Rise and Fall Delay Specification.
◼ and #(rise_val, fall_val) a2(out, i1, i2);
◼ // Rise, Fall, and Turn-off Delay
◼ Specification bufif0 #(rise_val, fall_val,
turnoff_val) b1 (out, in, control);
◼ Examples of delay specification are shown
below.
◼ 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 mentioned above.
◼ For each type of 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 be 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. (For Verilog-
XL , the values are chosen by specifying options
+maxdelays, +typdelays, and +mindelays at run time. If
no option is specified, the typical delay value is the
◼
default).
This allows the designers the flexibility of building three
delay values for each transition into their design.
◼
The
◼
designer can experiment with delay values without
modifying the design.
◼
◼ Example 3-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, turn-off = min(3,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);
◼ // 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);
◼ Examples of invoking the Verilog-XL simulator with the
command-line options are shown below. Assume that the
module with delays is declared in the file test.v. //invoke
◼
simulation with maximum delay
◼
> verilog test.v +maxdelays
◼
//invoke simulation with minimum delay
◼
> verilog test.v +mindelays
//invoke simulation with typical delay
◼
> verilog test.v +typdelays
◼
Delay Example
◼ Let us consider a simple example to
illustrate the use of gate delays to model
◼
timing in the logic circuits.
A simple module called D implements the
◼
following logic equations:
out = (a b) + c
◼
The gate-level implementation is shown in
Module D (Figure 3-8). The module
contains two gates with delays of 5 and 4
time units.
◼ Example 3-12 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
◼ Example 3-13 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
◼ The waveforms from the simulation are shown in Figure
3-9 to illustrate the effect of specifying delays on
◼ gates.
◼ The waveforms are not drawn to scale. However,
simulation time at each transition is specified below the
◼
transition.
◼ The outputs E and OUT are initially unknown.
◼
At time 10, after A, B, and C all transition to 1, OUT
transitions to 1 after a delay of 4 time units and E
changes value to 1 after 5 time units.
At time 20, B and C transition to 0. E changes value to 0
◼
after 5 time units, and OUT transitions to 0, 4 time units
after E changes.
Data Flow Modeling
◼ For small circuits, the gate-level modeling approach
works very well because the number of gates is limited
and the designer can instantiate and connects every gate
individually.
◼ Also, gate-level modeling is very intuitive to a designer
with a basic knowledge of digital logic design. However,
in complex designs the number of gates is very large.
◼
Thus, designers can design more effectively if they
concentrate on implementing the function at a level of
abstraction higher than gate level.
◼
Dataflow modeling provides a powerful way to implement
a design.
◼
Verilog allows a circuit to be designed in terms of the
data flow between registers and how a design processes
data rather than instantiation of individual gates.
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 is as
◼
follows. continuous_assign ::= assign
[ drive_strength ] [ delay3 ]
list_of_net_assignments ;
◼
list_of_net_assignments ::= net_assignment { ,
net_assignment }
◼
net_assignment ::= net_lvalue = expression
◼ 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.
Continuous assignments have the following characteristics:
◼ 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.
◼ 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.
◼ The operands on the right-hand side can be registers or nets or
function calls. Registers or nets can be scalars or vectors.
◼ Delay values can be specified for assignments in terms of time
units. Delay values are used to control the time when a net is
assigned the evaluated value.
◼ This feature is similar to specifying delays for gates. It is very
useful in modeling timing behavior in real circuits.
◼ Example 3-14 Examples of Continuous
Assignment
◼ // Continuous assign. out is a net. i1 and i2 are nets.
◼ assign out = i1 & i2;
◼ // Continuous assign for vector nets. addr is a 16-bit
vector net // addr1 and addr2 are 16-bit vector
registers.
◼ assign addr[15:0] =addr1_bits[15:0]^addr2_bits[15:0];
◼ // Concatenation. Left-hand side is a concatenation of
a scalar// net and a vector net.
◼ assign {c_out, sum[3:0]} = a[3:0] + b[3:0] + c_in;
Implicit Continuous Assignment
◼ Instead of declaring a net and then writing a continuous
assignment on the net, Verilog provides a shortcut by which a
continuous assignment can be placed on a net when it is
declared. There can be only one implicit declaration
◼ assignment per net because a net is declared only once. In
◼ //same as
◼ wire out;
◼
Examples: integer count,
final_count;
final_count = count + 1;//count is
◼ c = a - b; //a and b are real operands
◼ 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
◼ reg ret_value;
◼ ret_value=calculate_parity(A,B);//calculate_p
arity is a//function type operand
Operators
◼ Operators act on the operands
to produce desired results.
◼ Verilog provides various types
of operators. Operator
◼ Types d1 && d2 // && is an
operator on operands d1 and
◼ d2.
◼ !a[0] // ! is an operator on
operand a[0]
B >> 1 // >> is an operator on
operands B and 1
Operator Types
◼ Arithmetic
◼ There are five arithmetic operators in Verilog. module
◼ Arithmetic (A, B, Y1, Y2, Y3, Y4, Y5);
◼ input [2:0] A, B;
◼ output [3:0] Y1;
◼ output [4:0] Y3;
◼ output [2:0] Y2, Y4, Y5;
◼ reg [3:0] Y1;
◼ reg [4:0] Y3;
◼ reg [2:0] Y2, Y4, Y5;
◼ always @(A or B)
◼ begin
◼ Y1=A+B;//addition
◼ Y2=A-B;//subtraction
◼ Y3=A*B;//multiplication
◼ Y4=A/B;//divisionY5=A%B;//modulus of A divided by B
◼ end
◼ endmodule
◼
Logical and Relational Operators
Equality and Bitwise Operators
◼ Equality and inequality
◼ Equality and inequality operators are used in exactly the same way
as relational operators and return a true or false indication
depending on whether any two operands are equivalent or not.
◼ module Equality (A, B, Y1, Y2, Y3);
◼ input [2:0] A, B;
◼ output Y1, Y2;
◼ output [2:0] Y3;
◼ reg Y1, Y2;
◼ reg [2:0] Y3;
◼ always @(A or B)
◼ begin
◼ Y1=A==B;//Y1=1 if A equivalent to B
◼ Y2=A!=B;//Y2=1 if A not equivalent to B
◼ if (A==B)//parenthesis needed
◼ Y3=A;
◼ else
◼ Y3=B;
◼ end
◼ endmodule
◼ Bit-wise
◼ Logical bit-wise operators take two single or multiple operands on
either side of the operator and return a single bit result. The only
exception is the NOT operator, which negates the single operand that
follows. Verilog does not have the equivalent of NAND or NOR
operator, their funstion is implemented by negating the AND and OR
operators.
◼ module Bitwise (A, B, Y);
◼ input [6:0] A;
◼
input [5:0] B;
◼
output [6:0] Y;
◼
reg [6:0] Y;
always @(A or B)
◼
begin
◼
Y(0)=A(0)&B(0); //binary AND
◼
Y(1)=A(1)|B(1); //binary OR
◼
Y(2)=!(A(2)&B(2)); //negated AND
◼
Y(3)=!(A(3)|B(3)); //negated OR
◼
Y(4)=A(4)^B(4); //binary XOR
◼
Y(5)=A(5)~^B(5); //binary XNOR
◼ Y(6)=!A(6); //unary negation
◼ end
◼ endmodule
◼
◼ Reduction
◼ Verilog has six reduction operators, these operators accept a single
vectored (multiple bit) operand, performs the appropriate bit-wise
reduction on all bits of the operand, and returns a single bit result.
For example, the four bits of A are ANDed together to produce Y1.
◼ module Reduction (A, Y1, Y2, Y3, Y4, Y5, Y6);
◼ input [3:0] A;
◼ output Y1, Y2, Y3, Y4, Y5, Y6;
◼ reg Y1, Y2, Y3, Y4, Y5, Y6;
◼ always @(A)
◼ begin
◼ Y1=&A; //reduction AND
◼ Y2=|A; //reduction OR
◼ Y3=~&A; //reduction NAND
◼ Y4=~|A; //reduction NOR
◼ Y5=^A; //reduction XOR
◼ Y6=~^A; //reduction XNOR
◼ end
◼ Shift
◼ Shift operators require two operands. The operand before the
operator contains data to be shifted and the operand after the
operator contains the number of single bit shift operations to be
performed. 0 is being used to fill the blank positions.
◼ module Shift (A, Y1, Y2);
◼
◼ input [7:0] A;
◼ output [7:0] Y1, Y2;
◼ parameter B=3; reg [7:0] Y1, Y2;
◼
◼ always @(A)
◼ begin
◼ Y1=A<<B; //logical shift left
◼ Y2=A>>B; //logical shift right
◼ end
◼ endmodule
◼ Concatenation and Replication
◼ The concatenation operator "{ , }" combines (concatenates) the bits
of two or more data objects. The objects may be scalar (single bit) or
vectored (muliple bit). Multiple concatenations may be performed
with a constant prefix and is known as replication.
◼ module Concatenation (A, B, Y);
◼ input [2:0] A, B;
◼ output [14:0] Y;
◼ parameter C=3'b011;
◼ reg [14:0] Y;
◼ always @(A or B)
◼ begin
◼ Y={A, B, (2{C}}, 3'b110};
◼ end
◼ endmodule
◼
◼ Conditional
◼ An expression using conditional operator
evaluates the logical expression before the
"?".
◼ If the expression is true then the expression
before the colon (:) is evaluated and assigned
to the output.
◼ If the logical expression is false then the
expression after the colon is evaluated and
assigned to the output.
4-to-1 Multiplexer
◼ Gate-level modeling of a 4-to-1 multiplexer,
Example. The logic diagram for the
multiplexer is given in Figure 3.4 and the
gate-level Verilog description is shown in
◼
Example.
We describe the multiplexer, using dataflow
◼
statements. We show two methods to model
the multiplexer by using dataflow statements.
◼
Method 1: logic equation
◼
We can use assignment statements instead
of gates to model the logic equations of the
◼
multiplexer.
Notice that everything is same as the gate-
level Verilog description except that
computation of out is done by specifying one
◼ I/O ports remain the same.
◼ This important so that the interface with the environment
does not change. Only the internals of the module
change.
◼
Example 4-to-1 Multiplexer, Using Logic Equations //
◼
Module 4-to-1 multiplexer using data flow. logic equation
module mux4_to_1 (out, i0, i1, i2, i3, s1, s0);
◼ 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: Conditional Operator
◼ There is a more concise way to specify the 4-to-1
multiplexers.
◼ Example of 4-to-1 Multiplexer, Using Conditional
Operators
◼ // 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;
◼
assign out = s1 ? ( s0 ? i3 : i2) : (s0 ? i1 : i0) ; endmodule
◼
◼
4 bit Full Adder
◼
Method 1: dataflow
◼
operators Example 4-bit Full
◼
Adder, Using 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
Example 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
◼ 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];c4, c3, c2, c1;
◼ 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 I
◼ 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
◼
Ripple Counter
Example: Verilog Code for Ripple
Counter
◼ module counter(Q , clock, clear);
◼ // I/O ports
◼ output [3:0] Q;
◼ input clock, clear;
◼ // Instantiate the T flipflops
◼ T_FF tff0(Q[0], clock, clear);
◼ T_FF tff1(Q[1], Q[0], clear);
◼ T_FF tff2(Q[2], Q[1], clear);
◼ T_FF tff3(Q[3], Q[2], clear);
◼ endmodule
Stimulus Module for Ripple
Counter
◼ // Top level stimulus module
◼ module stimulus;
◼ // Declare variables for stimulating input
◼ reg CLOCK, CLEAR;
◼ wire [3:0] Q;
◼ initial
◼ $monitor($time, " Count Q = %b Clear=
%b", Q[3:0],CLEAR);
◼ // Instantiate the design block counter
◼ counter c1(Q, CLOCK, CLEAR)
◼ // Stimulate the Clear Signal
◼ initial
◼ begin
◼ CLEAR = 1'b1;
◼ #34 CLEAR = 1'b0;
◼ #200 CLEAR = 1'b1;
◼ #50 CLEAR = 1'b0;
◼
End
◼
// Set up the clock to toggle every 10 time units
◼
initial
◼
begin
◼
CLOCK = 1'b0;
◼
forever #10 CLOCK = ~CLOCK;
◼
end
◼ // Finish the simulation at time 400
◼ initial
◼ begin
◼ #400 $finish;
◼ end
◼ endmodule
The output of the simulation is shown below. Note that the clear signal resets
the count to zero.
T-Flipflop
Example :Verilog Code for T-flipflop
◼ // Edge-triggered T-flipflop. Toggles every clock
◼ // cycle.
◼ module T_FF(q, clk, clear);
◼ // I/O ports
◼ output q;
◼ input clk, clear;
◼ // Instantiate the edge-triggered DFF
◼ // Complement of output q is fed back.
◼ // Notice qbar not needed. Unconnected port.
◼ edge_dff ff1(q, ,~q, clk, clear);
◼
endmodule
D-flipflop
Verilog Code for Edge-Triggered
D-flipflop
◼ // Edge-triggered D flipflop
◼ module edge_dff(q, qbar, d, clk, clear);
◼ output q,qbar;
◼ // Internal variables
Education 2
education 2
SJB INSTITUTE OF
TECHNOLOGY
BGS Health & Education City, Kengeri , Bangalore – 60 .
DEPARTMENT OF
ELECTRONICS &
COMMUNICATION
ENGINEERING
Verilog
Module 4: Behavioural ModellingHDL
and Tasks Functions
[18EC56]
By:
Mrs. LATHA S
Assistant
Professor,
Dept. of ECE,
SJBIT
1
Content
◼ Structured procedures
◼ Initial and always,
◼ Blocking and non-blocking statements
◼ Delay control, generate statement
◼ Event control, conditional statements
◼ Multiway branching, loops
◼ sequential and parallel blocks
◼ Tasks and Functions: Differences between tasks
and functions, declaration, invocation, automatic
tasks and functions.
Learning Objectives
◼ To Explain the significance of structured procedures
always and initial in behavioral modeling.
To Define blocking and nonblocking procedural
◼ assignments.
To Understand delay-based timing control
◼ mechanism in behavioral modeling. Use regular
delays, intra-assignment delays, and zero delays.
To Describe event-based timing control mechanism
◼ in behavioral modeling. Use regular event control,
named event control, and event OR control.
Learning Objectives
◼ To Use level-sensitive timing control
mechanism in behavioral modeling.
◼ To Explain conditional statements using if and
else.
◼ To Describe multiway branching, using case,
casex, and casez statements.
◼ To Understand looping statements such as
while, for, repeat, and forever.
◼ To Define sequential and parallel blocks
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 state The statements
◼
always and initial cannot be nested. ments.
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
◼ Example 4.1: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
◼ In the above example, 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. Thus, the execution sequence of the statements inside
the initial blocks will be as follows.
◼ 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 used for initialization,
monitoring, waveforms and other 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. Example 4-2 shows such a
◼
declaration.
◼
Example 4-2 Initial Value Assignment
//The clock variable is defined first reg clock;
◼
//The value of clock is set to 0 initial clock = 0;
◼
//Instead of the above method, clock variable
◼
//can be initialized at the time of declaration
◼
//This is allowed only for variables declared //at
◼
module level. reg clock = 0;
Combined Port/Data Declaration
and Initialization
◼ The combined port/data declaration can also be
combined with an initialization. Example 4-3 shows such
a declaration.
◼ Example 4-3 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 Style Port
Declaration and Initialization
◼ Verilog-2001 introduced an abbreviated module port declaration
enhancement, often referred to as “ANSI-C” style port
declarations, where each module port could be declared just
once and include the port position, port direction and port data
type all in a single declaration
◼ ANSI C style port declaration can also be combined with an
initialization. Example 4-4 shows such a declaration.
◼ Example 4-4 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. Example 4-5
illustrates one method to model a clock generator in
Verilog.
◼ Example 4-5 always Statement
◼ module clock_gen (output reg clock);
◼ //Initialize clock at time zero initial
◼ clock = 1'b0;
◼
//Toggle clock every half-cycle (time period = 10) Always
◼ #10 clock = ~clock;
◼
initial
◼
#1000 $finish;
◼
endmodule
◼
◼ In Example 4-5, 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.
◼ These are unlike continuous assignments, Dataflow
Modeling, where one assignment statement can
cause the value of the right-hand-side expression
to be continuouly expression sly placed onto the
left-hand-side net.
◼
The syntax for the simplest form of procedural
assignment is shown below.
◼
assignment ::= variable_lvalue =
[ delay_or_event_control ] 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. In behavioral modeling, all operators can be
used in behavioral expressions. There are two types of
procedural assignment statements: blocking and
◼
nonblocking.
Blocking Assignments
◼ Blocking assignment statements are executed in
the order they are specified in a sequential block.
◼ A blocking assignment will not block execution of
statements that follow in a parallel block.
◼
The = operator is used to specify blocking
assignments. A blocking assignment gets its
◼
name because a blocking assignment must
evaluate the RHS arguments and complete the
assignment without interruption from any other
◼
Verilog statement.
The assignment is said to "block" other
assignments until the current assignment has
completed.
◼ Example 4-6 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
◼
◼ In Example 4-6, the statement y = 1 is executed only
after x = 0 is executed. The behavior in a particular block
is sequential in a begin-end block if blocking statements
are used, because the statements can execute only in
sequence.
◼ The statement count = count + 1 is executed last. The
simulation times at which the statements are executed
are as follows:
◼ All statements x = 0 through reg_b = reg_a are 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
◼ Nonblocking assignments allow scheduling of
assignments without blocking execution of the
statements that follow in a sequential block.
◼ A <= operator is used to specify nonblocking
assignments. Note that this operator has the same
symbol as a relational operator, less_than_equal_to.
◼ The operator <= is interpreted as a relational operator
in an expression and as 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 Example 4-7, where we convert some
blocking assignments to nonblocking assignments,
and observe the behavior.
◼ Example 4-7 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 intege(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.
◼ 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)
Thus, the simulator schedules a non blocking assignment
◼
statement to execute and continues to the next statement
in the block without waiting for the non blocking
statement to complete execution.
◼ Typically, nonblocking assignment statements are
executed last in the time step in which they are
scheduled, that is, after all the blocking assignments
in that time step are executed.
◼ In the example above, we mixed blocking and non
blocking assignments to illustrate their behaviour.
◼
However, it is recommended that blocking and non
blocking assignments not be mixed in the same
always block.
◼ module block_nonblock();
◼ reg a, b, c, d , e, f ;
◼ // Blocking assignments
◼ initial begin
◼ a = #10 1'b1;// The simulator assigns 1 to a at time 10
◼ b = #20 1'b0;// The simulator assigns 0 to b at time 30 c
◼ = #40 1'b1;// The simulator assigns 1 to c at time 70
◼ end
◼ // Nonblocking assignments
◼ initial
◼
begin 13
◼ d <= #10 1'b1;// The simulator assigns 1 to d at time 10
◼ e <= #20 1'b0;// The simulator assigns 0 to e at time 20
◼ f <= #40 1'b1;// The simulator assigns 1 to f at time 40
◼
end
◼
endmodule
Application of non blocking
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
◼ At each positive edge of clock, the following sequence
takes place for the non blocking assignments.
◼ A read operation is performed on each right-hand-side
variable, in1, in2, in3, and reg1, at the positive edge of
clock.
◼ The right-hand-side expressions are evaluated, and the
results are stored internally in the simulator.
◼
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, that is,
schedule "write" to reg1 after 1 time unit, to reg2 at the
next negative edge of clock, and to reg3 after 1 time unit.
◼ The write operations are executed at the scheduled time
steps.
◼ The order in which the write operations are executed is
not important because the internally stored right-hand-
side expression values are used to assign to the left-
hand-side values.
◼ For example, note that reg3 is assigned the old value of
reg1 that was stored after the read operation, even if the
write operation wrote a new value to reg1 before the write
operation to reg3 was executed.
◼
Thus, the final values of reg1, reg2, and reg3 are not
dependent on the order in which the assignments are
processed.
Nonblocking Statements to Eliminate
Race Conditions
◼ //Illustration 1: Two concurrent always blocks with
blocking statements//
◼ always @(posedge clock) a = b;
◼ always @(pose dge clock) b = a;
◼ //Illustration 2: Two concurrent always blocks with
nonblocking statements//
◼
always @(posedge clock) a <= b;
◼
always @(posedge clock) b <= a;
◼
In Example 4-8, in Illustration 1, 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.
Instead, both registers will get the same value (previous
value of a or b), based on the Verilog simulator
implementation
◼ However, nonblocking statements used in Illustration 2
eliminate the race condition. 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, regardless of the order in which the write
operations are performed.
Example 4-9 Implementing Nonblocking
Assignments using Blocking
◼Assignments
Example 4-9 shows how non blocking assignments
shown in Illustration 2 could be emulated using blocking
assignments.
◼ //Emulate the behavior of nonblocking assignments by
◼ //using temporary variables and blocking assignments
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.
◼ Nonblocking assignments can be used effectively to
model concurrent data transfers because the final result
is not dependent on the order in which the assignments
are evaluated.
◼ Typical applications of nonblocking assignments include
pipeline modeling and modeling of several mutually
exclusive data transfers.
◼ On the downside, nonblocking assignments can
potentially cause degradation in the simulator
performance and increase in memory usage.
Timing Controls
◼ Various behavioral timing control
constructs are available in Verilog.
◼ In Verilog, if there are no timing control
statements, the simulation time does not
◼ advance.
Timing controls provide a way to specify
the simulation time at which procedural
◼ statements will execute.
There are three methods of timing
control: delay- based timing control,
event-based timing control, and 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.
◼ delay3 ::= # delay_value | # ( delay_value [ , delay_value
[ , delay_value ] ] )
◼
delay2 ::= # delay_value | # ( delay_value [ ,
delay_value ] ) delay_value ::= unsigned_number |
parameter_identifier | specparam_identifier |
mintypmax_expression
◼ Delay-based timing control can be 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. Usage of
regular delay control is shown in Example 4-10.
Example 4-10 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 // delay control with a
number. Delay execution of // y = 1 by 10units
#10 y = 1;
◼
#latency z = 0; // Delay control with identifier. Delay of
◼
20units
◼ #(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
◼ In Example 4-10, the execution of a procedural
assignment is delayed by the number specified by the
delay control.
◼
For begin-end groups, delay is always relative to time
when the statement is encountered.
◼
Thus, y =1 is executed 10 units after it is encountered in
the activity flow.
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.
◼ Example 4-11 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 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
◼
Regular delays defer the execution of the entire assignment.
Intra-assignment delays compute the righthand- 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
◼ Procedural statements in different always-
initial blocks may be evaluated at the same
◼
simulation time.
The order of execution of these 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 4-12 illustrates zero delay control.
Example 4-12:- Zero Delay Control
◼ initial
◼ begin
◼ x = 0;
◼ y = 0;
◼ end
◼ initial
◼ begin
◼ #0 x = 1; //zero delay control
◼ #0 y = 1;
◼ end
◼ In Example 4-12, 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 above 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 Example 4-13.
◼ Example 4-13 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
◼
if (<expression>) true_statement ;
◼ //Type 2 conditional statement. One else statement
◼ //Either true_statement or false_statement is evaluated
◼ if (<expression>) true_statement ; else false_statement ; //Type
◼ 3 conditional statement. Nested if-else-if.
◼ //Choice of multiple statements. Only one is executed.
◼ 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. The
<expression> can contain any operators. 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.
◼ Example 4-18 Conditional Statement Examples
◼ //Type 1 statements
◼ if(!lock) buffer = data; if(enable) out = in;
◼ //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
◼ 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: statement1; 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. The following Verilog code implements the type 3
conditional statement in Example 4-18.
◼ //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
◼ Example 4-19 4-to-1 Multiplexer with Case Statement
◼ 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)
◼ 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
◼
Casex, Casez Keywords
◼ There are two variations of the case statement.
They are denoted by keywords, 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.
◼
The use of casex and casez allows comparison of
only non- x or -z positions in the case expression
and the case alternatives. Example 4-21 illustrates
the decoding of state bits in a finite state machine
using a casex statement. The use of casez is
similar. Only one bit is considered to determine the
next state and the other bits are ignored.
◼ Example 4-21 casex Use reg [3:0]
encoding; integer state;
◼ casex (encoding) //logic value x represents a
don't care bit.
◼ 4'b1xxx : next_state = 3;
◼ 4'bx1xx : next_state = 2;
◼ 4'bxx1x : next_state = 1;
◼ 4'bxxx1 : next_state = 0;
◼ default : next_state = 0; endcase
◼ Thus, an input encoding = 4'b10xz would
cause next_state = 3 to be executed.
Loops
◼ There are four types of looping
statements in Verilog: while, for, repeat,
and forever. The syntax of these loops
is very similar to the syntax of loops in
the C programming language. All
◼
looping statements can appear only
inside an initial or always block. Loops
◼
may contain delay expressions.
While Loop
The keyword while is used to specify
this 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. Each expression can
contain the operators. Any logical
expression can be specified with these
◼ //Illustration 1: Increment count from 0 to 127. Exit at
count 128.
◼ //Display the count variable.
◼ 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; 148
◼ 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
◼
The counter described in Example 4-
22 can be coded as a for loop
(Example 4-23). The initialization
condition and the incrementing
procedural assignment are included in
the for loop and do not need to be
specified separately. Thus, the for loop
provides a more compact loop
◼ Example 4-23 For Loop
◼ 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. //Initialize array elements 'define MAX_STATES 32
◼
integer state [0: 'MAX_STATES-1]; //Integer array state with
elements 0:31
◼ integer i;
◼ initial begin
◼ for(i = 0; i < 32; i = i + 2) //initialize all even locations with 0 state[i]
= 0;
◼
for(i = 1; i < 32; i = i + 2) //initialize all odd locations with 1
◼
state[i] = 1;
◼
end
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.
The counter in Example 4-22 can be
expressed with the repeat loop, as
◼ Example 4-24 Repeat Loop
◼ //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
◼
Forever loop
◼ The keyword forever is used to express
◼
this 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, e.g., while (1). A forever loop can be
exited by use of the disable statement.
◼
A forever loop is typically used in
conjunction with timing control constructs.
If timing control constructs are not used,
the Verilog simulator would execute this
statement infinitely without advancing
simulation time and the rest of the design
◼ Example 4-25 Forever Loop
◼ //Example 1: Clock generation
◼ //Use forever loop instead of always block 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;
◼
Sequential and Parallel Blocks
◼ Block statements are used to group multiple statements
to act together as one.
◼ In previous examples, we used keywords begin and
end to group multiple statements.
◼ Thus, we used sequential blocks where the statements
in the block execute one after another.
◼
In this section we discuss the block types: sequential
blocks and parallel blocks.
◼
We also discuss three special features of blocks:
named blocks, disabling named blocks, and nested
blocks. There are two types of blocks: sequential
◼
blocks and parallel blocks
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.
◼ Example 4-26 Sequential Blocks
◼ In Illustration 1, the final values are x = 0, y= 1, z = 1, w =
2 at simulation time 0.
◼ //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};
◼
end
◼
◼ In Illustration 2, the final values are the same except that
the simulation time is 35 at the end of the block.
◼ //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. 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.
◼
Notice the fundamental difference
between sequential and parallel blocks.
All statements in a parallel block start at
the time when the block was entered.
Thus, the order in which the statements
◼ Let us consider the sequential block with delay in Example
4-26 and convert it to a parallel block. The converted
Verilog code is shown in Example 4-27. The result of
simulation remains the same except that all statements
start in parallel at time 0. Hence, the block finishes at time
20 instead of time 35.
◼ //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
Special Features of Blocks
◼ We discuss three special features available with block
statements: nested blocks, named blocks and disabling of
named blocks.
◼ Nested blocks:- Blocks can be nested.
◼ Sequential and parallel blocks can be mixed, as
shown in Example 4-28. Example 4-28 Nested Blocks
◼ //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 4-29 shows naming of blocks and hierarchical
naming of blocks.
◼ Example 4-29 Named Blocks
◼ //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.
Task and Functions
◼ Learning Objectives
◼ Describe the differences between
tasks and functions.
◼ Identify the conditions required for
tasks to be defined. Understand task
declaration and invocation.
◼ Explain the conditions necessary for
functions to be defined. Understand
function declaration and invocation.
Task and Functions
◼ A designer is frequently required to implement the same
functionality at many places in a behavioral design.
◼ This means that the commonly used parts should be
abstracted into routines and the routines must be invoked
instead of repeating the code.
◼ Most programming languages provide procedures or
subroutines to accomplish this.
◼
Verilog provides tasks and functions to break up large
behavioral designs into smaller pieces.
◼
Tasks and functions allow the designer to abstract Verilog
code that is used at many places in the design.
◼ Tasks have input, output, and inout arguments; functions
have input arguments.
◼ Thus, values can be passed into and out from tasks and
functions.
◼ Considering the analogy of FORTRAN, tasks are similar
to SUBROUTINE and functions are similar to FUNCTION.
Tasks and functions are included in the design hierarchy.
◼
Like named blocks, tasks or functions can be addressed
◼
by means of hierarchical names.
Differences between Tasks and Functions
◼ Both task and functions must be defined in a module and are
local to the module.
◼ Tasks are used for common Verilog code that contains delays,
timing, event constructs, or multiple output arguments.
◼ Functions are used when common Verilog code is purely
combinational, executes in zero simulation time and provides
exactly one output
◼ Functions are typically used for conversions and commonly
used calculations.
◼ Task can have input, output and in-out ports
◼ Functions can have input ports. In addition they can have local
variables, integers, real or events.
◼ Tasks and functions cannot have wires, they contain behavioral
statements only.
◼
Tasks and functions do not contain always and initial statements
but are called form always block, initial block and other task and
functions.
Task
◼ Tasks are declared with the keywords task
and endtask. Tasks must be used if any
one of the following conditions is true
◼ for the procedure:
◼
There are delay, timing, or event control
◼
constructs in the procedure. The
◼
procedure has zero or more than one
output arguments.
◼ The procedure has no input arguments.
◼ I/O declaration use keywords input, output
◼
or input, based on the type of argument
declared.
Input and output arguments are passed
◼
into the task.
◼
Input arguments are processed in the task
◼ statements.
Output and inout argument values are
Task Declaration and Invocation
◼ task_declaration ::=
◼ task [ automatic ] task_identifier ;
◼ { task_item_declaration }
◼ statement
◼ endtask
◼ | task [ automatic ] task_identifier
( task_port_list ) ;
◼ { block_item_declaration }
◼ statement
◼ endtask
◼ task_item_declaration ::=
◼ block_item_declaration
◼ | { attribute_instance } tf_input_declaration ;
◼ | { attribute_instance } tf_output_declaration ;
◼ | { attribute_instance } tf_inout_declaration ;
◼ task_port_list ::= task_port_item { , task_port_item }
◼ task_port_item ::=
◼ { attribute_instance } tf_input_declaration
◼ | { attribute_instance } tf_output_declaration
◼ | { attribute_instance } tf_inout_declaration
◼ tf_input_declaration ::=
◼ input [ reg ] [ signed ] [ range ]
list_of_port_identifiers
◼ | input [ task_port_type ] list_of_port_identifiers
◼ tf_output_declaration ::=
◼ output [ reg ] [ signed ] [ range ]
list_of_port_identifiers
◼
| output [ task_port_type ] list_of_port_identifiers
◼
tf_inout_declaration ::=
◼
inout [ reg ] [ signed ] [ range ]
list_of_port_identifiers
| inout [ task_port_type ] list_of_port_identifiers
◼
task_port_type ::=
◼
time | real | realtime | integer
◼
◼ I/O declarations use keywords input, output, or inout,
based on the type of argument declared.
◼ Input and inout arguments are passed into the task. Input
◼
arguments are processed in the task statements. Output
and inout argument values are passed back to the
variables in the task invocation statement when the task is
completed.
◼ Tasks can invoke other tasks or functions.
◼ Although the keywords input, inout, and output used for
I/O arguments in a task are the same as the keywords
used to declare ports in modules, there is a difference.
◼
Ports are used to connect external signals to the module.
I/O arguments in a task are used to pass values to and
from the task.
Task Examples
◼ Use of input and output arguments
◼ //Define a module called operation that
contains the task bitwise_oper
◼ module operation;
◼ ...
◼ parameter delay = 10;
◼ reg [15:0] A, B;
◼ reg [15:0] AB_AND, AB_OR, AB_XOR;
◼ always @(A or B) //whenever A or B changes
◼ in value
◼ begin
◼ //invoke the task bitwise_oper. provide 2 input
arguments A, B //Expect 3 output arguments
AB_AND, AB_OR, AB_XOR
◼ //The arguments must be specified in the same order as they //appear
in the task declaration.
◼ bitwise_oper(AB_AND, AB_OR, AB_XOR, A, B);
◼ end
◼ ...
◼ //define task bitwise_oper
◼ task bitwise_oper;
◼ output [15:0] ab_and, ab_or, ab_xor; //outputs from the task
◼ input [15:0] a, b; //inputs to the task
◼ begin
◼ #delay ab_and = a & b;
◼ ab_or = a | b;
◼ ab_xor = a ^ b;
◼ end
◼ endtask
◼ ...
◼ endmodule
◼ In the above task, the input values passed to the task are
A and B.
◼ Hence, when the task is entered, a = A and b = B. The
three output values are computed after a delay.
◼ This delay is specified by the parameter delay, which is
10 units for this example.
◼
When the task is completed, the output values are
passed back to the calling output arguments. Therefore,
◼
AB_AND = ab_and, AB_OR = ab_or, and AB_XOR =
ab_xor when the task is completed.
◼ Example 9-3. Task Definition using ANSI C
Style Argument Declaration
◼ //define task bitwise_oper
◼ task bitwise_oper (output [15:0] ab_and, ab_or, ab_xor,
◼ input [15:0] a, b);
◼ begin
◼ #delay ab_and = a & b;
◼ ab_or = a | b;
◼ ab_xor = a ^ b;
◼
end
◼
endtask
Asymmetric Sequence Generator
◼ Tasks can directly operate on reg variables defined in the module.
◼ Example 8-4 directly operates on the reg variable clock to continuously
produce an asymmetric sequence.
◼ The clock is initialized with an initialization sequence.
◼ Example 9-4. Direct Operation on reg Variables
◼ //Define a module that contains the task asymmetric_sequence module
◼ sequence;
◼ reg clock;
◼ ...
◼ initial
◼ init_sequence; //Invoke the task init_sequence
◼ ...
◼ always
◼ begin
◼ asymmetric_sequence; //Invoke the task asymmetric_sequence
◼ End
◼ //Initialization sequence
◼ task init_sequence;
◼ begin
◼ clock = 1'b0;
◼ end
◼ endtask
◼ //define task to generate asymmetric sequence
◼ //operate directly on the clock defined in the module.
◼ task asymmetric_sequence;
◼ begin
◼ #12 clock = 1'b0;
◼ #5 clock = 1'b1;
◼ #3 clock = 1'b0;
◼ #10 clock = 1'b1;
◼ end
◼ endtask
◼ Endmodule
Functions
◼ Functions are declared with the
keywords function and
◼ endfunction.
Functions are used if all of the
◼ following conditions are true for the
procedure:
◼ 1. There are no delay, timing, or
event control constructs in the
◼
procedure.
◼
2. The procedure returns a single
◼
value.
3. There is at least one input
argument.
Function Declaration and Invocation
◼ Example 9-6. Syntax for Functions
◼ function_declaration ::=
◼ function [ automatic ] [ signed ] [ range_or_type ]
◼ function_identifier ;
◼ function_item_declaration {function_item_declaration }
◼ function_statement
◼ endfunction
◼ | function [ automatic ] [ signed ] [ range_or_type ]
◼ function_identifier (function_port_list ) ;
◼ block_item_declaration { block_item_declaration }
◼ function_statement
◼ endfunction
◼ function_item_declaration ::=
◼ block_item_declaration
◼ | tf_input_declaration ;
◼ function_port_list ::= { attribute_instance }
tf_input_declaration {,
◼ { attribute_instance } tf_input_declaration }
◼
range_or_type ::= range | integer | real | realtime
| time
◼ When a function is declared, a register with name
function_identifer is declared implicitly inside Verilog.
◼ The output of a function is passed back by setting the value of
the register function_identifer appropriately.
◼ The function is invoked by specifying function name and input
arguments.
◼ At the end of function execution, the return value is placed
where the function was invoked.
◼ The optional range_or_type specifies the width of the internal
register.
◼ If no range or type is specified, the default bit width is 1.
Functions are very similar to FUNCTION in FORTRAN. Notice
◼
that at least one input argument must be defined for a function.
There are no output arguments for functions because the
implicit register function_identifer contains the output value.
Also, functions cannot invoke other tasks. Theycan invoke
only other functions.
Function Examples
◼ Parity calculation
◼ //Define a module that contains the function
◼ calc_parity module parity;
◼ ...
◼ reg [31:0] addr;
◼ reg parity;
◼ //Compute new parity whenever address
◼ value changes always @(addr)
◼ begin
◼ parity = calc_parity(addr); //First invocation of
◼ calc_parity $display("Parity calculated = %b",
◼ calc_parity(addr) ); //Second invocation of
◼ calc_parity
end
◼ //define the parity calculation function
◼ function calc_parity;
◼ input [31:0] address;
◼ begin
◼ //set the output value appropriately. Use the implicit
◼ //internal register calc_parity.
◼ calc_parity = ^address; //Return the xor of all address
bits.
◼
end
◼
endfunction
◼
...
◼
...
endmodule
◼
◼ Example 9-8. Function Definition using ANSI C Style
Argument Declaration
◼ //define the parity calculation function using ANSI C Style
arguments
◼ function calc_parity (input [31:0] address);
◼ begin
◼
//set the output value appropriately. Use the implicit
◼
//internal register calc_parity.
◼ calc_parity = ^address; //Return the xor of all address
bits.
end
◼
endfunction
◼
Automatic (Recursive) Functions
Functions are normally used non-recursively . If a
◼
function is called concurrently from two locations, the
results are non-deterministic because both calls operate
on the same variable space.
◼ However, the keyword automatic can be used to
declare a recursive (automatic) function where all
function declarations are allocated dynamically for each
recursive calls.
◼
Each call to an automatic function operates in an
independent variable space.Automatic function items
cannot be accessed by hierarchical references.
Automatic functions can be invoked through the use of
their hierarchical name.
◼ Example 9-10. Recursive (Automatic) Functions
◼ //Define a factorial with a recursive function
◼ module top;
◼ ...
◼ // Define the function
◼ function automatic integer factorial;
◼ input [31:0] oper;
◼ integer i;
◼ begin
◼ if (operand >= 2)
◼ factorial = factorial (oper -1) * oper; //recursive call
◼ else
◼
factorial = 1 ;
◼
end
◼
endfunction
◼ // Call the function
◼ integer result;
◼ initial
◼ begin
◼ result = factorial(4); // Call the factorial of 7
◼ $display("Factorial of 4 is %0d", result); //Displays 24
◼ end
◼ ...
◼ ...
◼ endmodule
Constant Functions
◼ A constant function[1] is a regular Verilog HDL function,
but with certain restrictions.
◼ These functions can be used to reference complex val
ues and can be used instead of constants
◼ Example:-Constant Functions -shows how a
constant function can be used to compute the width of
◼ the address bus in a module. //Define a RAM model
◼ module ram (...);
◼ parameter RAM_DEPTH = 256;
◼ input [clogb2(RAM_DEPTH)-1:0] addr_bus; //width of
bus computed
◼
//by calling constant//function defined below//Result of
◼
clogb2 = 8 //input [7:0] addr_bus;
◼ --
◼ --
◼ //Constant function
◼ function integer clogb2(input integer depth);
◼ begin
◼ for(clogb2=0; depth >0; clogb2=clogb2+1)
◼ depth = depth >> 1;
◼ end
◼ endfunction
◼ --
◼ --
◼ endmodule
Signed Functions
◼ Signed functions allow signed operations to
be performed on the function return values.
◼ Example 8-12 shows an example of a
◼ signed function. Example 9-12. Signed
◼ Functions
◼ module top;
◼ //Signed function declaration
◼ //Returns a 64 bit signed value
function signed [63:0] compute_signed(input
◼
[63:0] vector);
◼
--
--
◼
endfunction
◼ //Call to the signed function from the higher
module
◼ if(compute_signed(vector) < -3)
◼ begin
◼ --
◼ end
◼ endmodule
◼ Recommended Questions
◼ 1. Describe the following statements with an example: initial and
always
◼ 2. What are blocking and non-blocking assignment statements?
Explain with examples.
◼ 3. With syntax explain conditional, branching and loop
statements available in Verilog HDL behavioural description.
◼ 4. Describe sequential and parallel blocks of Verilog HDL.
◼
5. Write Verilog HDL program of 4:1 mux using CASE statement.
◼
6. Write Verilog HDL program of 4:1 mux using If-else statement.
7. Write Verilog HDL program of 4-bit synchronous up counter. 8.
◼
Write Verilog HDL program of 4-bit asynchronous down counter.
◼
9. Write Verilog HDL program to simulate traffic signal controller
◼
Reference / Text Book Details
Sl.No Title of Book Author Publication Edition
.
1 Digital Design
Verilog HDL: Aand Synthesis
Guide to Samir Palnitkar Pearson nd
Education 2
education 2
SJB INSTITUTE OF
TECHNOLOGY
BGS Health & Education City, Kengeri , Bangalore – 60 .
DEPARTMENT OF
ELECTRONICS &
COMMUNICATION
ENGINEERING
Verilog
Module 5: Useful ModellingHDL
Techniques
[18EC56]
By:
Mrs. LATHA S
Assistant
Professor,
Dept. of ECE,
SJBIT
1
Content
Procedural continuous assignments
overriding parameters,
conditional compilation and execution
useful system tasks
Logic Synthesis
Impact of logic synthesis
Verilog HDL Synthesis
Synthesis design flow, Verification of Gate-Level
netlist
Learning Objectives
◼ Describe procedural continuous assignment
statements assign, deassign, force, and release.
Explain their significance in modeling and
debugging.
◼ Understand how to override parameters by using the
defparam statement at the time of module
instantiation.
◼ Explain conditional compilation and execution of parts
of the Verilog description.
◼ Identify system tasks for file output, displaying
hierarchy, strobing, random number generation,
memory initialization, and value change dump
Procedural Continuous Assignments
◼ Procedural assignments assign a value to a register.
The value stays in the register until another
procedural assignment puts another value in that
register.
◼ Procedural continuous assignments behave
differently. They are procedural statements which
allow values of expressions to be driven
continuously onto registers or nets for limited
◼
periods of time. Procedural continuous assignments
override existing assignments to a register or net.
They provide an useful extension to the regular
procedural assignment statement.
Assign and Deassign
◼ The keywords assign and deassign are used to
express the first type of procedural continuous
◼
assignment.
The left-hand side of procedural continuous
◼
assignments can be only be a register or a
concatenation of registers. It cannot be a part or
bit select of a net or an array of registers.
◼
Procedural continuous assignments override the
effect of regular procedural assignments.
◼
Procedural continuous assignments are
normally used for controlled periods of time.
D-Flipflop with Procedural Continuous
Assignments
◼ // Negative edge-triggered D-flipflop with asynchronous
reset
◼ module edge_dff(q, qbar, d, clk, reset);
◼ // Inputs and outputs
◼ output q,qbar;
◼ input d, clk, reset;
◼
reg q, qbar; //declare q and qbar are registers
◼
always @(negedge clk) //assign value of q & qbar at
active edge of clock.
begin
◼
q = d;
◼
qbar = ~d;
◼
end
◼
◼ always @(reset) //Override the regular assignments to q and qbar
◼ //whenever reset goes high. Use of procedural continuous
//assignments.
◼ if(reset)
◼ begin //if reset is high, override regular assignments to q with //the
◼ new values, using procedural continuous assignment. assign q =
◼ 1'b0;
◼ assign qbar = 1'b1;
◼ end
◼ else
◼ begin //If reset goes low, remove the overriding values by
//deassigning the registers. After this the regular
◼
//assignments q = d and qbar = ~d will be able to change
◼
//the registers on the next negative edge of clock.
◼
deassign q;
◼
deassign qbar;
◼
end
◼
endmodule
Force and Release
◼ Keywords force and release are used to
express the second form of the procedural
◼ continuous assignments. They can be used
to override assignments on both registers
◼
and nets.
Force and release statements are typically
used in the interactive debugging process,
where certain registers or nets are forced to a
◼
value and the effect on other registers and
nets is noted.
It is recommended that force and release
statements not be used inside design blocks.
They should appear only in stimulus or as
debug statements.
Force and Release on registers
◼
◼ Closing files
◼ Files can be closed with the system task
$fclose.
◼ Usage: $fclose(<file_handle>);
◼ //Closing Files
◼ $fclose(handle1);
◼ A file cannot be written to once it is closed.
The corresponding bit in the multichannel
descriptor is set to 0. The next $fopen call
can reuse the bit.
Displaying Hierarchy
◼ Hierarchy at any level can be displayed by
means of the %m option in any of the
display tasks, $display, $write task, $monitor,
or $strobe task, as discussed briefly in
◼ Section 4.3, Hierarchical Names.
This is a very useful option. For example,
when multiple instances of a module
execute the same Verilog code, the %m
◼ option will distinguish from which module
instance the output is coming.
No argument is needed for the %m option in
the display tasks. See Example 9-10.
Displaying Hierarchy
◼ //Displaying hierarchy information
◼ module M;
◼ ...
◼ initial
◼ $display("Displaying in %m");
◼ endmodule
◼ //instantiate module M
◼ module top;
◼ ...
◼ M m1();
◼ M m2();
◼ //Displaying hierarchy information
◼ M m3();
◼ endmodule
◼ The output from the simulation will look like
the following:
◼ Displaying in top.m1
◼ Displaying in top.m2
◼ Displaying in top.m3
◼ This feature can display full hierarchical
names, including module instances, tasks,
functions, and named blocks.
Strobing
◼ Strobing is done with the system task
keyword $strobe. This task is very
similar to the $display task except for
◼
a slight difference.
If many other statements are
executed in the same time unit as the
$display task, the order in which the
statements and the $display task are
◼
executed is nondeterministic.
If $strobe is used, it is always
executed after all other assignment
◼
statements in the same time unit
have executed.
Thus, $strobe provides a
synchronization mechanism to
ensure that data is displayed only
◼ Example 5-11. Strobing
◼ //Strobing
◼ always @(posedge clock)
◼ begin
◼ a = b;
◼ c = d;
◼ end
◼
always @(posedge clock)
◼
$strobe("Displaying a = %b, c = %b", a, c); // display
values at posedge
In Example 9-11, the values at positive edge of clock will
◼
be displayed only after statements a = b and c = d
execute.
If $display was used, $display might execute
◼
beforestatements a = b and c = d, thus displaying
different
Random Number Generation
◼ Random number generation capabilities are required for
generating a random set of test vectors.
◼ Random testing is important because it often catches
hidden bugs in the design.
◼ Random vector generation is also used in performance
analysis of chip architectures.
◼ The system task $random is used for generating a
random number.
◼ Usage: $random;
◼ $random(<seed>);
◼ The value of <seed> is optional and is used to ensure the
same random number sequence each time the test is run.
The <seed> parameter can either be a reg, integer, or
time variable. The task $random returns a 32-bit signed
integer.
Random Number Generation
◼ //Generate random numbers and apply them to a simple
◼ ROM module test;
◼ integer r_seed;
◼ reg [31:0] addr;//input to ROM
◼ wire [31:0] data;//output from ROM
◼ ...
◼ ROM rom1(data, addr);
◼ initial
◼ r_seed = 2; //arbitrarily define the seed as 2.
◼ always @(posedge clock)
◼ addr = $random(r_seed); //generates random numbers
◼ ...
◼ <check output of ROM against expected results>
◼ ...
◼ Generation of Positive and Negative Numbers by
$random Task
◼ reg [23:0] rand1, rand2;
◼ rand1 = $random % 60; //Generates a random
number between -59 and 59
◼ rand2 = {$random} % 60; //Addition of concatenation
operator to
◼ //$random generates a positive value between //0
and 59.
◼ Initializing Memory from File
◼ We discussed how to declare memories in Section 3.2.7, Memories.
◼ Verilog provides a very useful system task to initialize memories from
a data file.
◼ Two tasks are provided to read numbers in binary or hexadecimal
format.
◼ Keywords $readmemb and $readmemh are used to initialize
memories.
◼ Usage: $readmemb("<file_name>", <memory_name>);
$readmemb("<file_name>", <memory_name>, <start_addr>);
◼ $readmemb("<file_name>", <memory_name>, <start_addr>,
◼ <finish_addr>);
◼ Identical syntax for $readmemh.
◼ The <file_name> and <memory_name> are mandatory; <start_addr>
and <finish_addr> are optional.
◼
Defaults are start index of memory array for <start_addr> and end of
the data file or memory for <finish_addr>.
◼
Initializing Memory
◼ module test;
◼ reg [7:0] memory[0:7]; //declare an 8-byte
◼ memory
◼ integer i;
◼ initial
◼ begin
◼ //read memory file init.dat. address locations
◼ given in memory $readmemb("init.dat",
◼ memory);
◼ module test;
◼ //display contents of initialized memory
◼ for(i=0; i < 8; i = i + 1)
◼ $display("Memory [%0d] = %b", i, memory[i]);
end
endmodule
◼ The file init.dat contains the initialization data.
Addresses are specified in the data file with
@<address>. Addresses are specified as
hexadecimal numbers. Data is separated by
whitespaces. Data can contain x or z.
Uninitialized locations default to x. A
sample file, init.dat, is shown below. @002
◼ 11111111 01010101
◼ 00000000 10101010
◼ @006
◼ 1111zzzz 00001111
◼
◼ When the test module is simulated, we will
get the following output:
◼ Memory [0] = xxxxxxxx
◼ Memory [1] = xxxxxxxx
◼ Memory [2] = 11111111
◼ Memory [3] = 01010101
◼ Memory [4] = 00000000
◼ Memory [5] = 10101010
◼ Memory [6] = 1111zzzz
◼ Memory [7] = 00001111
Value Change Dump File (VCD)
◼ A value change dump (VCD) is an ASCII file that contains
information about simulation time, scope and signal definitions,
and signal value changes in the simulation run. All signals or a
◼ selected set of signals in a design can be written to a VCD file
during simulation.
◼ Postprocessing tools can take the VCD file as input and
visually display hierarchical information, signal values, and
signal waveforms.
◼ Many postprocessing tools as well as tools integrated into the
simulator are now commercially available.
◼ For simulation of large designs, designers dump selected
signals to a VCD file and use a postprocessing tool to debug,
analyze, and verify the simulation output.
Debugging and Analysis of Simulation with
VCD File
◼ System tasks are provided for selecting module
instances or module instance signals to dump
($dumpvars), name of VCD file ($dumpfile), starting and
stopping the dump process ($dumpon, $dumpoff), and
generating checkpoints ($dumpall).
◼ The uses of each task are shown in Example 9-15.
◼ //specify name of VCD file. Otherwise,default name is
◼ //assigned by the simulator.
◼ initial
◼ $dumpfile("myfile.dmp"); //Simulation info
dumped to myfile.dmp
◼ //Dump signals in a module
◼ initial
◼ $dumpvars; //no arguments, dump all signals
in the design
◼ initial
◼ $dumpvars(1, top); //dump variables in
module instance top.
◼ //Number 1 indicates levels of hierarchy.
Dump one
◼ //hierarchy level below top, i.e., dump
variables in top,
◼ //but not signals in modules instantiated by
top.
◼ initial
◼ $dumpvars(2, top.m1);//dump up to 2 levels of
hierarchy below top.m1
◼ initial
◼ $dumpvars(0, top.m1);//Number 0 means
dump the entire hierarchy
◼ // below top.m1
◼ //Start and stop dump process
◼ initial
◼ begin
◼ $dumpon; //start the dump process.
◼ #100000 $dumpoff; //stop the dump process after 100,000
time units
◼
end
//Create a checkpoint. Dump current value of all VCD
variables
initial
◼
$dumpall;
◼
The $dumpfile and $dumpvars tasks are normally specified at
◼
the beginning of the simulation. The $dumpon, $dumpoff, and
$dumpall control the dump process during the simulation.[5]
Questions
Education 2
education 2