Professional Documents
Culture Documents
Application
Version 6.2
Lecture Manual
March 6, 2008
Cadence Trademarks
Trademarks and service marks of Cadence Design Systems, Inc. (Cadence) contained in this document are attributed to Cadence with the appropriate symbol.
For queries regarding Cadences trademarks, contact the corporate legal department at the address above or call 800.862.4522.
Allegro
Accelerating Mixed Signal Design
Assura
BuildGates
Cadence (brand and logo)
CeltIC
Conformal
Connections
Diva
Dracula
ElectronStorm
Encounter
EU CAD
Fire & Ice
First Encounter
HDL-ICE
Incisive
InstallScape
IP Gallery
NanoRoute
NC-Verilog
NeoCell
NeoCircuit
OpenBook online documentation library
OrCAD
Palladium
Pearl
PowerSuite
PSpice
SignalStorm
Silicon Design Chain
Silicon Ensemble
Silicon Express
SKILL
SoC Encounter
SourceLink online customer support
Specman
Spectre
Speed Bridge
UltraSim
Verifault-XL
Verification Advisor
Verilog
Virtuoso
VoltageStorm
Xtreme
Other Trademarks
Open SystemC, Open SystemC Initiative, OSCI, SystemC, and SystemC Initiative are trademarks or registered trademarks of Open SystemC Initiative, Inc. in
the United States and other countries and are used with permission.
All other trademarks are the property of their respective holders.
Confidentiality Notice
No part of this publication may be reproduced in whole or in part by any means (including photocopying or storage in an information storage/retrieval system)
or transmitted in any form or by any means without prior written permission from Cadence Design Systems, Inc. (Cadence).
Information in this document is subject to change without notice and does not represent a commitment on the part of Cadence. The information contained herein
is the proprietary and confidential information of Cadence or its licensors, and is supplied subject to, and may be used only by Cadences customer in accordance
with, a written agreement between Cadence and its customer. Except as may be explicitly set forth in such agreement, Cadence does not make, and expressly
disclaims, any representations or warranties as to the completeness, accuracy or usefulness of the information contained in this document. Cadence does not
warrant that use of such information will not infringe any third party rights, nor does Cadence assume any liability for damages or costs of any kind that may
result from use of such information.
RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) of the
Rights in Technical Data and Computer Software clause at DFARS 252.227-7013.
UNPUBLISHED This document contains unpublished confidential information and is not to be disclosed or used except as authorized by written contract with
Cadence. Rights reserved under the copyright laws of the United States.
Table of Contents
Table of Contents
Verilog Language and Application
Chapter 1
Chapter 2
Verilog Application
Verilog Application ......................................................................................................... 2-3
What is Verilog? .............................................................................................................. 2-5
Benefits of Using an HDL ............................................................................................... 2-7
Issues in using HDLs ....................................................................................................... 2-9
Applications ................................................................................................................... 2-11
Levels of Abstraction..................................................................................................... 2-13
Abstraction Level Trade-offs......................................................................................... 2-15
Schematic-Based Simulation ......................................................................................... 2-19
Verilog-Based Simulation.............................................................................................. 2-21
Chapter 3
March 6, 2008
iii
Chapter 4
Table of Contents
Chapter 5
Verilog Operators
Arithmetic Operators ....................................................................................................... 5-5
Bit-Wise Operators .......................................................................................................... 5-7
Logical Operators ............................................................................................................ 5-9
Unary Reduction Operators ........................................................................................... 5-11
Shift Operators ............................................................................................................... 5-13
Relational Operators ...................................................................................................... 5-15
Logical and Case Equality ............................................................................................. 5-17
Equality Operators ......................................................................................................... 5-19
Conditional Operator ..................................................................................................... 5-21
Concatenation ................................................................................................................ 5-23
Replication ..................................................................................................................... 5-25
Operator Precedence ...................................................................................................... 5-27
Chapter 6
Procedural Statements
The initial and always Keywords.......................................................................... 6-5
Procedural Assignments .................................................................................................. 6-7
iv
March 6, 2008
Table of Contents
Chapter 8
Chapter 9
March 6, 2008
Table of Contents
vi
March 6, 2008
Table of Contents
March 6, 2008
vii
Table of Contents
viii
March 6, 2008
Table of Contents
March 6, 2008
ix
Table of Contents
March 6, 2008
Table of Contents
March 6, 2008
xi
Table of Contents
xii
March 6, 2008
Table of Contents
Appendix D Verilog-2001
IEEE Std. 1364-2001 ...................................................................................................... D-3
Enhanced Unsized Constant Extension .......................................................................... D-5
Attributes ........................................................................................................................ D-7
Variable Declaration Assignment ................................................................................... D-9
Enhanced Signed Arithmetic ........................................................................................ D-11
Enhanced Implicit Declarations.................................................................................... D-13
Multi-Dimensional Arrays ............................................................................................ D-15
Local Parameters........................................................................................................... D-17
Enhanced Specify Parameters....................................................................................... D-19
Power Operator ............................................................................................................. D-21
Indexed Vector Part Selects .......................................................................................... D-23
Array Bit and Part Selects............................................................................................. D-25
Alternative Event OR Operator .................................................................................... D-27
Implicit Event Expression List ..................................................................................... D-29
Re-Enterable Tasks and Recursive Functions .............................................................. D-31
Combined Port/Data Type Declarations ....................................................................... D-33
ANSI-style Port Lists.................................................................................................... D-35
Constant Functions ....................................................................................................... D-37
Verilog Generate........................................................................................................... D-39
Parameter Value Assignment by Name ........................................................................ D-41
Verilog Configurations ................................................................................................. D-43
On-Detect Pulse Error Propagation .............................................................................. D-45
Negative Pulse Detection.............................................................................................. D-47
Enhanced Timing Constraint Checks ........................................................................... D-49
New Timing Constraint Checks.................................................................................... D-51
C-Style File I/O............................................................................................................. D-55
SDF Annotation ............................................................................................................ D-57
Enhanced PLA Modeling.............................................................................................. D-59
Standard Random Number Generator........................................................................... D-61
Invocation Option Tests................................................................................................ D-63
Extended VCD Files ..................................................................................................... D-65
Disable Implicit Net Declarations................................................................................. D-67
Enhanced Conditional Compilation.............................................................................. D-69
New `line Directive .................................................................................................. D-71
Appendix E SystemVerilog-2005
IEEE Std. 1800-2005 .......................................................................................................E-3
March 6, 2008
xiii
Table of Contents
xiv
March 6, 2008
1-1
Notes
1-2
Whats Coming . . .
Objectives
Introduce Verilog language
Understand its uses, strengths and weaknesses
Format
Morning Lectures
Afternoon Lab Exercises
Timing
Coffee . . .
Lunch . . .
1-3
Whats Coming . . .
1-4
1-5
1-6
Workshop Philosophy
1-7
Workshop Philosophy
We will introduce the main concepts several times throughout the course.
Don't worry if you don't understand the first time: the main ones will be covered again later!
1-8
RTL
Language
Basics
Day 2
Further RTL
Language
Language
Application
Day 3
HDL for
Synthesis
in-depth
Day 4
Day 5
Advanced
Language
Advanced
Language
Testbench
Design
Design
Management
Advanced module
Advanced Plus (customized)
1-9
1-10
Conventions
Code
signifies code
omitted for
reasons of space
Caution
These may differ to those used inside your own company
Icons
Error
1-11
Conventions
1-12
Verilog Application
VAP3
2-1
Notes
2-2
Verilog Application
Objectives
2-3
Simulator
Software that reads the HDL and emulates the hardware described by the
HDL
Level of Abstraction
The detail level defined by the modeling style used, such as behavioral and
gate-level
ASIC
ASIC Vendor
A design methodology in which you build the low-level components first and
then connect them to make large systems
A design methodology in which you define the system at a very high level of
abstraction and build down.
Register Transfer Logic (RTL) A level of abstraction applicable to designs that will be synthesized
Tool Command Language (Tcl) A scripting language used for issuing commands to interactive programs
2-4
What is Verilog?
structure
b
c
Behavioral modeling
Serial (sequential)
Tpd
Concurrent (parallel)
Timing
Abstraction levels
behavior
Tsetup
Thold
Tclk-q
Tnet
clk
timing
Verilog Application (VAP3)
2-5
What is Verilog?
Verilog is an HDL, not a conventional software language like C, Pascal, Fortran or Basic.
An HDL contains some high-level programming language constructs, along with constructs to describe
the digital electronic systems.
The Verilog language contains features and constructs to support description of:
Structure both physical, such as hierarchical block diagrams and component netlists, and
software, such as subprograms. This allows you to describe large, complex systems and manage
the complexity.
Behavior both serial and parallel. In serial behavior, you pass the output of one functional block
to the input of another, which is similar to the behavior of a conventional software language.
However in parallel behavior, you can pass a block output to the inputs of a number of blocks
acting in parallel, and the outputs of these blocks may eventually converge back together. Verilog
has to support concurrent behavior, where many, separate events will be happening at the same
moment in time
Time. Typically, programming languages have no concept of time. In hardware, there are
propagation delays, clock periods and timing checks to be modeled.
Different abstraction levels. You can describe a hardware function at several levels of abstraction,
from a high-level algorithmic model to a low level netlist.
2-6
2-7
2-8
2-9
2-10
Applications
The Verilog HDL is used by:
Model developers describing ASIC or FPGA macrocells and higher-level IP
2-11
Applications
2-12
Levels of Abstraction
Behavioral
- algorithmic
Register
Transfer
Level
Verilog
Logic synthesis
Gate level
- structural
- netlist
Layout/
Place & Route
Physical
- silicon
- polygons
2-13
Levels of Abstraction
At each level of abstraction, you can describe a system as a group of hierarchical models in varying
amount of detail.
Within the Verilog language, you can write models with different levels of detail. The three main levels
of abstraction in Verilog are:
Behavioral
Describe the system using mathematical equations
You can omit timing the system may simulate in zero-time like a software program
Structural (Gate-Level)
Instantiate and interconnect already-defined modules
Instantiate and interconnect built-in logic primitives (gates) for greater accuracy, especially in
timing
Output a netlist from a logic synthesis tool
2-14
Behavioral
- algorithmic
Less detailed
Register
Transfer
Level
Gate level
- structural
- netlist
Slower simulation/
entry
Physical
- silicon
- polygons
More detailed
2-15
Designers first model functional blocks at the behavioral level, for ease and maximum simulation
speed
They later refine the functional blocks to the RTL level for a logic synthesis tool
Library developers model most cell components at the structural level. These libraries are used in
synthesis. The Structural Modeling unit of this course provides more information on structural
(gate-level) modeling.
2-16
data
always @(data)
op <= data/2;
/2
4
op
data
// RTL
SR1
4
always @(posedge clk)
op <= data >> 1;
clk
// STRUCTURAL
FD1 op[2:0] (.D(data),.CP(clk),.Q(op));
2-17
2-18
Schematic-Based Simulation
10011100
00110011
01101001
2-19
Schematic-Based Simulation
2-20
Verilog-Based Simulation
Testbench
behavioral
Design
RTL
Compare
Actual
results
Expected
results
2-21
Verilog-Based Simulation
You can use Verilog at all levels of abstraction. It is very common to have a behavioral testbench exercise
a design having behavioral, RTL, and structural components. Verilog also has rudimentary switch
primitives for modeling at the transistor level.
2-22
Review
1. What is Verilog?
2. How is Verilog implementation independent and why is this an advantage?
3. What level of abstraction is used in:
a. Testbenches
b. Synthesisable designs
c. Net lists
2-23
Review
2-24
3-1
Notes
3-2
Aim
Examine fundamental language objects
Introduce the main language concepts
Topics
Verilog objects
Verilog connection model
Hierarchy
Rules and regulations
3-3
3-4
Important
Verilog is case sensitive for identifiers
halfadd
a
sum
+
b
carry
3-5
Every module description starts with the keyword module, has a name (halfadd, dff, alu,
etc.), and ends with the keyword endmodule.
The module name must be unique.
Here is the module for a half adder block. Notice that the module defines a name for the block (halfadd
in this case); the input ports a and b and output ports sum and carry.
The outputs sum and carry are defined in terms of the inputs a and b so we have described the behavior
of our half-adder. The ^ (xor) and & (and) functions used here are not gates but Verilog operators. This
way of describing the behavior uses concurrent Verilog assign constructs (we can reverse the order of
the statements and still get the same behavior!). We will discuss the differences between concurrent and
sequential (procedural) statements in later sections.
3-6
Representing Hierarchy
Create hierarchy by
Instantiating module(s)
fulladd
b
cin
sum
n_sum
a
U1
U2
halfadd
halfadd
n_carry2
U3
n_carry1
carry
or
3-7
Representing Hierarchy
You can create a larger system or hierarchy by listing instances of other modules and connecting those
instances by their ports.
Now we have fully-described our half-adder, we can use it to build a full-adder. We need to create two
instances of the half-adder block for the full-adder.
First we need a module for the full-adder, defining the name, inputs and outputs. Then we need to
instantiate two half-adder blocks and an OR gate and connect them up to make the full-adder.
Instantiating a module is not the same as calling a routine. Each instance is a complete, independent, and
concurrently active copy of the module.
We also need some internal nets to connect up the half-adders; we create these using the wire
declaration.
Note that each module has its own instance name (U1, U2, and U3). The instance name gives a unique
identity to every object, and is used in navigating the design hierarchy.
The module instantiation syntax is:module_identifier [ parameter_value_assignment ] module_instance
{ , module_instance } ;
The module instance syntax is:
name_of_instance ( [ list_of_port_connections ] )
Verilog supplies some pre-defined modules for basic logical functions, called primitives. Here we use an
or gate primitive in the structural model of the full adder. Alternatively we could use an assign
statement to describe the OR gate behavior
assign out = nsela | selb;
Verilog Application Workshop
3-8
instantiation
a
n_sum
n_carry1
module
U2
sum
carry
halfadd
wire n_carry1 of
module fulladd
mapped to output
carry of module
halfadd
Tip
Use named port connection
for linking hierarchy
Verilog Language Introduction (VLE7)
3-9
3-10
instantiation
module
n_sum
n_carry1
U2
sum
carry
halfadd
Caution
Less readable and more error-prone
than named port connection
Verilog Language Introduction (VLE7)
3-11
3-12
Procedural Blocks
1
op
sel
Synthesis
initial blocks are not synthesizable
initial
begin
a = 1;
b = 0;
end
3-13
Procedural Blocks
When we defined the behavior of our half-adder we used concurrent Verilog assign statements.
We could have described the behavior using a Verilog procedure such as the example on the slide. Inside
a procedure we can use Verilog procedural statements which work like conventional software. Inside a
procedure the statements are executed line-by-line so the order of statements is important. Verilog has a
variety of procedural statements many of which are very similar to statements in conventional software
languages such as the if statement in the example. Procedural statements give Verilog a lot of power
when describing complex behavior as we will see later.
A Verilog procedure can only be used inside an module. A single module can have many procedure
which execute concurrently and communicate simultaneously with each other using variables.
initial and always procedures are used in different ways:
The initial block is an unsynthesizable proactive testbench construct that executes exactly
once
The always block is a synthesizable reactive hardware construct that loops forever
3-14
Event List
event list constructed using or operator
3-15
Event List
Note: The or event list operator has nothing to do with the bitwise OR operator | or the logical OR
operator ||.
The language allows any events or variables to be placed in the @(events list) control of a procedural
block.
The gives rise to the concept of the complete event list, where all of the variables whose values are
read in the procedure are included in it.
A change in value of any input to a block of combinational logic can change the outputs. Therefore we
need to force the execution of a procedure modeling combination logic when any of the inputs change,
to re-evaluate the output. Note that a change in strength of the variable can also trigger a procedure.
Hence to model and simulate combinational logic we need a complete event list.
3-16
Procedure
Communicate
concurrently through
events and variables
Procedure
Procedure
Procedure
3-17
3-18
Compilation Libraries
Some Verilog tools use compilation
libraries: A collection of compiled modules or
primitives
my_design.v
WORK
PRIMS
primitives
MYWORK
module
module
module
module
primitives
primitives
PROJ
module
module
Important
Not all Verilog simulators use compilation
libraries
3-19
Compilation Libraries
To simulate a Verilog model, we must first convert our source files into a binary form that can be
recognized by the simulator. The process of checking the syntax and producing the binary file is known
as compilation.
Some Verilog tools use libraries in the compilation and simulation of models. This is a feature
particularly of tools which allow the compilation and simulation of VHDL and Verilog models together
co-execution tools. The following is only applicable to tools which use libraries:When you compile a design in Verilog, you can compile it into a data structure known as a library.
A library is normally a directory on the computer's disc where the compiled, binary design units are
placed.
There is also a mechanism to allow different libraries to be selected as the current working library.
When Verilog source files are compiled, the resulting binary files are stored in the current working
library.
3-20
Design Configurations
Verilog-2001 provides a standard means to specify a design configuration
You can specify a compiler mapping of source files into libraries
library rtlLib rtlSrc/*.v;
You can declare named configuration blocks, each of which can specify:
The module to which it applies
An ordered list of libraries from which to bind instance descriptions by default
Specific library lists or named configurations for specific types or instances
config bot;
design rtlLib.bot;
default liblist rtlLib gateLib;
cell ALU liblist gateLib;
endconfig
config top;
design behLib.top;
default liblist behLib rtlLib;
instance top.bot1 use rtlLib.bot:config;
endconfig
Verilog Language Introduction (VLE7)
3-21
Design Configurations
Configuration names may be the same as cell names and do not need to be related, though you are
strongly advised to make them related if you use the same name. If a cell and configuration have the same
name, then to differentiate between the two, you add the :config qualifier when referring to the
configuration name.
Here is the formal syntax of a configuration block:
config_declaration ::=
config config_identifier ;
design_statement
{config_rule_statement}
endconfig
design_statement ::=
design { [library_identifier.]cell_identifier } ;
config_rule_statement ::=
default liblist [{library_identifier}]
| instance inst_name liblist [{library_identifier}]
| instance inst_name use [library_identifier.]cell_identifier[:config]
| cell [ library_identifier.]cell_identifier liblist [{library_identifier}]
| cell [ library_identifier.]cell_identifier use
[library_identifier.]cell_identifier[:config]
3-22
Design Compilation
tb_one
testbench
Contains compiler
directives
design
Provides additional
information for the
compiler/simulator
structural
cpu
pnet_read
behavioral
RTL/structural
read_frame
netlist
pnet_write
Hierarchical connections
are automatically made
behavioral
write_frame
primitives
3-23
Design Compilation
Now let's look at an example which puts together all of the building blocks we have discussed so far.
The diagram on the slide shows a complete hierarchical design structure. The top-level of the hierarchy
is the module tb_one, a behavioral level testbench. This instantiates a structural module design,
which contains the top level partitioning of the design. Three modules are instantiated within module
design; cpu and pnet_write, which are behavioral models, and pnet_read which is a structural
module instantiating the modules read_frame and write_data. write_data is hand-crafted
gate level model of Verilog primitives, and read_frame contains a synthesized netlist.
There are a number of dependencies in the hierarchical design structure we discussed on the previous
slide.
Verilog does not require the modules of a hierarchical design to be compiled in any particular order.
However, the order of the Verilog code compiled may be important if compiler directives are being used.
You will see compiler directives later in the course.
Compile the testbench module first if it contains compiler or simulator directives which may affect the
compilation of all the modules in the design. The compiler must be aware of these directives before
compiling any other information, hence the testbench is generally compiled first.
The compiler will automatically link together the design hierarchy as the individual modules are
compiled.
3-24
a free-format language
spaces can be used to enhance readability
= a ^ b;
= a & b;
3-25
Comments
Verilog is a free-format language.
You can use white space to enhance the readability and the organization of code. The Verilog language
ignores these characters, except when they serve to separate other language tokens.
Verilog comments are created using //. Anything on a line to the right of the double-slash is taken as
a comment. If the line begins with // then the whole line is a comment. Verilog also provides multi-line
comments. If you want to use comment headers at the beginning of Verilog files to define version control
information, change histories and descriptions of the block then the comment header must start with /*
and end with */. Note that block comments cannot be nested.
Indentation and line breaks can help make your code more readable, particularly for large nested if
structures, and aid debugging - by having one executable statement per line, source code debug is easier.
Use comments only where necessary to communicate your intentions to later readers.
This comment for example is totally unnecessary:
// multiply a and b and set the answer to c
always @ (a or b)
c = a * b;
Why? Because it is already obvious from the code that a and b are being multiplied!
3-26
unit_32
structural
bus_16_bits
a$b
unit@32
unit-32
16_bit_bus
3-27
\unit-32
Escaped identifiers are primarily designed for Verilog compatibility with tools and technology libraries.
For example, many technology libraries have historical names for cells where the first character specifies
the number of inputs, e.g. 2nand 4or 2and2or. Using escaped identifiers would allow Verilog to use
instantiate modules with such names.
Escaped identifiers should not be used unless there are no other options.
3-28
Review
1. What is the basic building block of a Verilog design?
2. How do Verilog procedures communicate?
3. What Verilog file do you compile first?
4. Write the code to instantiate the following module:ALU1
data
ac_out
opcode
clock
reset
ALU
a_in
y_out
b_in
op_in
z_out
clk
rst
alu__out
zero
3-29
Review
3-30
4-1
Notes
4-2
Aims
To introduce the Verilog logic value system and to understand the different data
types and the rules covering their use.
Topics
Logic value system
Data type classes
Vectors and literal values
Net data types and their use
Register data types and their use
Choosing the correct data type
Parameters
Memory arrays
4-3
4-4
buf
buf
bufif1
Important
The unknown logic value x is not the same as dont care.
Verilog Logic System and Data Types (VDL5)
4-5
4-6
Data Types
4-7
Data Types
4-8
Concept of a Type
1
op
b
sel
reg op;
type reg
module mux
(
input
input
output reg
);
variable name(s)
a, b,
sel,
op
endmodule
4-9
Concept of a Type
If you use the list of ports syntax, you separately declare the port direction and again (if needed)
separately declare the port type.
module mux (a, b, sel, op);
input a, b;
input sel;
output op;
reg
op;
If you use the list of port declarations syntax, you declare the port direction and type together.
module mux (
input
a, b,
input
sel,
output reg op
);
4-10
Vectors
Tip
a
4
b
sel
endmodule
1
op
0
4-11
Vectors
Format is [msb:lsb] <name>
Variable vector type declaration:
You can declare more than one net in the same declaration by using a list of names separated by commas.
4-12
obus = ibus;
outp[3]
inp[3]
obus[3]
ibus[0]
outp[2]
inp[2]
obus[2]
ibus[1]
outp[1]
inp[1]
obus[1]
ibus[2]
outp[0]
inp[0]
obus[0]
ibus[3]
inp[3]
outp[2]
inp[2]
outp[1]
inp[1]
outp[0]
inp[0]
4-13
4-14
You can use slices and concatenation operator {} to match vector widths
reg [3:0] zbus;
// 4 bit vector
reg [5:0] widebus; // 6 bit vector
zbus = widebus;
zbus[3]
zbus[2]
zbus[1]
zbus[0]
widebus = zbus;
widebus[5]
widebus[4]
widebus[3]
widebus[2]
widebus[1]
widebus[0]
slice
zbus = widebus[3:0];
widebus[5]
widebus[4]
widebus[3]
widebus[2]
widebus[1]
widebus[0]
0
0
zbus[3]
zbus[2]
zbus[1]
zbus[0]
concatenation
widebus = {2'b00, zbus};
4-15
Where the source is bigger then the target, take a slice of the source to specify which bits of the source
to use:zbus = widebus[3:0];
zbus = widebus[5:2];
4-16
4-17
4-18
Literal Values
...
reg [3:0] zbus;
...
zbus = 4b1001;
zbus = 4o05;
zbus = 4d14;
zbus = 4h2f;
...
//
//
//
//
1001
0101
1110
1111
Important
To avoid truncation or padding, size
literal to match target
8b1100_0001
8-bit binary
64hff01
64-bit hexadecimal
9o17
9-bit octal
12
h83a
32bz
4-19
Literal Values
Good coding style uses lower case for base to distinguish octal o from logic 0
Details
Unsized
Sized
<size><base><value>
where base and value are case insensitive.
It is good practice to size a literal to match the value of the literal, and the variable to which it is
assigned.
Remember over-long values are truncated, and over-short values padded with 0 in the msb
e.g the following are legal Verilog, but not good design practice
A Verilog compiler may report warnings for some or all of the below...
...
reg [2:0] zbus;
...
zbus = 4'b1001;
zbus = 3'ha;
zbus = 3'b10;
zbus = 2'b1;
//
//
//
//
001
010
010
001
literal
literal
literal
literal
4-20
Question
What is the value in a after these
assignments?
reg [7:0] a;
reg [11:0] b;
initial
begin
// 0 padding
a = 8h11;
a = 8b11;
a = 8d11;
a = 8h01;
a = 8h10;
a = 0;
// z padding
b = 12hzzz;
b = 12hz;
b = 12h0z;
b = 12hz0;
end
//
//
//
//
//
//
contents of a
00010001
00000001
00010000
00000000
z padding
contents of b
// zzzzzzzzzzzz
// zzzzzzzzzzzz
// 00000000zzzz
// zzzzzzzz0000
0 padding
4-21
4-22
Net Types
Various net types are available (wire is the most commonly used)
Undeclared identifiers you use in instance port connections default to wire type
Verilog-2001 adds undeclared identifiers when target of continuous assignment
Change default with `default_nettype <nettype> compiler directive
sel;
[31:0] w1, w2;
c;
[15:0] busa;
//
//
//
//
Scalar wire
Two 32-bit wires with msb = bit 31
Scalar wired-AND net
A 16-bit tri-state bus, msb = bit 15
module halfadd (
input a, b,
// default to wire
output sum, carry // default to wire
);
// change with assign
assign sum = a ^ b;
assign carry = a & b;
endmodule
Verilog Logic System and Data Types (VDL5)
4-23
Net Types
Nets are continuously driven by the devices that drive them Verilog automatically propagates a
new value onto a net when the drivers on the net change value.
input and inout ports can only use net types
output ports can use net or integral register types
Net types are changed with assign statements in what are called continuous statements. They
can also be changed by a module, primitive or gate which is driving them.
Various net types are available for modeling design-specific and technology-specific
functionality. The most common net type is wire.
Net Types
Functionality
wire, tri
supply1, supply0
wor, trior
wand, triand
trireg
tri1, tri0
Synthesis
The IEEE Std. 1364.1 supports synthesis of all net types except tri0, tri1, and trireg.
In some contexts, undeclared nets default to the wire type. You can override this using the
`default_nettype <nettype> compiler directive. With this directive, undeclared nets
default to the nettype in the compiler directive. For this directive, Verilog-2001 adds the none net
type, i.e. do not allow implicit net declarations.
Verilog Application Workshop
4-24
Note: ~ is an inversion
operator
nsela
sel
out
nsel
selb
Nets
module mux (
input sel, b, a,
output out
);
wire nsela, selb, nsel;
assign nsel = ~sel;
assign selb = sel & b;
assign nsela = nsel & a;
assign out
= nsela | selb;
endmodule
module mux (
input sel, b, a,
output out
);
wire nsel = ~sel;
wire selb = sel & b;
wire nsela = nsel & a;
assign out
= nsela | selb;
endmodule
4-25
4-26
b
y declared as
y declared as
y declared as
ab
0
1
x
z
0
x
x
0
x
1
x
1
x
x
x
x
0
1
x
z
0
1
x
z
0
0
0
0
0
1
x
1
0
x
x
x
0
1
x
z
wor y;
trior y;
wand y;
triand y;
wire y;
tri y;
assign y = a;
assign y = b;
0
1
x
z
0
1
x
0
1
1
1
1
x
x
1
x
x
z
0
1
x
z
4-27
Net types have a truth table (net resolution function) to determine final value of target
Net types tri and wire are identical in functionality. You can use the different names to
enhance readability. For example, you can use tri for the nets that have multiple drivers.
Another reason to declare a net as a tri is to indicate that this net can be driven to a
high-impedance (z) state.
Synthesis tools that support wor and wand, will create extra logic to implement the wired-AND
or wired-OR connections.
4-28
Register Types
Register types store value until you
procedurally assign a new value.
Verilog has these register types:
reg unsigned user-defined width 4-state
Verilog-2001 adds reg signed
module mux (
input
a, b, sel,
output reg op
);
always @(a or b or sel)
if (sel == 1)
op = a;
else
op = b;
endmodule
Synthesis
Synthesis tools accept integer and reg but do not
necessarily infer a storage device
reg [3:0] vect;
reg [2:0] p, q;
integer aint;
reg s;
time delay;
//
//
//
//
//
4-29
Register Types
A register variable holds its value until a new value is assigned to it.
reg is the most common register type. You can declare it to be scalar or vector.
integer is used for signed (2s complement) arithmetic. It is always 32 bits.
real has the same usage as integer, except that you use it for real numbers.
time stores and manipulates simulation time, delays etc.
Reals
4-30
Register Assignment
Error
Error
Register type
assigned outside
procedure
module mux (
input a, b, sel,
output mux
);
wire aandb, nmux;
reg mux, nota;
always @(a or b or sel)
if (sel == 1)
begin
mux = a;
nmux = b;
end
else
begin
mux = a;
nmux = b;
end
assign nota = ~a;
assign aandb = a & b;
...
4-31
Register Assignment
If we assign a value to a variable from within a procedure, then the variable must be a register type.
Likewise a register variable type can only be updated from within a procedure.
Net types can be assigned to register types in procedural assignment
Register types can be assigned to net types in assign statements
4-32
Integer Assignment
...
// Verilog-2001 declaration assignment
integer int = 129; // 11..1000001
reg [3:0] data;
initial
begin
data =
int =
int =
data =
int =
end
...
int;
data;
-3;
int;
data;
Under-sized data is
padded with 0
//
//
//
//
//
data = 0001
int = 1
11..1111101
data = 1101
int = 13
signed integer
assigned to
unsigned reg...
...value assigned
back to integer
as positive number
Caution
When assigning integer to reg
(by default unsigned) sign is lost
4-33
Integer Assignment
Remember:
reg and integer types can be freely assigned to each other using procedural assignment
statements
When a negative integer value is assigned to a reg variable, the reg variable will contain the
2s complement value of the negative value: but because reg types are unsigned, this value will
be treated as positive. So if the value is then assigned back to the integer variable, the
integer variable will contain a positive value.
Verilog-2001 adds the reg signed declaration to preserved sign information
Verilog-2001 adds the $signed and $unsigned system tasks to convert between signed
and unsigned types
4-34
Input Port
net/register
atop
net
a
b
Output Port
net/register
net
btop
module top;
wire ytop;
reg atop, btop;
net
ytop
Inout Port
net
initial
begin
atop = 1b0;
btop = 1b0;
end
module dut (
input a, b,
output y
);
assign y = a & b;
endmodule
4-35
An input port can be driven by a net or a register, but it can only drive a net.
An output port can be driven by a net or a register, but it can only drive a net.
An inout port can only be driven by a net, and it can only drive a net.
Here are some common user errors, along with their typical error messages:
You make a procedural assignment to a signal that you either declared as a net or you forgot to
declare.
illegal assignment
You connect an output from an instance to a signal declared as a register. This is illegal as a
module output can only drive a net.
illegal output port specification
You declare a signal as a module input and as a register. This is illegal as inputs can only be nets
incompatible declarations
4-36
Module Parameters
// Verilog-1995 syntax
module mux (a, b, sel, out);
parameter WIDTH = 2;
input [WIDTH-1:0] a, b;
input
sel;
output [WIDTH-1:0] out;
reg
[WIDTH-1:0] out;
...
endmodule
// Verilog-2001 alternative
module mux
#(
parameter integer WIDTH = 2
)
(
input wire [WIDTH-1:0] a, b
input wire
sel,
output reg [WIDTH-1:0] out
);
...
endmodule
4-37
Module Parameters
You can use a module parameter anywhere that you can use a literal
Typically, you use module parameters to define delays and widths of variables
You cannot modify module parameters during runtime they are not variables
Verilog-2001 allows you to specify a type and to sign and size vector parameters:
parameter_declaration ::=
parameter [ signed ] [ range ] list_of_param_assignments ;
| parameter integer list_of_param_assignments ;
| parameter real list_of_param_assignments ;
| parameter realtime list_of_param_assignments ;
| parameter time list_of_param_assignments ;
4-38
Synthesis
The synthesis standard disallows the defparam construct.
4-39
Use the #() construct to override the values of parameters for a particular instance of a module
in the module instantiation statement
Update module parameter values in the order you declared the parameters in the module
For Verilog-1995 to update a parameter value, you must also update positionally earlier values
For example, if module mod declared three parameters, a, b, and c:
mod U1 #(a,b) (...);
// valid - parameter c unchanged
mod U2 #(a) (...);
// valid - parameters b & c unchanged
mod U3 #(a, ,c) (...); // invalid - cannot omit b
mod U4 #(, b,c) (...); // invalid - cannot omit a
Note: You also use the # character to specify primitive delays. As modules cannot have associated
primitive delays, for modules, this character always means a module parameter override.
Caution
The defparam construct also overrides parameter values. The statement must include the relative
hierarchical name of the parameter from the defparam statement location. Use of defparam is
superfluous when done locally and can potentially cause much confusion when not done locally.
4-40
Local Parameters
Verilog-2001 adds the localparam construct.
A constant you cannot override not a module parameter
=
=
=
=
0,
1,
2,
3;
4-41
Local Parameters
4-42
Arrays
Verilog-1995 supports one-dimensional arrays of integer, reg, and time
integer int_a [0:99]; // array of 100 integer
reg [7:0] reg_a [0:99]; // array of 100 8-bit vectors
You cannot directly take bit or part selects of a word (use an intermediate variable)
reg [7:0] word, array [0:255]; // memory word and array
reg bit;
...
word = array[5]; // access address 5
word = array[10]; // access address 10
bit = word[7];
// access bit 7 of extracted word
You can directly take bit and part selects of an indexed element
reg [7:0] array [0:255]; // memory array
bit = array[10][7];
Verilog Logic System and Data Types (VDL5)
4-43
Arrays
You can declare word size and array depth with any legal expression.
You can use module parameters to specify the memory size:
parameter WORDSIZE = 16;
parameter MEMSIZE = 1024
reg [WORDSIZE-1:0] mem3 [MEMSIZE-1:0];
An array element is accessed using any valid expression as an index to the array.
array_name [addr_expr]
4-44
Summary
4-45
Summary
4-46
Review
1. What is the primary difference between a net and a register?
2. The bitwise AND operator is &. Code the following hardware using (i) a reg type
(ii) a wire type
a
c
4-47
Review
4-48
Verilog Operators
VVO4
5-1
Notes
5-2
Aims
Introduce the operators available in the Verilog language
Topics
Operator Type
Symbol
arithmetic
+ - * / %
~ & | ^ ~^
! && ||
& | ^ ~& ~| ~^
<< >>
< > <= >=
== != === !==
?:
{}
{{}}
bit-wise
logical
reduction
shift
relational
equality
conditional
concatenation
replication
5-3
Operator Types
Verilog has arithmetic, bit-wise, logical, reduction, shift, relational, equality, conditional,
equality, concatenation and replication operators. An explanation of each with an example is
shown in this chapter.
5-4
Arithmetic Operators
+
add
subtract
multiply
divide
% modulus
integer is signed
reg is unsigned
Verilog-2001 you can
also declare a reg signed
Verilog-2001 you can
convert between signed and
unsigned using $signed
and $unsigned
module arithops;
//Verilog-2001 local constants
localparam integer CONST_INT = -3,
CONST_5
= 5;
localparam [3:0] rega = 3,
regb = 4b1010,
regc = 14;
integer val;
reg [3:0] num;
initial
begin
val
val
val
num
num
num
num
end
=
=
=
=
=
=
=
CONST_5 * CONST_INT;
(CONST_INT + 5)/2;
CONST_5/CONST_INT;
rega + regb;
rega + 1;
CONST_INT;
regc % rega;
//
//
//
//
//
//
//
-15
1
-1
1101
0100
1101
2
endmodule
5-5
Arithmetic Operators
An arithmetic operation on an integer type behaves differently than an operation on a reg type. In
Verilog, a reg data type can only contain an unsigned value while an integer type contains a signed
value.
Integers are always truncated to a whole number. Hence in the example ans = FIVE/int; 5 divided
by -3 yields -1.
The example num = int; shows the integer -3 assigned to a 4 bit reg. -3 in 2's compliment is
32b1111111....11101. This is truncated to our 4 bit reg yielding 4b1101 . Since reg variables
are unsigned, this is interpreted as +13!
Caution
Binary arithmetic on unsigned quantities, such as reg variables, is unsigned (negative results are
converted to the twos complement).
5-6
Bit-Wise Operators
~ not
& and
| or
^ xor
~^ xnor
^~ xnor
Bit-wise operators
operate on vectors.
Operations are
performed bit by bit
on individual bits.
num = ~rega;
num = rega &
num = rega &
num = rega |
num = regb &
num = regb |
end
endmodule
0;
regb;
regb;
regc;
regc;
//
//
//
//
//
//
num
num
num
num
num
num
=
=
=
=
=
=
0110
0000
1000
1011
10x0
1110
Note: Unknown bits in an operand do not necessarily lead to unknown bits in the result.
5-7
Bit-Wise Operators
Bit-wise binary operators perform bit-wise manipulations on two operands. They compare each bit in
one operand with its corresponding bit in the other operand to calculate each bit for the result. Normally
used for vectors but works equally on scalar (single bit) values.
regb = 4b1010
regc = 4b1x10
num = regb & regc = 1010;
The operators can be used with operands of different sizes - the smaller operand is zero-extended to the
size of the larger operand and the result is the width of the larger operand (result could be truncated if
assigned to a variable of smaller width)
For example:
reg
reg
reg
...
a =
b =
c =
[3:0] a;
[7:0] b;
[5:0] c;
4b1011;
8b01010011;
a | b;
5-8
Logical Operators
!
not
module logical;
// Verilog-2001 local constants
localparam integer FIVE = 5;
localparam [3:0] CONST_A = 4b0011,
CONST_B = 4b10xz,
CONST_C = 4b0z0x;
reg ans;
&& and
|| or
Logical operators interpret their
operands as either true (1b1) or false
(1b0) or unknown (1bx)
1 if any bit 1
0 if all bits 0
x if any bit z or x and no bit 1
initial
begin
ans
ans
ans
ans
ans
ans
end
=
=
=
=
=
=
!CONST_A;
CONST_A &&
CONST_A ||
CONST_A &&
CONST_A &&
CONST_C ||
0;
0;
FIVE;
CONST_B;
0;
//
//
//
//
//
//
0
0
1
1
1
X
endmodule
5-9
Logical Operators
Logical operators reduce both operands to a single bit, and then performs a single bit operation.
Rules for reduction are:
If the operand contains no ones, but does contain one or more x or z values, its logical value is
ambiguous, and it reduces to x
The logical negation operator reduces an operand to its logical inverse. For example, if an operand
contains all zeroes, it is false (logic 0), so its inverse is true (logic 1).
5-10
and
or
xor
module reduction;
// Verilog-2001 local constants
localparam [3:0] CONST_A = 4b0100,
CONST_B = 4b1111;
reg val;
~& nand
~| nor
~^ xnor
^~ xnor
Reduction operators
perform a bit-wise
operation on all the bits of
a single operand.
initial
begin
val
val
val
val
val
val
val
val
val
end
=
=
=
=
=
=
=
=
=
&CONST_A ;
|CONST_A ;
&CONST_B ;
|CONST_B ;
^CONST_A ;
^CONST_B ;
~|CONST_A;
~&CONST_A;
^CONST_A && &CONST_B;
//
//
//
//
//
//
//
//
//
0
1
1
1
1
0
0
1
1
endmodule
5-11
5-12
Shift Operators
<< logical shift left
>> logical shift right
initial
begin
regb = rega << 1; // 00110010
regb = rega >> 1; // 01001100
regb = rega << -1; // 00000000
end
endmodule
-1 is 2**32-1
5-13
Shift Operators
<< shifts the left operand left by the number of positions specified by the right operand.
>> shifts the left operand right by the number of positions specified by the right operand.
In an assignment, if the result of the RHS is of:
Greater bit-width than the LHS, its most significant bits are truncated
5-14
Relational Operators
>
greater than
<
less than
module relationals;
reg [3:0] rega, regb, regc;
reg val;
initial
begin
rega = 4b0011;
regb = 4b1010;
regc = 4b0x10;
val
val
val
val
end
=
=
=
=
regc
regb
regb
regb
> rega ;
< rega ;
>= rega;
> regc ;
//
//
//
//
val
val
val
val
=
=
=
=
x
0
1
x
endmodule
5-15
Relational Operators
If differently sized vectors are compared, the shorter is padded out with leading 0s to match the length
of the larger operand.
5-16
...
a = 2b1x;
b = 2b1x;
if (a == b)
// values match & do not contain z or x
else
// values do not match or contain z or x
// above values execute this else branch
...
a = 2b1x;
b = 2b1x;
if (a === b)
// values match exactly
// above values execute this if branch
else
// values do not match
5-17
5-18
Equality Operators
== logical equality
!= logical inequality
=== case equality
!== case inequality
module equalities();
reg [3:0] rega, regb, regc;
reg val;
initial
begin
rega = 4b0011;
regb = 4b1010;
regc = 4b1x10;
val = rega
val = rega
val = regb
val = regc
val = rega
val = rega
val = regb
val = regc
end
endmodule
== regb;
!= regb;
!= regc;
== regc;
=== regb;
!== regc;
=== regc;
=== regc;
//
//
//
//
//
//
//
//
val
val
val
val
val
val
val
val
=
=
=
=
=
=
=
=
0
1
x
x
0
1
0
1
5-19
Equality Operators
An expression with the equality operator evaluates to:
1 (true) if the LHS and RHS have equal, known values. Known values do not contain x or z
0 (false) if the LHS and RHS have known values and are not equal.
x (unknown) if either the LHS or RHS have unknown values. Unknown values contain x or z.
!= is the inequality operator. It is the inverse of the == operator and works the same way.
The case equality operators are also called the identity operators because they test to see if the operands
are identical.
An expression with the identity operator evaluates to:
1 (true) if the LHS and RHS have identical values, including x and z
!== is the inverse of the === operator and works the same way.
5-20
Conditional Operator
module tribuf (
input
in, enable,
output reg out
);
?: conditional
in
out
endmodule
enable
...
wire out3;
reg out1, out2;
always @ (a or b or sel)
out1 = sel ? a : b;
out
b
sel
Note: Sometimes the if else
construct may be more
readable
always @ (a or b or sel)
if (sel)
out2 = a;
else
out2 = b;
assign out3 = sel ? a : b;
...
Verilog Operators (VVO4)
5-21
Conditional Operator
The syntax for the conditional operator is:
<LHS> = <condition> ? <true_expression> : <false_expression>
5-22
Concatenation
{} concatenation
Important
Literals used in concatenation
must be sized
module concatenation;
reg [7:0] rega, regb, regc, regd, new;
reg [3:0] nib1, nib2;
initial
begin
rega =
regb =
regc =
regd =
8b00000011;
8b00000100;
8b00011000;
8b11100000;
5-23
Concatenation
You can use concatenation on an unlimited number of operands. The operator symbol is {} with
operands separated by commas. For example: {A, B, C, D, E}
You must use sized quantities in concatenation. If you do not, an error message will be displayed.
Here are some examples that fail to size their operators:
a[7:0] = {5b01010, 2}; //decimal value 2 unsized
c[3:0] = {3b011, b0}; //binary value b0 unsized
5-24
Replication
{{}} replication
Syntax is:-
{<repetitions> {<variable>}}
Important
Literals used in replication must be sized
4x rega concatenated
with 2x regc[1:0]
regc concatenated
with 2x regb
regc concatenated with 2x
1b1 and replicated 2 times
bus = {8{rega}};
// bus = 11111111
bus = { {4{rega}}, {2{regc[1:0]}} };
// bus = 1111_01_01
bus = { regc, {2{regb}} };
// bus = 1001_11_11
bus = { 2{regc[2:1], {2{1b1}}} };
// bus = 00_1_1_00_1_1
end
endmodule
5-25
Replication
The operator symbol is {{}}
Syntax is:- {<no repetitions> {<variable>}}
In the second and third examples above, replication is used with concatenation to make a new 8 bit
register.
You can also use replication on an unlimited number of operands.
For example: {{4{A}}, {6{B}}, C}
You must use sized quantities in concatenation and replication. If you do not, an error message will be
displayed.
Here are some examples that fail to size their operators:
a[7:0] = {4{b10}};
//binary value b10 unsized
b[7:0] = {2{5}};
//decimal value 5 unsized
5-26
Operator Precedence
Reliance on operator precedence may make your code unreadable use parentheses!
Type of Operators
Symbols
Concatenation / Replication
Inversion (Logical / Bitwise / Arithmetic)
Exponential
Arithmetic
Shift
Relational
Equality
Bit-wise / Reduction
Logical
Conditional
{ }
!
**
*
+
<<
<
==
&
^
|
&&
||
? :
{{ }}
~
/
>>
<=
!=
~&
^~
~|
Highest
%
(binary)
<<< >>>
>
>=
=== !==
Precedence
~^
Lowest
Verilog Operators (VVO4)
5-27
Operator Precedence
Without looking at the above table, what is the precedence of the subexpressions?
a ? ~ b * c << d : e < f ^ g || h
Wouldnt it really help if the author used parentheses?
a ? ((~b * c) << d) : (((e < f) ^ g) || h)
5-28
Review
1. How many bits is the result of a logical && operation?
2. What is the difference between && and &, if any?
3. What must you do to values you replicate with the replication operator?
4. Given
regx = 4b0101;
what is the value of:bus = { 2{regx[3:1], {3{1b0, regx[0]}}} };
5. If regb is defined as a four bit signed number as shown below, give the code for
an arithmetic binary division by two. Hint: the sign bit (or most significant bit) must
remain intact.
reg [3:0] regb;
5-29
Review
5-30
Procedural Statements
V1E3
6-1
Notes
6-2
Aim
To introduce some of the most commonly used procedural statements
Topics
Procedures
Procedural statements
if then else
case
loops
6-3
6-4
Synthesis
The synthesis standard does not support the initial
construct
...
reg a, b, zor, zand;
initial
begin
a
= 1b1;
b
= 1b0;
end
Verilog-2001
wildcarded
always @*
event list
begin
if (a | b)
zor = 1b1;
else
zor = 1b0;
if (a & b)
zand = 1b1;
else
zand = 1b0;
end
...
Procedural Statements (V1E3)
6-5
always blocks act like a continuous loop, but initial blocks operate once and stop.
always
initial
s
s
s
s
s
s
s
s
s
s
s
s
s
s
6-6
Procedural Assignments
module fulladder (
input
a, b, cin,
output reg [1:0] out
);
reg sum, carry;
always @(a,
begin
sum
=
carry =
out
=
end
b, cin)
a ^ b ^ cin;
(a & b) | cin & (a ^ b);
{carry, sum};
endmodule
6-7
Procedural Assignments
Assignments made inside procedural blocks are called procedural assignments.
Right-hand side of a procedural assignment can be any valid expression - there is no restriction on
the data types used in the expression.
Left-hand side of procedural assignment must be a suitable register type, e.g. reg
6-8
Event Control
Synthesis
For the generation of combinational logic, ensure
that all signals read by the block are in the event list.
6-9
Event Control
Note: The or event control modifier has nothing to do with the bitwise OR operator | or the logical OR
operator ||.
The language allows any variables to be placed in the @(events list) control of a procedural block.
This gives rise to the concept of the complete event list, where all of the variables whose values are
read in the procedure are included in it.
A change in value of any input signal to a block of combinational logic can result in a change at the
outputs. Therefore, whenever any of the inputs to a procedural block which models combinational logic
change, we need to force the re-execution of the block to re-evaluate the output.
Hence to model and synthesize combinational logic we need a complete event list.
Synchronous or registered logic outputs will only be updated on the rising or falling edge of a clock
(assuming the logic is not asynchronously reset). Therefore we only need to force the execution of a
sequential logic procedure on the edge of a clock.
So to model and synthesize sequential logic, we use either (posedge clk) or (negedge clk).
More on this later.
Synthesis requires the triggers in an event list to be either all edge-qualified or none edge-qualified.
6-10
= !sel;
= sel & b;
Procedure
= nsel & a;
Procedure
// continuous statements
Procedure
...
endmodule
6-11
6-12
if Statement
if is a conditional
statement
Condition is boolean
expression
Each if condition is
tested in sequence
module if_example (
input
[3:0] a, b, c, d,
output reg [3:0] y
);
always @(a or b or c or d)
if (d == 4b0000)
y = a;
else if (d <= 4'b0101)
y = b;
else
y = c;
endmodule
?Question
What would be the effect of
swapping the if and else if
conditions?
Inferred hardware
structure
c
Synthesis
if synthesizes to mux structures
0101
b
a
0000
<=
=
0
1
mux
mux
Procedural Statements (V1E3)
6-13
if Statement
So having looked at the theory behind continuous and procedural statements, we will spend the rest of
this section looking at three different examples of procedural statements: if, case and for loops
if statements are conditional and allow procedural statements to be executed dependant on the result
of testing a conditional statement.
In the example above, when a, b, c or d change value, the always procedure is executed.
If d is equal to zero (logical equality) then the procedural statements associated with the condition are
executed, and y is assigned the value of a.
If d is not equal to 0, then the else branch is taken. This branch contains another if statement testing
whether d is less than or equal to 0101. If this condition is true, then b is assigned to y. If this condition
is false, then the else branch is executed - this does not contain any further conditions, so c is assigned
to d.
Notice that the conditions d == 0 and d <= 4'b0101 overlap, but because d == 0 is tested
first, then y is assigned a when d = 0000. It is only if d does not equal 0 that the second condition is
tested.
Therefore the conditions of an if-else-if statement are tested in order - the first condition having
the highest priority, the second condition having the next highest priority, etc.
6-14
if Statement Syntax
if (CONDITION) begin
// procedural statements
end
if (CONDITION) begin
// procedural statements
end
else begin
// procedural statements
end
if (CONDITION) begin
// procedural statements
end
else if (CONDITION) begin
// procedural statements
end
else begin
// procedural statements
end
6-15
if Statement Syntax
The order of evaluation (priority) is sequential, testing the if condition first...
If the conditional evaluates to true, the simulator executes the procedural statements for the if branch.
If false the optional else branch is executed
On completion of the active branch the if-else statement will terminate.
Notice that omitting the optional else may result in no branches being executed.
In nested if sequences, else is associated with the closest previous if.
Use indentation to aid readability.
To ensure proper association, use begin...end block statements.
6-16
case Statement
case is a multiway
conditional statement
case expression is
evaluated and compared
against each item in turn
Branch items can overlap
The first item match
executes that branch
module case_example (
input
[3:0] a, b, c, d,
output reg [3:0] y
);
always @*
case (d)
0
1,2,3,4,5
6
7
default
endcase
:
:
:
:
:
y
y
y
y
y
=
=
=
=
=
a;
b;
c;
c;
4'b0000;
endmodule
6-17
case Statement
The case statement evaluates an expression and selects one of a number of sequences of statements
depending on the value of the expression.
In the example above, when a, b, c or d change value, the always procedure is executed. The case
statement examines the value of d. If d is 0000, output y is assigned a; if d is 0001, 0010, 0011,
0100 or 0101, output y is assigned b; if d is 0110 or 0111, y is assigned c. For all other values of d,
the default statement ensures that y is assigned 0000
We can decode multiple case values to a single statement by simply listing the values, separated by
commas. So in the example above, a value of 1, 2, 3, 4 or 5 will cause variable b to be assigned to y
The default catches all undeclared values including undefined x
Note that expression is checked against the case items in the order in which they appear.
It is not illegal to have the same value appear more than once in the list. As the list is checked in
order, the first match will mask any subsequent matches.
e.g. value 5 below is in the branch for y = b and y = c, but because the values are checked in
the order they are listed, y = b when d = 5.
:
:
:
:
:
y
y
y
y
y
=
=
=
=
=
a;
b;
// 1st 5: this branch taken when d = 5
c;
// 2nd 5: this branch masked when d = 5
c;
4'b0000;
6-18
casex (expression)
item1
: statements
....
itemn
: statements
default : statements
endcase
casez (expression)
item1
: statements
....
itemn
: statements
default : statements
endcase
6-19
The case statement does a bit-by-bit comparison for an exact match (including x and z).
The default statement is optional. It is executed when none of the statements match the case
expression. If it is not specified, Verilog takes no action.
Important
It is a good programming practice to always use the default statement, especially to check for x and z.
6-20
casex
module casex_example (
input
[3:0] a, b, c, d,
output reg [3:0] y
);
always @(a or
casex (d)
4'b0000 :
4'b0xx1 :
4'b111x :
4'bxxx1 :
default :
endcase
endmodule
b or c or d)
y
y
y
y
y
=
=
=
=
=
a;
b;
c;
c;
4'b0000;
Important
In your testbench use casez in preference to casex to expose initialization problems
Synthesis
casex is supported by most synthesis tools and provides a means to better optimization
Procedural Statements (V1E3)
6-21
casex
The casex statement is a variation of the case statement that allows you to specify bit positions it
should not compare.
The casex statement treats x, z, and ? as dont-care values.
The casex statement does not compare bit positions of either the case expression or the case items that
have any of these dont-care values.
Avoid using z as the dont care value to avoid confusion with the high-impedance logic state.
You must use binary or hexadecimal radix for literals containing dont-care values.
4b? = ????
4h? = ????
As the casex statement treats an undefined or uninitialized value in the case expression as dont-care,
this form of the case statement can hide initialization problems. For this reason, casez is a better
construct to use than casex in your testbench.
6-22
casez
module casez_example (
input
[3:0] a, b, c, d,
output reg [3:0] y
);
always @(a or
casez (d)
4'b0000 :
4'b0??1 :
4'b111? :
4'b???1 :
default :
endcase
b or c or d)
y
y
y
y
y
=
=
=
=
=
a;
b;
c;
c;
4'b0000;
endmodule
Tip
Do not use z as dont care within casez as you may later confuse it with the high impedance
state
6-23
casez
The casez is a variation on a case statements and allows dont-care conditions in the comparisons.
Dont-care values, in any bit of either the case expression or the case items, are treated as dont-care
conditions during the comparison. In other words, that bit position is not considered in the comparison.
In casez statements, ? and z are treated as dont-care values.
Avoid using z as the dont care value to avoid confusion with the high-impedance logic state
You must use binary or hexadecimal radix for literals containing dont-care values.
4b? = ????
4h? = ????
6-24
module finscase (
input
[3:0] a, b, c, d,
input
x, y,
output reg [3:0] op
);
always @*
case (1'b1)
x
:
y
:
(c==d) :
default :
endcase
op
op
op
op
=
=
=
=
a;
b;
c;
d;
endmodule
6-25
6-26
Synthesis
The synthesis standard support for loops
that have constant bounds.
module parity (
input wire [3:0] a,
output reg
odd
);
integer i;
reg tmp;
always @ a
begin
tmp = 0;
for (i = 0; i <= 3; i = i + 1)
tmp = tmp ^ a[i];
odd = tmp;
end
endmodule
a[0]
a[1]
a[2]
a[3]
tmp
6-27
6-28
...
while (count < 10)
begin
// statements
count = count + 1;
end
...
6-29
6-30
Synthesis
The synthesis standard does not support the
forever, repeat, and while constructs. Use these
constructs only in testbenches and simulation
models.
repeat(expression)
begin
// statements
end
forever
begin
// statements
end
6-31
for loop variable can be written as well as read, although this can be dangerous!
for (i = 0; i <= 3; i = i + 1)
begin
// statements
i =0;
// resetting variable means condition never false end
infinite loop
6-32
Review
1. If more than one condition of an if..else statement is true, which condition
takes priority?
2. Are if, case and for statements continuous or procedural statements?
3. Code the following conditional logic:-
a
b
mux
mux
1b0
1
0
<
ctrl
f
4b0110
6-33
Review
6-34
Find at least
twelve things
wrong!
input [3:0] a, b, c, s;
output [3,0] w, v, y, t;
reg
[3:0] w, v, y, t,
assign W = s;
always @(a or b or c and s)
if (s == 0)
v = a;
y = b;
t = c;
else if (s <= 4b0101)
begin
v = c;
y = b;
t = a;
a = s;
end
else if (s == 6 or s == 7)
v = c;
else v == 4bxxxx;
endmodule
Procedural Statements (V1E3)
6-35
6-36
7-1
Notes
7-2
Aims
To explain the difference between continuous and procedural statements.
Topics
Continuous assignments
Multiple continuous assignments to single source
Procedural assignments
Multiple procedural assignments to single source
Conditional assignment
Feedback loops
7-3
7-4
Continuous Assignments
Continuous assignments:
Reside outside procedures
assign tp = a + b;
assign op = c + tp;
assign op = c + tp;
assign tp = a + b;
tp
op
c
Continuous and Procedural Statements (VSE8)
7-5
Continuous Assignments
So first lets look at the issues with continuous assignments
The example on the slide shows two continuous assignments to op and tp
We can see that continuous assignments are order independent, so we can write these statements in either
way and we are describing the same topology.
Best way to visualize what is going on is to draw each operation like a schematic: such a drawing is
always concurrent!
7-6
+
b
op
+
d
Question
How is the value of op resolved?
wire/tri
0
1
x
z
0 1 x z
0
x
x
0
x
1
x
1
x
x
x
x
0
1
x
z
7-7
a
wand op;
...
assign op = a + b;
assign op = c + d;
+
b
&
op
+
d
Verilog Application Workshop
7-8
Review of Procedures
module and_or (a, b, z_or, z_and);
Remember...
Procedures execute concurrently
input a, b;
output z_or, z_and;
reg z_or, z_and;
always @*
begin
if (a | b)
z_or = 1;
else
z_or = 0;
if (a & b)
z_and = 1;
else
z_and = 0;
end
Procedural
Statements
endmodule
7-9
Review of Procedures
Now lets take a look at how we use procedural statements
Remember that procedural statements can only be used within a procedural block, either always or
initial.
Procedures start with the key word always or initial, followed by a list of variables that will cause
the procedure to execute when they change value.
Multiple procedural statements must be contained within begin and end statements. begin and end
are not required for a single statement.
Variables update immediately in procedures using blocking assignments (=). We have only seen
blocking assignments (=) so far, but there is another assignment called the non-blocking assignment (<=)
where the variables are not updated immediately, but are sampled in value, and then scheduled to be
updated later.
7-10
+
b
op
+
d
reg op;
...
always @(a, b, c, d)
begin
op = a + b;
op = c + d;
end
...
op
7-11
7-12
end
always @(a or b or sel)
begin
op = b; // default
if (sel)
op = a;
end
7-13
7-14
Conditional Operator
module
input
output
reg
7-15
Conditional Operator
Conditional operator can be used instead of an if statement with a single target.
In the proc_if module above, the if statement only assigns to opr, and so can be replaced by a
conditional operator statement.
The conditional operator assignment can be used in both procedural and continuous assignments.
Therefore a procedure which only contains an if statement with a single target can be replaced by a
continuous assignment using the conditional operator.
Note In the procedural form the target variable must be a register type, but in the continuous assignment
form the target must be a net type.
7-16
op
7-17
7-18
Review
1. What happens if multiple procedural assignments are made to the same variable?
2. Is a conditional assignment statement continuous, procedural or both?
3. Why should you not create combinational feedback loops?
4. Code the following hardware using (i) a continuous assignment and (ii) using a
procedure.
a[3:0]
d[4:0]
b[3:0]
0
c[4:0]
add
7-19
Review
7-20
8-1
Notes
8-2
Aim
Fully explain capabilities that a procedure can offer
Topics
Procedures and event control(review)
Blocking procedural assignment
Non-blocking procedural assignment
The simulation cycle
Timing control
Event based
Level based
Simple delays
8-4
endmodule
procedure
module flop (
input wire clr, d, clk,
output reg q
);
endmodule
8-6
Blocking assignment: =
Error
byte[7:4] =
byte[3:0] =
4b0000
initial
begin
byte = 8b00001111;
#10;
// try to swap nibbles
byte[3:0] = byte[7:4];
byte[7:4] = byte[3:0];
#10;
...
Caution
byte[3:0]
immediately updated
with 4b0000
Synthesis
blocking assignment is used in combinational logic descriptions
8-8
byte[7:4]
scheduled to
receive 4b1111
initial
begin
byte <= 8b00001111;
#10;
// try to swap nibbles
byte[3:0] <= byte[7:4];
byte[7:4] <= byte[3:0];
#10;
...
byte[3:0]
scheduled to
receive 4b0000
Synthesis
Use non-blocking assignments in sequential procedures.
8-10
Variable
Event List
Procedure
Scheduler
8-11
Important
The above refers only to variables which are assigned values within a procedure using Non-Blocking
assignment. Variables assigned via blocking assignment update immediately
Caution
The simulation cycle explained here is a simplification of the actual simulation cycle
8-12
Variable
Event List
Procedure
Scheduler
always @(a or m)
begin:P1
m <= a;
y <= m;
end
a <= 1
always @(m)
begin:P2
w <= m;
end
Assume a, m, y, w all
1b0
a changes value from
1b0 to 1b1
endmodule
Variable values
at start
a
m
y
w
:
:
:
:
0
0
0
0
8-13
8-14
Variable
Event List
Procedure
Scheduler
m <= 1
P1
always @(a or m)
begin:P1
m <= a;
y <= m;
end
Procedure P1 executes
Update to m scheduled
always @(m)
begin:P2
w <= m;
end
endmodule
Variable values
at start
a
m
y
w
:
:
:
:
1
0
0
0
8-15
8-16
Variable
Event List
Procedure
Scheduler
m <= 1
P1
P2
always @(a or m)
begin:P1
m <= a;
y <= m;
end
always @(m)
begin:P2
w <= m;
end
Procedure P1 placed on
scheduler list
Procedure P2 placed on
scheduler list
endmodule
Variable values
after 1 delta
a
m
y
w
:
:
:
:
1
1
0
0
8-17
8-18
Variable
Event List
always @(a or m)
begin:P1
m <= a;
y <= m;
end
Procedure
Scheduler
y <= 1
w <= 1
always @(m)
begin:P2
w <= m;
end
endmodule
Variable values
after 1 delta
a
m
y
w
:
:
:
:
1
1
0
0
8-19
8-20
Variable
Event List
Procedure
Scheduler
y and w updated to
1b1
No more procedures to
be executed
module sim_ex (
input
a,
output reg m, y, w
);
always @(a or m)
begin:P1
m <= a;
y <= m;
end
always @(m)
begin:P2
w <= m;
end
endmodule
Variable values
after 2 deltas
a
m
y
w
:
:
:
:
1
1
1
1
8-21
8-22
a
m
y
w
:
:
:
:
0
0
0
0
Variable
Event list
Procedure
scheduler
a <= 1
P1
a
m
y
w
:
:
:
:
1
0
0
0
m <= 1
P1
P2
a
m
y
w
:
:
:
:
1
1
0
0
a
m
y
w
:
:
:
:
1
1
1
1
y <= 1
w <= 1
Variable
values
module sim_ex (
input
a,
output reg m, y, w
);
always @(a or m)
begin:P1
m <= a;
y <= m;
end
always @(m)
begin:P2
w <= m;
end
endmodule
8-23
8-24
Simple delays: #
Simulation Time
8-25
#<delay>
simple delay
Delays execution until expr evaluates true (non-zero). If expr is already true, the statement executes
immediately.
8-26
8-27
8-28
Wait Statement
module latch_adder
input
input
[2:0]
output reg [3:0]
);
(
en,
a, b,
out
always @(a or b)
begin
// continue if/when en is low
wait (!en)
out = a + b;
end
endmodule
Synthesis
The synthesis standard does not support
wait statements
8-29
Wait Statement
In the example above, the addition is executed only when en is low. If en is already low when a or b
changes, the wait statement triggers immediately.
8-30
Simple Delays
...
reg [3:0] current_time;
reg
in_a, out_b;
initial
begin
current_time
#10; // wait
current_time
#5; // wait
end
= 4'b0000;
10 time units
= 4'b1001;
5 time units
always @(in_a)
// in_a assigned to out_b
// after 10 time-units
#10 out_b = in_a;
...
initial clk = 0;
always clk = ~clk;
Synthesis
Synthesis tools ignore delays
8-31
Simple Delays
You can use module parameters to parameterize simple delays that you can set for each instance.
module clock_gen
#(
parameter integer CYCLE=20
)
(
output reg clk
);
initial clk = 0;
always
#(CYCLE/2) clk = ~clk;
endmodule
8-32
Format
timescale <unit>/<precision>
Delays are scaled to <unit>,
rounded up to <precision>
Important
timescale 1 ns/100 ps
module tb_ddrv ;
reg [3:0] current_time;
initial
begin
current_time
#10; // wait
current_time
#5; // wait
end
= 4'b0000;
10 ns
= 4'b1001;
5 ns
Compiler directives:
Start with the grave accent
8-33
The `timescale compiler directive declares the time unit and its precision.
`timescale <time_unit> / <time_precision>
<time_unit> specifies the units of measurement for delays and time.
<time_precision> tells the simulator how to round delay values before using them in
simulation.
The time_precision and time_unit both consist of an integer representing the magnitude and a
character string representing the unit.
The valid integers are 1, 10, and 100.
The valid unit strings are s(second), ms(millisecond), ns(nanosecond), us(microsecond),
ps(picosecond), and fs(femtosecond).
Any combination of these is allowed.
The simulation speed may be greatly reduced if there is a large difference between the time units
and the precision, as some simulators advance by increments equal to the precision, e.g.
For `timescale 1s/1ps, to advance 1 second, the simulator increments 1012 times versus
`timescale 1s/1ms, where it only increments 103 times.
If a timescale is not specified, some simulators have a default timescale unit which will be used for all
blocks.
8-34
10
30
50
70
90
= 2b00;
1b1;
1b0;
1b1;
110
clk
set
q
15
48
33
70
43
93
103
8-35
8-36
Review
1. Within the simulation cycle, what is one loop known as?
2. How is time advanced in a simulation?
3. Name three methods of timing control?
4. What is the difference in updating a variable when using:
i) A non-blocking assignment?
ii) A blocking assignment?
5. Where is the timescale compiler directive placed?
8-37
Review
8-38
9-1
Notes
9-2
Aim
To explain the differences between blocking and non-blocking assignments
To give guidelines on the usage of blocking and non-blocking assignments
Topics
Blocking assignment review
Non-blocking assignment review
Blocking and non-blocking procedural assignment in sequential procedures
Blocking and non-blocking assignment in combinational procedures
Mixing blocking and non-blocking assignment
9-3
9-4
Blocking assignment: =
always @ (a or b or sel)
if (sel)
d = a;
else
d = b;
module seqblocking (
output reg [2:0] seq
);
integer i;
initial
begin
seq = 3'b000;
for (i = 0; i <= 4; i = i + 1)
begin
if incremented
seq
#10;
incremented
seq = 3b100,
seq = seq + 1;
every 10 ns
reset
if (seq == 3'b100)
seq = 3'b000;
end
seq sequence
end
endmodule
omits 3b100
value
ns
0
10
20
30
40
50
seq
000
001
010
011
000
001
9-5
9-6
...
reg q;
Update scheduled for after procedures suspend always @(posedge clk)
q <= d;
module seqnonblocking (
output reg [2:0] seq
);
integer i;
initial
begin
seq = 3'b000;
for (i = 0; i <= 4; i = i + 1)
seq
begin
scheduled for
if current seq =
#10;
increment
3b100, reset
seq <= seq + 1;
after
procedure
if (seq == 3'b100)
completes
seq <= 3'b000;
end
seq
end
sequence
includes
3b100
endmodule
ns
0
10
20
30
40
50
seq
000
001
010
011
100
000
9-7
9-8
initial
begin
avar = 1b1;
bvar = 1b1;
end
always @(posedge clock)
bvar = avar + 1b1;
Important
Procedures can execute in any order. Do
not rely upon execution order.
9-9
9-10
initial
begin
avar = 1b1;
bvar = 1b1;
end
always @(posedge clock)
bvar <= avar + 1b1;
always @(posedge clock)
cvar <= bvar;
Tip
Use non-blocking assignment for sequential logic
9-11
9-12
?Question
What would the diagrams look like if non-blocking assignments were used?
Blocking and Non-Blocking Assignments (BNB2)
9-13
9-14
Combinational Logic
always @(a or b)
begin
m = a;
n = b;
p = m + n;
end
always @(a or b or m or n)
begin : P1
m <= a;
n <= b;
p <= m + n;
end
Variable
Event list
Procedure
scheduler
a <= 1
b <= 2
P1
m <= 1
n <= 2
P1
p <= 3
Tip
Use blocking assignment for combinational procedures
Blocking and Non-Blocking Assignments (BNB2)
9-15
Combinational Logic
Simulators and synthesis tools can support use of either blocking or non-blocking assignments to
describe combinational logic.
However use of non-blocking assignments can be inefficient. If the combinational logic description uses
intermediate variables (used to temporarily store a value) then these intermediate variables need to be
added to the procedure event list. In the example above, when variable a changes to 1, m will be
scheduled with an update to 1, but when p is assigned, the current value of m is used to calculate a value.
m needs to be added to the event list to force a re-execution of the procedure when m changes value in
order to calculate a value for p using this new value of m. Hence the procedure will take 2 delta cycles
to reach a steady state.
With blocking assignment, the procedure is evaluated in a single delta cycle
9-16
Multiple Assignments
always
begin
m <=
n <=
p <=
m <=
q <=
end
always @(a, b, c)
begin
m = a;
n = b;
p = m + n;
m = c;
q = m + n;
end
+
?
@(a, b, c, m, n)
a;
b;
m + n;
c;
m + n;
?Question
What are the inputs to these
adders (in terms of a, b, and c)
for each procedure?
9-17
Multiple Assignments
Blocking and non-blocking assignments can create completely different results. For these examples:
For blocking assignments, variable update is completed before execution continues. Intermediate values
are available until overwritten. In the blocking example above, the value of a assigned to m is used to
calculate p (a+b), and the value of c assigned to m is used to calculate q (b+c).
For non-blocking assignments, variable update is scheduled. Values are available only after the update
occurs. In the non-blocking example above, the assignment of a to m is scheduled and immediately
overwritten by the scheduled assignment of c to m. In the variable update phase, only the value of c is
assigned to m.
9-18
Mixed Assignments
Usage model
Assign inputs to temporary
variables with blocking assignment
9-19
Mixing Assignments
You can use blocking assignments to temporary variables within sequential procedures.
An efficient usage model is: capture the needed procedure inputs into local temporary variables using
blocking assignment; do required calculations using local temporary variables and blocking
assignments; and assign to procedure output variables using non-blocking assignments to avoid race
conditions.
This usage model requires that you declare separate variables for temporary use within a procedure, and
that no other procedure access those variables. It is best to declare these temporary variables as locally
as possible to where they are used. This discourages their use elsewhere.
9-20
Example
Write the Verilog code for the following block diagram. You can write it in one
procedure.
a
b
c
0
1
0
1
sl
clk
9-21
Example
Write your outline code here. Dont worry about declarations, were only interested in the structure of
the code.
9-22
Review
1. What is the primary difference between blocking and non-blocking assignments?
2. Where should you use non-blocking assignments?
3. Where should you use blocking assignments?
4. When might you use blocking assignments in a sequential procedure?
9-23
Review
9-24
10-1
Notes
10-2
Aim
To look at some of the different applications of Verilog and the methods and
coding styles involved
Topics
Testbench style
RTL style
Behavioral versus RTL
10-3
10-4
Testbench Organization
Simple testbench
Testbench
Stimulus
Design to
Verify
Testbench
Design to
Verify
As in lab exercises
Sophisticated testbench
Models environment around
design
Talks to design, e.g bus
cycles
Evolves towards board model
Possibilities of self checking
10-5
Testbench Organization
Testbenches tend to start off simple but quickly become sophisticated. Typically, at least 50% of the time
you will spend writing Verilog on a project will be taken up with coding your test bench. In our simple
testbench, a circle represents a process and a square represents a component instantiation. The outer
rectangle represents the testbench entity which doesn't have any ports. Such a testbench simplifies the
business of getting into the simulator and is useful for checking out an idea, or a bit of Verilog you are
not sure of.
In a sophisticated testbench you may well want to model the environment with which your design has to
interact, you might want to model the bus cycles of a microcontroller which talks to your design, you
may want to evolve your testbench towards a model of your design sub-system.
10-6
Design to
Testbench
Verify
Test Data
Errors
Visualization
Results
10-7
10-8
Sequential Procedure
always @(posedge clock)
begin
...
...
...
end
Synthesis
Procedures must conform to specific templates to be synthesizable!
10-9
10-10
?Question
What is the problem with this counter
description?
endmodule
4d0
1
0
4
count
sel
>=
clk
4d9
Verilog Coding Styles (VDE8)
10-11
10-12
RTL Modelling
Generally required to be
synchronous
10-13
Create a functional model of the specification, which can help highlight ambiguities and errors in
the specification.
Experiment with different architectures and partitioning for implementation, with the possibility
of obtaining some performance analysis of alternatives through simulation.
Create libraries of test data - both stimuli and expected responses - which can be used in the
verification of RTL models.
Although behavioral synthesis tools are available, behavioral to RTL translation is usually manual.
Therefore full behavioral modeling may only be used for the design of a completely new, major system.
An RTL model has to consider implementation effects such as propagation delays and signal glitches.
To solve these problems, we make our circuits synchronous. A synthesis methodology is, essentially, a
synchronous methodology. We do not model the delays through the combinational logic which, for
simulation efficiency we assume to be zero.
We do have to worry about registers, which we use to store values, about what clocking scheme to use,
about the reset and the amount of logic in between them.
10-14
Specification
max 20
data
data_read
data read
data_valid
CPU_RD
data_valid
DATA
WRITER
data
DATA
READER
local_buffer
data_read
always
begin: CPU_RD
wait(data_valid == 1);
data_read = 1;
#20;
local_buffer = data;
#10;
data_read = 0;
wait(data_valid == 0);
end
10-15
10-16
clk
data_valid
data_read
data read
data read
read_state
WAITING STATE1
STATE2
STATE3
STATE1
STATE2
STATE3
!data_valid
data_read = 0
WAITING
data_valid
STATE1
STATE3
data_read = 1
STATE2
local_buffer = data
10-17
STATE1
STATE2
STATE3
clear data_read
10-18
=
=
=
=
0,
1,
2,
3;
10-19
10-20
Review
1. What are the two types of procedure used for RTL code?
2. How do we infer registers for synthesis?
3. What is behavioral modeling used for?
4. How do you define the states for an FSM?
10-21
Review
10-22
11-1
Notes
11-2
Aims
To introduce the synthesis process and look at its strengths and weaknesses
Topics
How a synthesis tool works
Synthesis based methodology
Synthesis strengths and weaknesses
Programmable Logic Device synthesis issues
Language subsets
11-3
11-4
clk
11-5
11-6
Technology Library is
used to build the circuit
from the verilog
description.
Verilog
Code
Technology
Library
Synthesis
Engine
Speed
Area/Speed Curve
Constraints
File
Area
Schematic
The Synthesis Process (VSP8)
11-7
11-8
Constraints
File
Boolean
Parsing
Mapping
Technology
Library
Gates
Optimization
Schematic
The Synthesis Process (VSP8)
11-9
Synthesis tools represent a design internally both as logic (in the form of boolean equations and
registers), and as an interconnection of gates from a specific technology.
A synthesis tool translates the Verilog constructs into boolean equations which are represented in
the logic level.
When optimization, or mapping is carried out, then the synthesis tool optimizes these equations
using boolean algebra, and then implements then in a specific silicon technology at the gate level.
The gate level design is also optimized. More sophisticated synthesis tools are able to re-optimize
the logic based upon information learned from the initial mapping to gates.
When the optimization is complete, then a gate level description can be written out from the
synthesis tool for gate level simulation and layout.
The diagram shown on the slide is a rather simplified view of reality. During the synthesis process, the
first thing that happens is that your Verilog gets mapped to two-level sum of products logic expressions;
i.e. the output of each blob of combinational logic is expressed in terms of the inputs to the logic. These
expressions are then minimized. Common factors are then extracted to create multi-level expressions
which are also minimized. All synthesis tools use the same algorithms for these minimization steps. The
optimized multi-level expressions are then mapped to the target technology and the algorithm used for
mapping will vary from tool to tool. Next, a timing analysis is performed on the result to see if any of
your constraints have been violated. If they have, remapping, perhaps to higher drive cells, could solve
the problem; if not, the synthesis tool will re-factorize and try again, perhaps with fewer levels of logic.
11-10
Number of registers
Combinational logic optimized only, not register numbers or placement
Structure of logic
clk
11-11
11-12
Here the == operator is redundant but may still appear in the synthesized netlist
Question
What would be the input at ?
Inferred hardware
structure
011
011
011
>
c
b
a
<
mux
0
1
mux
0
1
y
mux
clk
11-13
11-14
Clock trees
Usually require detailed, accurate net delay information
Specific macro-cells
11-15
11-16
11-17
11-18
A Synthesis Methodology
change code
change constraints file
netlist
tech library
constraints
n
synthesis
Verilog
rtl
simulation
testbench
y
meets area/speed?
functional?
y
gate
simulation
compare
change code
golden results
results
The Synthesis Process (VSP8)
11-19
A Synthesis Methodology
With all synthesis tools you will be following a very similar methodology to the one shown here. First
you select a block of an appropriate size for the capacity of your tool. The size of the block is often a
trade-off between how much of your design you want to synthesize at once and the ability of your
computer resources to produce you a result in a reasonable time! After simulation you synthesize the
block after setting up some timing constraints such as the maximum allowable propagation delay. At the
same time, you could make your design more testable by automatically inserting scan chains, or at least
scan path flip flops which you join up into scan chains later.
After synthesis you would do a static timing analysis using the synthesis tool's built-in analyzer to check
how well the tool has met your constraints. If satisfied, you would carry out a gate-level simulation to
check that you still have the same functionality you started with.
The problems arise if the results from synthesis are not good; perhaps because you are exceeding some
critical timing delay. There are a number of things you can do then which we have listed in order of effort
from top to bottom. The easiest thing to do is to change some of the switches available in the synthesis
tool which affect how the optimization algorithms work. This is not predictable but they are worth
playing about with. Secondly, you could modify some of your constraints; if you have over constrained
the tool you will have unnecessarily limited the degrees of freedom it has to meet your constraints
automatically.
Finally you could change the Verilog; the easiest thing to do here is alter the hierarchy by partially
flattening it - this again gives the tool more degrees of freedom to meet your constraints. Finally, if
nothing else works, you may have to bite the bullet and change the architecture of your design.
We will come back to this important subject. Hopefully we have said enough now to make it obvious to
you that a synthesis methodology is an iterative one and one in which you are learning more and more
about how your synthesis tool works best.
11-20
Language Support
11-21
Language Support
If you write your RTL code using the coding guidelines and templates described in this course, then your
code will be portable between the maximum number of synthesis tools
11-22
Summary
11-23
Summary
In this section we have explored the subject of synthesis by looking at what a synthesis tool does with
your RTL Verilog code. The motto of this course, which we will take up in future lectures is Think
Hardware!
11-24
12-1
Notes
12-2
Aims
To review basic Verilog concepts and code structures
To explore a real life example
Topics
FIFO (First-In First-Out) design specification
Implementation
Module declarations
Functional code
Testbench design and implementation
12-3
Sample Design
12-4
FIFO Specification
When the FIFO is full, set f_full high and ignore write operations
When the FIFO is empty, set f_empty high and ignore read operations
12-5
FIFO Specification
12-6
FIFO Implementation
FIFO length
0 1 2 3 . . . . . . . n
FIFO
width
FIFO full
FIFO empty
rd_ptr
wr_ptr
Read pointer
follows write
and accesses
data in same
order as
written
<free>
wr_ptr
write here
four
three
two
one
rd_ptr
FIFO write:
assign data to
current write
pointer &
increment
wr_ptr
Verilog Sample Design (VSD3)
12-7
FIFO Implementation
The FIFO is implemented using an array of registers. The array is indexed by separate FIFO write and
FIFO read pointers. When we write to the FIFO, data is written to the current write pointer location and
the pointer is incremented. As more data is written, the write pointer moves forward through the array.
When we read data, we read from the current read pointer location, and increment the read pointer. So
the read pointer chases the write pointer through the array, reading the data in the order in which it was
written to the array. When the pointers reach the end of the array, they independently wrap back to the
start. This allows the write pointer to overwrite data which has been read from the FIFO.
The write pointer operates on a write, then increment approach. Input data is written directly to the
current write pointer location, and then the pointer is incremented to point to the next free location.
By monitoring the relative values of the pointers, we can determine whether the FIFO is full or empty.
12-8
12-9
12-10
Design Constants
You can use module
parameters to define the
data and address width
0 1 2 3 . . . . . . LENGTH-1
0
1
2
. . .
WIDTH-1
rd_ptr[ADDRESS_WIDTH-1:0]
module fifo
// Verilog-2001 list_of_parameter_declarations
#(
parameter integer DWIDTH = 8,
parameter integer AWIDTH = 5
)
12-11
Design Constants
You can use a module parameter anywhere that you can use a literal
Typically, you use module parameters to define delays and widths of variables
You cannot modify module parameters during runtime they are not variables
The IEEE Std. 1364-2001 allows you to specify a type and to sign and size vector parameters:
parameter_declaration ::=
parameter [ signed ] [ range ] list_of_param_assignments ;
| parameter integer list_of_param_assignments ;
| parameter real list_of_param_assignments ;
| parameter realtime list_of_param_assignments ;
| parameter time list_of_param_assignments ;
The IEEE Std. 1364-2001 allows to declare a module parameter port list:
module_declaration ::=
{ attribute_instance } module_keyword module_identifier
[ module_parameter_port_list ] [ list_of_port...
module_parameter_port_list ::=
# ( parameter_declaration { , parameter_declaration } )
Verilog Application Workshop
12-12
FIFO I/O
module fifo
// Verilog-2001 list_of_parameter_declarations
#(
parameter integer DWIDTH = 8,
parameter integer AWIDTH = 5
)
// Verilog-2001 list_of_port_declarations
(
input clock, reset, wr_en, rd_en,
input [DWIDTH-1:0] data_in,
data_in
output f_full, f_empty,
output [DWIDTH-1:0] data_out
);
fifo
DWIDTH
// local variables
// functional code
data_out
DWIDTH
wr_en
f_full
rd_en
f_empty
endmodule
reset
clock
12-13
FIFO I/O
Use the parameters in the definition of the input and output ports of the FIFO module.
12-14
rd_ptr
1
2
3
. . . . . . .
// pointer declarations
reg [AWIDTH-1:0] wr_ptr;
reg [AWIDTH-1:0] rd_ptr;
. . . . . . . . . .
mem
LENGTH-1
wr_ptr
[DWIDTH-1:0]
12-15
12-16
12-17
12-18
wr_ptr
// output
assign data_out = mem[rd_ptr];
endmodule
rd_ptr
<free>
// sequential procedure
read data
if write pointer
catches read
pointer, FIFO full!
write here
write here
FIFO Outputs
wr_ptr
12-19
FIFO Outputs
Ports of a type not explicitly declared default to the wire type, so the output ports are nets. You set net
values using continuous assign statements.
We generate the data_out output by indexing the FIFO array with the read pointer rd_ptr.
We generate the FIFO status flags by comparing the read and write pointer values. If rd_ptr is equal
to wr_ptr, then the FIFO is either empty or full. If the last operation was a write, then it must be full,
and otherwise empty.
12-20
The Testbench
Testbench
Design Under Test
Stimulus
and
Control
data_out
data_in
f_full
clock
reset
wr_en
rd_en
f_empty
Response
Generation
and
Verification
The testbench:
Instantiates and connects to the Design Under Test (DUT)
12-21
The Testbench
To verify that our FIFO model works correctly we need to simulate the model with some meaningful
stimuli. We will need to write a testbench to apply this stimuli to the FIFO and check for the correct
response. A testbench will typically perform 3 functions:1. Instantiate the Device Under Test (DUT) and connect the input and output ports to local variables
2. Apply stimuli to the input data and control (clock, reset) ports
3. Monitor the output ports to capture the response of the design to the applied stimuli, and verify
that these results are as expected
This final function may actually be performed by examining the input and output variables in a waveform
viewer and taking the manual decision whether the design behavior is correct or not.
Testbenches tend to start off simple but quickly become sophisticated. Typically, at least 50% of the time
you will spend writing Verilog on a project will be taken up with coding your test bench.
12-22
Testbench Declarations
module fifo_tb;
// Verilog-2001 local constants
localparam integer DWIDTH = 8;
localparam integer AWIDTH = 5;
localparam integer PERIOD = 10;
// Signal declarations
// for FIFO inputs
reg [WIDTH-1:0] data_in;
reg clock, wr_en, rd_en, reset;
// for FIFO ouputs
wire f_full;
wire f_empty;
wire [WIDTH-1:0] data_out;
// FIFO instantiation
// Apply stimulus
endmodule
Question
Why does the testbench have no ports?
12-23
Testbench Declarations
The testbench has no ports because we expect it to not be instantiated in another module.
12-24
DUT Instantiation
module fifo_tb;
// Declarations
// FIFO instantiation
fifo
// Verilog-2001 parameter value by name
#(
.AWIDTH(AWIDTH)
.DWIDTH(DWIDTH),
)
dut
(
.data_in
.data_out
.clock
.reset
.wr_en
.rd_en
.f_full
.f_empty
);
(data_in),
(data_out),
(clock),
(reset),
(wr_en),
(rd_en),
(f_full),
(f_empty)
// Apply stimulus
endmodule
12-25
DUT Instantiation
12-26
Describing Stimulus
//Apply stimulus
initial begin
$monitorb("%d",$time,,clock,,reset,,wr_en,,rd_en,,
data_in,,f_full,,f_empty,,data_out);
@(negedge clock) // assert reset
reset = 1b1;
@(negedge clock) // deassert reset
reset = 1b0;
{wr_en, rd_en} = 2b00;
@(negedge clock) // load 1 word
wr_en = 1b1;
data_in = {WIDTH {1b1}};
repeat(2**AWIDTH-2)
@(negedge clock) // load n-2 words
data_in = data_in - 1;
@(negedge clock) // load 1 word
data_in = data_in - 1;
@(negedge clock) // attempt load
data_in = data_in - 1;
@(negedge clock) // unload 1 word
{wr_en, rd_en} = 2b01;
data_in = {WIDTH {1bX}};
repeat(2**AWIDTH-2)
@(negedge clock); // unload n-2 words
@(negedge clock); // unload 1 word
@(negedge clock); // attempt unload
@(negedge clock)
$finish;
end
establish clock
monitor value changes
synchronize to clock
initialize flags
load 1 word - not empty
12-27
Describing Stimulus
$finish is a system task that ends simulation.
$monitor is a system task that outputs the value of the variables if they change.
12-28
Simulation Results
0
clock
reset
f_full
f_empty
wr_en
data_in
rd_en
data_out
100
200
300
400
500
600
FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE EDEC EB EA E9 E8 E7 E6 E5 E4 E3 E2 E1 E0
FF
700
800
1000
900
1100
1200
1300
clock
reset
f_full
f_empty
wr_en
data_in DF
rd_en
data_out FF FE FD FC FB FA F9 F8 F7 F6 F5 F4 F3 F2 F1 F0 EF EE ED EC EB EA E9 E8 E7 E6 E5 E4 E3 E2 E1 E0 FF
12-29
Simulation Results
12-30
Review
1. How can you change the value of a parameter?
2. What are the basic functional blocks of a test fixture?
3. Using a parameter, write code that creates a clock stimulus.
12-31
Review
12-32
13-1
Notes
13-2
Aim
To define the rules and coding guidelines for RTL code, and to give an overview
of portability issues
Topics
Combinational Procedures
Sequential Procedures
13-3
13-4
// Sequential Block
Synthesis
Procedures to be synthesized must conform to specific templates!
13-5
13-6
Combinational Logic
The event list for a combinational block
must contain all inputs to the logic.
Question
What would the behavior be if sel
was missing from the event list?
always @(a or b or c)
begin : comb_blk
reg temp;
temp = a + b;
q = temp + c;
end
13-7
Combinational Logic
The Verilog language allows you to place any variables in the sensitivity list and use blocking and
nonblocking assignments anywhere in the procedure. The synthesis tool requires code that
unambiguously states your design intentions. Code meant for the synthesis tool may use only a subset of
the Verilog constructs and coding styles.
For combinational logic:
All edges of all signals input to the logic must be present in the sensitivity list. This is due to the
rule that any changes on any inputs to the logic must be given the opportunity to immediately
affect the output
Do not place temporary variables in the sensitivity list. A temporary variable is one that the
block reads (and is read nowhere else) only after the block writes it. It is not input to the logic.
You should use only blocking assignments within purely combinational procedures. This is a
recommendation to obtain higher simulation performance nonblocking assignments are not
necessary and simulate more slowly.
It is an absolute requirement that you never mix blocking and nonblocking assignments to the
same variable!
The synthesis standard states that the sensitivity list shall not affect the generation of combinational
logic. That means that if the synthesis tool recognizes the block as combinational logic, it will proceed
as if you had included all inputs to the logic in the sensitivity list. The synthesis tool may or may not warn
you about missing inputs. The generated gates will simulate correctly, but very likely differently than the
incorrect RTL block.
13-8
Synthesis
For combinational logic, include all
in the event list all variables that are
input to the logic. When in doubt use
the * wildcard.
// incomplete
always @(a or b)
// complete
always @(a or b or sel)
always @(*)
sel
sel
13-9
If sel is missing from the event list, the assignment to y is made on changes of a or b
Changes in sel have no affect
Debug of problems caused by incomplete sensitivity lists is difficult you might want to develop
the habit of simply always using * for combinational blocks
13-10
?Question
What is the value of b if ctrl = 0 ?
module incomplete (
input wire a, ctrl,
output reg y
);
always @(ctrl or a)
if (ctrl)
y = a;
endmodule
13-11
13-12
Avoiding Latches
Two very common ways exist to
avoid latch inference...
// Default Assignment
always @(ctrl or a)
begin
b = 0; // default
if (ctrl)
b = a;
end
?Question
Which would you use for a procedure
with complex nested if statements?
13-13
Avoiding Latches
There are two ways to prevent a synthesis tool creating transparent latches:1. Initialize b at the top of the procedure with a default assignment
2. Use an else clause for the if statement
Which is the best technique in a real design?
If you have a procedure with a complex set of conditional assignments, you are likely to not assign a
value to the output for one or more of these branches. A single default assignment to the output at the top
of the procedure prevents this problem.
13-14
Continuous Assignments
Continuous assignments drive values onto nets.
Continuous assignments always represent combinational logic.
The output is a function of the current inputs
module orand (
input a, b, c, d, e,
output y
);
assign y = e & (a|b) & (c|d);
endmodule
a
b
e
c
d
13-15
Continuous Assignments
13-16
13-17
13-18
Sequential Logic
The event list for a sequential block contains only
single edges of clock signals.
Use only posedge/negedge in event list
module counter (
input wire clk,
output reg [3:0] count
);
always @(posedge clk)
if (count >= 9)
count <= 0;
else
count <= count + 1;
endmodule
count
1
4
Question
Is there a problem with
this counter description?
sel
<
9
clk
13-19
Sequential Logic
This sequential procedure only has the clock variable clk in its event list. The posedge event control
will only trigger the procedure on the rising edge of the clock. The if statement in the procedure
describes the combinational logic required to calculate a new value for count on the next rising edge
of clk. Since this is a sequential procedure, any variables assigned to with non-blocking assignment in
the procedure will be registered.
Synthesis tools recognize sequential procedures by looking for a particular code template in this case,
a procedure with an event list containing only edge-qualified signals. Although some synthesis tools do
support other coding styles for sequential procedures, if you stick to the one shown here you won't go
wrong and you will be writing code which is most portable between synthesis tools.
Note: This example lacks a reset to initialize the count value!
13-20
module synch_rst (
input wire clk, rst,
output reg [3:0] count
);
always @(posedge clk)
if (rst) // active high reset
count <= 4b0;
else if (count >= 9)
count <= 4b0;
else
count <= count + 4b1;
endmodule
module async_rst (
input
clk, rst,
output reg [3:0] count
);
always @(posedge clk or posedge rst)
if (rst) // active high reset
count <= 4b0;
else if (count >= 9)
count <= 4b0;
else
count <= count + 4b1;
endmodule
Definition of RTL Code (VRE7)
13-21
13-22
Tip
Keep procedures with asynchronous resets
separate from procedures with synchronous
resets and separate from procedures with no
reset.
13-23
13-24
module dffn (
input wire d, clk, en,
output reg q
);
always @(posedge clk)
if (en)
q <= d;
endmodule
q
mux
en
clk
Question
Write this using one combinational
block and one sequential block.
Definition of RTL Code (VRE7)
13-25
13-26
clk
?Question
Code this design in Verilog.
13-27
13-28
3: WORKS
2: GOOD
4: BROKEN
13-29
13-30
?Question
module flops1 (
input wire in1, clk,
output reg out1
);
always @(posedge clk)
begin: fblk
reg tmp;
tmp
= !in1;
out1 <= tmp;
end
Synthesis
Use blocking assignment in sequential procedures
only for temporary variables.
module flops2 (
input wire in1, clk,
output reg out1
);
always @(posedge clk)
begin: fblk
reg tmp;
out1 <= tmp;
tmp
= !in1;
end
Definition of RTL Code (VRE7)
13-31
13-32
Review Questions
Find and fix the coding mistakes in the following procedures intended for synthesis:
13-33
Review
13-34
Synthesis of Mathematical
Operators
VME7
14-1
Notes
14-2
Aims
To explain the issues associated with both simulation and synthesis of
mathematical operators
Topics
High level synthesis
Resource sharing
Intermediate variables
Operator architectures
Macro generation
14-3
14-4
Operator
a = b + c;
Logic
b
c
Gates
not u1 (nsel,sel);
and u2 (selb,sel,b);
and u3 (nsa,ns,a,);
14-5
14-6
Optimization of Operators
The synthesis tools treatment of operators focuses on four issues:
Does it infer the operator hardware from a library or does it implement the operator
as discrete gates?
Sharing of operators . . .
14-7
Optimization of Operators
The first issue is how the synthesis tool implements the operator.
The synthesis tool can choose to map to a single adder cell from the vendors library or to an
implementation in discrete gates.
The second issue is what architecture to select or build.
The synthesis tool can (for example) choose between ripple carry and carry look-ahead architecture.
Modern synthesis tools can automatically choose the architecture based upon design cost factors such
as area and speed.
Modern synthesis tools also permit you to specify the architecture using a synthesis directive.
The third issue to be aware of that synthesis tools may implement complex operators in a new level of
hierarchy.
The fourth issue is that of resource sharing.
14-8
Question
Draw the hardware architecture
that you think this code will infer.
14-9
14-10
?Question
Rewrite this code to use
only a single add operator.
14-11
14-12
o = a + b + c;
n = b + a + d;
m = c + d;
o = a + b + c;
n = a + d + b;
m = c + d;
Caution
Operand order and position may affect automatic resource sharing.
Tip
Use intermediate terms to force resource sharing
t
o
n
m
=
=
=
=
a
t
t
c
+
+
+
+
b;
c;
d;
d;
14-13
14-14
Mathematical Optimization
Chain (serial) structure
op = a + b + c + d;
op = (a + b) + (c + d);
a
c
op
op
Synthesis of Mathematical Operators (VME7)
14-15
Mathematical Optimization
Most compilers parse an expression from left to right. Thus a synthesis tool might initially construct
hardware for a + b + c + d by adding a and b and then adding that result to c and then that
result to d. This would likely not be the most optimal implementation, so the synthesis tool might need
to slightly transform the design.
You can help the tool arrive at an initially more optimal structure by judicious use of parentheses.
14-16
Instantiation of Macro-Cells
Explicit macro instantiation creates issues:
Makes the code less readable
14-17
Instantiation of Macro-Cells
In the case where a synthesis tool is not able to infer a technology-specific macro from a statement it may
be necessary to explicitly instantiate the macro as a component in order to obtain the required optimal
results.
Instantiating a specific macro will make the code technology-dependent (i.e. the code will need to be
edited if another technology is targeted), but explicit instantiation does give more control over the
resulting synthesized design.
Modern synthesis tools generate good results for arithmetic operators. You may still need to explicitly
instantiate memory blocks, embedded processors and third-party Intellectual Property (IP).
To make the design more technology independent, it is possible to instantiate the vendors macro within
a user defined module, and then to instantiate this module in the actual design. In this case, it is easier to
change to a new technology at a later date, as you are only required to modify the definition of the user
defined cells, rather than having to change each case where one of these parts has been instantiated.
14-18
Summary
Read the synthesis vendors documentation!
Understand what the synthesis tool does about operators
Apply this knowledge to your structure of Verilog expressions
14-19
Summary
14-20
Review Questions
1. In what two ways may the synthesis tool implement mathematical operators?
2. What are two disadvantages to directly instantiating macrocells instead of using
mathematical operators?
3. How would you implement the following expression in hardware using just one two
input adder? Give the hardware and also the code.
y = a + b + c;
14-21
Review
14-22
15-1
Notes
15-2
Aims
To take a detailed look at how Verilog constructs relate to hardware and
therefore understand how coding style will affect synthesis results.
Topics
Structuring Procedures
State machines
if and case statement synthesis
Synthesis directives
Initialization
15-3
15-4
Structuring Procedures
clk
?Question
end
15-5
Structuring Procedures
It is important when writing your RTL code to correctly partition design behavior between procedures
to control the location of registers in the design.
Lets look at an example. Does this code describe this logic?
15-6
clk
?Question
How should the code be structured?
(There are at least three options)
15-7
15-8
clk
Moore FSM
clk
Mealy FSM
15-9
15-10
A
a = 1b1
o1 = 1b0
o2 = 1b0
c
3b011
B
b = 1b0
o1 = 1b1
o2 = 1b1
a = 1b0
{a,b} = 2b01
Transition
Conditions:
{a,b}=2b01
{a,b} = 2b11
3b001
State Encoding:
A=3b000,
B=3b001...
3b000
b = 1b1
State Names
(A,B,C,D,E)
o1 = 1b0
o2 = 1b0
Output values:
o1=1b0
D
3b010
a = 1b1
o1 = 1b0
o2 = 1b0
E
3b110
o1 = 1b0
o2 = 1b1
15-11
15-12
State Register
o1
o2
next_state
// state encoding
localparam [2:0] A
B
C
D
E
=
=
=
=
=
3b000,
3b001,
3b011,
3b010,
3b110;
// state vectors
reg [2:0] state, next_state;
Output Logic
a
b
module fsm (
input wire a, b, clock, reset,
output reg o1, o2
);
15-13
15-14
// output decode
always @ (state)
begin
// default assignments
o1 = 1b0;
o2 = 1b0;
case (state)
B: begin
o1 = 1b1;
o2 = 1b1;
end
E: o2 = 1b1;
endcase
end
15-15
Separating the next-state logic and the state register requires a variable (next_state) to carry
information from the combinational next state procedure to the synchronous state register procedure.
This is only one valid partitioning of the state machine.
The combinational next state and output decode procedures can be merged.
The sequential block can absorb the combinational next state function.
15-16
Synthesis of if Statements
module if_example (
input
a, b, c,
input [3:0] ctrl,
output reg op
);
always @(a or b or c or ctrl)
if (ctrl == 4'h0)
op = a;
else if (ctrl <= 4'h4)
op = b;
else
op = c;
endmodule
Question
Draw the hardware architecture this represents.
15-17
Synthesis of if Statements
Spend a few minutes working this out architecture in terms of multiplexers and comparators.
It is important to understand what hardware architecture the synthesis tool would produce.
Your Verilog coding style influences the initial architecture the synthesis tool produces.
Thus making it more or less difficult for the synthesis tool to meet timing requirements.
15-18
ctrl
0
<=
4
case (ctrl)
0:
op = a;
0,1,2,3,4: op = b;
default:
op = c;
endcase
ctrl
=
0
op
Synthesis
How would this change if we directed the
synthesis tool to build the case branches in
parallel?
15-19
15-20
ctrl
0
<=
case (ctrl)
0:
op = a;
1,2,3,4: op = b;
default:
op = c;
endcase
ctrl
=
0
op
15-21
15-22
(* synthesis, parallel_case *)
case (1)
this:
op = a;
that:
op = b;
default: op = c;
endcase
Important
Never apply to a non-parallel case.
this
a
that
b
this
that
c
op
no priority
structure
15-23
15-24
Synthesis Directives
Most synthesis tools also
accept synthesis
directives as
metacomments.
Metacomments are
Verilog comments,
ignored by simulation but
meaningful to other tools.
15-25
Synthesis Directives
The directives usually have the tool or company name in the comment. Some tool vendors also support
the directives of other companies.
Refer to your tool documentation to understand which specific directives your tools support.
The examples below show directives from Synopsys Design Compiler, Ambit BuildGates, and
Exemplar, and a generic directive (synthesis ...) initially recommended by Accellera.
Case Directives
//synopsys translate_on
//synthesis parallel_case
//synopsys translate_off
//ambit synthesis on
//exemplar parallel_case
//synopsys full_case
Other directives can be used to control, for example, the implementation of arithmetic operators or
FSMs.
NOTE: Since directives are ignored by simulation but affect synthesis they can lead to mismatches
between RTL and gate level behavior - use them with extreme caution!
15-26
Question
Are these casex statements parallel?
always @(pri_in)
casex (pri_in)
4'b1???: op = 3;
4'b01??: op = 2;
4'b001?: op = 1;
4'b0001: op = 0;
default: op = 0;
endcase
end
always @(ctrl) begin
int = 3'b000;
casex (ctrl)
3'b??1: int[0] = 1'b1;
3'b?1?: int[1] = 1'b1;
3'b1??: int[2] = 1'b1;
endcase
end
15-27
15-28
// no latch
always @(ctrl or a or b)
case (ctrl)
0,1: op = a;
2:
op = b;
3:
op = 1bx;
endcase
// no latch
always @(ctrl or a or b)
case (ctrl)
0,1:
op = a;
2:
op = b;
default op = 1bx;
endcase
// no latch
Synthesis
Assigning the unknown state x is telling the synthesis tool that
you dont care what the output is for that input combination.
always @(ctrl or a or b)
begin
op = 1bx;
case (ctrl)
0,1: op = a;
2:
op = b;
endcase
end
Synthesis Coding Styles (VYE9)
15-29
15-30
// no latch
// no latch
always @(ctrl or a or b)
(* synthesis, full_case *)
case (ctrl)
0,1:
op = a;
2:
op = b;
endcase
always @(ctrl or a or b)
case (ctrl)
0,1:
op = a;
2:
op = b;
default op = 1bx;
endcase
15-31
15-32
Any variable not fully assigned in the combinational block is still latched
module select (
input wire [1:0] sel
output reg
a, b
);
always @(sel) begin
a = 0; b = 0; // prevents latch for a
(* synthesis, full_case *)
case (sel)
2'b00: begin a = 0; b = 0; end
2'b01: begin a = 1; b = 1; end
2'b10: begin a = 0; b = 1; end
2'b11:
b = 1;
default: begin a = 'bx; b = 'bx; end
endcase
end
endmodule
15-33
15-34
module counter (
input wire clk, rst,
output reg [3:0] q
);
initial q = 0;
always
if (q
q <=
else
q <=
@(posedge clk)
= 9)
4h0;
q + 1;
endmodule
endmodule
Synthesis
The synthesis standard supports the initial
construct only for initialization of ROM data
and requires it be accompanied by the
logic_block or rom_block attributes.
15-35
15-36
Review Questions
1. What sort of hardware structure are inferred by both case and if statements, by
default, in Verilog?
2. How could you change a case statement in order that its implementation does not
result in a priority structure?
3. If you are not using a synthesis attribute, how can you assure coverage of all
conditions for a case statement?
4. Give the code for an asynchronously and synchronously resettable flip-flop as
shown in the diagram below?
async_reset
1b0
sync_reset
clock
15-37
Review
15-38
16-1
Notes
16-2
Aims
To examine some more advanced synthesis coding styles and issues
Topics
Unsupported Verilog constructs
Register inference in synchronous logic
Latches and Tristates
Hierarchy management
16-3
16-4
repeat
time
tri0/tri1/trireg
cmos/nmos/pmos/rcmos/rnmos/rpmos
tran/tranif0/tranif1/rtran/rtranif0/rtranif1
wait
while
-> (event emission)
===/!=== (identity operator)
expression in event list
hierarchical identifiers
system functions (except $signed/$unsigned)
system tasks
variable declaration assignment
`celldefine, `endcelldefine, `line, `timescale
`unconnected_drive, `nounconnected_drive
Advanced Synthesis Coding Styles (VMS2)
16-5
16-6
op
shift_reg[7]
shift_reg[6]
shift_reg[5]
shift_reg[4]
shift_reg[3]
shift_reg[2]
shift_reg[1]
shift_reg[0]
=
=
=
=
=
=
=
=
=
shift_reg[7];
shift_reg[6];
shift_reg[5];
shift_reg[4];
shift_reg[3];
shift_reg[2];
shift_reg[1];
shift_reg[0];
ip;
end
?Question
How many registers are inferred?
16-7
16-8
module tworeg (
input wire d, clk,
output reg q
);
reg rega;
always @(posedge clk)
begin
rega = d;
q
<= rega;
end
endmodule
mux
1
0
rega
d
clk
module tworeg (
input wire d, clk,
output reg q
);
reg rega;
always @(posedge clk)
begin
rega <= d;
q
<= rega;
end
endmodule
mux
q
1
0
rega
d
clk
Advanced Synthesis Coding Styles (VMS2)
16-9
16-10
Inferring Latches
An incomplete assignment in a
combinational procedure infers
latch storage.
This is how you code a latch-based
design if you want one.
You most likely do not really want
latches so correctly code the
combinational block.
Latches can have asynchronous
set/reset.
module latch (
input data, enable,
output reg q
);
always @(enable, data)
if (enable)
q = data;
endmodule
module latch (
input enable, data, set, clr,
output reg q
);
always @(enable, data, set, clr)
if (set)
q = 1;
else if (clr)
q = 0;
else if (enable)
q = data;
endmodule
Advanced Synthesis Coding Styles (VMS2)
16-11
Inferring Latches
16-12
Inference of Tristates
module tri_state_drivers (
input
en_1, en_2,
input [7:0] data_1, data_2,
output [7:0] data_bus
);
en_1
data_1
data_bus
Caution
Use of net type wire assumes enable lines are mutually exclusive,
otherwise use triand or trior net type (check synthesis support)
16-13
Inference of Tristates
This example shows the type of code that represents the behavior of tri-state drivers, and the code that
synthesis tools require to infer tri-state drivers in the design.
A tri-state driver is inferred from a specific form of conditional assignment.
The assignment condition examines the enable variable of the conditional assignment.
If the enable is active, the input value is driven onto the tri-state bus
If the enable is inactive, the z value is driven onto the tri-state bus
For simulation, you can also use procedures containing if statements. The synthesis standard does not
explicitly specify whether synthesis tools shall accept or reject this method.
output reg [7:0] data_bus;
always @(data_1 or en_1)
if (en_1)
data_bus = data_1;
else
data_bus = 8'bz;
always@(data_2 or en_2)
if (en_2)
data_bus = data_2;
else
data_bus = 8'bz;
16-14
16-15
With registered outputs, the synthesis tool has almost a complete clock period to implement the
combinational logic at the input of the second block.
With unregistered outputs, the designer must specify what proportion of the clock period is
available to implement each combinational block. This is done by specifying input and output
delays for each block. These delays must be realistic and reflect the comparative performance of
the logic blocks
16-16
Hierarchy Management
Some things to consider:
Merging combinational logic
Optimization strategies
Synthesizeable sizes
Decoder
FSM
Multiplexer
ALU
16-17
Hierarchy Management
16-18
Review
1. Under what conditions does the synthesis tool infer a register for a blocking
assignment to a reg variable? If the synthesis tool does not infer a register, what
does it do with the reg variable?
2. How do you infer tristate gates for synthesis?
3. Under what conditions is a for loop synthesizable?
16-19
Review
16-20
17-1
Notes
17-2
Aims
Explain these two types of subprogram
Topics
Subprogram concepts
Functions
Tasks
Issues
17-3
17-4
inputs
function...
<function call>
Function subprograms:
Have one or more inputs and
return a single value
Task subprograms:
Have zero or more
input/outputs
outputs
17-5
17-6
Function Declaration
return type
function name
input <port_type>
time
real
realtime
Synthesis
Always synthesizes to
combinational logic
integer
<function_identifier> ( <function_port_list> ) ;
17-7
Function Declaration
Here are some key features of functions:
You can specify a type for the function. Functions by default represent single-bit integral values.
The function declaration implicitly declares a variable of that type local to the function, of the
same name as the function, to which your function can make blocking procedural assignments.
You must declare at least one input port and must not declare any output or inout ports.
You may declare variables in a function declaration, to which your function can make blocking
procedural assignments.
Functions define a new scope in Verilog. Variables declared in that scope are local to the function.
You must not declare design structure, such as modules or nets, in a function declaration.
17-8
Function Call
function integer zero_count;
input [7:0] in_bus;
integer i;
begin
zero_count = 0;
for (i = 0; i < 8; i = i + 1)
if (!in_bus[i])
zero_count = zero_count+1;
end
endfunction
in_bus
32
zero_count
module zfunct (
input clk,
input [7:0] a_bus, b_bus,
output [31:0] bcount,
output reg azero
);
// function declaration
assign bcount = zero_count(b_bus);
always @ (posedge clk)
if (zero_count(a_bus) == 0)
azero = 1b1;
else
azero = 1b0;
endmodule
Important
Call a function as an expression term
17-9
Function Call
You call a function as an expression operand. The simulator assigns the values of the argument
expressions to the input ports in the order in which they appear in the call.
When the function completes, the simulator uses the value of the function name variable where the call
appears in the calling expression. Functions return a single value that you use as an operand in rvalue
expression. An rvalue expression is one that may appear only on the right side of an assignment, you
cannot assign a value to an rvalue expression. If the function never completes, for example, in a loop that
loops forever, it never returns and the simulation hangs.
In this example, the zero_count function returns an integer value representing the number of bits of
the in_bus port that are zero. It returns a value between 0 and 8. The continuous assignment call assigns
the returned value to the bcount module output port. The conditional expression call uses the function
return value as an operand of a relational expression.
17-10
Constant Functions
Verilog-2001 introduces the constant function.
You can use a constant function anywhere Verilog requires a constant expression.
Replication, part-select, initialization, etc.
A constant function is a function for which the elaborator can determine its value:
Cannot define within a generate scope
Cannot invoke system functions (system tasks other than $display are ignored)
Can call other constant function defined in the same module if the other function
does not use a constant expression
17-11
Constant Functions
Verilog-2001 introduces the constant function.
You can use a constant function anywhere Verilog requires a constant expression.
The standard severely restricts the definition of a constant function. Several of the features of a
non-constant function cannot be present in a constant function.
17-12
Task Declaration
task name
task zero_count;
input [7:0] in_bus;
width defaults
output [3:0] count;
to single bit
integer i;
begin
local variable
count = 0;
#5;
for (i = 0; i < 8; i = i + 1)
if (!in_bus[i])
count = count + 1;
end
assign to outputs
endtask
Synthesis
Can synthesize only if
no timing controls
real
realtime
integer
<task_identifier> ( <task_port_list> ) ;
Functions and Tasks (VFE9)
17-13
Task Declaration
Here are some key features of tasks:
You can declare any number (including zero) of ports of any mode (input, output, inout).
You may declare variables in a task declaration, to which your task can make blocking or
non-blocking procedural assignments.
Tasks define a new scope in Verilog. Variables declared in that scope are local to the task.
You must not declare design structure (such as modules or nets) in a task declaration.
17-14
Task Call
task zero_count;
input [7:0] in_bus;
output [3:0] count;
integer i;
begin
count = 0;
#5;
for (i = 0; i < 8; i = i + 1)
if (!in_bus[i])
count = count + 1;
end
endtask
module zerotask (
input clk,
input [7:0] a_bus,
output reg azero
reg [3:0] a_count;
// task declaration
always @(posedge clk)
begin
zero_count(a_bus, a_count);
if (a_count == 4b0)
azero = 1b1;
else
azero = 1b0;
end
endmodule
Important
Call a task as a procedural statement
17-15
Task Call
You call a task as a procedural statement. The simulator assigns the values of the input and inout
argument expressions to their ports.
When the task completes, the simulator assigns the values of the output and inout ports to their lvalue
expression arguments (an lvalue expression may appear on the left side of an assignment, you can assign
a value to an lvalue expression) If the task never completes for example, in a loop that loops forever, it
never returns and its calling procedure cannot continue. However, if the task consumes time,
procedures other than the calling procedure may execute.
17-16
Synthesis
The synthesis standard supports tasks that have
no timing controls.
17-17
17-18
Disabling Tasks
You can disable a task (force it to exit):
In this example, detection of an
interrupt disables any currently
running cpu_driver task
Tip
You can also disable named blocks in the
same manner.
module test_busif;
...
always #50 clk = !clk;
initial
begin: stimulus
neg_clocks(5);
cpu_driver(8'h00);
cpu_driver(8'haa);
...
end
...
always @(posedge interrupt)
begin
disable cpu_driver;
service_interrupt;
end
endmodule
17-19
Disabling Tasks
A Verilog task can consume simulation time, by using event controls and wait statements.
Code that calls the task cannot continue execution until the task completes.
Some other executing process can disable the task, thus allowing the calling process to continue.
17-20
data_valid
data_read
data read
data read
task cpu_driver_bad;
input read;
input [7:0] write_data;
begin
arguments upon invocation
#30 date_valid = 1'b1;
wait(read == 1'b1);
Output argument values assigned to
#20 cpu_data =
variables upon return
write_data;
wait(read == 1'b0);
#20 cpu_data = 8'hzz;
Error
data_valid = 1'b0;
Task never completes changes in read not detected
end
endtask
cpu_driver_bad(data_read, 8'hff);
17-21
17-22
17-23
17-24
// Returns 1
function integer f;
input integer in;
if (in <= 1)
f = in;
else
f = f(in-1) * in;
endfunction
// Returns factorial
function automatic integer f;
input integer in;
if (in <= 1)
f = in;
else
f = f(in-1) * in;
endfunction
17-25
17-26
module test_local_vars;
reg data_read, data_valid;
reg [7:0] cpu_data;
data_valid
task cpu_driver;
input [7:0] write_data;
begin
#5 data_valid = 1;
wait(data_read == 1);
#20 cpu_data = write_data;
wait(data_read == 0);
#20 cpu_data = 8'hzz;
data_valid = 0;
end
endtask
initial
begin
cpu_driver(8'hff);
cpu_driver(8'h00);
...
write_data
data_read
data read
module variable
read inside task
17-27
17-28
cpu_data
task neg_clocks;
input integer number;
repeat(number)
@(negedge clk);
endtask
data_valid
write_data
data_read
data read
// test harness
module test_busif;
task cpu_driver;
input [7:0] write_data;
begin
#5 data_valid = 1b1;
wait(data_read == 1b1);
#20 cpu_data = write_data;
wait(data_read == 1b0);
#20 cpu_data = 8'hzz;
data_valid = 1b0;
end
endtask
reg clk = 0;
always #50 clk = ~clk;
// instantiate mytasks
mytasks m1 ();
// creating stimulus
initial begin
m1.neg_clocks(6);
m1.cpu_driver(8h00);
...
$finish;
end
endmodule
hierarchical paths
endmodule
Functions and Tasks (VFE9)
17-29
17-30
Review Questions
1. Write a function that adds two four-bit unsigned numbers and returns an unsigned
five-bit result, and write a call to the function.
2. Which type of subprogram can contain event control?
3. Can logic synthesis infer sequential logic from statements in a function?
4. Write the count_from task to produce the following stimulus. The function
of the task is to load a_bus with a value (passed as a parameter) and to increment
a_bus for 3 clock cycles. The task also controls the select signal.
start
finish
clock
module testbench;
reg clk;
reg [3:0] a_bus;
reg select;
initial clk = 1b0;
always #50 clk = !clk;
select
a_bus[3:0]
initial
begin
count_from(4d4);
count_from(4d2);
end
endmodule
17-31
Review
17-32
System Control
VSV2
18-1
Notes
18-2
Aims
Describe some of the compiler directives, system tasks and system functions
available in Verilog
Topics
Compiler directives (indicated with accent grave )
System tasks and functions (indicated with $)
Text output in Verilog
Accessing simulation time
Simulation system tasks
File I/O capabilities
18-3
18-4
Important
timescale must appear outside of the module
timescale 10ns/1ns
module test;
localparam real tdelay = 2.55;
inital
begin
#tdelay; // 26 ns delay
...
endmodule
timescale 1ns/100ps
module first (...);
...
#10; // 10 ns delay
...
endmodule
timescale 1ps/100fs
module second (...);
...
#100; // 100 ps delay
...
endmodule
18-5
18-6
localparam INITIAL_CLOCK = 1;
localparam integer MAX_CYCLES = 100;
localparam time PERIOD = 10;
`include "globals.txt"
initial
begin : CLK
time END_TIME;
END_TIME = PERIOD * MAX_CYCLES;
while ($time < END_TIME)
begin
CLK = INITIAL_CLOCK;
#(PERIOD/2);
CLK = !INITIAL_CLOCK;
#(PERIOD/2);
end
$display($time,"Test Finished");
$stop;
end
18-7
Include global or commonly used definitions (e.g. define directives) stored in a separate file.
Include tasks without repeating the code within multiple module definitions, to simplify
maintenance of the code.
18-8
18-9
Define global design constants, like delays and widths of vectors, in a single place. The advantage
is that to change the configuration, you only need to make changes in one place.
You can place a list of `define directives in a single file that is compiled with the other design files
and included as required with the include directive
To remove the definition of a macro use:
undef macro_name
Important
A mistake in the text macro gives you an error at the point where the text macro is used.
18-10
18-11
18-12
$value$plusargs("prefix%format",variable)
Formatters are: %b %o %d %h %e %f %g %s
Returns 0 if no command-line plusarg starts with the provided prefix
Returns 1 if a command-line plusarg starts with the provided prefix
Places scanned command-line plusarg suffix in variable
ncverilog +"stimulus=test2" ...
if ($value$plusargs("stimulus=test%d",testnum)) ...
18-13
18-14
module disp_wr;
reg [7:0] var1, var2, var3, var4;
initial
begin
var1 = 8'h0F;
// 15
var2 = 8'b01010101;
// 85
var3 = 8'b11001100;
// 204
$display (var1,var2,var3);
$displayb (var1,, var2,, var3);
$displayh (var1);
$write (var1);
$writeh (" var2(hex) is ", var2);
$writeo ("\n var3(oct) is ", var3);
end
endmodule
$displayo
$displayh
15 85204
0f
15 var2(hex) is 55
var3(oct) is 314
System Control (VSV2)
18-15
\t
\n
\\
\"
%%
tab
new line
backslash
double quote
percentage
18-16
You can distribute them among the task arguments (subject to rules)
They are matched to argument values in order one to one match
It is an error to have more format specifiers than values to format
Extra unformatted values simply use the default format
module disp_wr_fmt;
reg [7:0] var1, var2,
00001111
var3, var4;
var2 binary: 01010101
hex:
initial
begin
0f
55
cc
var1 = 8'h0F;
var2 = 8'b01010101;
var3 is hex cc octal 314
var3 = 8'b11001100;
$display ("%b", var1);
$display ("var2 binary: %b \t", var2, "\t hex: %h", var2);
$display ("%h \t %h \t %h", var1, var2, var3);
$write ("var3 is hex %h \t octal %o", var3, var3);
end
endmodule
55
18-17
%o
%O
octal
%d
%d
decimal
%b
%B
binary
%c
%C
ASCII
%s
%S
string
%v
%V
strength
%m
%M
module
%t
%T
time
18-18
display
strobe
scheduled
executed
$strobe
executed
module strobe_non;
reg [31:0] data;
initial
begin
data <= 10;
$strobe ("strobe ", data);
$display("display", data);
data <= 20;
#10;
data <= 30;
end
endmodule
10
20
display
strobe
x
20
18-19
18-20
$stime
returns time as a 32-bit integer
$realtime
returns time as a real number
module timeop;
reg [5:0] data;
initial
begin
#10;
data = 6d20;
$display ($time,, data);
#10.4;
data = 6d30;
$write ("time: %0d", $time);
$write (" real time: ", $realtime);
$write (" data: ", data);
end
endmodule
10 20
time: 20 real time: 20.4 data: 30
18-21
18-22
module monitor_time;
reg [7:0] var1, var2, var3, var4;
initial
begin
$monitor("%0d \t %h %h %h",
$time, var1, var2, var3);
var1 = 8'h0F;
var2 = 8'b0101_0101;
var3 = 8'b1100_1100;
#5;
var1 = 8'h80;
#8;
var2 = 8'h66;
var3 = 8'h77;
#4;
var1 = 8'h55;
end
endmodule
0
5
13
17
0f
80
80
55
55
55
66
66
cc
cc
77
77
18-23
18-24
`timescale 1 ns / 10 ps
module time_fmt;
wire o1;
reg in1;
assign #9.53 o1 = ~in1;
initial
begin
$display("time \t realtime \t in1 \t o1");
$timeformat(-9, 2, " ns", 10);
$monitor("%0d \t %t \t %b \t %b",
$time, $realtime, in1, o1);
in1 = 0;
#10;
in1 = 1;
#10;
end
endmodule
time
0
10
10
20
realtime
0.00 ns
9.53 ns
10.00 ns
19.53 ns
in1
0
0
1
1
o1
x
1
1
0
18-25
Formatting Time
You can use the $timeformat system task to specify how the %t formatter displays time values.
The syntax of the $timeformat system task is:
$timeformat(<unit>, <precision>, <suffix>, <min_width>);
Parameter
Definition
unit
Integer between 0 (s) and -15 (fs), indicating the time scale
precision
suffix
min_width
Important
The Verilog standard states that the $timeformat applies to all %t formats specified in all
modules that follow in the source description until another $timeformat system task is invoked.
The $realtime function returns the time as a real number scaled to the timescale of the calling
module.
The $stime system function returns the time as a 32-bit integer scaled to the timescale of the calling
module and then rounded to an integer value.
The $time system function returns the time as a 64-bit integer scaled to the timescale of the calling
module and then rounded to an integer value.
Verilog Application Workshop
18-26
initial
begin
wait (empty);
$display("Data buffer empty");
$display("TEST COMPLETE");
$finish;
end
18-27
18-28
ifdef SAVE
initial $save("tb_sim.db");
always #5000 $incsave("tb_inc.db");
endif
ifdef RESTART
initial $restart("tb_inc.db");
endif
verilog +define+SAVE
verilog +define+RESTART
Note: The Cadence NC-Verilog simulator
does not support these system tasks.
Instead use the save and restart
interactive commands.
18-29
18-30
18-31
18-32
18-33
18-34
...
integer data_chan, warn_chan;
reg [7:0] var1, var2;
initial
begin
data_chan = $fopen("data.txt");
if (!data_chan) $finish;
warn_chan = $fopen("warn.txt");
if (!warn_chan) $finish;
$fmonitor (data_chan, var1, var2);
...
$fclose(data_chan);
end
18-35
18-36
18-37
18-38
$readmemh (hex)
vect.txt
00000000
00000001
00000010
00000011
module readfile;
reg [7:0] array4 [0:3];
reg [7:0] array7 [6:0];
start end
initial
begin
$readmemb("vect.txt", array4);
$readmemb("vect.txt", array7, 2, 5);
end
...
endmodule
array4
3: 00000011
2: 00000010
1: 00000001
0: 00000000
array7
6: xxxxxxxx
5: 00000011
4: 00000010
3: 00000001
2: 00000000
1: xxxxxxxx
0: xxxxxxxx
System Control (VSV2)
18-39
array is the name of the array into which the data is to be loaded
Optional start and finish addresses determine the addresses of the array to be loaded. The start
value becomes the starting address and the finish value becomes the end address. If you do not
specify start and end addresses as either system task arguments or in the data file, $readmemb/h
reads from the left index of the memory array (as declared) toward the right index.
Note: Cadence simulators in this situation read from the lowest address toward the highest
address.
The simulator loads data numbers from the file into words in memory. You should ensure that the
numbers are the width of the memory word.
The simulator will report a warning if there are too many or too few data items in the file.
18-40
0000_0000
0110_0001 0011_0010
// comments are ignored
// addresses 3-255 not defined
@100 // hex
1111_1100
/* addresses 257-1022 not defined */
@3FF
1110_0010
7 .... 0
3FF: 11100010
...
reg [7:0] mem1Kx8 [0:1023];
...
$readmemb("format.txt", mem1Kx8);
...
100: 11111100
00110010
01100001
000: 00000000
18-41
If the file contains address values, then any address values provided with the $readmemb/h call must
lie within the range of provided addresses.
18-42
Note: The standard does not address MCD support of the new routines.
18-43
// close a file
errcode
char
= $fgetc ( fd ) ;
// get a character
errcode
= $fgets ( str, fd ) ;
// get a string
$fflush ( [ fd ] ) ;
fd
// open a file
errcode
= $fread ( reg, fd ) ;
errcode
errcode
errcode
position
= $ftell ( fd ) ;
errcode
errcode
= $rewind ( fd ) ;
length
= $ungetc ( c, fd ) ;
18-44
Review
1. Which two system tasks display the steady state values of the argument list?
2. Which is better to use when creating test vectors? $display or $strobe?
3. How would you cater with opening 35 files?
4. What is the output of the following piece of code?
module test;
reg [3:0] a;
initial
begin
a <= 11;
a = 4b0011;
$display("display", a);
$strobeb("strobe", a);
end
endmodule
18-45
Review
18-46
18-47
18-48
19-1
Notes
19-2
Aims
Learn coding styles and methods that are commonly used to create a test bench
Topics
Simulation behavior
Testbench organization
Stimulus
Concurrent blocks
event
fork - join
Vector capture and playback
Clock generation
19-3
19-4
Design Organization
vendor
libraries
include
files
simulator
design
files
compilation
data
clk
read
write
file input:
stimulus,
simulation
expect patterns
file output:
stimulus, results
patterns
19-5
Design Organization
Dashed lines indicate that compilation can check for the existence and readability of input files, as well
as the permission to create output files.
19-6
compilation
Procedure
Procedure
initialization
Procedure
Procedure
Procedure
Procedure
simulation
Procedure
z
Procedure
19-7
19-8
Testbench Organization
Simple testbench
Just sends data to design
Few processes
No interaction
Simple Testbench
Design
to verify
stimulus
Sophisticated testbench
Models environment
around design
Talks to design
Self-checking
Sophisticated Testbench
stimulus
Design
to verify
verify
results
19-9
Testbench Organization
A simple testbench applies vectors to the design under test and the user manually verifies the results.
A sophisticated testbench is self-checking, it automatically verifies the results.
Placing stimulus in a separate level of hierarchy is useful if you want to have multiple versions of the
stimulus for different situations.
You could also have a separate hierarchical block monitoring the results.
Real projects tend to use some form of intelligent or smart testbench that reacts to the response from
the DUT (e.g. bus cycles, handshake mechanisms, etc.)
Sophistication of your testbench is only limited by your time and imagination...
19-10
In Line Stimulus
You need only specify the variable value
transitions.
You can easily specify complex timing
relationships.
This type of testbench can become very
large for complex tests.
module inline_tb;
reg [7:0] data_bus, addr;
reg reset;
// instance of DUT
initial
begin
reset = 1b0;
data_bus = 8h00;
#5 reset = 1b1;
#15 reset = 1b0;
#10 data_bus = 8h45;
#15 addr = 8hf0;
#40 data_bus = 8h0f;
end
endmodule
19-11
In-Line Stimulus
When first developing a test, you might simply write a sequence of stimulus over time in a single process.
You describe the stimulus using a series of signal assignments separated by wait statements.
Although having separate delays between each signal assignment allows you to describe complex timing
relationships, this is an inefficient way to write large amount of stimulus.
19-12
Compact description
Regular values
Important
Do not forget to insert a timing control
in the loop!
module loop_tb;
reg clk;
reg [7:0] stimulus;
integer i;
// instance of DUT
// clock generation
initial
begin
for (i=0; i<=255; i=i+1)
@(negedge clk)
stimulus = i;
end
endmodule
19-13
19-14
Irregular values
module array_tb;
// stimulus word and array
reg [7:0] data_bus, stim_array[0:15];
integer i;
// instance of dut
// define clock
initial begin
// load array with values
stim_array[0] = 8h2f;
stim_array[1] = 8h7a;
...
stim_array[15] = 8h0b;
// apply stimulus from array
for (i = 0; i <= 15; i = i + 1)
@(negedge clk)
data_bus = stim_array[i];
end
endmodule
19-15
19-16
module file_array_tb;
// stimulus word and array
reg [7:0] data_bus, stim_array[0:15];
integer i;
// instance of dut
// define clock
initial begin
// load array with values
$readmemb("stimulus.txt",stim_array);
// apply stimulus from array
for (i = 0; i <= 15; i = i + 1)
@(negedge clk)
data_bus <= stim_array[i];
end
endmodule
19-17
19-18
module random_tb;
reg [3:0] avec;
reg [7:0] bvec;
...
initial
begin
avec = $random;
bvec = $random;
...
end
endmodule
$dist_chi_square
$dist_erlang
$dist_exponential
$dist_normal
$dist_poisson
$dist_t
$dist_uniform
Using a Verilog Test Bench (VTB4)
19-19
Random Stimulus
You can use the $random system function to easily create random data patterns.
Random data may find errors in a design that more predictable data does not.
The function returns a 32-bit random value that you can assigned to any size vector (extra bits are
truncated). For random numbers wider than 32 bits, you can concatenate multiple calls to $random.
You can provide a seed value to produce a repeatable sequence of pseudo-random numbers.
Note: Simulators compliant with the 1995 Verilog standard may produce different random number
sequences. Simulators compliant with the 2001 Verilog standard must produce identical
random number sequences. You must refer to the vendors documentation to determine whether
these algorithms are different and how to select the standard algorithm.
19-20
module forkfoin_tb;
reg [7:0] data, addr;
// instance of DUT
initial
fork
data = 8h00;
#10 data = 8h45;
#15 addr = 8hf0;
#30 data = 8h0f;
join
Synthesis
The synthesis standard does not support the
fork...join construct.
endmodule
fork
#10
#15
data= data= addr=
8'h00; 8'h45; 8'hf0;
#30
data=
8'h0f;
join
Using a Verilog Test Bench (VTB4)
19-21
19-22
module concurrent_tb;
reg [7:0] data;
// instance of DUT
initial
fork
#10 data =
#20 repeat
#10 data
#25 repeat
#20 data
#99 data =
join
8h45;
(7)
= data + 1;
(5)
= data << 1;
8h0f;
endmodule
19-23
19-24
Synthesis
The synthesis standard does not support
the event construct
module event_example (
input [3:0] in1, in2,
output [4:0] o1
);
event e1; // declare event
always @ (in1 or in2)
begin
o1 = in1 + in2;
-> e1; // notify event
end
always @(e1) // use event
$displayb(o1);
endmodule
19-25
19-26
module testbench;
reg [40*8:1] message;
task reset;
begin
message = "reset";
@(negedge clock);
reset <= 1b1;
@(negedge clock);
reset <= 1b0;
end
endtask
task test1;
input [3:0] a_vec,b_vec;
output [7:0] d_vec;
begin
message = "test one";
...
end
endtask
always @ (message)
$display("%s",message);
initial begin
reset;
test1(a,b,out);
end
endmodule
Using a Verilog Test Bench (VTB4)
19-27
19-28
Hierarchical Variables
You can access out-of-module
variables using a hierarchical
pathname.
This is useful in testbenches.
Pathnames can be relative or absolute.
This example has a relative pathname.
The equivalent absolute pathname
might be:
module mux (
input a, b, sel, clk,
output reg f );
wire g = sel ? a : b;
always @ (posedge clk)
f <= g;
endmodule
module tb;
...
mux uut (.a (1b0), .b (bnet), .sel
(select), .clk (clk),.f (f));
wait (tb.uut.g);
initial
begin
wait (uut.g);
$display("mux has a logic one");
end
...
endmodule
19-29
Hierarchical Variables
This example uses a relative pathname from the accessing module to the hierarchical variable. Relative
pathnames can only go down the hierarchy and not up the hierarchy. You can alternatively use an
absolute pathname starting from the hierarchy root. Absolute pathnames can access any net and
persistent variable. You cannot access nonpersistent variables such as those declared in Verilog-2001
automatic tasks and functions.
19-30
Vector Capture
You can capture the
stimulus and response at
the pins of your DUT.
You can play these vectors
back against the DUT
using only a
stripped-down test
environment.
You can provide these test
vectors to the device
manufacturer.
module capture_tb;
reg [7:0] stimulus, response;
integer stimfile, respfile;
// instance of dut
initial
begin
stimfile = $fopen("stimulus.txt");
respfile = $fopen("results.txt");
fork
if (stimfile != 0 )
forever #(period)
$fstrobeb (stimfile, "%b", stimulus);
if (respfile != 0 )
#(period/2) forever #(period)
$fstrobeb (respfile, "%b", response);
join
end
endmodule
19-31
Vector Capture
19-32
Vector Playback
You can play back vectors
read from a file
module playback_tb;
localparam integer num_vecs = 256;
reg [7:0] data_bus;
reg [7:0] stim [0:num_vecs-1];
integer i;
//instance of dut
00111000
00111001
00111010
00111100
00110000
00101000
00011000
01111000
10111000
...
initial
begin
// load stimuli
$readmemb("vec.txt", stim);
// replay vectors
for (i=0; i<num_vecs; i=i+1)
#50 data_bus = stim[i];
end
vec.txt
endmodule
19-33
Vector Playback
Using vector files for input and output of your simulation means:
19-34
Creating Clocks
Clock generator examples
always begin // simple
#(period/2) clk = 0;
#(period/2) clk = 1;
end
initial begin // delayed
clk = 0;
#(period)
forever
#(period/2) clk = ~clk;
end
initial begin // irregular
#(period + 1) clk = 1;
#(period/2 - 1)
forever begin
#(period/4) clk = 0;
#(3 * period/4) clk = 1;
end
end
19-35
Creating Clocks
There are many ways to model a clock oscillator. Here are a few examples.
19-36
Use of Tasks
Using tasks in a testbench
encapsulates repeated operations,
making your code more efficient.
data
clk
data_valid
module bus_ctrl_tb
reg [7:0] data;
reg data_valid;
wire data_read;
task cpu_driver;
input [7:0] data_in;
begin
#30 data_valid = 1;
wait (data_read == 1);
#20 data = data_in;
wait (data_read == 0);
#20 data = 8hzz;
#30 data_valid == 0;
end
endtask
data_read
// cpu instantiation
initial
begin
cpu_driver (8b0000_0000);
cpu_driver (8b1010_1010);
cpu_driver (8b0101_0101);
end
endmodule
19-37
Use of Tasks
19-38
Summary
Several Verilog constructs are useful in testbench construction:
Concurrent blocks and fork..join statements
Include files
19-39
Summary
19-40
20-1
Notes
20-2
Aims
To look at testbenches for verifying complex designs
Topics
Pseudo-code based testbenches
Simulation output
20-3
20-4
Testbench
Design to
Verify
user defined
instructions
20-5
20-6
Assemble and
transmit the
packets
Data
generator
Header
generator
Data packet
transmission
8-bit
header
16-bit data
packet
CRC
generator
Data
RAM
Header
RAM
Clock
generator
Check
Instruction
decode
Instructions
8-bit
CRC
RX
Protocol
Engine
CRC
generator
UUT
Testbench broken
into 5 tasks
(external file)
20-7
20-8
Generate a CRC
for the packet
20-9
20-10
Instruction Decode
Testbench passes instruction
to decode task.
Decode task assembles and
returns packet.
Utilizes other tasks
20-11
Instruction Decode
Text macro substitution can sometimes make your code more readable.
20-12
The Testbench
module datacomms_tb;
reg xmit, clk, ce_1, ce_2, wrb;
wire [31:0] xmit_packet;
reg [15:0] instr_mem [255:0];
integer i;
`include "tasks.v"
ff_02
6e_01
00_03
00_04
00_00
...
...
55_02
c2_01
00_03
00_04
00_00
//
//
//
//
//
get_hdr
get_data
crc_gen
xmit_pkt
nop
//
//
//
//
//
get_hdr
get_data
crc_gen
xmit_pkt
nop
20-13
The Testbench
The testbench is reduced to a few simple instructions.
The operations performed are complex but offloaded to individual tasks.
You can use such subprograms to make your testbench more readable.
20-14
Emulator?
The processor model could run a low level set of instructions, such as a
firmware-based power-up self-test.
Hardware/software co-verification tools are available, allowing
interactive debug of Verilog and software.
Testbench
Design to
Verify
user defined
instructions
20-15
20-16
Testbench
Design to
Verify
Test Data
Errors &
Warnings
Visualization
Results for
comparison
and analysis
Manufacturing
test vectors
20-17
20-18
Visualized Output
Analyzing binary data for errors can be difficult.
Graphical display of data may aid the debug efforts.
Design to
Testbench
Verify
Test Data
####
#
#
#
#
#
#
#
#
####
Visualization
#
#
#
#
#
#
#
#
####
20-19
Visualized Output
You can sometimes better analyze binary output if you can somehow visualize it.
In the Alarm Clock labs, it is difficult to verify by looking at the binary output data that the correct
segments of the seven-segment display are active. You can alternatively visualize the output by
generating output text files from your simulation. You can represent the seven-segment display as a
two-dimensional array of space and '#' characters set in a seven-segment pattern. You can output this
two-dimensional character array each time the display signals change value, and monitor the file content
in a shell window.
20-20
CHARACTER_WIDTH
CHARS_PER_DIGIT
DIGIT_WIDTH
NUMBER_OF_DIGITS
LINE_WIDTH
NUMBER_OF_LINES
MESSAGE_WIDTH
=
=
=
=
=
=
=
8 ;
10 ;
CHARS_PER_DIGIT * CHARACTER_WIDTH ;
4 ;
DIGIT_WIDTH*NUMBER_OF_DIGITS + CHARACTER_WIDTH*1 ;
11 ;
LINE_WIDTH * NUMBER_OF_LINES ;
####
always @ ( DISP_7SEG )
#
#
begin : DISPLAY
#
#
integer mcd ;
#
#
integer line ;
#
#
integer digit ;
reg [2:0] code ; // five things a digit line can look like
####
reg [1:DIGIT_WIDTH] digit_string ;
#
#
reg [1:LINE_WIDTH] line_string ;
#
#
reg [1:MESSAGE_WIDTH] message_string ;
#
#
for ( line=1; line<=NUMBER_OF_LINES; line=line+1 )
#
#
begin
####
// digit 0 is RIGHTMOST digit
for ( digit=0; digit<=(NUMBER_OF_DIGITS-1); digit=digit+1 )
begin
case ( line )
1:
code = { DISP_7SEG[digit*7+0],
1'b0,
1'b0 } ;
2,3,4,5:
code = {
1'b0, DISP_7SEG[digit*7+5], DISP_7SEG[digit*7+1] } ;
6:
code = { DISP_7SEG[digit*7+6],
1'b0,
1'b0 } ;
7,8,9,10:
code = {
1'b0, DISP_7SEG[digit*7+4], DISP_7SEG[digit*7+2] } ;
11:
code = { DISP_7SEG[digit*7+3],
1'b0,
1'b0 } ;
endcase
...
20-21
20-22
####
#
#
#
#
#
#
#
#
####
#
#
#
#
#
#
#
#
####
20-23
20-24
Testbench
Design to
Verify
Results for
comparison
and analysis
Known-good
results
20-25
A truly sophisticated testbench would check the response of the design under test throughout the
simulation, and as soon as it detected an error, output detailed data to help the debugging effort.
20-26
Design to
Testbench
Verify
Test Data
op1
op2
Manufacturing
test vectors
clk
strobe
Strobe Here
20-27
20-28
Summary
Input methods
Pseudo-code
Processor code
Output methods
Errors and warnings
Visualization output
Results for comparison and analysis
ASIC manufacturing test vectors
20-29
Summary
20-30
Structural Modeling
VSM2
21-1
Notes
21-2
Aims
Learn about the full capabilities of Verilog for structural and gate level
modeling.
Topics
Built-in primitives
Module instantiation options
Strength modeling
21-3
Verilog Primitives
21-4
Structural Modeling
A purely structural model contains only instantiated modules and primitives and their
interconnections. Examples include:
Schematic capture
Post-synthesis netlist
sela
sel
out
nsel
selb
module mux (
input a, b, sel,
output out
);
wire nsel, sela, selb;
IV U32 ( .A(sel), .Z(nsel) );
AN2 U33 ( .A(a), .B(nsel), .Z(sela) );
AN2 U34 ( .A(b), .B( sel), .Z(selb) );
OR2 U35 ( .A(sela), .B(selb), .Z(out) );
endmodule
Structural Modeling (VSM2)
21-5
Structural Modeling
A structural model is equivalent to a schematic. You instantiate and connect predefined components to
create a more complex component.
21-6
Verilog Primitives
Verilog primitives include
pre-defined basic logic functions.
You instantiate and connect them
almost like hierarchical modules:
Primitives do not require an
instance name
sela
sel
out
nsel
Logical And
Logical Or
Inverter
Buffer
Logical Exclusive Or
Logical And Inverted
Logical Or Inverted
Logical Exclusive Or Inverted
module mux (
input a, b, sel,
output out
);
wire nsel, sela, selb;
not (nsel, sel);
and (selb, sel, b);
and (sela, nsel, a);
or (out, sela, selb);
endmodule
selb
21-7
Verilog Primitives
Verilog provides predefined primitives for basic logical functions.
Most ASIC and FPGA component libraries utilize primitives.
21-8
in1
out
in1
in2
in3
in1
in2
in3
in4
out
out
21-9
21-10
Conditional Primitives
Conditional primitives have three terminals: output, input, and enable.
When disabled, outputs are at high impedance.
Verilog has four types of conditional primitives:
Primitive Name
Functionality
bufif1
bufif0
notif1
notif0
21-11
Conditional Primitives
21-12
bufif0
data
data
out
enable
out
enable
bufif0 (out, data, enable)
enable
enable
data
bufif1
bufif0
data
Note: Verilog uses the symbols L and H to represent partially unknown logic values.
21-13
21-14
Primitive Instantiation
Important
For primitives the # character specifies a delay.
21-15
Primitive Instantiation
You must specify all the outputs of the primitive before specifying its inputs.
It is optional to specify an instance name for a primitive instantiation.
You can specify an optional delay to define the intrinsic delay of the primitive. In other words, a signal
takes the specified delay time before a change in input is reflected at the output. Without the delay
specification, the primitive operates at zero delay.
You can specify optional signal strengths to any signals that a primitive drives.
If you need to specify both strength and delay, the strength value comes first.
In addition to built-in primitives, you can create User Defined Primitives (UDPs). UDPs are covered in
the appendix, User Defined Primitives.
21-16
Module Instantiation
A module instance must have an instance name.
Positional mapping: Port map order follows port declaration order
21-17
Module Instantiation
A module instance must have an instance name.
For positional port mapping, the port map order follows the port declaration order.
For named port mapping, the port map order is independent of the port declaration order. You specify
the port name followed by the local net or register that connects to that port:
.port_name(signal_name)
You can leave a port unconnected in a module instantiation. Most simulators issue an associated warning
message.
21-18
Array of Instances
You can instantiate an array of instances.
For an instance array, an instance name is required (even for primitives)
module driver1 (
input
en,
input [2:0] in,
output [2:0] out
);
// Separate primitive instantiations
bufif0 u2 (out[2], in[2], en);
bufif0 u1 (out[1], in[1], en);
bufif0 u0 (out[0], in[0], en);
endmodule
module driver2 (
input
en,
input [2:0] in,
output [2:0] out
);
// Array of primitive instantiations
bufif0 u[2:0] (out[2], in[2], en);
endmodule
21-19
Array of Instances
The syntax for an instance array is:
21-20
21-21
The example illustrates an array of 1 instance of module comp, and an illegal attempt to
specify an array of instances of module comp on more than one line using the same instance
name m1
21-22
generate
genvar var;
for (var=const_expr;
const_expr; var=const_expr)
begin: blockname
gen_item
end
endgenerate
generate
if (const_expr)
gen_item
else
gen_item
endgenerate
generate
case (const_expr)
const_expr: gen_item
default
: gen_item
endcase
endgenerate
21-23
21-24
Supply
Strong
Pull
Large
Weak
Medium
Small
High Z
Level
Type
%v formats
7
6
5
4
3
2
1
0
Drive
Drive (default)
Drive
Capacitive
Drive
Capacitive
Capacitive
Impedance
Su0
St0
Pu0
La0
We0
Me0
Sm0
Hi0
Su1
St1
Pu1
La1
We1
Me1
Sm1
Hi1
Specification
supply0, supply1
strong0, strong1
pull0, pull1
large
weak0, weak1
medium
small
highz0, highz1
Structural Modeling (VSM2)
21-25
// no instance name
The capacitive strengths (large, medium, small) apply only to nets of type trireg and to tran primitives.
21-26
Resolving Strengths
The highest strength level overrides all other drivers.
strong1, pull0
a
out
b
as output
bs output
out
strong1
pull0
pull0
strong1
pull0
HiZ
HiZ
strong0
weak1
strong0
weak1
HiZ
weak1
HiZ
strongX
pull0
strong0
strong1
pull0
weak1
HiZ
weak1, strong0
21-27
Resolving Strengths
21-28
Review
1. What is structural modeling in Verilog?
2. What are the two ways that module ports can be connected? Which is safer?
3. What does an array of instances do?
4. When are instance names optional?
21-29
Review
21-30
Modeling Delay
VMD2
22-1
Notes
22-2
Aims
Understand how to model simple delays for simulations and gate level models
Topics
Lumped delays
Distributed delays
Path delays
Specify timing blocks
Intra-assignment delays
22-3
A path across a module that connects a module input (an input or an inout port)
with a module output (an output or an inout port)
Path Delay
22-4
a
b
n1
net1
o1
2
Distribute the delay
across each gate.
out
22-5
You can lump the delay onto the last gate driving the output. Lumped delay is:
Easy to model
Accurate only in simple cases
22-6
Lumped Delay
Lumped delays place all the delay on the last gate.
This is simple to implement...
a
b
#3
out
c
`timescale 1ns/1ns
module noror (
input a, b, c,
output out
);
nor n1 (net1, a, b);
or #3 o1 (out, c, net1);
endmodule
22-7
Lumped Delay
You can model propagation delay across devices by lumping the delay onto the last gate in a model. This
is an easy method of modeling delay. However, there is a loss of control multiple paths to a single
output share the delay. If you use lumped delay, it is best to use the worst-case delay (usually the largest
value).
In the example above the delay that defines the path from b to out is also used for the paths from a to
out and from c to out.
22-8
Distributed Delays
Distributed delays divide the delay over more than one gate.
This allows different delays for different paths
a
#2
b
#1
out
c
`timescale 1ns/1ns
module noror (
input a, b, c,
output out
);
nor #2 n1 (net1, a, b);
or #1 o1 (out, c, net1);
endmodule
Modeling Delay (VMD2)
22-9
Distributed Delays
Distributed delays allow you to have different delays for different paths to the same output. This example
splits delay among multiple gates. The delay from a to out and from b to out is 2 + 1. Distributing
delays on a real structural model can quickly become complex. Note too, that it is still not possible to
represent different delays from different pins of the same primitive.
22-10
`timescale 1ns/1ns
module noror (
input a, b, c,
output out
);
nor n1 (net1, a, b);
or o1 (out, c, net1);
a
b
c
specify
(a => out) = 2;
(b => out) = 3;
(c => out) = 1;
endspecify
n1
net1
o1
out
path delays
a->out is 2
b->out is 3
c->out is 1
endmodule
22-11
22-12
// rise, fall
// rise, fall, turn-off
// rise, fall
// rise, fall, turn-off
You can specify minimum, typical, and maximum values for each delay
or #(3.2:4.0:6.3) o1(out, in1, in2); // min:typ:max
not #(1:2:3, 2:3:5) (o,in);
// min:typ:max for rise, fall
specify
// min:typ:max for rise, fall, and turnoff
(b => y) = (2:3:4, 3:4:6, 4:5:8);
endspecify
22-13
You can specify minimum, typical, and maximum values for each delay.
22-14
`timescale 1ns/1ns
module noror (
input a, b, c,
output out
);
nor n1 (net1, a, b);
or o1 (out, c, net1);
specify
(a => out) = 2;
(b => out) = 3;
(c => out) = 1;
endspecify
endmodule
22-15
You declare and use a module parameter (parameter) only inside a module and outside a
specify block.
You declare and use a specify parameter (specparam) only inside a specify block.
Verilog-2001 permits declaration and use within a module.
Describe timing paths across the module and assign delays to those paths.
Describe timing checks to ensure that the timing constraints of the device are met.
Define the pulse filtering limits for the module or for particular paths across a module.
Note: Synthesis tools ignore all simulation timing. This is not how you specify timing constraints to
a synthesis tool.
22-16
q
output
bits
qb
2 paths
Bit-to-bit connections
Use => to define path
input
bits
qb
output
bits
4 paths
Bit-to-vector connections
Use *> to define path
(a, b *> q, qb) = 15;
is equivalent to:
is equivalent to
(a
(b
(a
(b
(a => q) = 15;
(b => qb) = 15;
=>
=>
=>
=>
q) = 15;
q) = 15;
qb) = 15;
qb) = 15;
Modeling Delay (VMD2)
22-17
22-18
=
=
=
=
(5:6:7);
(5:7:8);
(4:5:7);
(5:7:9);
a
op
b
endmodule
Note: not an if statement no else is allowed.
22-19
22-20
module noror (
input a, b, c,
output op
);
specify
specparam aop = 2,
bop = 3,
cop = 1;
(a => op) = aop;
(b => op) = bop;
(c => op) = cop;
endspecify
parameter my_parameter =
my_specparam; // Verilog-2001
endmodule
specparam my_specparam =
my_parameter; // NO!
22-21
Specify Parameter
Can override values using defparam Can override values only using SDF annotation
Replicated with each module instance Not replicated with each module instance
Verilog-1995:
specify_item ::= specparam_declaration | ...
specparam_declaration ::= specparam list_of_specparam_assignments ;
list_of_specparam_assignments ::=
specparam_assignment { , specparam_assignment }
specparam_assignment ::= identifier = constant_expression | ...
Verilog-2001:
module_item ::= { attribute_instance } specparam_declaration | ...
specify_item ::= specparam_declaration | ...
specparam_declaration ::= specparam [ range ] list_of_specparam_assignments ;
list_of_specparam_assignments ::=
specparam_assignment { , specparam_assignment }
specparam_assignment ::= identifier = constant_mintypmax_expression | ...
22-22
Inertial delay mode: path delays smaller than intrinsic gate delay are swallowed
out
delay = 2 ns
Input Waveform
Note rejection of pulses that
are shorter than intrinsic delay.
Inertial out
Transport out
0 1 2 3 4 5 6 7 8 9 10 11 ...
time in ns
Note: Different simulators use default delay modes, and may require command-line options or
simulator-specific compiler directives to manipulate the delay mode.
Modeling Delay (VMD2)
22-23
22-24
pulsestyle_ondetect
specify
(inp => outp) = 5 ;
specparam
PATHPULSE$inp$outp = (2,4) ;
pulsestyle_onevent outp ;
endspecify
specify
(inp => outp) = 5 ;
specparam
PATHPULSE$inp$outp = (2,4) ;
pulsestyle_ondetect outp ;
endspecify
outp
outp
outp
(delayed)
outp
(delayed)
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
22-25
PATHPULSE$ = 3;
is the same as:
PATHPULSE$ = (3, 3);
Verilog-1995 uses the onevent method of pulse propagation. The simulator propagates an input pulse that
meets the reject limit but does not meet the error limit, with its value changed to the unknown state. The
output pulse appears with the expected delay.
Verilog-2001 gives you the option to select the ondetect method of pulse propagation. The output pulse
appears immediately upon detection of the too-short pulse width, thus more clearly indicating for debug
purposes the point at which the error is detected.
22-26
showcancelled
specify
(inp => outp) = (6,3) ;
showcancelled outp ;
endspecify
outp
outp
outp
(delayed)
outp onevent
(delayed)
0 1 2 3 4 5 6 7 8
ondetect
0 1 2 3 4 5 6 7 8
22-27
22-28
Intra-Assignment Delay
// model of flip flop with timing
reg [3:0] q;
always @ (posedge clock)
#5 q1 <= d; // simple delay
#20
#5
clock
d
q1
q2
22-29
Intra-Assignment Delay
The problem with the q1 variable is that it is assigned 5 time units after the rising edge of the clock. The
d input to the flip flop may change during this period after the rising edge of the clock.
The intra assignment delay more accurately models this by sampling the d input at the clock edge and
assigning q2 with the sampled version after 5 time units.
22-30
a <= #1 b;
sample schedule update continue
0
2
10
12
a=x
a=x
a=1
a=1
b=x
b=x
b=x
b=0
c=x
c=x
c=1
c=1
d=x
d=0
d=0
d=0
module delay_test;
reg a,b,c,d;
initial
begin
a = #10 1b1;
b = #2 1b0;
end
initial
begin
c <= #10 1b1;
d <= #2 1b0;
end
endmodule
22-31
22-32
"log_file"
"mtm_spec"
22-33
22-34
Review
1. Model the following circuit:
1.2:1.6:1.8
a
1.1:1.6:1.7
b
c
0.6
2. Give the code for the following circuit. Do you see any problems with such a circuit
from (i) a simulation point of view (ii) a synthesis point of view? Can you fix them?
4b0001
4
4
22-35
Review
22-36
Timing Checks
TC1
23-1
Notes
23-2
Timing Checks
Objectives:
Following study of this section, you should be able to specify timing checks for your
module definitions.
23-3
Timing Checks
This section provides an overview of the Verilog timing checks as described by the year 2001 standard.
It provides sufficient technical detail to enable you to incorporate the timing checks into your module
definitions.
23-4
Overview
You use timing checks to verify that signals obey timing constraints.
Second signal does not change while first signal in specified state
Pulse width is sufficiently long
Period is sufficiently long
Time between two signals is sufficiently short
Time between two signals is sufficiently short (variation)
Time between two signals is sufficiently short (variation)
Timing Checks (TC1)
23-5
Overview
You use timing checks to verify that signals obey timing constraints. All timing checks are variations of
the same theme: the simulator notes the simulation time of the reference event, and then at the data event
verifies that the time between the events is either sufficient or not too much.
You place the timing check within a specify block and provide arguments to specify the reference event,
data event, and time limit(s). Timing checks start with the ($) character, but are not system tasks. You
cannot place system tasks within a specify block.
The events are value transitions of port signals. You can further qualify the transitions with the posedge
or negedge keywords. Most timing checks also accept edge descriptors such as edge 01. You can
conditionalize the events using the &&& operator and a conditionalizing scalar expression. Some timing
checks alternatively accept conditionalizing expressions as a separate argument. Some timing checks
accept a negative time limit.
For each timing check, you can optionally provide the name of a reg that the simulator toggles each time
it violates the timing check. You can use this "notifier" to trigger procedural blocks containing your
response (if any) to the timing check violation. Almost all ASIC vendors use notifiers in their simulation
libraries to cause the output of the UDP modeling the synchronous device to transition to the X state.
Timing checks are of two main groups: with the first group, you verify that one signal is stable with
respect to another signal for some specified time window; with the second group, you verify that the time
interval between two transitions is either sufficient or not too much.
23-6
23-7
23-8
23-9
23-10
A setup violation (if both limits positive) is: data < clock <= data + limit
A hold violation (if both limits positive) is: clock <= data < clock + limit
data
setuphold
clk
$setuphold ( posedge clk, data, 6, 2 ) ;
data
setuphold
clk
$setuphold ( posedge clk, data, 9, -1,,,, data_dly ) ;
Timing Checks (TC1)
23-11
Permits one or the other limit (but not both) to be negative if the sum of these limits is greater than
zero by more than the simulation precision. The simulator adjusts the negative limit upward to
zero plus the simulation precision, adds the same amount to the other limit, and delays the
appropriate reference signal or data signal, so that it can perform the check using positive limits.
You can (and should) provide signal names for the delayed versions, and drive internal module
logic with the delayed versions, to enable correct functional operation of your design.
Permits you to conditionalize the stamptime (reference) event and/or checktime (data) event using
arguments separate from the event description.
Note that the exact start of the setup window and the exact end of the hold window are not part of the
violation region. A $setuphold check will report a violation for simultaneous clock and data if both limits
are positive. A $setuphold check cannot report a violation when both limits are zero.
23-12
23-13
23-14
A recovery violation (if both limits positive) is: control <= clock < control + limit
A removal violation (if both limits positive) is: clock < control <= clock + limit
rst_
recrem
clk
23-15
Permits one or the other limit (but not both) to be negative if the sum of these limits is greater than
zero by more than the simulation precision. The simulator adjusts the negative limit upward to
zero plus the simulation precision, adds the same amount to the other limit, and delays the
appropriate reference signal or data signal, so that it can perform the check using positive limits.
You can (and should) provide signal names for the delayed versions, and drive internal module
logic with the delayed versions, to enable correct functional operation of your design.
Permits you to conditionalize the stamptime (reference) event and/or checktime (data) event using
arguments separate from the event description.
Note that the exact start of the recovery window and the exact end of the removal window are part of the
violation region. A $recrem check will report a violation for simultaneous clock and control if both limits
are positive. A $recrem check cannot report a violation when both limits are zero.
23-16
23-17
23-18
Nochange Checks
$nochange ( reference_event , data_event , start_edge_offset , end_edge_offset [ ,
notify_reg ] ) ;
Data is stable while reference is at specified state
A violation is:
(reference leading edge - offset) < data < (reference trailing edge + offset)
clk
nochange
rst_
$nochange ( posedge clk, rst_, 0, 0 ) ;
23-19
Nochange Checks
The $nochange timing check reports a timing violation if the data event occurs during the specified level
of the reference signal. You can increase (with positive offsets) or decrease (with negative offsets) either
or both edges of that time window. Note that both endpoints of the time window are not part of the
violation region.
You can qualify the reference event with the posedge or negedge keywords, but not with the edge control
specifiers, for example not edge 01.
You can qualify the data event with the posedge or negedge keywords or the edge control specifiers.
You can conditionalize either or both events with the &&& operator and a scalar expression.
23-20
23-21
23-22
Skew Checks
$skew ( reference_event , data_event , timing_check_limit [ , notify_reg ] ) ;
Data event occurs sufficiently soon after reference event
Resets waiting period with each new reference event
23-23
Skew Checks
You can qualify either or both events with the posedge or negedge keywords or the edge control
specifiers.
You can conditionalize either or both events with the &&& operator and a scalar expression.
23-24
Skew Checks
$timeskew ( reference_event , data_event , timing_check_limit [ , [ notify_reg ] [ , [
event_based_flag ] [ , remain_active_flag ] ] ] ) ;
Report violation once at limit if data event did not occur
With event_based_flag: Report violation once if data event occurs after limit
23-25
Skew Checks
With the event_based_flag and remain_active_flag both set, the $timeskew check is identical to the
$skew check.
You can qualify either or both events with the posedge or negedge keywords or the edge control
specifiers.
You can conditionalize either or both events with the &&& operator and a scalar expression.
23-26
Example JKFF
primitive UDP_JKFF ( output
reg Q, input J, input K, input
CLK, input RSTN, input SETN,
input FLAG ) ;
table
// J K C R S F : s : out
? ? ? 0 ? ? : ? : 0 ;
? ? ? 1 0 ? : ? : 1 ;
? ? ? p 1 ? : ? : - ;
0 0 p 1 1 ? : ? : - ;
0 1 r 1 1 ? : ? : 0 ;
0 1 p 1 1 ? : 0 : - ;
1 0 r 1 1 ? : ? : 1 ;
1 0 p 1 1 ? : 1 : - ;
1 1 r 1 1 ? : 0 : 1 ;
1 1 r 1 1 ? : 1 : 0 ;
? ? n ? ? ? : ? : - ;
* ? ? ? ? ? : ? : - ;
? * ? ? ? ? : ? : - ;
? ? ? ? ? * : ? : X ;
endtable
endprimitive
23-27
Example JKFF
The module definition separately buffers the Q and QN outputs for two reasons:
A UDP can have only one output, so you must either instantiate two UDPs or generate the second
output yourself.
You separately buffer outputs to ensure that you can provide each output with a path delay
independent of other path delays.
23-28
Example JKFF
specify
specparam tPD = 12:15:20 ;
specparam tPERIOD = 33 ;
specparam tWCLK0 = 20 ;
specparam tWRSTN = 25 ;
specparam tWSETN = 25 ;
specparam tSU
= 20 ;
specparam tSURSTN = 20 ;
specparam tSUSETN = 25 ;
specparam tH
= 2 ;
(CLK,RSTN,SETN *> Q,QN) = tPD ;
$period ( posedge CLK, tPERIOD, flag ) ;
$width ( negedge CLK, tWCLK0, 0, flag ) ;
$width ( negedge RSTN, tWRSTN, 0, flag ) ;
$width ( negedge SETN, tWSETN, 0, flag ) ;
$setuphold ( posedge CLK &&& condition, J &&& condition,
flag ) ;
$setuphold ( posedge CLK &&& condition, K &&& condition,
flag ) ;
$recovery ( posedge RSTN, posedge CLK, tSURSTN, flag )
$recovery ( posedge SETN, posedge CLK, tSUSETN, flag )
endspecify
tSU, tH,
tSU, tH,
;
;
23-29
Example JKFF
You can provide specparams with either single values or values in the min:typ:max format.
Do not confuse a module timing path with a functional path. For convenience this specify block defines
the timing path (CLK,RSTN,SETN *> Q,QN), but of course no functional paths exist originating at
negedge CLK or posedge SETN.
23-30
Summary
You should now be able to specify timing checks for your module definitions:
Second signal does not change while first signal in specified state
Pulse width is sufficiently long
Period is sufficiently long
Time between two signals is sufficiently short
Time between two signals is sufficiently short (variation)
Time between two signals is sufficiently short (variation)
Timing Checks (TC1)
23-31
Summary
23-32
Review
1. Which timing check(s) accept a negative limit?
2. Can you qualify all events in all timing checks with edge specifiers such as edge 01?
3. For which timing check(s) must you always qualify events?
4. When does $skew report a violation?
23-33
Review
1. The $setuphold and $recrem timing checks accept one negative limit. The other limit must be
sufficiently positive that the sum of the two limits exceeds zero by more than the simulation
precision.
2. You cannot qualify the reference event of the $nochange check with edge specifiers such as edge
01. You can qualify this event with the posedge or negedge keywords. You can use edge
specifiers to qualify all other events in all other timing checks.
3. For the $width and $period timing checks you must provide qualified events.
4. The $skew timing check reports a violation each time the data event occurs more than the limit
after the most recent reference event. It does not report a violation if the data event never occurs.
23-34
Modeling Memories
VMM2
24-1
Notes
24-2
Aims
Issues with modeling memories in Verilog
Topics
Simple ROM and RAM models
Scalable memory models
Using bidirectional ports
Learn how to model a bidirectional port in Verilog
24-3
MSB
24-4
24-5
24-6
0000
0101
1100
0011
1101
0010
0011
1111
1000
1001
1000
0001
1101
1010
0001
1101
endmodule
ROM data is stored
in a separate file
Modeling Memories (VMM2)
24-7
24-8
4 X 16 reg array
//read
assign data = (read ? memory[addr] : 4bz);
endmodule
Note: Simulation models for internal RAM/ROM usually supplied by technology vendor
24-9
24-10
24-11
24-12
Loading a Memory
You need to preload a ROM and perhaps initialize a RAM.
You can do this from an external file...
$readmemb("mem_file.txt", mema)
Or using a loop
for (i=0; i < memsize; i = i+1)
mema[i] = {wordsize{1b0}}
24-13
Loading a Memory
You can load a ROM or RAM with data by using a $readmem task. For a ROM, this data would be the
actual content at startup. For a RAM, you can initialize the device, saving valuable simulation time by
not requiring separate write cycles for each loaded word.
24-14
module mymem (
input read, write,
input [3:0] addr,
inout [3:0] data
);
...
assign data = (read ? memory[addr] : 4bz);
...
24-15
24-16
bus_b
bus_a
b2
en_b_a
When en_a_b = 1,
primitive b1 is
enabled and the
value on bus_a is
transferred to bus_b
module bus_xcvr (
input en_a_b, en_b_a,
inout bus_a, bus_b
);
bufif1 b1 (bus_b, bus_a, en_a_b);
bufif1 b2 (bus_a, bus_b, en_b_a);
When en_b_a = 1,
primitive b2 is
enabled and the
value on bus_b is
transferred to bus_a
endmodule
24-17
data
bufif1
24-18
bus_b
bus_a
b2
en_b_a
module bus_xcvr (
input en_a_b, en_b_a,
inout bus_a, bus_b
);
assign bus_b = en_a_b ? bus_a : bz;
assign bus_a = en_b_a ? bus_b : bz;
endmodule
When en_b_a = 1,
this assignment
drives the value of
bus_b onto bus_a
When en_a_b = 1,
this assignment
drives the value of
bus_a onto bus_b
24-19
24-20
RAM cell
rd
databus
data
reg
wr
module ram_cell (
input rd, wr,
inout databus
);
reg datareg;
When rd = 1 the
value of datareg is
assigned to databus
When wr deasserts,
the value of databus
is written to datareg
endmodule
24-21
24-22
Review
1. What Verilog construct do you use to define a memory array?
2. How can you load a memory with data?
3. How can you send values through a bidirectional port (an inout)?
4. Given the RAM cell below, write a simple testbench to exercise the design.
module ram_cell (
input rd, wr,
inout databus
);
reg datareg;
assign databus = rd ? datareg : bz;
always @(negedge wr)
datareg <= databus;
endmodule
24-23
Review
24-24
A-1
Notes
A-2
Topics
(VDP2)
A-3
A-4
What is a UDP?
Verilog has over two dozen gate level primitives for modeling structural logic. In addition
to these primitives Verilog has user defined primitives (UDPs) that extend the built in
primitives by allowing you to define logic in tabular format.
UDPs are useful for AISC library cell design as well as small scale chip and medium scale
chip design.
You can use UDPs to augment the set of predefined primitive elements.
(VDP2)
A-5
What is a UDP?
UDPs permit the user to augment the set of predefined primitive elements.
A UDP can replace the logic of many primitives. Thus, the simulation time and the memory
requirements can be reduced significantly compared to running the separate primitives.
Behavioral models of the same logic may be even faster depending on the simulator.
A-6
UDP Features
The UDP output terminal can be initialized to a known value at the start of
simulation.
(VDP2)
A-7
UDP Features
UDPs can have only one output. Thus, if the functionality requires more than one output, then the
additional primitives need to be connected to the output of the UDP, or several UDPs can be used
together.
UDPs can have 1 to 10 inputs. However, the memory requirements increase dramatically as the
number of inputs increases from 5. The table below shows the memory requirement per definition
for the number of inputs.
# inputs
Memory (k bytes)
1-5
<1
17
56
187
10
623
The output terminal of a sequential UDP can be initialized to a known value at the start of
simulation using the initial statement.
A-8
The output becomes x for any input combination not specified in the table.
(VDP2)
A-9
The first two entries say that if s = 1 then, irrespective of the value of the input b, the value on
the output o will be the same as that of input a.
The next two entries say that if s = 0 then, irrespective of the value of the input a, the value on
the output o will be the same as that of input b.
The last two entries are added to reduce pessimism. We say that if both the inputs, a and b, have
the same logic value, then even if sel = x, the output o will have the same value as inputs a or
b. This behavior cannot be modeled using Verilog built-in primitives.
A-10
G1
Sum
G2
G4
G5
Cin
A
B
table
a b ci : co
1 1 ? : 1;
1 ? 1 : 1;
? 1 1 : 1;
0 0 ? : 0;
0 ? 0 : 0;
? 0 0 : 0;
endtable
endprimitive
Sum
U_ADDR2_C
Cout
Cout
G3
U_ADDR2_S
ci
0
0
1
1
0
0
1
1
:
0
1
0
1
0
1
0
1
s
:
:
:
:
:
:
:
:
0;
1;
1;
0;
1;
0;
0;
1;
(VDP2) A-11
For a large number of instantiations of the full adder, the memory requirements are greatly
reduced.
The number of events greatly decreases. Using built-in primitives, events propagate through three
primitives to the carry-out. Using UDPs, an event must propagate through only one primitive.
A ? symbolizes a 0, 1, or x.
A-12
(VDP2) A-13
A next state value of - means that there will be no change on the output.
The statement initial q = 1b1; is the sequential UDPs initialization statement. It causes
the output terminal of the UDP to have a value of 1 at the start of simulation.
This type of power-on initialization is rarely used in real components, but is useful for testing the
functionality of your UDP.
A-14
(VDP2) A-15
At most, one input transition may be specified in any table entry statement.
In each timestep, level entries take precedence over edge entries because they are processed last.
A-16
Interpretation
Explanation
0 or 1
(01)
0->1 transition
(10)
1->0 transition
(??)
Any transition
(VDP2) A-17
A-18
(VDP2) A-19
A-20
(bo, a, b, bi);
a<b, borrow
a<=b, bi=0, borrow
a<=b, bi=0, borrow
a>b, dont borrow
a>=b, bi=1, dont borrow
a>=b, bi=1, dont borrow
(VDP2) A-21
A-22
(VDP2) A-23
A-24
(VDP2) A-25
A-26
Summary
UDPs allow you to create your own primitives to extend those built-in to Verilog
Behavior is defined using a table
UDPs are instantiated like a built-in primitive
There are some restrictions on using UDPs, including: There must be a separate UDP for every output
The Z value is not supported, hence UDP ports cannot be bi-directional
UDPs are not synthesizeable
(VDP2) A-27
Summary
A-28
Review Answers
QVA2
B-1
Notes
B-2
Verilog Application
1. What is Verilog?
2. How is Verilog implementational independent and why is this an advantage?
3. What level of Verilog is used in :
a. Testbenches
b. Synthesizable design
c. Net list
(QVA2)
B-3
Verilog Application
1. Verilog is a Hardware Description Language (HDL) - a programming language with special
constructs for modeling hardware, such as timing; abstraction; serial and concurrent behavior.
2. Verilog is implementational independent because behavioral and RTL descriptions are not
specific to a particular technology or vendor. The actual technology for the implementation of the
design does not need to be specified until an RTL description is synthesized.
3.
a. Behavioral level Verilog is used in testbenches
b. Register Transfer Level (RTL) Verilog is used in synthesizable design
c. Structural level Verilog is used in net lists
B-4
ALU1
data
ac_out
opcode
clock
reset
ALU
a_in
y_out
b_in
op_in
z_out
clk
rst
alu__out
zero
(QVA2)
B-5
B-6
a
c
(QVA2)
B-7
wire b = a & c;
B-8
Verilog Operators
1. How many bits is the result of a logical && operation?
2. What is the difference between && and &, if any?
3. What must you do to values you replicate with the replication operator?
4. Given
regx = 4b0101;
what is the value of:bus = { 2{regx[3:1], {3{1b0, regx[0]}}} };
5. If regb is defined as a four bit signed number as shown below, give the code for
an arithmetic binary division by two. Hint: the sign bit (or most significant bit) must
remain intact.
reg [3:0] regb;
(QVA2)
B-9
Verilog Operators
1. The && logical operator reduces each operand to a single bit (1b0, 1b1 or 1bx), then ANDs
these bits together to give a single bit result.
2. & does a bit-by-bit AND of its operands, from LSB to MSB, producing a result which is the same
width as the longest operand.
&& reduces each operand to a single bit, then ANDs these bits to give a single bit result.
3. Operands to which you must apply the replication operator must be sized.
For example: {3{'b1}} is illegal because 'b1 is not sized, {3{1'b1}} is OK.
4. Given regx = 4b0101; then
bus = { 2{regx[3:1], {3{1b0, regx[0]}}} };
can be evaluated as follows:bus = { 2{3b010, {3{1b0, 1b1}}} };
bus = { 2{3b010, {3{2b01}}} };
bus = { 2{3b010, 6b010101} };
bus = { 2{9b010010101} };
bus = 18b010010101010010101;
5. A divide by 2 operation is equivalent to shifting regb right 1 bit. A shift operator could be used,
but this would insert a 0 in the MSB of the result, losing any sign information and making the
result always positive. We need to shift regb right 1 bit and maintain the value of the MSB:-
B-10
Procedural Statements
1. If more than one condition of an if..else statement is true, which condition
takes priority?
2. Are if, case and for statements continuous or procedural statements?
3. Code the following conditional logic:-
a
b
mux
mux
1b0
1
0
<
ctrl
f
4b0110
(QVA2) B-11
Procedural Statements
1. if conditions are evaluated in the order in which they appear, so the first condition which evaluates
to true takes priority over
B-12
a[3:0]
d[4:0]
b[3:0]
0
c[4:0]
add
(QVA2) B-13
i) Continuous assignment
assign d = (add == 1) ? a + b : c;
B-14
(QVA2) B-15
B-16
(QVA2) B-17
B-18
(QVA2) B-19
STATE3 = 3;
B-20
(QVA2) B-21
ii) Stimulus and control to apply stimuli to data and control inputs
iii) Response generation and verification to capture output values and check their correctness
3. We have to declare our clock variable: declare a parameter for the clock period; initialize the
clock and then write code to create the clock waveform:// parameter declaration
parameter PERIOD = 10;
// clock declaration
reg clock;
//clock initialization
initial clock = 1b0;
// clock waveform
always #(PERIOD/2) clock = ~clock;
B-22
(QVA2) B-23
if condition checks for rst high, but procedure is triggered by negedge rst.
two:
three: Reset and sequential functionality for q should be in the same procedure.
four: Use non-blocking assignment. Test for clk is meaningless, should test reset (synchronous)
five: Assignments to p and q must be made from within a single if statement, not two.
six:
or keyword should be used between variables in the event list, not the OR operator (|),
although (ctrl | s) is simulatable, triggering when event occurs on the expression.
B-24
(QVA2) B-25
rst
c
b
+
0
1
clk
rst
sel
clk
B-26
sync_reset
clock
(QVA2) B-27
B-28
(QVA2) B-29
B-30
finish
start
module testbench;
reg clk;
reg [3:0] a_bus;
reg select;
finish
clock
clock
select
select
a_bus[3:0]
a_bus[3:0]
5
4
6
5
initial
begin
count_from(4d4);
count_from(4d2);
end
endmodule
7
6
(QVA2) B-31
module
input
output
reg
// function declaration
always@(a_bus or b_bus)
result = add4(a_bus, b_bus);
endmodule
task count_from;
input [3:0] number;
begin
// start of task body
@ (posedge clk);
a_bus <= number;
@ (negedge clk);
select <= 1'b1;
repeat (3)
begin
@ (posedge clk);
a_bus <= a_bus + 4'b1;
end
select <= 1'b0;
@ (negedge clk);
end // end of task body
endtask
B-32
System Control
1. Which two system tasks display the steady state values of the argument list?
2. Which is better to use when creating test vectors? $display or $strobe?
3. How would you cater with opening 35 files?
4. What is the output of the following piece of code?
module test;
reg [3:0] a;
initial
begin
a <= 11; // 4b1011
a = 4b0011;
$display("display", a);
$strobeb("strobe", a);
end
endmodule
(QVA2) B-33
B-34
Structural Modeling
1. What is structural modeling in Verilog?
2. What are the two ways that module ports can be connected? Which is safer?
3. What does an array of instances do?
4. When are instance names optional?
(QVA2) B-35
Structural Modeling
1. A structural model is equivalent to a schematic, only containing instantiated modules and wire
connections. Structural modeling is used for block diagrams, schematics, post-synthesis netlists
and ASIC/FPGA cell library models.
2. Module ports can be connected by positional or named port mapping. Named port mapping is
safer because it explicitly identifies which port is mapped to which connection.
3. An array of instances creates a number of module instantiations from one instantiation statement,
e.g. a primitive can be instantiated on each bit of a bus in one statement rather than having a
separate instantiation statement for each bit in the bus.
4. Instance names are optional only when instantiating primitives.
B-36
Modeling Delay
1. Model the following circuit:
1.2:1.6:1.8
a
1.1:1.6:1.7
b
c
0.6
2. Give the code for the following circuit. Do you see any problems with such a circuit
from (i) a simulation point of view (ii) a synthesis point of view? Can you fix them?
4b0001
4
4
(QVA2) B-37
Modeling Delay
1.
2. Note we use an initial block to initialize a and prevent a being stuck at 4bx. Note also
non-blocking assignment used to increment a and re-trigger the procedure when a changes. If
blocking assignment is used, the procedure will not detect any event on a and will not trigger.
module delayadd (a);
output [3:0] a;
reg [3:0] a;
initial
a = 4'b0000;
always @(a)
a <= a + 4b0001;
endmodule
B-38
Modeling Memories
1. What Verilog construct do you use to define a memory array?
2. How can you load a memory with data?
3. How can you send values through a bidirectional port (an inout)?
4. Given the RAM cell below, write a simple testbench to exercise the design.
(QVA2) B-39
Modeling Memories
1. A memory is declared in Verilog as a 2-dimensional register array.
2. You can load a memory model with data using the $readmemh or the $readmemb system
tasks, or by using procedural assignments.
3. Because an inout must be a net data type on both sides, you can only drive values onto it with
a primitive, submodule, or continuous assignment. You must also be careful to ensure that
conflicting values are not driven onto it from either side.
4. databus is an inout port and so must be driven by a continuous assignment or primitive. In the
example below, write values are set up from a procedure in reg type data. drive is used to
control a conditional continuous assignment to drive either data or z onto the wire dataio.
module tb_ram_cell ();
// simple ram_cell testbench
wire [3:0] dataio;
reg [3:0] data;
reg read, wrte, drive;
ram_cell U1 (.databus(dataio),
.rd(read), .wr(wrte));
initial
begin
//init
{read, wrte, drive} = 3'b010;
#10;
//write
data = 4'b1010;
drive = 1'b1;
// continued next column
B-40
B-41
B-42
RTL Templates
VRT1
C-1
Notes
C-2
Objectives
Objectives
(VRT1) C-3
Multiplexers
// 1. using an always
a
always@(a or b or sel)
1
c
if (sel == 1b1)
c = a;
else
sel
c = b;
Caution
// 3. using the case statement
always @ (a or b or sel)
case (sel)
1b1: c = a;
1b0: c = b;
endcase
(VRT1) C-4
Priority Decoders
sel
always @ (sl or a or b or c)
2b10
case (sel)
2b11
2
2b11: d = a;
2b10: d = b;
default:d = c;
endcase
// 2. using an if statement
always @ (sl or a or b or c)
if (sel == 2b11)
d
1
d = a;
else if (sel ==2b10)
d = b;
else
d = c;
endcase
Caution
1. Both case and if statements result in
priority structures.
2. The order of the variables determines the
priority
(VRT1) C-5
sel
2b10: d = b;
default:d = c;
endcase
2b0x
2b10
2b11
(VRT1) C-6
enable
c[3:0]
d[3:0]
4
reg [3:0] d;
always @ (c or enable)
d = c & {4{enable}};
a[3:0]
reg [2:0] e;
e = {a[1],b[3:2]}
3
b[3:0]
always @ (a or b)
e = {a[1],b[3:2]};
(VRT1) C-7
Comparators
// 1. using a wire
wire d;
a[3:0]
4
assign d = (a == c);
c[3:0]
// 2. using a reg
d
1
reg d;
always @ (a or c)
d = (a == c);
(VRT1) C-8
q <= d;
clock
q <= d;
clock
Caution
Use non-blocking assignments (<=) in
sequential procedures.
(VRT1) C-9
1b0
q
if (reset)
q <= 1b0;
reset
else
q <= d;
clock
reset
q <= 1b0;
else
q <= d;
clock
(VRT1)
C-10
d
enable
clock
q <= d;
Caution
clock
enable
gclk
(VRT1)
C-11
Latches
// 1. latch
always @ (enable or d)
if (enable)
q = d;
enable
// 2.resettable latch
reset
q = 1b0;
else if (enable)
q = d;
enable
(VRT1)
C-12
Tri-state Drivers
// 1. using a reg
enable
reg y;
always @ (d or enable)
if (enable)
y = d;
else
y = 1bz;
// 2. using a wire
wire y;
assign y = enable ? d : 1bz;
// 3. using a primitive
bufif1 (y,d,enable);
(VRT1)
C-13
Counter
3 bit asynchronously resettable counter which counts 0, 1, 2, 3, 4, 5, 0, 1, 2, ... etc.
reset
3b001
3b000
// 3 bit asynchronously resettable
count
1
0
enable
if (reset)
3b101
if (count == 3b101)
clock
(VRT1)
C-14
Verilog-2001
V2K1
D-1
Notes
D-2
Re-entrant tasks
generate statement
Configurations
Enhanced timing
More ...
(V2K1)
D-3
D-4
D-5
D-6
Attributes
2.8 Attributes
New tokens: (* *)
Verilog-2001 standardizes a means to specify tool specific information
Prefix to declaration, module item, statement, port connection
(V2K1)
D-7
Attributes
Synthesis vendors have historically defined pragmas (tool directives called metacomments hidden
within Verilog comments) to at least partially control the operation of the tool. Those vendors will
undoubtedly continue to also honor the pragmas.
D-8
(V2K1)
D-9
D-10
The parser interprets an integer with an unsigned base specifier as an unsigned value.
intA = -d12 / 3 ;
The parser interprets an integer with an signed base specifier as an signed value.
intA = -4'sd12 / 3 ;
D-12
(V2K1) D-13
D-14
Multi-dimensional Arrays
3.10 Arrays
Verilog-1995:
You can declare one-dimension arrays of integer, reg, and time
Use arrays of reg to model memories
Use arrays of integer and time in your testbench
Verilog-2001:
You can declare arrays of any variable or net type
(V2K1) D-15
Multi-dimensional Arrays
Verilog-1995:
reg_declaration ::= reg [range] list_of_register_identifiers ;
time_declaration ::= time list_of_register_identifiers ;
integer_declaration ::= integer list_of_register_identifiers ;
list_of_register_identifiers ::= register_name { , register_name }
register_name ::=
register_identifier
| memory_identifier [upper_limit_constant_expression :
lower_limit_constant_expression ]
Verilog-2001:
reg_declaration ::= reg [ signed ] [ range ] list_of_variable_identifiers ;
time_declaration ::= time list_of_variable_identifiers ;
integer_declaration ::= integer list_of_variable_identifiers ;
list_of_variable_identifiers ::= variable_type { , variable_type }
variable_type ::=
variable_identifier [ = constant_expression ]
| variable_identifier dimension { dimension }
real_declaration ::= real list_of_real_identifiers ;
realtime_declaration ::= realtime list_of_real_identifiers ;
list_of_real_identifiers ::= real_type { , real_type }
real_type ::=
real_identifier [ = constant_expression ]
| real_identifier dimension { dimension }
D-16
Local Parameters
3.11.2 Local parameters - localparam
New reserved word: localparam
Verilog-1995:
You can declare module parameters keyword parameter
These are constants you can change during elaboration
Use module parameters to parameterize each instance of the module
You can modify an instances parameters with the defparam keyword
You can modify an instances parameters with a parameter value assignment
Verilog-2001:
You can also declare local parameters keyword localparam
These are constants you cannot change
(V2K1) D-17
Local Parameters
A localparam is identical to a parameter except that you cannot modify a localparam with the
defparam statement or by the ordered or named parameter value assignment.
Verilog-1995:
module_item_declaration ::= parameter_declaration | ...
block_item_declaration ::= parameter_declaration | ...
parameter_declaration ::= parameter list_of_param_assignments ;
Verilog-2001:
module_parameter_port_list ::=
# ( parameter_declaration { , parameter_declaration } )
module_item ::= ...
| { attribute_instance } parameter_declaration ...
| { attribute_instance } local_parameter_declaration
block_item_declaration ::= ...
| { attribute_instance } parameter_declaration ...
| { attribute_instance } local_parameter_declaration
parameter_declaration ::=
parameter [ signed ] [ range ] list_of_param_assignments ;
| parameter integer list_of_param_assignments ;
| parameter real list_of_param_assignments ;
| parameter realtime list_of_param_assignments ;
| parameter time list_of_param_assignments ;
local_parameter_declaration ::=
localparam [ signed ] [ range ] list_of_param_assignments ;
| localparam integer list_of_param_assignments ;
| localparam real list_of_param_assignments ;
| localparam realtime list_of_param_assignments ;
| localparam time list_of_param_assignments ;
D-18
Verilog-2001:
You can also declare a specparam as a module item
(V2K1) D-19
Verilog-2001:
module_item ::= { attribute_instance } specparam_declaration | ...
specify_item ::= specparam_declaration | ...
specparam_declaration ::= specparam [ range ] list_of_specparam_assignments ;
list_of_specparam_assignments ::=
specparam_assignment { , specparam_assignment }
specparam_assignment ::=
specparam_identifier = constant_mintypmax_expression | ...
D-20
Power Operator
4.1.5 Arithmetic operators
New operator: **
Verilog-2001 adds the power ** operator
Operation similar to C pow() function
(V2K1) D-21
Power Operator
The result is unsigned if both operands are unsigned.
The result is real if either operand is real, integer, or signed.
The result is unspecified if the first operand is zero and the second operand is non-positive.
The result is unspecified if the first operand is negative and the second operand is not an integral value.
Verilog-1995:
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | && | || | ...
Verilog-2001:
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | && | || | ** | ...
D-22
(V2K1) D-23
Verilog-2001:
net_lvalue ::= ...
| hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] }
| hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] }
[ constant_range_expression ]
| hierarchical_net_identifier [ constant_range_expression ] | ...
constant_range_expression ::=
constant_expression
| msb_constant_expression : lsb_constant_expression
| constant_base_expression +: width_constant_expression
| constant_base_expression -: width_constant_expression
variable_lvalue ::= ...
| hierarchical_variable_identifier [ expression ] { [ expression ] }
| hierarchical_variable_identifier [ expression ] { [ expression ] }
[ range_expression ]
| hierarchical_variable_identifier [ range_expression ] | ...
primary ::= ...
| hierarchical_identifier [ expression ] { [ expression ] }
| hierarchical_identifier [ expression ] { [ expression ] } [ range_expression ]
| hierarchical_identifier [ range_expression ] | ...
range_expression ::=
expression
| msb_constant_expression : lsb_constant_expression
| base_expression +: width_constant_expression
| base_expression -: width_constant_expression
Verilog Application Workshop
D-24
(V2K1) D-25
D-26
(V2K1) D-27
Verilog-2001:
event_control ::=
@ event_identifier
| @ ( event_expression )
| @*
| @ (*)
event_expression ::=
expression
| hierarchical_identifier
| posedge expression
| negedge expression
| event_expression or event_expression
| event_expression , event_expression
Verilog Application Workshop
D-28
(V2K1) D-29
D-30
(V2K1) D-31
D-32
D-34
(V2K1) D-35
D-36
Constant Functions
10.3.5 Use of constant functions
Verilog-1995:
You can use constant expressions to parameterize a model
Array depth, vector width, replication
parameter WIDTH_A = 5, WIDTH_D = 8 ;
reg [WIDTH_D-1:0] mem [1:2**WIDTH_A] ;
Verilog-2001:
You can also use constant functions to parameterize a model
You can use them anywhere you would use a constant expression
parameter DEPTH = 32, width = 8 ;
reg [log2(DEPTH)-1:0] mem [1:2**WIDTH_A] ;
(V2K1) D-37
Constant Functions
Constant functions are normal Verilog functions that contain no construct or reference that the elaborator
cannot resolve. In general that means that a constant function definition:
As a further restriction, you cannot within the definition of a constant function itself, replace a constant
expression with a call to a constant function.
Verilog-1995
Verilog-2001
constant_primary ::=
number
| parameter_identifier
| constant_concatenation
| constant_multiple_concatenation
constant_primary ::=
number
| parameter_identifier
| constant_concatenation
| constant_multiple_concatenation
| constant_function_call
| ( constant_mintypmax_expression )
| genvar_identifier
| specparam_identifier
D-38
Verilog Generate
12.1.3 Generated instantiation
New reserved words: generate endgenerate genvar
Verilog-2001 adds:
Conditional (case, if) generation
Instances, functions, tasks, variables, and procedural blocks
(V2K1) D-39
Verilog Generate
Place your generated instances, functions, tasks, variables, and procedural blocks between the generate
and endgenerate reserved words (you may not include parameters, ports, or specify blocks).
Declare genvar index variables for your generate for loops. You can declare them either inside or outside
the generate statement. You can assign only integer values to them, and only within a for loop. These
variables disappear after elaboration and are not available during simulation.
Iteratively generate statements using the for construct. Declare a named block within the for construct
this becomes the name of an array of scopes to match the iterations of the for construct. Inside this
named block place your generated instances, variables, and procedural blocks (you cannot define tasks
and function within a generate for construct).
Conditionally generate statements using case and if constructs.
generate
if ( (a_width < 8) || (b_width < 8) )
CLA_multiplier #(a_width,b_width)
u1 ( a, b, product ) ;
else
WALLACE_multiplier #(a_width,b_width)
u1 ( a, b, product ) ;
endgenerate
D-40
Work around by reassigning the initial values to parameters you do not modify
ram #(256,16) ram1 ( ... ) ;
Verilog-2001:
parameter_value_assignment ::= # ( list_of_parameter_assignments )
list_of_parameter_assignments ::=
ordered_parameter_assignment { , ordered_parameter_assignment }
| named_parameter_assignment { , named_parameter_assignment }
ordered_parameter_assignment ::= expression
named_parameter_assignment ::= . parameter_identifier ( [expression ] )
D-42
Verilog Configurations
13. Configuring the contents of a design
New reserved words: config cell design endconfig -incdir include instance liblist
library use
Verilog-2001 adds a new design building block called a configuration that you can
provide in a library map file.
include /hm/me/libmap.txt ;
library techlib techlib.v ;
library projlib projlibdir/ ;
library testlib . ;
config rtl ;
design testlib.top ;
default liblist testlib projlib techlib ;
cell alu liblist projlib techlib ;
cell cpu use techlib.cpu ;
instance top.u1.d5 liblist projlib techlib ;
instance top.u1.d6 use dff:config ;
endconfig
(V2K1) D-43
Verilog Configurations
The standard describes the library map file, and also describes configurations, which may reside in the
library map file or in a separate source file.
The primary purpose of the library map file is to contain an order list of library declarations. Each library
declaration names a library and maps source to that library. You can define the source path names with
wildcard characters. The compiler places in a library called work any source you compile that it does not
find mapped to a library. The elaborator by default searches the libraries in their declared order to resolve
module references. The simulator vendor must provide a way to specify on the command line a library
list that overrides this default order.
A configuration is a set of rules governing how the elaborator determines which representation of the
module to bind to an instance. You can define configuration(s) for the top level module(s) in your design.
Any configuration can utilize lower level configurations, bindings, and ordered library search lists (you
may not provide a binding or a library list for an instance located within a utilized lower level
configuration). Where you provide both a binding and a library list, the binding overrides the library list.
Where you provide a binding or a library list on both a module definition basis and a module instance
basis, the instance-specific information overrides the more global information. The elaborator searches
the libraries in their listed order to resolve module references. Where no specific binding and no library
list exist, the elaborator searches only within the library of the unit making the reference.
The IEEE Std. 1364-2001 provides no means to maintain more than one representation of a module
within a single library. You must maintain your disparate representations (for example; gate, rtl,
behavioral) in separate libraries. Use the optional [library.] prefix to specify a binding from a specific
library, and use the optional [:config] suffix (config is currently a literal string) to specify the binding
of a configuration when the configuration has the same name as a module.
D-44
pulsestyle_ondetect
specify
(inp => outp) = 5 ;
specparam
PATHPULSE$inp$outp = (2,4) ;
pulsestyle_onevent outp ;
endspecify
specify
(inp => outp) = 5 ;
specparam
PATHPULSE$inp$outp = (2,4) ;
pulsestyle_ondetect outp ;
endspecify
outp
outp
outp
(delayed)
outp
(delayed)
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
(V2K1) D-45
D-46
showcancelled
specify
(inp => outp) = (6,3) ;
showcancelled outp ;
endspecify
outp
outp
outp
(delayed)
outp onevent
(delayed)
0 1 2 3 4 5 6 7 8
ondetect
0 1 2 3 4 5 6 7 8
(V2K1) D-47
D-48
$setup
setup
clk
$hold
hold
clk
data
setuphold
clk
Permits one or the other limit (but not both) to be negative if the sum of these limits is greater than
zero by more than the simulation precision. The simulator adjusts the negative limit upward to
zero plus the simulation precision, adds the same amount to the other limit, and delays the
appropriate reference signal or data signal, so that it can perform the check using positive limits.
You can optionally provide signal names for the delayed versions, and you should drive internal
module logic with the delayed versions to enable correct functional operation of your design.
Permits you to conditionalize the stamptime (reference) event and/or checktime (data) event using
arguments separate from the event description.
D-50
$recovery
rst_
recovery
clk
$removal
rst_
removal
clk
$recrem
rst_
recrem
clk
Permits one or the other limit (but not both) to be negative if the sum of these limits is greater than
zero by more than the simulation precision. The simulator adjusts the negative limit upward to
zero plus the simulation precision, adds the same amount to the other limit, and delays the
appropriate reference signal or data signal, so that it can perform the check using positive limits.
You can optionally provide signal names for the delayed versions, and you should drive internal
module logic with the delayed versions to enable correct functional operation of your design.
Permits you to conditionalize the stamptime (reference) event and/or checktime (data) event using
arguments separate from the event description.
D-52
$skew
clk
skew
clka
D-54
No filesystem manipulation
// close a file
errcode
char
= $fgetc ( fd ) ;
// get a character
errcode
= $fgets ( str, fd ) ;
// get a string
$fflush ( [ fd ] ) ;
fd
// open a file
errcode
= $fread ( reg, fd ) ;
errcode
errcode
errcode
position
= $ftell ( fd ) ;
errcode
errcode
= $rewind ( fd ) ;
length
= $ungetc ( c, fd ) ;
D-56
SDF Annotation
17.2.9 Loading timing data from an SDF file
New system task: $sdf_annotate
Verilog-2001:
Formally defines an already de-facto standard
(V2K1) D-57
SDF Annotation
The IEEE Std. 1364-2001 clause 17.2.9 (Loading timing data from an SDF file) formally defines the
built-in SDF annotation that most simulator vendors have already previously provided. A
$sdf_annotate() system task takes the following arguments, of which only the first is required. You can
omit any trailing arguments and can substitute a comma placeholder for any other omitted argument.
Default values are in bold font.
"sdf_file"
SDF file
module_instance
"config_file"
Configuration file
"log_file"
Log file
"mtm_spec"
"scale_factors"
"scale_type"
The annotator starts with the "scale_type" values, applies the "scale_factors", then annotates the result to the
"mtm_spec".
D-58
(V2K1) D-59
D-60
(V2K1) D-61
$random ( [ seed ] ) ;
$dist_chi_square ( seed , degree_of_freedom ) ;
$dist_erlang ( seed , k_stage , mean ) ;
$dist_exponential ( seed , mean ) ;
$dist_normal ( seed , mean , standard_deviation ) ;
$dist_poisson ( seed , mean ) ;
$dist_t ( seed , degree_of_freedom ) ;
$dist_uniform ( seed , start , end ) ;
D-62
(V2K1) D-63
D-64
(V2K1) D-65
$dumpall;
$dumpoff
Suspend dump
$dumpon;
Resume dump
$dumplimit ( filesize );
$dumpflush;
$dumpportsall [ ( [ pathname ] ) ] ;
$dumpportsoff [ ( [ pathname ] ) ] ;
Suspend dump
$dumpportson [ ( [ pathname ] ) ] ;
Resume dump
$dumpportsflush [ ( [ pathname ] ) ] ;
D-66
(V2K1) D-67
D-68
2001
`ifdef defined
`ifdef notdefined
// cannot undef
`endif
`else
`define defined
`endif
`ifndef defined
`define defined
`elsif notdefined
`undef notdefined
`endif
(V2K1) D-69
D-70
(V2K1) D-71
D-72
Summary
You should now be ready to incorporate the new Verilog-2001 features into your Verilog
design and testbench.
Multi-dimensional arrays
Re-entrant tasks
generate statement
Configurations
Enhanced timing
More ...
(V2K1) D-73
Summary
D-74
SystemVerilog-2005
SV2K5
E-1
Notes
E-2
Verification features
New block type to encapsulate test programs Constrained randomization
New block type encapsulate signal timing
Property assertions
Process synchronization
Functional coverage
Templated classes
Overloaded operators
(SV2K5)
E-3
E-4
Data Types
Arrays
Declarations
Operators
Procedural Statements
Processes
Interfaces
(SV2K5)
E-5
E-6
Literal Values
SystemVerilog adds syntax with which to define literal:
integer and logic values
unsized, unbased single-bit values fill all bits to any size with specified value
0
time values
Write as an integer (e.g. 40ps) or fixed-point (e.g. 0.1ns) value followed
immediately by the time unit without an intervening space
New time unit step (e.g. 1step) refers to simulation precision
string values
\v (vertical tab) \f (form feed) \a (bell) \x41 (hex number)
\ escapes newline to continue string on following line
assignment to any integral type is right justified (Verilog standard)
assignment to unpacked array of byte is left justified
(SV2K5)
E-7
Literal Values
E-8
structure values
member key and type key and default value
typedef struct {int i, logic l, real r} s_t;
s_t s = {logic:x, r:1.2, default: 0};
nested braces must reflect array structure and replication must cover all members
typedef struct {int i, ia[4];} s_t;
s_t s[1:0][2:0] = {2{{3{42,{2{38,-5}}}}}};
(SV2K5)
E-9
E-10
Data Types
SystemVerilog adds and enhances data types :
Adds bit, byte, shortint, int, longint 2-state integer types, logic 4-state type,
shortreal floating-point type, void type, chandle (C pointer) type, string type
string methods len(), putc(), getc(), substr(), etc.
alias events, trigger them with a delay, wait for their triggered state
(SV2K5) E-11
Data Types
SystemVerilog supports the C built-in types, but to avoid confusion renames long to longint
and float to shortreal and specifies that an int is always 32 bits and a longint is always 64
bits. These are all 2-state types (integer is still a 4-state type). Similarly to C, SystemVerilog
also provides enumerations (enum) and structures (struct), and users can define types using
typedef.
SystemVerilog adds bit, string, chandle, and class data types and enhances the event type.
SystemVerilog discerns between an object and its type. The type defines the permitted values
and operations, but not the simulation semantics (such as strength resolution). Thus a net
(wire) and variable (var) can both be of the logic data type, but act differently.
You can define modules and interfaces to take data types as a parameter (similarly to C++
class templates).
E-12
Arrays
SystemVerilog adds and enhances array types:
Packed and unpacked arrays
Packed dimensions are before object name and unpacked dimensions after
Packed dimensions are bit, logic, reg types and can be treated as a single vector
logic [3:0][7:0] mem [1:256];
Dynamic arrays that user can resize during runtime
Any one unsized unpacked array dimension (must size other dimensions
bit [8:5][4:2]A[][1:0] = new[2]; A = new[3](A);
Associative arrays
Index can be any 2-state type for which there is an equality operator
event e; event eA[MyClass]; MyClass c = new; eA[c] = e;
Queues
Arrays
SystemVerilog refers to dimensions declared before the object name as a packed array and to
dimensions declared after the object name as a unpacked array. The packed array is what the
Verilog standard refers to as the vector width, but in SystemVerilog can be any number of
dimensions.
Verilog:
vector
reg [31:0]
dimensions
mem [1:255]
SystemVerilog:
packed
reg [3:0][7:0]
unpacked
mem [1:255]
A packed array is simply a mechanism for dividing a bit or logic vector into conveniently
accessed elements. Although you cannot pack integer types, you can use a packed array as if
it were an integer type, and can take bit and part selects of an integer as if it were a
one-dimensional packed array.
Unpacked arrays can be of of any data type. Each unpacked dimension can be a fixed or
unfixed size. You can procedurally change the size of one of the dimensions of an unpacked
array. To assign an unpacked array to another unpacked array, the array structure must be
identical. To assign a packed array to an unpacked array you need to explicitly cast the type.
SystemVerilog also has:
Associative arrays Dynamically resized, element associated with an index of a declared type
E-14
Declarations
SystemVerilog adds and enhances declarations:
You can drive a variable with a single continuous assignment
You can set the type (as well as the value) of a module parameter upon instantiation
You can get the type of an expression and use that type in another expression
(SV2K5) E-15
Declarations
SystemVerilog permits you to drive a variable with a single continuous assignment or with one
or more procedural assignments (but not both). For this purpose, elements of an unpacked
array or structure are treated as separate variables. As the reg keyword no longer means a
register object, SystemVerilog adds the logic data type that you can apply to either a net (e.g.
wire) or a variable (var).
SystemVerilog permits the static keyword in an automatic subprogram to declare a static
variable, and the automatic keyword in an static subprogram to declare an automatic variable.
SystemVerilog adds the const local constant. While a localparam is a static module constant
set during elaboration, const can be an automatic local constant set during simulation.
SystemVerilog discerns between the kind of a declaration and the type of a declaration. The
kind of the declaration defaults to variable (var) and to declare a net you need to specify the
kind of net (e.g. wire). The type of the declaration defaults to logic and to declare any other
type you need to specify the type (e.g. bit). SystemVerilog permits a net to be of any 4-state
type, including arrays and structures containing only 4-state elements.
SystemVerilog data declared outside any module, interface or program have static lifetime and
global scope.
SystemVerilog permits variable declarations in unnamed blocks. These variables are
inaccessible outside of the block scope.
SystemVerilog adds the alias statement to create multiple names for one physical entity.
SystemVerilog permits you to specify a data type as a module parameter that can be changed
on a per-instance basis. You can declare (and override) module parameters using a parameter
port list syntax similar to the port list syntax.
SystemVerilog adds the type operator to extract the type of its expression operand.
Verilog Application Workshop
E-16
Operators
SystemVerilog adds and enhances operators:
Assignment operators (always blocking)
if ( (a=b) ) ++b;
The pattern match operator matches for use in case, if, and conditional expressions
(SV2K5) E-17
Operators
SystemVerilog adds the C assignment (e.g. +=) and increment/decrement (e.g. ++) operators.
These are blocking assignments.
SystemVerilog adds wildcard inequality operators (==? !=?) that treat Z and X values in the
right operand as positions to not be compared.
SystemVerilog provides a built-in implicitly imported std package that users can add to.
SystemVerilog supports (rvalue only) string concatenation and replication.
SystemVerilog supports array and structure assignment patterns.
You can bind some operators to a function that implement that operation for your user-defined
data type.
For the situation where bit reordering is required, SystemVerilog provides stream operators to
pack or unpack integral types in left-to-right {>>} or right-to-left {<<} order. You can specify
the slice size and you can operate on aggregates of integral types.
SystemVerilog adds pattern matching to case and if statements and conditional expressions.
A pattern is a nesting of tagged union and structure expressions with identifiers, constant
expressions, and the wildcard pattern .* at the leaves.
SystemVerilog supports singular value sets and the inside membership operator (an aggregate
type is an unpacked array, structure or union; a singular type is anything else). The operator
performs an equality (==) comparison with nonintegral set elements and a wildcard equality
(==?) comparison with integral set elements. Set elements may also be a unpacked array of
singular types.
Verilog Application Workshop
E-18
Procedural Statements
SystemVerilog adds a final block that executes at the end of simulation.
Must execute in zero time (like a function call). Useful to print diagnostics.
SystemVerilog adds the C-like do...while, break, continue, and return keywords.
SystemVerilog adds the priority and unique keywords to qualify case or if.
The priority keyword checks that at least one branch condition is true.
The unique keyword checks that exactly one branch condition is true.
case match expressions may be value sets (use inside operator) or patterns (use matches)
SystemVerilog checks that any block name at the block end matches the block name.
begin: myBlk statements... end: myBlk
SystemVerilog adds an iff qualifier to the @ event control.
always @(posedge clk iff enabled)
(SV2K5) E-19
Procedural Statements
E-20
Processes
SystemVerilog adds process block keywords to indicate the designers intent:
An always_comb block always represents combinational logic
Processes
To prevent inadvertent latch inference, SystemVerilog adds always_comb, always_latch and
always_ff blocks to guarantee execution semantics and indicate the designers intent.
SystemVerilog provides fine-grained process contol with the process class. Every process is
associated with an object of this class. Processes can retrieve their handle with the static
process::self() method and store it, and any process with access to this handle can use it to
obtain the status of the process, suspend and resume and kill it, and await its completion.
E-22
You can import subprograms to (and export subprograms from) a foreign language
(SV2K5) E-23
E-24
Importing data, type, class, task, and function declarations from a package
import p::*;
Nested module declarations (to keep submodule definitions out of global space)
Implicit .name and .* port connection (if variable and port have the same name)
mod mod1(.clk(clk1), .din, .dout), mod2(.clk(clk2), .*);
(SV2K5) E-25
E-26
Interfaces
Interfaces capture inter-block communication to promote design refinement and reuse.
A named bundle of nets, parameters, constants, variables, functions and tasks
Whose element types you can optionally pass as a per-instance parameter
To which you can control access by defining modports (views)
Instantiate and bind to ports and access through port name or instance name.
module top;
bit clk = 0;
my_IF IF();
memMod mem(.*);
cpuMod cpu(.*);
endmodule : top
interface my_IF;
logic req, gnt;
logic [7:0] addr,data;
logic [1:0] mode;
logic start, rdy;
endinterface: my_IF
module memMod (
interface IF,
input bit clk );
logic avail;
always @(posedge clk)
IF.gnt <= IF.req & avail;
endmodule: memMod
module cpuMod (
interface IF,
input bit clk
);
...
endmodule: cpuMod
(SV2K5) E-27
Interfaces
SystemVerilog provides the interface construct to encapsulate inter-block communication
Separating the inter-block communication from the block implementation facilitates iterative
block refinement and reuse. A SystemVerilog interface is:
You instantiate an interface as you would a module. You bind an interface to a port as a single
item (rather than as all the variables etc. it represents). You access interface elements through
the interface instance name (from the instantiating module) or through the port instance name
(from an instantiated submodule).
You can declare a virtual interface, a handle to which you can throughout the simulation
assign to different interfaces without changing the code that accesses the interface elements
(those interface elements must be similarly named, though would presumably be differently
implemented).
An interface can make available (import) a subprogram to modules. The interface can export
that subprogram from some other module (all interface directions are with respect to the
modules using the interface). Using the extern forkjoin construct, the interface can export a
task (but not a function) from multiple instances of the same module (the task definition must
contain code to ensure that only one of the instances writes task outputs upon return).
E-28
Constrained Randomization
Interprocess Synchronization
Clocking Blocks
Program Blocks
(SV2K5) E-29
E-30
Classes
You model dynamic objects (cells, packets) with classes.
SystemVerilog classes closely parallel C++ classes, with:
Constructors
Static members
Data hiding
Class templates
Abstract classes
Virtual methods
class Packet;
local bit [3:0] command; // private data
local bit [40:0] address;
local bit [4:0] master_id;
local integer time_requested;
local integer time_issued;
local integer status;
task clean(); // public interface methods
command
= IDLE;
address
= 0;
master_id = 5'bx;
endtask
task issue_request( int delay );
... // send request to bus
endtask
function integer current_status();
return status;
endfunction
function new(); // constructor
clean();
endfunction
endclass : Packet
(SV2K5) E-31
Classes
A class is a user-defined type that may include member properties (data) and member
subprograms (methods) to manipulate the data.
You define a class to represent a kind of an object. For example, engineers commonly define
a class to represent a packet. The packet properties may include a command field, an address
field, a sequence number, a time stamp, and a payload. The packet methods may include
subprograms to initialize the packet, set the command, read the packets status, or check the
sequence number. Each instance of the packet has these member properties and methods.
The features of a SystemVerilog class are a subset of the features of a C++ class:
You use object handles instead of class instances or class pointers. All class objects are
dynamic objects, automatically deleted when they go out of scope. This automatic
garbage collection prevents memory leaks. You may not assign a handle of an
unrelated type to a class handle.
E-32
E-34
Constrained Randomization
Constrained random variables can direct tests toward scenarios you have not thought of.
SystemVerilog provides these capabilities:
Simple randomization of unsigned integers of up to 32 bits
Randomization of scope variables with in-line constraints that may be weighted and
may involve multiple random variables, with ability to order constraint resolution
class MyRand;
rand bit [1:0] x;
constraint c1 {x != 2b00;}
endclass : MyRand
class MyXRand extends MyRand;
constraint c2 {x inside {[0:2]};}
endclass : MyXRand
(SV2K5) E-35
Constrained Randomization
Use of random values can make your test environment more effective because the random
values can steer your tests toward scenarios that you might not have imagined. However, you
do need to constrain the random values to useful sets or ranges to also make your tests
reasonably efficient.
SystemVerilog provides these mechanisms to generate random values:
You can use $urandom to generate 32-bit unsigned random values, and $urandom_range to
restrict those values to a range.
You can use std::randomize() to randomize any set of integral scope variables. With
std::randomize() you can provide an in-line constraint block. In the constraint block, you
specify constraints and can specify an order for the solver. Constraint expressions may involve
relationships between the values of random variables and may provide weights to sets or
ranges of values. The weights can be variables that you change during simulation.
You can use the built-in randomize() class method to (without arguments) randomize all
integral properties of the class instance hierarchy declared rand or randc or (with arguments)
to randomize only the specified class properties. With class randomization, you can also
predefine constraint blocks as class members. You can enable and disable these class or
individual constraint blocks using their built-in constraint_mode() method, and can enable
and disable randomization of a class or individual variable using their built-in rand_mode()
method. All classes also implement the built-in pre_randomize() and post_randomize()
callbacks that you can reimplement to do whatever you want to do just before and after the
randomization.
You can use the randcase and randsequence constructs to randomize execution of procedural
statements.
SystemVerilog provides for object and thread stability. Adding new objects or threads after
previous ones in the same block does not affect the random values of previous ones.
Verilog Application Workshop
E-36
Interprocess Synchronization
SystemVerilog adds synchronization mechanisms:
A built-in semaphore class with:
function new(int keyCount=0);
task get(int keyCount=1);
function int try_get(int keyCount=1);
task put(int keyCount=1);
(SV2K5) E-37
Interprocess Synchronization
To model a complex system or a reactive testbench, you need synchronization and
communication mechanisms.
SystemVerilog adds a built-in semaphore class for synchronization and mutual exclusion to
shared resources, and a built-in mailbox class for communication between processes, and
enhances the event type with a persistent triggered state and some operations.
A semaphore is conceptually a holder of keys. When you create the semaphore you initialize
it with a certain number of keys. You code your processes to get keys before utilizing the
limited resource. You can choose to block the process execution until it gets the keys. You
code your processes to put the keys back when they have finished utilizing the resource.
A mailbox is conceptually a queue of messages. When you create the mailbox you initialize it
to a limited or unlimited size. You code your processes to put messages at the front of the
mailbox. You can choose to block the process execution until room is available in the mailbox.
You code your processes to get messages from the back of the mailbox. You can choose to
block the process execution until a message is available. The message can be any type except
unpacked array, unpacked structure or unpacked union.
The nonblocking event trigger emits the referenced event in the nonblocking assignment
region of the simulation cycle.
The value of the events triggered property persists throughout the simulation time step.
You can use this property as an argument to wait().
The wait_order construct suspends the calling process until all of the specified events are
emitted. If in order, it executes the pass block of the optional action block. If not in order, it
executes the fail block of the optional action block.
Verilog Application Workshop
E-38
Clocking Blocks
A clocking block separately captures a set of signals timing requirements:
The clocking event
ack drive
default sample
addr sample
(SV2K5) E-39
Clocking Blocks
SystemVerilog adds the clocking construct to specify a set of timing requirements for a set
of signals. The clocking block construct is a key element of a cycle-based verification
methodology it frees the user from specifying the sample and drive time for each assignment.
For each clocking block, the user specifies a clock expression and can specify default and
signal-specific sample and drives skews with respect to that clock. The user can define
multiple clocking blocks and specify which to use on a per-assignment basis. The user can
optionally nominate a default clocking block for use with any cycle delays that do not
otherwise specify an associated clocking block.
Signals and clock events may appear in multiple clocking blocks.
To avoid races when #0 skews are specified, clocking block inputs are sampled in the
Observed region and clocking block outputs are driven in the NBA region.
Sampling is otherwise done in the Preponed region.
You cannot directly reference a hierarchical signal through a clocking block. You need to
declare a clocking block alias for the hierarchical expression (which may contain bit-selects,
part-selects and concatenations):
input instruction = { opcode, regA, regB[3:1] };
E-40
Program Blocks
A program block separately captures testbench data, subprograms, and processes.
Its restrictions and scheduling semantics help minimize races:
Cannot contain always blocks, UDPs, modules, interfaces, or other programs
(SV2K5) E-41
Program Blocks
The program block:
Modules and programs use similar port declaration and mapping syntax.
Nested programs with no ports or top-level programs that are not explicitly instantiated are
implicitly instantiated once, using the same instance and declaration name.
A program can have initial and final blocks but not always blocks.
E-42
concurrent assertion
always_comb
if (sel==0)
mux_out = in0;
else if (sel==1)
mux_out = in1;
else
assert (0)
else
$error("Bad mux select");
property abcd;
@(posedge clk)
a ##1 b |=> c ##1 d;
endproperty
A1: assert property (abcd);
(SV2K5) E-43
You make an immediate assertion statement in a procedural block. You assert that a boolean
expression is at that point true.
You make a concurrent assertion within the scope of an interface, module, or program. You assert
that a design property holds. You define the property as a sequence of design states, and specify
a clock with which to sample the design states. Your property definition may utilize other
(potentially predefined, even parameterized) sequences and properties, each of which may have a
different clock.
You can place a concurrent assertion as a procedural statement in an always or initial block.
If in an initial block, it is checked only once at the first clock. It can inherit its clock from the
procedural block. It will inherit enabling from its surrounding conditional statement (if any),
if no timing control preceeds it in the block. This placement of an assertion does not suspend
block execution.
You can place an assertion after the expect keyword as a procedural statement. This placement
of an assertion does suspend block execution until the assertion passes or fails.
You can associate an action block with each assertion. The pass part of the block executes if the
assertion passes, and the fail part of the block executes if the assertions fails. You can use $info,
$warning, $error and $fatal system tasks to associate a severity with assertion failure.
E-44
bins b3 = { [85:169] };
bins b4 = { [170:255] }; }
c : cross a, b {
bins c1 = ! binsof(a) intersect
{[100:200]};
bins c2 = binsof(a.a2) || binsof(b.b2);
bins c3 = binsof(a.a1) && binsof(b.b4);
}
endgroup
(SV2K5) E-45
E-46
(SV2K5) E-47
E-48
Summary
The IEEE standard for SystemVerilog (1800) is a substantual enhancement to the IEEE
standard for Verilog (1364)
Pages:
Sections:
Appendices:
Keywords:
Verilog-2001
791
27
8
123
SystemVerilog adds
664
30
11
97
Implementing and using SystemVerilog is a huge effort for vendors and designers
Some vendors may not yet support some language constructs
(SV2K5) E-49
Summary
SystemVerilog is an enhancement to Verilog-2001. A SystemVerilog compiler must accept all
Verilog constructs. SystemVerilog deprecates only the defparam and assign/deassign
keywords.
Having reserved new keywords means that a SystemVerilog compiler might not compile
an existing Verilog design. For example, if you have a data out signal named do, then
a SystemVerilog compiler cannot compile the design, as do is a SystemVerilog
keyword.
As SystemVerilog is an enhancement to Verilog-2001, to optimally implement your designs
in SystemVerilog, you need to also be comfortably familiar with Verilog-2001.
E-50
E-52
Index
Symbols
# - see delay
$display 18.15, 18.19, 18.23
$fclose 18.35
$fdisplay 18.38
$finish 18.27
$fmonitor 18.38
$fopen 18.35
$fstrobe 18.38
$fstrobeb 19.31
$fwrite 18.38
$monitor 18.23
$random 19.19
$readmemb 18.39
$readmemh 18.39
$realtime 18.21, 18.26
$stime 18.21
$stop 18.27
$strobe 18.19
$time 18.21, 18.26
$timeformat 18.25
$write 18.15
-> trigger 19.25
@ - file input format 18.41
@ - timing control 8.27
define 18.9
ifdef 18.11
include 18.7
timescale 8.33, 18.5
undef 18.10
begin...end 6.5
behavioral modeling 2.14, 10.1310.16
bit-wise operators 5.7
blocking assignment 8.7, 9.59.19
clocked procedure 9.9, 13.31
combinational procedure 9.15
intra-assignment delay 22.31, 22.32
register inference in synthesis 16.7
C
case 6.176.26
full 15.2915.34
parallel 15.23
synthesis 15.1915.34
clocked procedures
synthesis 13.1913.32
combinational logic
synthesis 13.713.18
comments 3.25
compilation 3.23
concatenation 5.23
conditional operator 5.21, 7.15
constant
see parameter
continuous assignment
see assign
define
see define
A
defparam 4.40
abstraction levels 2.132.18
delay 8.31
always 3.13, 6.9, 8.5
intra-assignment delay 22.29
arithmetic operators 5.5
delay modeling 22.5
array 4.43
distributed 22.9
assign 4.234.27, 7.57.8, 12.20
inertial versus transport 22.23
synthesis 13.15
lumped 22.7
assignment
min, typ, max 22.13
incomplete 13.11
path
intra-assignment delay 22.29
see specify
see also blocking and non-blocking assignment rise and fall times 22.13
delta cycle 8.11
J
join
see fork
file
latch
synthesis 13.13, 16.11
library 3.19
literals 4.19
integer 4.33
logic strength modeling 21.25
logic value system 4.5
logical operators 5.9
loop 6.276.32
for 6.27
repeat 6.29
synthesis 6.31
while 6.29
lumped delays 22.5
input 18.3918.42
output 18.3518.38, 20.17
comparison results 20.25
test vectors 20.27
visualization 20.19
for loop 6.27
fork 19.2119.24
format specifiers 18.17
function 17.517.30
call 17.9
declaration 17.7
issues 17.23
marker 17.11
multiple calls 17.25
macro
see define
MCD
see multi-channel descriptor
memories
modeling 24.11
module 3.5
instantiation 3.73.12, 12.25, 14.17, 21.17
array of instances 21.19
multi-channel descriptor (MCD) 18.3518.38
gate-level modeling
see structural modeling
H
hierarchy
connecting 3.73.12
I
if 6.136.16
synthesis 15.17
ifdef
see ifdef
include
see include
incomplete assignment 13.11, 13.25
indentation 3.25
initial 3.13
synthesis 15.35
initialization 4.6, 19.8
N
name
rules 3.27
negedge 6.9, 13.19
net type 4.7, 4.234.27
conflict resolution 4.27
non-blocking assignment 8.5, 8.98.23, 9.79.19
clocked procedure 9.11, 10.11, B.20
intra-assignment delay 22.31, 22.32
ii
operator 5.3
arithmetic 5.5
synthesis 14.314.18
bit-wise 5.7
concatenation 5.23
conditional 5.21, 7.15
equality 5.19
difference between logical and case 5.17
logical 5.9
precedence 5.27
relational 5.15
replication 5.25
shift 5.13
unary reduction 5.11
output ports 3.5
S
shift operators 5.13
simulation
cycle 8.118.23
initialization 19.7
specify 22.11
conditional path delays 22.19
features 22.15
full path 22.17
parallel paths 22.17
parameter 22.21
path delays 22.18
specparam 22.21
state machine 15.915.16
stimulus 19.1119.24
clock generation 19.35
strength modeling
see logic strength modeling
strings 19.27
structural modeling 2.14, 21.521.28
synthesis directives 15.2515.34
system task
$display 18.15
$fclose 18.35
$fdisplay 18.38
$fmonitor 18.38
$fopen 18.35
$fstrobe 18.38
$fwrite 18.38
$monitor 18.23
$random 19.19
$readmemb 18.39
$readmemh 18.39
P
parameter 4.7, 4.37, 12.11
compared to specparam 22.22
defparam 4.40
overriding 4.39
see also specparam
path delays 22.11
PATHPULSE$ 22.26
ports
inout(bidirectional) 3.5, 24.15
input 3.5
named connection 3.9
ordered connection 3.11
output 3.5
unconnected 3.10, 3.12
posedge 6.9, 13.19
primitives 21.721.16
conditional 21.11
instantiation 21.15
see also UDP
procedural assignments 6.7, 7.11
procedure
always 6.5, 8.5
see also always
initial 6.5
see also initial
named 8.5
iii
$realtime 18.21
$stime 18.21
$strobe 18.19
$time 18.21
$timeformat 18.25
$write 18.15
formating 18.17
types
choosing the correct type 4.35
see net, register or parameter
summary of rules 4.45
U
UDP A.4
combinational A.9
edge-sensitive A.15, A.18
level sensitive A.13
ult 6.17
unary reduction operator 5.12
unknown logic values 21.13
user defined primitive
See UDP
T
task 17.5, ??17.30
call 17.15
declaration 17.13
disabling 17.19
issues 17.23
multiple calls 17.25
static 17.21
testbench use 19.37
without timing controls 17.17
testbench 2.21, 10.510.8
example 12.2112.30
organisation 19.9
pseudo-code driven 20.520.14
testbench output
see system task or file output
timescale
see timescale
timing control 8.258.35
event based 8.27
wait 8.29
tristates 16.13
V
variable
hierarchical access 19.29
vector 4.11
bit length 4.15
bit order 4.13
capture and playback 19.3119.34
W
wait 8.29
while loop 6.29
wire 4.234.27
work library 3.19
iv