Sunteți pe pagina 1din 369

Table of Contents

Overview..........................................................................................................................................................................1
Keywords........................................................................................................................................................................2
Formal Syntax.................................................................................................................................................................4
Evaluation Model..........................................................................................................................................................37
Literals...........................................................................................................................................................................38
Integer and Logic Literals..................................................................................................................................38
Real Literals.......................................................................................................................................................38
Time Literals......................................................................................................................................................38
String Literals.....................................................................................................................................................38
Array Literals.....................................................................................................................................................39
Structure Literals...............................................................................................................................................39
Arrays of Unpacked Structures...................................................................................................................39
Attributes.......................................................................................................................................................................40
Syntax................................................................................................................................................................40
Examples...........................................................................................................................................................40
Data Types....................................................................................................................................................................41
Integer Data Types............................................................................................................................................41
Non Integer Data Types....................................................................................................................................42
Real and Shortreal Type.............................................................................................................................42
Void Data Type...........................................................................................................................................42
Chandle Data Type.....................................................................................................................................42
Event Data Type.........................................................................................................................................42
Classes.......................................................................................................................................................43
String Type........................................................................................................................................................44
String Methods............................................................................................................................................45
Example................................................................................................................................................46
String Relational Operators.........................................................................................................................46
User-defined Type.............................................................................................................................................47
Enumeration Types...........................................................................................................................................49
Enumerated Type Ranges..........................................................................................................................49
Example................................................................................................................................................50
Example................................................................................................................................................50
Enumeration Methods.................................................................................................................................50
Structures..........................................................................................................................................................52
Packed Structures.......................................................................................................................................52
Signed and Unsigned Structures..........................................................................................................53
Unpacked Structures...................................................................................................................................53
Member Initialization.............................................................................................................................53
Assignment...........................................................................................................................................53
Limitations.............................................................................................................................................54
Unions...............................................................................................................................................................55
Packed Unions............................................................................................................................................55
Unpacked Unions........................................................................................................................................55
Tagged Unions............................................................................................................................................55
Class..................................................................................................................................................................56
Casting..............................................................................................................................................................57
Static Casting..............................................................................................................................................57
Bit-stream Casting.......................................................................................................................................57
Example 1.............................................................................................................................................57

Table of Contents
Data Types
Example 2.............................................................................................................................................58
$cast Dynamic Casting...............................................................................................................................58
Example 3.............................................................................................................................................59
Const Casting..............................................................................................................................................59
Arrays and Queues.......................................................................................................................................................60
Packed and Unpacked Arrays...........................................................................................................................60
Packed and Unpacked Array Dimensions...................................................................................................60
Multiple Dimensions....................................................................................................................................60
Packed Array Properties.............................................................................................................................60
Unpacked Array Properties.........................................................................................................................61
Indexing, Part-selects, and Slices...............................................................................................................61
Parameters of Unpacked Array Type..........................................................................................................61
Limitations.............................................................................................................................................61
Dynamic Arrays.................................................................................................................................................62
Dynamic Array Constructors.......................................................................................................................62
Other Dynamic Array Methods....................................................................................................................62
Associative Arrays.............................................................................................................................................64
Syntax.........................................................................................................................................................64
Associative Array Methods..........................................................................................................................66
Queues..............................................................................................................................................................67
Queue Methods...........................................................................................................................................67
Limitations.........................................................................................................................................................68
Array Querying Functions..................................................................................................................................69
Array Manipulation Methods..............................................................................................................................70
Array Locator Methods................................................................................................................................70
Array Ordering Methods..............................................................................................................................71
Array Reduction Methods............................................................................................................................72
Iterator Index Querying...............................................................................................................................73
Examples:.............................................................................................................................................73
Limitations...................................................................................................................................................74
Array Assignment..............................................................................................................................................75
Fixed-Size Arrays........................................................................................................................................75
Dynamic Arrays...........................................................................................................................................75
Associative Arrays.......................................................................................................................................75
Queues........................................................................................................................................................76
Different Array Kinds in The Assignment....................................................................................................76
Overwriting Existing Elements....................................................................................................................76
Out-of-bounds Elements.............................................................................................................................77
Vectors and Unpacked Arrays..............................................................................................................77
Data Declarations.........................................................................................................................................................78
Constants..........................................................................................................................................................78
Parameter Constants..................................................................................................................................78
Parameter Port List...............................................................................................................................78
Type Parameters..................................................................................................................................78
Omitting Default Parameter Values......................................................................................................79
$ as a Parameter Value........................................................................................................................79
Const Constants..........................................................................................................................................80
Localparam Constants................................................................................................................................80
Variables............................................................................................................................................................81
Nets...................................................................................................................................................................82
Specifying the Net Data Type.....................................................................................................................82
Scope and Lifetime............................................................................................................................................83

ii

Table of Contents
Data Declarations
Specifying the Lifetime of Local Variables..................................................................................................83
Signal Aliasing...................................................................................................................................................84
Type Operator...................................................................................................................................................85
Classes..........................................................................................................................................................................86
Overview............................................................................................................................................................86
Objects, Object Properties and Methods...........................................................................................................87
SystemVerilog Handles vs C Pointers........................................................................................................87
Object Properties and Object Parameters..................................................................................................87
Object Methods...........................................................................................................................................88
Constructors......................................................................................................................................................89
Inheritance.........................................................................................................................................................90
Chaining Constructors.......................................................................................................................................91
Specifying Arguments in the super.new Call...............................................................................................91
Specifying Arguments in the extends Clause..............................................................................................92
Assigning, Renaming, Copying.........................................................................................................................93
Assignment.................................................................................................................................................93
Shallow Copy..............................................................................................................................................93
Full Copy.....................................................................................................................................................94
Static Properties and Methods..........................................................................................................................95
Static Properties..........................................................................................................................................95
Static Methods............................................................................................................................................95
This....................................................................................................................................................................97
Super.................................................................................................................................................................98
Casting..............................................................................................................................................................99
When to Use $cast......................................................................................................................................99
Data Hiding and Encapsulation.......................................................................................................................101
Local and Protected Members..................................................................................................................101
Constant Class Properties...............................................................................................................................103
Overridden Members.......................................................................................................................................104
Virtual Methods................................................................................................................................................105
Default Values for Virtual Method Arguments...........................................................................................106
Abstract Classes and Pure Virtual Methods....................................................................................................107
Class Scope Resolution Operator...................................................................................................................108
Nested Classes...............................................................................................................................................110
Out-of-block Declarations................................................................................................................................111
Parameterized Classes...................................................................................................................................112
Type Parameters in Parameterized Classes.............................................................................................112
Omitting Default Parameter Values...........................................................................................................113
Equivalence of Specializations..................................................................................................................113
Static Properties in Parameterized Classes..............................................................................................114
Benefits of Parameterized Classes...........................................................................................................114
Local Class Parameters............................................................................................................................114
Typedef Class..................................................................................................................................................115
Memory Management......................................................................................................................................116
Assignment Statements.............................................................................................................................................117
Assignment Patterns.......................................................................................................................................117
Assignment Pattern Expressions..............................................................................................................117
Assignment Keys......................................................................................................................................118
Assignment Keys Precedence............................................................................................................119
Assignment Pattern on the left-hand side of an assignment.....................................................................119
Unpacked Array Concatenations.....................................................................................................................121
Limitations.................................................................................................................................................122

iii

Table of Contents
Tasks and Functions..................................................................................................................................................123
Functions.........................................................................................................................................................123
Non-mandatory begin ... end or fork ... join Blocks...................................................................................123
Formal Arguments.....................................................................................................................................123
Lifetime......................................................................................................................................................123
Return Values and void Functions............................................................................................................124
Discarding Function Return Values...........................................................................................................124
Constant Function Calls............................................................................................................................124
Statements Allowed in Functions by SystemVerilog 2009........................................................................124
Tasks...............................................................................................................................................................126
Non-mandatory begin ... end or fork ... join Blocks...................................................................................126
Formal Arguments.....................................................................................................................................126
Lifetime......................................................................................................................................................126
The return Statement................................................................................................................................127
Passing Arguments to Tasks and Functions...................................................................................................128
Pass by Value...........................................................................................................................................128
Pass by Reference....................................................................................................................................128
Limitations...........................................................................................................................................128
Default Argument Values..........................................................................................................................128
Argument Binding by Name......................................................................................................................129
Operators and Expressions.......................................................................................................................................130
Operators Precedence and Associativity.........................................................................................................130
Assignment Operators.....................................................................................................................................131
Wild Equality and Wild Inequality Operators....................................................................................................131
Real Operators................................................................................................................................................132
Concatenation.................................................................................................................................................132
Replication.......................................................................................................................................................132
Tagged Union Expressions and Member Access............................................................................................133
Aggregate Expressions...................................................................................................................................133
Operator Overloading......................................................................................................................................133
Streaming Operators (pack/unpack)................................................................................................................133
Conditional Operator.......................................................................................................................................134
Inside Operator................................................................................................................................................134
Constraint Block Operators.............................................................................................................................135
Behavioral Statements and Control Flow................................................................................................................136
Selection Statements.......................................................................................................................................136
Priority and Unique Keywords...................................................................................................................136
Set Membership Case Statement.............................................................................................................136
Pattern Matching.......................................................................................................................................137
Loop and Jump Statements.............................................................................................................................138
Loop Statements.......................................................................................................................................138
do ... while Loop..................................................................................................................................138
for Loop Enhancements......................................................................................................................138
foreach Loop.......................................................................................................................................138
Jump Statements......................................................................................................................................139
Final Blocks.....................................................................................................................................................140
Example....................................................................................................................................................140
Event and Level Control..................................................................................................................................141
iff Qualifier.................................................................................................................................................141
Sequence Events......................................................................................................................................141
Level-sensitive sequence controls............................................................................................................141
Event Control on Dynamic Class Members.....................................................................................................142
Waiting on a non-event Property...............................................................................................................142

iv

Table of Contents
Behavioral Statements and Control Flow
Waiting on an Event Property...................................................................................................................142
Waiting on a Method.................................................................................................................................143
Other Statements............................................................................................................................................144
Enhancement to Assignments Statements...............................................................................................144
Named Blocks...........................................................................................................................................144
Statements Labels....................................................................................................................................144
Disable Statement.....................................................................................................................................145
Processes....................................................................................................................................................................146
Always Processes...........................................................................................................................................146
always_comb and always_latch................................................................................................................146
always_ff...................................................................................................................................................146
Parallel fork-join Blocks...................................................................................................................................147
Process Control...............................................................................................................................................148
wait fork.....................................................................................................................................................148
disable fork................................................................................................................................................148
Class process..................................................................................................................................................150
Process Methods......................................................................................................................................150
Constrained Random Value Generation...................................................................................................................152
Overview..........................................................................................................................................................152
Rand, randc Modifiers.....................................................................................................................................153
Rand Modifier............................................................................................................................................153
Randc Modifier..........................................................................................................................................153
Disabling Random Variables - rand_mode...............................................................................................153
Random Variables...........................................................................................................................................156
Random Integral Types.............................................................................................................................156
Unpacked Arrays.......................................................................................................................................156
Dynamic Arrays.........................................................................................................................................157
Queues......................................................................................................................................................158
Associative Arrays.....................................................................................................................................158
Randomized Class Objects.......................................................................................................................159
Random Unpacked Structures..................................................................................................................159
Constraints Block.............................................................................................................................................161
External Constraint Blocks........................................................................................................................161
Constraint Inheritance...............................................................................................................................162
Operators..................................................................................................................................................162
Set Membership..................................................................................................................................163
Implication...........................................................................................................................................163
Distribution..........................................................................................................................................164
if-else Constraints...............................................................................................................................164
Iterative Constraints............................................................................................................................164
Global Constraints.....................................................................................................................................164
Variable Ordering......................................................................................................................................165
Static Constraint Blocks............................................................................................................................166
Function Calls in Constraints....................................................................................................................166
Limitations...........................................................................................................................................167
Controlling Constraints - constraint_mode................................................................................................167
Constraint Guards.....................................................................................................................................168
Debugging Constraints..............................................................................................................................169
Randomization Methods..................................................................................................................................170
Randomize Method...................................................................................................................................170
Inline Constraints................................................................................................................................170
In-line Random Variable Control.........................................................................................................171

Table of Contents
Constrained Random Value Generation
Inline Constraint Check.......................................................................................................................171
local:: Scope Resolution.....................................................................................................................172
Restricted inline constraint block........................................................................................................172
Pre_randomize and post_randomize Methods.........................................................................................173
Randomization of Scope Variables std::randomize().......................................................................................174
Syntax.......................................................................................................................................................174
Randomization of Scope Variables std::randomize() with Constraints.....................................................174
Extensions to std::randomize()..................................................................................................................174
System Functions and Methods......................................................................................................................176
$urandom()................................................................................................................................................176
$urandom_range()....................................................................................................................................176
srandom()..................................................................................................................................................176
get_randstate()..........................................................................................................................................176
set_randstate()..........................................................................................................................................177
$get_sv_seed............................................................................................................................................177
$get_random_seed...................................................................................................................................177
Random Weighted Case.................................................................................................................................178
Random Sequence Generation.......................................................................................................................179
Production Statements..............................................................................................................................179
Aborting Productions.................................................................................................................................180
Interleaving Productions............................................................................................................................181
Value Passing between Productions.........................................................................................................182
Random Stability.............................................................................................................................................184
Initialization of The Random Number Generator.......................................................................................184
Thread Stability.........................................................................................................................................184
Object Stability..........................................................................................................................................184
Manual Seeding........................................................................................................................................184
Example 1...........................................................................................................................................184
Example 2...........................................................................................................................................185
Maintaining Random Stability....................................................................................................................185
Changes in The Project Hierarchy......................................................................................................185
Rearrangement of The Code..............................................................................................................186
Code Execution Order........................................................................................................................187
Changes within Object Declarations...................................................................................................187
Preventing Random Stability Loss......................................................................................................187
Interprocess Synchronization...................................................................................................................................188
Semaphores....................................................................................................................................................188
Semaphore Methods.................................................................................................................................188
Mailboxes........................................................................................................................................................190
Mailbox Methods.......................................................................................................................................191
Parameterized Mailboxes..........................................................................................................................192
Non-parameterized Mailboxes..................................................................................................................192
Events..............................................................................................................................................................193
Triggering an Event...................................................................................................................................193
Waiting for an Event..................................................................................................................................193
triggered Property.....................................................................................................................................193
wait_order()...............................................................................................................................................193
Merging Events.........................................................................................................................................194
Reclaiming Events....................................................................................................................................194
Event Comparison.....................................................................................................................................194

vi

Table of Contents
Clocking Blocks..........................................................................................................................................................196
Clocking Block Declaration..............................................................................................................................196
Clocking Block Syntax...............................................................................................................................196
Example....................................................................................................................................................196
Clocking Block Scope and Lifetime...........................................................................................................197
Input and Output Skews..................................................................................................................................198
Input Sampling..........................................................................................................................................198
Cycle Delay Operator......................................................................................................................................199
Syntax.......................................................................................................................................................199
Example..............................................................................................................................................199
Default Clocking..............................................................................................................................................200
Events and Drives...........................................................................................................................................201
Clocking Block Events...............................................................................................................................201
Synchronous Drives..................................................................................................................................201
Clocking Properties.........................................................................................................................................202
Program.......................................................................................................................................................................203
$exit Task........................................................................................................................................................203
Anonymous Programs.....................................................................................................................................203
Example....................................................................................................................................................204
Assertions...................................................................................................................................................................205
Assertion Evaluation Model.............................................................................................................................205
Example....................................................................................................................................................205
Assertions Building Blocks..............................................................................................................................206
Overview...................................................................................................................................................206
Keywords..................................................................................................................................................206
List of Keywords.................................................................................................................................206
Identifiers...................................................................................................................................................207
Example..............................................................................................................................................207
Example 1....................................................................................................................................207
Example 2....................................................................................................................................207
Hierarchical References.....................................................................................................................207
Syntax..........................................................................................................................................207
Boolean Expressions................................................................................................................................207
Restrictions.........................................................................................................................................208
Built-in Functions.......................................................................................................................................208
Sampled value functions.....................................................................................................................208
Syntax..........................................................................................................................................208
$sampled......................................................................................................................................208
Example 1....................................................................................................................................209
Example 2....................................................................................................................................209
$rose, $fell, $stable......................................................................................................................209
Example 3....................................................................................................................................209
Example 4....................................................................................................................................210
$past............................................................................................................................................210
Example 5....................................................................................................................................210
System functions................................................................................................................................211
Example 6....................................................................................................................................211
Example 7....................................................................................................................................211
Sequences.......................................................................................................................................................212
Sequence Declaration...............................................................................................................................212
Syntax.................................................................................................................................................212
Sequence Instance.............................................................................................................................213
Example 1...........................................................................................................................................213

vii

Table of Contents
Assertions
Parameterized Sequences.................................................................................................................214
Untyped Arguments.....................................................................................................................214
Example 2..............................................................................................................................214
Typed Arguments.........................................................................................................................214
Example 3..............................................................................................................................215
Example 4..............................................................................................................................215
Example 5..............................................................................................................................215
Local Variable Formal Arguments................................................................................................216
Example 6..............................................................................................................................216
Sequence Operators.................................................................................................................................216
Syntax.................................................................................................................................................217
Sequence Operator Precedence...............................................................................................................217
Cycle Delay Operator ##...........................................................................................................................218
Syntax.................................................................................................................................................218
Examples............................................................................................................................................218
Example 1....................................................................................................................................218
Example 2....................................................................................................................................219
Example 3....................................................................................................................................219
Repetitions................................................................................................................................................219
Syntax.................................................................................................................................................219
Consecutive Repetition.......................................................................................................................220
Examples............................................................................................................................................220
Example 1....................................................................................................................................220
Example 2....................................................................................................................................221
Example 3....................................................................................................................................221
Example 4....................................................................................................................................222
Example 5....................................................................................................................................222
Nonconsecutive Repetition.................................................................................................................222
Example 6....................................................................................................................................222
Example 7....................................................................................................................................223
Goto Repetition...................................................................................................................................224
Example 8....................................................................................................................................224
And operator.............................................................................................................................................224
Syntax.................................................................................................................................................225
Example 1...........................................................................................................................................225
Intersect Operator.....................................................................................................................................225
Syntax.................................................................................................................................................226
Example..............................................................................................................................................226
Or Operator...............................................................................................................................................226
Syntax.................................................................................................................................................226
Example..............................................................................................................................................227
Example 1....................................................................................................................................227
Example 2....................................................................................................................................227
Throughout Operator.................................................................................................................................227
Syntax.................................................................................................................................................228
Example..............................................................................................................................................228
Within Operator.........................................................................................................................................228
Syntax.................................................................................................................................................228
Examples............................................................................................................................................229
First_match Operator................................................................................................................................229
Example..............................................................................................................................................229
End Point of a Sequence..........................................................................................................................230
Syntax.................................................................................................................................................231
Example..............................................................................................................................................231

viii

Table of Contents
Assertions
End Point of a Sequence in Multiclock Context........................................................................................232
Syntax.................................................................................................................................................232
Example..............................................................................................................................................232
Using Dynamic Variables in a Sequence..................................................................................................232
Assertion Variables Declared in a Named Sequence or Property......................................................233
Declaration Syntax.......................................................................................................................233
Assignment Syntax......................................................................................................................233
Local Variable Flow out Rules............................................................................................................234
Calling Subroutines on Match of a Sequence...........................................................................................235
Properties........................................................................................................................................................236
Property Declaration.................................................................................................................................236
Syntax.................................................................................................................................................236
Example 1...........................................................................................................................................236
Property Instance................................................................................................................................237
Example 2....................................................................................................................................237
Reset Expression................................................................................................................................237
Example 3....................................................................................................................................238
Parameterized Properties...................................................................................................................238
Untyped Arguments.....................................................................................................................239
Example 4..............................................................................................................................239
Typed Arguments.........................................................................................................................240
Example 5..............................................................................................................................240
Local Variable Formal Arguments................................................................................................240
Property Operators....................................................................................................................................240
Syntax.................................................................................................................................................240
Property Operator Precedence.................................................................................................................241
Not Operator.............................................................................................................................................241
Syntax.................................................................................................................................................241
Example..............................................................................................................................................241
And Operator.............................................................................................................................................242
Syntax.................................................................................................................................................242
Example..............................................................................................................................................242
Or Operator...............................................................................................................................................243
Syntax.................................................................................................................................................243
Example..............................................................................................................................................243
Implication Operators................................................................................................................................243
Syntax.................................................................................................................................................243
Examples............................................................................................................................................244
Example 1....................................................................................................................................244
Example 2....................................................................................................................................244
Implies Operator........................................................................................................................................245
Syntax.................................................................................................................................................245
Example..............................................................................................................................................245
iff Property.................................................................................................................................................247
Syntax.................................................................................................................................................247
Example..............................................................................................................................................247
Followed-by Property................................................................................................................................247
Syntax.................................................................................................................................................247
Examples............................................................................................................................................248
always, nexttime, and eventually Properties.............................................................................................248
always Property..................................................................................................................................248
Syntax..........................................................................................................................................248
Example.......................................................................................................................................249
nexttime Property................................................................................................................................249

ix

Table of Contents
Assertions
Syntax..........................................................................................................................................249
Example.......................................................................................................................................250
eventually Property.............................................................................................................................251
Syntax..........................................................................................................................................251
Example.......................................................................................................................................251
If Else Statement.......................................................................................................................................252
Example..............................................................................................................................................252
Case Statement........................................................................................................................................252
Syntax.................................................................................................................................................252
Example..............................................................................................................................................253
Recursive Properties.................................................................................................................................253
Abort Properties........................................................................................................................................253
Immediate Assertions......................................................................................................................................255
Syntax.......................................................................................................................................................255
Examples..................................................................................................................................................255
Concurrent Assertions.....................................................................................................................................257
Overview...................................................................................................................................................257
Syntax.................................................................................................................................................257
Assert Statement.......................................................................................................................................257
Syntax.................................................................................................................................................258
Example..............................................................................................................................................258
Cover Statements.....................................................................................................................................258
Syntax.................................................................................................................................................258
Example..............................................................................................................................................259
Embedding Concurrent Assertions in Procedural Code............................................................................260
Example..............................................................................................................................................260
Vacuity Feature.........................................................................................................................................261
Clocks..............................................................................................................................................................263
Examples..................................................................................................................................................263
Example 1...........................................................................................................................................263
Example 2...........................................................................................................................................263
Example 3...........................................................................................................................................263
Example 4...........................................................................................................................................264
Multiclock Support...........................................................................................................................................265
Multiclock sequences................................................................................................................................265
Example 1...........................................................................................................................................265
Multiclock properties.................................................................................................................................265
Example 2...........................................................................................................................................266
Encapsulating Assertions in Design Units.......................................................................................................267
Example....................................................................................................................................................267
Example 1...........................................................................................................................................267
Example 2...........................................................................................................................................268
Binding Assertions to Modules or Instances....................................................................................................269
Syntax.......................................................................................................................................................269
Example....................................................................................................................................................269
Binding to Specific Instance......................................................................................................................270
Example 1...........................................................................................................................................270
Example 2...........................................................................................................................................271
Binding SystemVerilog Assertions to VHDL..............................................................................................272
Example 1...........................................................................................................................................272
Expect Statement............................................................................................................................................274

Table of Contents
Coverage.....................................................................................................................................................................275
Overview..........................................................................................................................................................275
Covergroup......................................................................................................................................................276
Using Covergroups in Classes..................................................................................................................277
Coverage Points..............................................................................................................................................278
Specifying Bins for Values........................................................................................................................278
Wildcard Specification for Coverage Point Bins........................................................................................279
Specifying Bins for Transitions..................................................................................................................279
Limitations...........................................................................................................................................280
Automatic Bin Creation for Coverage Points.............................................................................................280
Cross Coverage...............................................................................................................................................281
Specifying Bins for Cross Coverage.........................................................................................................281
Coverage Options............................................................................................................................................282
Instance-specific Options..........................................................................................................................282
Type Options.............................................................................................................................................283
Coverage Methods..........................................................................................................................................285
Overriding build-in sample method...........................................................................................................285
Coverage System Tasks and Functions..........................................................................................................287
The Structure of option and type_option Members..........................................................................................288
Coverage Computation....................................................................................................................................289
Coverpoint Coverage Computation...........................................................................................................289
Cross Coverage Computation...................................................................................................................290
Type Coverage Computation....................................................................................................................290
Hierarchy.....................................................................................................................................................................292
Packages.........................................................................................................................................................292
Utilizing Package Contents.......................................................................................................................292
Referencing Package Contents with Scope Operator........................................................................293
Importing Package Contents..............................................................................................................293
Exporting Previously Imported Items..................................................................................................294
Compilation Unit and Top-level Instance.........................................................................................................296
Compilation Unit........................................................................................................................................296
Example..............................................................................................................................................296
Scoping Rules.....................................................................................................................................296
Top-level Instance.....................................................................................................................................297
Example..............................................................................................................................................297
Nested and Extern Modules............................................................................................................................298
Nested Modules........................................................................................................................................298
Binding PSL Units to Nested Modules................................................................................................298
Extern Modules.........................................................................................................................................298
Ports Declarations and Mapping.....................................................................................................................300
Ports Declarations.....................................................................................................................................300
List of Port Expressions......................................................................................................................301
Ports Mapping...........................................................................................................................................301
Implicit Mapping by Name..................................................................................................................301
Implicit Mapping by Wildcard..............................................................................................................301
Parameters in Hierarchical Path Name...........................................................................................................303
Timeunit and Timeprecision.............................................................................................................................304
Configurations.................................................................................................................................................305
Example....................................................................................................................................................305
Important Notes.........................................................................................................................................305
Type Parameters in Parameterized Design Elements.....................................................................................306

xi

Table of Contents
Interfaces.....................................................................................................................................................................307
Interface Declaration.......................................................................................................................................307
Interface Ports.................................................................................................................................................308
Example....................................................................................................................................................308
Modports..........................................................................................................................................................309
Modport Expressions................................................................................................................................309
Example..............................................................................................................................................310
Clocking Blocks and Modports..................................................................................................................310
Tasks and Function in Interfaces.....................................................................................................................311
Tasks and Functions in Modports.............................................................................................................311
Task Export in Modport.............................................................................................................................312
Multiple Tasks Exports..............................................................................................................................312
Parameterized Interfaces................................................................................................................................313
Example....................................................................................................................................................313
Interfaces and Specify Blocks.........................................................................................................................314
Virtual Interfaces..............................................................................................................................................315
Syntax.......................................................................................................................................................315
Virtual interfaces and clocking blocks.......................................................................................................316
Virtual interface modports and clocking blocks.........................................................................................317
System Tasks and Functions....................................................................................................................................318
Display Tasks and Functions...........................................................................................................................318
Overview...................................................................................................................................................318
$display system task...........................................................................................................................320
Example.......................................................................................................................................320
$sformat system task..........................................................................................................................320
Syntax..........................................................................................................................................320
Example.......................................................................................................................................321
$sformatf system function...................................................................................................................321
Syntax..........................................................................................................................................321
Example.......................................................................................................................................321
$psprintf function................................................................................................................................321
Syntax..........................................................................................................................................321
Example.......................................................................................................................................322
Printing Aggregates Using %p and %0p Formats.....................................................................................322
Arrays.................................................................................................................................................322
Structures...........................................................................................................................................323
Packed Unions....................................................................................................................................323
Class Handles.....................................................................................................................................324
Limiting Output with %0p.............................................................................................................325
Circular References.....................................................................................................................325
Truncating %p Field.....................................................................................................................326
Default Mode......................................................................................................................................326
Conversion Functions......................................................................................................................................328
Data Query Functions......................................................................................................................................329
$bits Function............................................................................................................................................329
$typename Function..................................................................................................................................329
$isunbounded Function.............................................................................................................................329
Array Query Functions.....................................................................................................................................330
Severity System Tasks....................................................................................................................................331
Example....................................................................................................................................................331
Assertion Control System Tasks......................................................................................................................332
Assertion Action Control System Tasks...........................................................................................................333
Example 1.................................................................................................................................................334
Example 2.................................................................................................................................................334

xii

Table of Contents
System Tasks and Functions
Example 3.................................................................................................................................................335
Assertion System Functions............................................................................................................................336
Random Number System Functions................................................................................................................337
Enhancements to Verilog System Tasks.........................................................................................................338
$readmem and $writemem Tasks...................................................................................................................340
$readmemb and $readmemh Tasks Enhancement..................................................................................340
$writememb and $writememh Tasks........................................................................................................340
Syntax.................................................................................................................................................340
Using Multidimensional Unpacked Arrays with $readmem and $writemem Tasks...................................340
File Format for Multidimensional Unpacked Arrays..................................................................................340
Miscellaneous Tasks and Functions................................................................................................................341
Syntax.......................................................................................................................................................341
Example....................................................................................................................................................341
Compiler Directives....................................................................................................................................................342
`define macros.................................................................................................................................................342
`include............................................................................................................................................................342
`begin_keywords and `end_keywords.............................................................................................................343
DPI................................................................................................................................................................................344
Overview..........................................................................................................................................................344
Tasks and Functions.................................................................................................................................344
Two Layers of DPI...........................................................................................................................................345
DPI SystemVerilog Layer..........................................................................................................................345
DPI Foreign Language Layer....................................................................................................................345
C/C++ and SystemVerilog Data Types............................................................................................................346
Open Arrays..............................................................................................................................................347
Enumerated Types....................................................................................................................................348
Ref Arguments..........................................................................................................................................348
Imported Tasks and Functions........................................................................................................................349
Function Result Type................................................................................................................................350
Formal Argument Types............................................................................................................................350
Function Arguments............................................................................................................................350
Pure and Context Properties.....................................................................................................................350
Miscellaneous...........................................................................................................................................351
Memory Management.........................................................................................................................351
Reentrancy of Imported Tasks............................................................................................................351
C++ Exceptions..................................................................................................................................351
Hierarchical Names on C++ Side.......................................................................................................351
Exported Tasks and Functions........................................................................................................................352
Name Space of Imported and Exported Functions..........................................................................................353
Disabling DPI Tasks and Functions.................................................................................................................354

xiii

Overview

SystemVerilog is a group of extensions to the Verilog HDL originally developed and approved by Accellera and then
standardized by IEEE.
SystemVerilog extends Verilog into the system-level space and the verification space.
This reference guide has been created based on the two revisions of IEEE Standard for SystemVerilog - Unified
Hardware Design, Specification, and Verification Language: IEEE Std 1800-2005 and IEEE Std 1800-2009.

Keywords

The list below shows Verilog and SystemVerilog keywords marked with two distinct colors. The Verilog-HDL keywords
are distinguished in blue while reserved keywords for SystemVerilog are displayed in black.
accept_on
alias
always
always_comb
always_ff
always_latch
and
assert
assign
assume
automatic
before
begin
bind
bins
binsof
bit
break
buf
bufif0
bufif1
byte
case
casex
casez
cell
chandle
checker
class
clocking
cmos
config
const
constraint
context
continue
cover
covergroup
coverpoint
cross
deassign
default
defparam
design
disable
dist
do
edge
else
end
endcase
endchecker
endclass
endclocking
endconfig
endfunction

endprimitive
endprogram
endproperty
endsequence
endspecify
endtable
endtask
enum
event
eventually
expect
export
extends
extern
final
first_match
for
force
foreach
forever
fork
forkjoin
function
generate
genvar
global
highz0
highz1
if
iff
ifnone
ignore_bins
illegal_bins
implies
import
incdir
include
initial
inout
input
inside
instance
int
integer
interface
intersect
join
join_any
join_none
large
let
liblist
library
local
localparam
logic

module
nand
negedge
new
nexttime
nmos
nor
noshowcancelled
not
notif0
notif1
null
or
output
package
packed
parameter
pmos
posedge
primitive
priority
program
property
protected
pull0
pull1
pulldown
pullup
pulsestyle_ondetect
pulsestyle_onevent
pure
rand
randc
randcase
randsequence
rcmos
real
realtime
ref
reg
reject_on
release
repeat
restrict
return
rnmos
rpmos
rtran
rtranif0
rtranif1
s_always
scalared
sequence
s_eventually
shortint
shortreal

specify
specparam
static
string
strong
strong0
strong1
struct
s_until
s_until_with
super
supply0
supply1
sync_accept_on
sync_reject_on
table
tagged
task
this
throughout
time
timeprecision
timeunit
tran
tranif0
tranif1
tri
tri0
tri1
triand
trior
trireg
type
typedef
union
unique
unique0
unsigned
until
until_with
untyped
use
uwire
var
vectored
virtual
void
wait
wait_order
wand
weak
weak0
weak1
while
wildcard
wire

SystemVerilog Reference
endgenerate
endgroup
endinterface
endmodule
endpackage

longint
macromodule
matches
medium
modport

Keywords
showcancelled
signed
small
s_nexttime
solve

with
within
wor
xnor
xor

Formal Syntax

A.1 Source text


A.1.1 Library source text
library_text ::= { library_description }
library_description ::=
|
|
|

library_declaration
include_statement
config_declaration
;

library_declaration ::= library library_identifier file_path_spec {, file_path_spec }


[ -incdir file_path_spec {, file_path_spec } ] ;
include_statement ::= include file_path_spec ;
A.1.2 SystemVerilog source text
source_text ::= [ timeunits_declaration ] { description }
description ::=
|
|
|
|
|
|
|

module_declaration
udp_declaration
interface_declaration
program_declaration
package_declaration
{ attribute_instance } package_item
{ attribute_instance } bind_directive
config_declaration

module_nonansi_header ::= { attribute_instance } module_keyword [ lifetime ]


module_identifier [ parameter_port_list ] list_of_ports ;
module_ansi_header ::= { attribute_instance } module_keyword [ lifetime ] module_identifier
[ parameter_port_list ] [ list_of_port_declarations ] ;
module_declaration ::=

|
|

module_nonansi_header
[ timeunits_declaration ]
{ module_item }
endmodule [ : module_identifier ]
module_ansi_header
[ timeunits_declaration ]
{ non_port_module_item }
endmodule [ : module_identifier ]
{ attribute_instance } module_keyword [ lifetime ] module_identifier ( .* ) ;
[ timeunits_declaration ]
{ module_item }
endmodule [ : module_identifier ]
extern module_nonansi_header
extern module_ansi_header

module_keyword ::= module | macromodule


interface_nonansi_header ::= { attribute_instance } interface [ lifetime ] interface_identifier
[ parameter_port_list ] list_of_ports ;
interface_ansi_header ::= {attribute_instance } interface [ lifetime ] interface_identifier
[ parameter_port_list ] [ list_of_port_declarations ] ;

SystemVerilog Reference

Formal Syntax

interface_declaration ::=

|
|

interface_nonansi_header
[ timeunits_declaration ]
{ interface_item }
endinterface [ : interface_identifier ]
interface_ansi_header
[ timeunits_declaration ]
{ non_port_interface_item }
endinterface [ : interface_identifier ]
{ attribute_instance } interface interface_identifier ( .* ) ;
[ timeunits_declaration ]
{ interface_item }
endinterface [ : interface_identifier ]
extern interface_nonansi_header
extern interface_ansi_header

program_nonansi_header ::= { attribute_instance } program [ lifetime ] program_identifier


[ parameter_port_list ] list_of_ports ;
program_ansi_header ::= {attribute_instance } program [ lifetime ] program_identifier
[ parameter_port_list ] [ list_of_port_declarations ] ;
program_declaration ::=

|
|

program_nonansi_header
[ timeunits_declaration ]
{ program_item }
endprogram [ : program_identifier ]
program_ansi_header
[ timeunits_declaration ]
{ non_port_program_item }
endprogram [ : program_identifier ]
{ attribute_instance } program program_identifier ( .* ) ;
[ timeunits_declaration ]
{ program_item }
endprogram [ : program_identifier ]
extern program_nonansi_header
extern program_ansi_header

class_declaration ::= [ virtual ] class [ lifetime ] class_identifier [ parameter_port_list ]


[ extends class_type [ ( list_of_arguments ) ] ];
{ class_item }
endclass [ : class_identifier]
package_declaration ::= { attribute_instance } package package_identifier ;
[ timeunits_declaration ] { { attribute_instance } package_item }
endpackage [ : package_identifier ]
timeunits_declaration ::= timeunit time_literal ;
| timeprecision time_literal ;
| timeunit time_literal ;
timeprecision time_literal ;
| timeprecision time_literal ;
timeunit time_literal ;
A.1.3 Module parameters and ports
parameter_port_list ::= # ( list_of_param_assignments {, parameter_port_declaration } )
| # ( parameter_port_declaration {, parameter_port_declaration } )
| #( )
parameter_port_declaration ::= parameter_declaration
| data_type list_of_param_assignments
| type list_of_type_assignments
list_of_ports ::= ( port {, port } )

SystemVerilog Reference

Formal Syntax

list_of_port_declarations ::= ( [ { attribute_instance} ansi_port_declaration


{, { attribute_instance} ansi_port_declaration }
] )
port_declaration ::=
|
|
|
|

{
{
{
{
{

attribute_instance
attribute_instance
attribute_instance
attribute_instance
attribute_instance

}
}
}
}
}

inout_declaration
input_declaration
output_declaration
ref_declaration
interface_port_declaration

port ::= [ port_expression ] | . port_identifier ( [ port_expression ] )


port_expression ::= port_reference | { port_reference {, port_reference } }
port_reference ::= port_identifier constant_select
port_direction ::= input | output | inout | ref
net_port_header ::= [ port_direction ] net_port_type
variable_port_header ::= [ port_direction ] variable_port_type
interface_port_header ::= interface_identifier [ . modport_identifier ]
| interface [ . modport_identifier ]
ansi_port_declaration ::= [ net_port_header | interface_port_header ]
port_identifier { unpacked_dimension }
| [ variable_port_header ] port_identifier
{ variable_dimension } [ = constant_expression ]
| [ net_port_header | variable_port_header ]
. port_identifier ( [ expression ] )
A.1.4 Module items
module_common_item ::=
|
|
|
|
|
|
|
|
|
|
|

module_or_generate_item_declaration
interface_instantiation
program_instantiation
concurrent_assertion_item
bind_directive
continuous_assign
net_alias
initial_construct
final_construct
always_construct
loop_generate_construct
conditional_generate_construct

module_item ::= port_declaration ; | non_port_module_item


module_or_generate_item ::=
|
|
|
|

{
{
{
{
{

attribute_instance
attribute_instance
attribute_instance
attribute_instance
attribute_instance

module_or_generate_item_declaration ::=
|
|
|
non_port_module_item ::=
|
|
|
|
|

}
}
}
}
}

parameter_override
gate_instantiation
udp_instantiation
module_instantiation
module_common_item

package_or_generate_item_declaration
genvar_declaration
clocking_declaration
default clocking clocking_identifier ;

generate_region
module_or_generate_item
specify_block
{ attribute_instance } specparam_declaration
program_declaration
module_declaration

SystemVerilog Reference

Formal Syntax
| interface_declaration
| timeunits_declaration

parameter_override ::= defparam list_of_defparam_assignments ;


bind_directive ::= bind bind_target_scope [: bind_target_instance_list] bind_instantiation ;
| bind bind_target_instance bind_instantiation ;
bind_target_scope ::= module_identifier | interface_identifier
bind_target_instance ::= hierarchical_identifier constant_bit_select
bind_target_instance_list ::= bind_target_instance {, bind_target_instance }
bind_instantiation ::= program_instantiation
| module_instantiation
| interface_instantiation
A.1.5 Configuration source text
config_declaration ::= config config_identifier ;
design_statement
{ config_rule_statement }
endconfig [ : config_identifier ]
design_statement ::= design { [ library_identifier . ] cell_identifier } ;
config_rule_statement ::=
|
|
|
|

default_clause liblist_clause ;
inst_clause liblist_clause ;
inst_clause use_clause ;
cell_clause liblist_clause ;
cell_clause use_clause ;

default_clause ::= default


inst_clause ::= instance inst_name
inst_name ::= topmodule_identifier { . instance_identifier }
cell_clause ::= cell [ library_identifier . ] cell_identifier
liblist_clause ::= liblist {library_identifier}
use_clause ::= use [ library_identifier . ] cell_identifier [ : config ]
A.1.6 Interface items
interface_or_generate_item ::= { attribute_instance } module_common_item
| { attribute_instance } modport_declaration
| { attribute_instance } extern_tf_declaration
extern_tf_declaration ::= extern method_prototype ;
| extern forkjoin task_prototype ;
interface_item ::= port_declaration ;
| non_port_interface_item
non_port_interface_item ::=
|
|
|
|

generate_region
interface_or_generate_item
program_declaration
interface_declaration
timeunits_declaration

A.1.7 Program items


program_item ::= port_declaration ;

SystemVerilog Reference

Formal Syntax

| non_port_program_item
non_port_program_item ::=
|
|
|
|
|
|

{ attribute_instance }
{ attribute_instance }
{ attribute_instance }
{ attribute_instance }
{ attribute_instance }
{ attribute_instance }
program_generate_item

continuous_assign
module_or_generate_item_declaration
initial_construct
final_construct
concurrent_assertion_item
timeunits_declaration

program_generate_item ::= loop_generate_construct


| conditional_generate_construct
| generate_region
A.1.8 Class items
class_item ::=
|
|
|
|
|
|

{
{
{
{
{
{
;

attribute_instance
attribute_instance
attribute_instance
attribute_instance
attribute_instance
attribute_instance

}
}
}
}
}
}

class_property
class_method
class_constraint
class_declaration
timeunits_declaration
covergroup_declaration

class_property ::= { property_qualifier } data_declaration


| const { class_item_qualifier } data_type
const_identifier [ = constant_expression ] ;
class_method ::=
|
|
|
|

{ method_qualifier } task_declaration
{ method_qualifier } function_declaration
extern { method_qualifier } method_prototype ;
{ method_qualifier } class_constructor_declaration
extern { method_qualifier } class_constructor_prototype

class_constructor_prototype ::= function new ( [ tf_port_list ] ) ;


class_constraint ::= constraint_prototype | constraint_declaration
class_item_qualifier ::= static | protected | local
property_qualifier ::= random_qualifier | class_item_qualifier
random_qualifier ::= rand | randc
method_qualifier ::= virtual | class_item_qualifier
method_prototype ::= task_prototype | function_prototype
class_constructor_declaration ::= function [ class_scope ] new [ ( [ tf_port_list ] ) ] ;
{ block_item_declaration }
[ super . new [ ( list_of_arguments ) ] ; ]
{ function_statement_or_null }
endfunction [ : new ]
A.1.9 Constraints
constraint_declaration ::= [ static ] constraint constraint_identifier constraint_block
constraint_block ::= { { constraint_block_item } }
constraint_block_item ::= solve identifier_list before identifier_list ;
| constraint_expression
constraint_expression ::= expression_or_dist ;
| expression -> constraint_set
| if ( expression ) constraint_set [ else constraint_set ]

SystemVerilog Reference

Formal Syntax
| foreach ( array_identifier [ loop_variables ] ) constraint_set

constraint_set ::= constraint_expression | { { constraint_expression } }


dist_list ::= dist_item {, dist_item }
dist_item ::= value_range [ dist_weight ]
dist_weight ::= := expression | :/ expression
constraint_prototype ::= [ static ] constraint constraint_identifier ;
extern_constraint_declaration ::= [ static ] constraint class_scope constraint_identifier
constraint_block
identifier_list ::= identifier {, identifier }
A.1.10 Package items
package_item ::= package_or_generate_item_declaration
| anonymous_program
| timeunits_declaration
package_or_generate_item_declaration ::= net_declaration
| data_declaration
| task_declaration
| function_declaration
| dpi_import_export
| extern_constraint_declaration
| class_declaration
| class_constructor_declaration
| parameter_declaration ;
| local_parameter_declaration
| covergroup_declaration
| overload_declaration
| concurrent_assertion_item_declaration
| ;
anonymous_program ::= program ; { anonymous_program_item } endprogram
anonymous_program_item ::= task_declaration
| function_declaration
| class_declaration
| covergroup_declaration
| class_constructor_declaration
| ;
A.2 Declarations
A.2.1 Declaration types
A.2.1.1 Module parameter declarations
local_parameter_declaration ::= localparam data_type_or_implicit list_of_param_assignments ;
| localparam type list_of_type_assignments ;
parameter_declaration ::= parameter data_type_or_implicit list_of_param_assignments
| parameter type list_of_type_assignments
specparam_declaration ::= specparam [ packed_dimension ] list_of_specparam_assignments ;
A.2.1.2 Port declarations
inout_declaration ::= inout net_port_type list_of_port_identifiers
input_declaration ::= input net_port_type list_of_port_identifiers

SystemVerilog Reference

Formal Syntax

| input variable_port_type list_of_variable_identifiers


output_declaration ::= output net_port_type list_of_port_identifiers
| output variable_port_type list_of_variable_port_identifiers
interface_port_declaration ::= interface_identifier list_of_interface_identifiers
| interface_identifier . modport_identifier list_of_interface_identifiers
ref_declaration ::= ref variable_port_type list_of_port_identifiers
A.2.1.3 Type declarations
data_declaration ::= [ const ] [ var ] [ lifetime ] data_type_or_implicit
list_of_variable_decl_assignments ;
| type_declaration
| package_import_declaration
| virtual_interface_declaration
package_import_declaration ::= import package_import_item {, package_import_item } ;
package_import_item ::= package_identifier :: identifier | package_identifier :: *
genvar_declaration ::= genvar list_of_genvar_identifiers ;
net_declaration ::= net_type [ drive_strength | charge_strength ] [ vectored | scalared ]
data_type_or_implicit [ delay3 ] list_of_net_decl_assignments ;
type_declaration ::= typedef data_type type_identifier { variable_dimension } ;
| typedef interface_instance_identifier . type_identifier type_identifier ;
| typedef [ enum | struct | union | class ] type_identifier ;
lifetime ::= static | automatic
A.2.2 Declaration data types
A.2.2.1 Net and variable types
casting_type ::= simple_type | constant_primary | signing
data_type ::= integer_vector_type [ signing ] { packed_dimension }
| integer_atom_type [ signing ]
| non_integer_type
| struct_union [ packed [ signing ] ] { struct_union_member { struct_union_member } }
{ packed_dimension }
| enum [ enum_base_type ] { enum_name_declaration {, enum_name_declaration } }
| string
| chandle
| virtual [ interface ] interface_identifier
| [ class_scope | package_scope ] type_identifier { packed_dimension }
| class_type
| event
| ps_covergroup_identifier
| type_reference
data_type_or_implicit ::= data_type | [ signing ] { packed_dimension }
enum_base_type ::= integer_atom_type [ signing ]
| integer_vector_type [ signing ] [ packed_dimension ]
| type_identifier [ packed_dimension ]
enum_name_declaration ::= enum_identifier [ [ integral_number [ : integral_number ] ] ]
[ = constant_expression ]
class_scope ::= class_type ::
class_type ::= ps_class_identifier [ parameter_value_assignment ]

10

SystemVerilog Reference

Formal Syntax

{ :: class_identifier [ parameter_value_assignment ] }
integer_type ::= integer_vector_type | integer_atom_type
integer_atom_type ::= byte | shortint | int | longint | integer | time
integer_vector_type ::= bit | logic | reg
non_integer_type ::= shortreal | real | realtime
net_type ::=
|
|
|
|
|
|
|
|
|
|
|

supply0
supply1
tri
triand
trior
trireg
tri0
tri1
uwire
wire
wand
wor

net_port_type ::= [ net_type ] data_type_or_implicit


variable_port_type ::= var_data_type
var_data_type ::= data_type | var data_type_or_implicit
signing ::= signed | unsigned
simple_type ::=
|
|
|

integer_type
non_integer_type
ps_type_identifier
ps_parameter_identifier

struct_union_member ::= { attribute_instance } [random_qualifier]


data_type_or_void list_of_variable_decl_assignments ;
data_type_or_void ::= data_type | void
struct_union ::= struct | union [ tagged ]
type_reference ::= type ( expression ) | type ( data_type )
A.2.2.2 Strengths
drive_strength ::= ( strength0, strength1 )
| ( strength1, strength0 )
| ( strength0, highz1 )
| ( strength1, highz0 )
| ( highz0, strength1 )
| ( highz1, strength0 )
strength0 ::= supply0 | strong0 | pull0 | weak0
strength1 ::= supply1 | strong1 | pull1 | weak1
charge_strength ::= ( small ) | ( medium ) | ( large )
A.2.2.3 Delays
delay3 ::= # delay_value
| # ( mintypmax_expression [, mintypmax_expression [, mintypmax_expression ] ] )
delay2 ::= # delay_value | # ( mintypmax_expression [, mintypmax_expression ] )

11

SystemVerilog Reference
delay_value ::=
|
|
|

Formal Syntax

unsigned_number
real_number
ps_identifier
time_literal

A.2.3 Declaration lists


list_of_defparam_assignments ::= defparam_assignment {, defparam_assignment }
list_of_genvar_identifiers ::= genvar_identifier {, genvar_identifier }
list_of_interface_identifiers ::= interface_identifier { unpacked_dimension }
{, interface_identifier { unpacked_dimension } }
list_of_net_decl_assignments ::= net_decl_assignment {, net_decl_assignment }
list_of_param_assignments ::= param_assignment {, param_assignment }
list_of_port_identifiers ::= port_identifier { unpacked_dimension }
{, port_identifier { unpacked_dimension } }
list_of_udp_port_identifiers ::= port_identifier {, port_identifier }
list_of_specparam_assignments ::= specparam_assignment {, specparam_assignment }
list_of_tf_variable_identifiers ::= port_identifier { variable_dimension } [ = expression ]
{, port_identifier { variable_dimension } [ = expression ] }
list_of_type_assignments ::= type_assignment {, type_assignment }
list_of_variable_decl_assignments ::= variable_decl_assignment {, variable_decl_assignment }
list_of_variable_identifiers ::= variable_identifier { variable_dimension }
{, variable_identifier { variable_dimension } }
list_of_variable_port_identifiers ::= port_identifier { variable_dimension }
[ = constant_expression ] {, port_identifier
{ variable_dimension } [ = constant_expression ] }
list_of_virtual_interface_decl ::= variable_identifier [ = interface_instance_identifier ]
{, variable_identifier [ = interface_instance_identifier ] }
A.2.4 Declaration assignments
defparam_assignment ::= hierarchical_parameter_identifier = constant_mintypmax_expression
net_decl_assignment ::= net_identifier { unpacked_dimension } [ = expression ]
param_assignment ::= parameter_identifier { unpacked_dimension } = constant_param_expression
specparam_assignment ::= specparam_identifier = constant_mintypmax_expression
| pulse_control_specparam
type_assignment ::= type_identifier = data_type
pulse_control_specparam ::= PATHPULSE$ = ( reject_limit_value [, error_limit_value ] )
|
PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor
= ( reject_limit_value [, error_limit_value ] )
error_limit_value ::= limit_value
reject_limit_value ::= limit_value
limit_value ::= constant_mintypmax_expression

12

SystemVerilog Reference

Formal Syntax

variable_decl_assignment ::=
|
|
|

variable_identifier { variable_dimension } [ = expression ]


dynamic_array_variable_identifier [ ] [ = dynamic_array_new ]
class_variable_identifier [ = class_new ]
[ covergroup_variable_identifier ] = new [ ( list_of_arguments ) ]

class_new ::= new [ ( list_of_arguments ) | expression ]


dynamic_array_new ::= new [ expression ] [ ( expression ) ]
A.2.5 Declaration ranges
unpacked_dimension ::= [ constant_range ] | [ constant_expression ]
packed_dimension ::= [ constant_range ] | unsized_dimension
associative_dimension ::= [ data_type ] | [ * ]
variable_dimension ::=
|
|
|

unsized_dimension
unpacked_dimension
associative_dimension
queue_dimension

queue_dimension ::= [ $ [ : constant_expression ] ]


unsized_dimension ::= [ ]
A.2.6 Function declarations
function_data_type ::= data_type | void
function_data_type_or_implicit ::= function_data_type | [ signing ] { packed_dimension }
function_declaration ::= function [ lifetime ] function_body_declaration
function_body_declaration ::= function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier ;
{ tf_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
| function_data_type_or_implicit
[ interface_identifier . | class_scope ] function_identifier
( [ tf_port_list ] );
{ block_item_declaration }
{ function_statement_or_null }
endfunction [ : function_identifier ]
function_prototype ::= function function_data_type function_identifier ( [ tf_port_list ] )
dpi_import_export ::= import dpi_spec_string [ dpi_function_import_property ]
[ c_identifier = ] dpi_function_proto;
| import dpi_spec_string [ dpi_task_import_property ]
[ c_identifier = ] dpi_task_proto;
| export dpi_spec_string [ c_identifier = ] function function_identifier;
| export dpi_spec_string [ c_identifier = ] task task_identifier;
dpi_spec_string ::= "DPI-C" | "DPI"
dpi_function_import_property ::= context | pure
dpi_task_import_property ::= context
dpi_function_proto ::= function_prototype
dpi_task_proto ::= task_prototype

13

SystemVerilog Reference

Formal Syntax

A.2.7 Task declarations


task_declaration ::= task [ lifetime ] task_body_declaration
task_body_declaration ::= [ interface_identifier . | class_scope ] task_identifier ;
{ tf_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
| [ interface_identifier . | class_scope ] task_identifier
( [ tf_port_list ] );
{ block_item_declaration }
{ statement_or_null }
endtask [ : task_identifier ]
tf_item_declaration ::= block_item_declaration | tf_port_declaration
tf_port_list ::= tf_port_item {, tf_port_item }
tf_port_item ::= { attribute_instance } [ tf_port_direction ] [ var ]
data_type_or_implicit [ port_identifier { variable_dimension } [ = expression ] ]
tf_port_direction ::= port_direction | const ref
tf_port_declaration ::= { attribute_instance } tf_port_direction [ var ]
data_type_or_implicit list_of_tf_variable_identifiers ;
task_prototype ::= task task_identifier ( [ tf_port_list ] )
A.2.8 Block item declarations
block_item_declaration ::=
|
|
|

{
{
{
{

attribute_instance
attribute_instance
attribute_instance
attribute_instance

}
}
}
}

data_declaration
local_parameter_declaration
parameter_declaration ;
overload_declaration

overload_declaration ::= bind overload_operator function data_type function_identifier


( overload_proto_formals ) ;
overload_operator ::= + | ++ | - | -- | * | ** | / | % | == | != | < | <= | > | >= | =
overload_proto_formals ::= data_type {, data_type}
A.2.9 Interface declarations
virtual_interface_declaration ::= virtual [ interface ] interface_identifier
list_of_virtual_interface_decl;
modport_declaration ::= modport modport_item {, modport_item } ;
modport_item ::= modport_identifier ( modport_ports_declaration {, modport_ports_declaration } )
modport_ports_declaration ::= { attribute_instance } modport_simple_ports_declaration
| { attribute_instance } modport_tf_ports_declaration
| { attribute_instance } modport_clocking_declaration
modport_clocking_declaration ::= clocking clocking_identifier
modport_simple_ports_declaration ::= port_direction modport_simple_port {, modport_simple_port }
modport_simple_port ::= port_identifier | . port_identifier ( [ expression ] )
modport_tf_ports_declaration ::= import_export modport_tf_port {, modport_tf_port }
modport_tf_port ::= method_prototype | tf_identifier
import_export ::= import | export

14

SystemVerilog Reference

Formal Syntax

A.2.10 Assertion declarations


concurrent_assertion_item ::= [ block_identifier : ] concurrent_assertion_statement
concurrent_assertion_statement ::= assert_property_statement
| assume_property_statement
| cover_property_statement
assert_property_statement::= assert property ( property_spec ) action_block
assume_property_statement::= assume property ( property_spec ) ;
cover_property_statement::= cover property ( property_spec ) statement_or_null
expect_property_statement ::= expect ( property_spec ) action_block
property_instance ::= ps_property_identifier [ ( [ list_of_arguments ] ) ]
concurrent_assertion_item_declaration ::= property_declaration | sequence_declaration
property_declaration ::= property property_identifier [ ( [ tf_port_list ] ) ] ;
{ assertion_variable_declaration }
property_spec ;
endproperty [ : property_identifier ]
property_spec ::= [clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr
property_expr ::=
|
|
|
|
|
|
|
|
|

sequence_expr
( property_expr )
not property_expr
property_expr or property_expr
property_expr and property_expr
sequence_expr |-> property_expr
sequence_expr |=> property_expr
if ( expression_or_dist ) property_expr [ else property_expr ]
property_instance
clocking_event property_expr

sequence_declaration ::= sequence sequence_identifier [ ( [ tf_port_list ] ) ] ;


{ assertion_variable_declaration }
sequence_expr ;
endsequence [ : sequence_identifier ]
sequence_expr ::=
|
|
|
|
|
|
|
|
|
|
|
|

cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }


sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
expression_or_dist [ boolean_abbrev ]
( expression_or_dist {, sequence_match_item } ) [ boolean_abbrev ]
sequence_instance [ sequence_abbrev ]
( sequence_expr {, sequence_match_item } ) [ sequence_abbrev ]
sequence_expr and sequence_expr
sequence_expr intersect sequence_expr
sequence_expr or sequence_expr
first_match ( sequence_expr {, sequence_match_item} )
expression_or_dist throughout sequence_expr
sequence_expr within sequence_expr
clocking_event sequence_expr

cycle_delay_range ::=
|
|
|

##
##
##
##

integral_number
identifier
( constant_expression )
[ cycle_delay_const_range_expression ]

sequence_method_call ::= sequence_instance . method_identifier


sequence_match_item ::= operator_assignment
| inc_or_dec_expression

15

SystemVerilog Reference

Formal Syntax

| subroutine_call
sequence_instance ::= ps_sequence_identifier [ ( [ list_of_arguments ] ) ]
formal_list_item ::= formal_identifier [ = actual_arg_expr ]
list_of_formals ::= formal_list_item {, formal_list_item }
actual_arg_expr ::= event_expression | $
boolean_abbrev ::= consecutive_repetition
| non_consecutive_repetition
| goto_repetition
sequence_abbrev ::= consecutive_repetition
consecutive_repetition ::= [* const_or_range_expression ]
non_consecutive_repetition ::= [= const_or_range_expression ]
goto_repetition ::= [-> const_or_range_expression ]
const_or_range_expression ::= constant_expression
| cycle_delay_const_range_expression
cycle_delay_const_range_expression ::= constant_expression : constant_expression
| constant_expression : $
expression_or_dist ::= expression [ dist { dist_list } ]
assertion_variable_declaration ::= var_data_type list_of_variable_identifiers ;
A.2.11 Covergroup declarations
covergroup_declaration ::= covergroup covergroup_identifier [ ( [ tf_port_list ] ) ] [ coverage_event ];
{ coverage_spec_or_option }
endgroup [ : covergroup_identifier ]
coverage_spec_or_option ::= {attribute_instance} coverage_spec | {attribute_instance} coverage_option;
coverage_option ::= option.member_identifier = expression | type_option.member_identifier = expression
coverage_spec ::= cover_point | cover_cross
coverage_event ::= clocking_event | @@( block_event_expression )
block_event_expression ::= block_event_expression or block_event_expression
| begin hierarchical_btf_identifier
| end hierarchical_btf_identifier
hierarchical_btf_identifier ::= hierarchical_tf_identifier
| hierarchical_block_identifier
| hierarchical_identifier [ class_scope ] method_identifier
cover_point ::= [ cover_point_identifier : ] coverpoint expression [ iff ( expression ) ] bins_or_empty
bins_or_empty ::= { {attribute_instance} { bins_or_options ; } }
| ;
bins_or_options ::= coverage_option
| [ wildcard ] bins_keyword bin_identifier [ [ [ expression ] ] ] = { open_range_list }
[ iff ( expression ) ]
| [ wildcard ] bins_keyword bin_identifier [ [ ] ] = trans_list
[ iff ( expression ) ]
| bins_keyword bin_identifier [ [ [ expression ] ] ] = default
[ iff ( expression ) ]

16

SystemVerilog Reference

Formal Syntax

| bins_keyword bin_identifier = default sequence [ iff ( expression ) ]


bins_keyword::= bins | illegal_bins | ignore_bins
range_list ::= value_range {, value_range }
trans_list ::= ( trans_set ) {, ( trans_set ) }
trans_set ::= trans_range_list { => trans_range_list }
trans_range_list ::=
|
|
|

trans_item
trans_item [ [* repeat_range ] ]
trans_item [ [-> repeat_range ] ]
trans_item [ [= repeat_range ] ]

trans_item ::= range_list


repeat_range ::= expression
| expression : expression
cover_cross ::= [ cover_point_identifier : ] cross list_of_coverpoints [ iff ( expression ) ]
select_bins_or_empty
list_of_coverpoints ::= cross_item, cross_item {, cross_item }
cross_item ::= cover_point_identifier | variable_identifier
select_bins_or_empty ::= { { bins_selection_or_option ; } }
| ;
bins_selection_or_option ::= { attribute_instance } coverage_option
| { attribute_instance } bins_selection
bins_selection ::= bins_keyword bin_identifier = select_expression [ iff ( expression ) ]
select_expression ::=
|
|
|
|

select_condition
! select_condition
select_expression && select_expression
select_expression || select_expression
( select_expression )

select_condition ::= binsof ( bins_expression ) [ intersect { open_range_list } ]


bins_expression ::= variable_identifier | cover_point_identifier [ . bins_identifier ]
open_range_list ::= open_value_range {, open_value_range }
open_value_range ::= value_range
A.3 Primitive instances
A.3.1 Primitive instantiation and instances
gate_instantiation ::= cmos_switchtype [delay3] cmos_switch_instance {, cmos_switch_instance };
| enable_gatetype [drive_strength] [delay3] enable_gate_instance
{, enable_gate_instance };
| mos_switchtype [delay3] mos_switch_instance {, mos_switch_instance };
| n_input_gatetype [drive_strength] [delay2] n_input_gate_instance
{, n_input_gate_instance };
| n_output_gatetype [drive_strength] [delay2] n_output_gate_instance
{, n_output_gate_instance };
| pass_en_switchtype [delay2] pass_enable_switch_instance
{, pass_enable_switch_instance };
| pass_switchtype pass_switch_instance {, pass_switch_instance } ;
| pulldown [pulldown_strength] pull_gate_instance {, pull_gate_instance };
| pullup [pullup_strength] pull_gate_instance {, pull_gate_instance };

17

SystemVerilog Reference

Formal Syntax

cmos_switch_instance ::= [ name_of_instance ] ( output_terminal, input_terminal,


ncontrol_terminal, pcontrol_terminal )
enable_gate_instance ::= [ name_of_instance ] ( output_terminal, input_terminal, enable_terminal )
mos_switch_instance ::= [ name_of_instance ] ( output_terminal, input_terminal, enable_terminal )
n_input_gate_instance ::= [ name_of_instance ] ( output_terminal, input_terminal {, input_terminal } )
n_output_gate_instance ::= [ name_of_instance ] ( output_terminal {, output_terminal }, input_terminal )
pass_switch_instance ::= [ name_of_instance ] ( inout_terminal, inout_terminal )
pass_enable_switch_instance ::= [ name_of_instance ] ( inout_terminal, inout_terminal, enable_terminal )
pull_gate_instance ::= [ name_of_instance ] ( output_terminal )
A.3.2 Primitive strengths
pulldown_strength ::= ( strength0, strength1 )
| ( strength1, strength0 )
| ( strength0 )
pullup_strength ::= ( strength0, strength1 )
| ( strength1, strength0 )
| ( strength1 )
A.3.3 Primitive terminals
enable_terminal ::= expression
inout_terminal ::= net_lvalue
input_terminal ::= expression
ncontrol_terminal ::= expression
output_terminal ::= net_lvalue
pcontrol_terminal ::= expression
A.3.4 Primitive gate and switch types
cmos_switchtype ::= cmos | rcmos
enable_gatetype ::= bufif0 | bufif1 | notif0 | notif1
mos_switchtype ::= nmos | pmos | rnmos | rpmos
n_input_gatetype ::= and | nand | or | nor | xor | xnor
n_output_gatetype ::= buf | not
pass_en_switchtype ::= tranif0 | tranif1 | rtranif1 | rtranif0
pass_switchtype ::= tran | rtran
A.4 Module, interface and generated instantiation
A.4.1 Instantiation
A.4.1.1 Module instantiation
module_instantiation ::= module_identifier [ parameter_value_assignment ] hierarchical_instance
{, hierarchical_instance };

18

SystemVerilog Reference

Formal Syntax

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 ::= param_expression
named_parameter_assignment ::= . parameter_identifier ( [ param_expression ] )
hierarchical_instance ::= name_of_instance ( [ list_of_port_connections ] )
name_of_instance ::= instance_identifier { unpacked_dimension }
list_of_port_connections ::= ordered_port_connection {, ordered_port_connection }
| named_port_connection {, named_port_connection }
ordered_port_connection ::= { attribute_instance } [ expression ]
named_port_connection ::= { attribute_instance } . port_identifier [ ( [ expression ] ) ]
| { attribute_instance } .*
A.4.1.2 Interface instantiation
interface_instantiation ::= interface_identifier [ parameter_value_assignment ]
hierarchical_instance {, hierarchical_instance } ;
A.4.1.3 Program instantiation
program_instantiation ::= program_identifier [ parameter_value_assignment ]
hierarchical_instance {, hierarchical_instance };
A.4.2 Generated instantiation
module_or_interface_or_generate_item ::= module_or_generate_item | interface_or_generate_item
generate_region ::= generate { module_or_interface_or_generate_item } endgenerate
loop_generate_construct ::= for ( genvar_initialization ; genvar_expression ; genvar_iteration )
generate_block
genvar_initialization ::= [ genvar ] genvar_identifier = constant_expression
genvar_iteration ::= genvar_identifier assignment_operator genvar_expression
| inc_or_dec_operator genvar_identifier
| genvar_identifier inc_or_dec_operator
conditional_generate_construct ::= if_generate_construct | case_generate_construct
if_generate_construct ::= if ( constant_expression ) generate_block_or_null
[ else generate_block_or_null ]
case_generate_construct ::= case ( constant_expression )
case_generate_item { case_generate_item }
endcase
case_generate_item ::= constant_expression {, constant_expression } : generate_block_or_null
| default [ : ] generate_block_or_null
generate_block ::= module_or_interface_or_generate_item
| [ generate_block_identifier : ] begin [ : generate_block_identifier ]
{ module_or_interface_or_generate_item }
end [ : generate_block_identifier ]
generate_block_or_null ::= generate_block | ;

19

SystemVerilog Reference

Formal Syntax

A.5 UDP declaration and instantiation


A.5.1 UDP declaration
udp_nonansi_declaration ::= { attribute_instance } primitive udp_identifier ( udp_port_list );
udp_ansi_declaration ::= { attribute_instance } primitive udp_identifier ( udp_declaration_port_list );
udp_declaration ::= udp_nonansi_declaration udp_port_declaration { udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
| udp_ansi_declaration
udp_body
endprimitive [ : udp_identifier ]
| extern udp_nonansi_declaration
| extern udp_ansi_declaration
| { attribute_instance } primitive udp_identifier ( .* ) ;
{ udp_port_declaration }
udp_body
endprimitive [ : udp_identifier ]
A.5.2 UDP ports
udp_port_list ::= output_port_identifier, input_port_identifier {, input_port_identifier }
udp_declaration_port_list ::= udp_output_declaration, udp_input_declaration
{, udp_input_declaration }
udp_port_declaration ::= udp_output_declaration ;
| udp_input_declaration ;
| udp_reg_declaration ;
udp_output_declaration ::= { attribute_instance } output port_identifier
| { attribute_instance } output reg port_identifier [ = constant_expression ]
udp_input_declaration ::= { attribute_instance } input list_of_udp_port_identifiers
udp_reg_declaration ::= { attribute_instance } reg variable_identifier
A.5.3 UDP body
udp_body ::= combinational_body | sequential_body
combinational_body ::= table combinational_entry { combinational_entry } endtable
combinational_entry ::= level_input_list : output_symbol ;
sequential_body ::= [ udp_initial_statement ] table sequential_entry { sequential_entry } endtable
udp_initial_statement ::= initial output_port_identifier = init_val ;
init_val ::= 1'b0 | 1'b1 | 1'bx | 1'bX | 1'B0 | 1'B1 | 1'Bx | 1'BX | 1 | 0
sequential_entry ::= seq_input_list : current_state : next_state;
seq_input_list ::= level_input_list | edge_input_list
level_input_list ::= level_symbol { level_symbol }
edge_input_list ::= { level_symbol } edge_indicator { level_symbol }
edge_indicator ::= ( level_symbol level_symbol ) | edge_symbol
current_state ::= level_symbol
next_state ::= output_symbol | -

20

SystemVerilog Reference

Formal Syntax

output_symbol ::= 0 | 1 | x | X
level_symbol ::= 0 | 1 | x | X | ? | b | B
edge_symbol ::= r | R | f | F | p | P | n | N | *
A.5.4 UDP instantiation
udp_instantiation ::= udp_identifier [ drive_strength ] [ delay2 ] udp_instance {, udp_instance } ;
udp_instance ::= [ name_of_instance ] ( output_terminal, input_terminal {, input_terminal } )
A.6 Behavioral statements
A.6.1 Continuous assignment and net alias statements
continuous_assign ::= assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;
| assign [ delay_control ] list_of_variable_assignments ;
list_of_net_assignments ::= net_assignment {, net_assignment }
list_of_variable_assignments ::= variable_assignment {, variable_assignment }
net_alias ::= alias net_lvalue = net_lvalue { = net_lvalue } ;
net_assignment ::= net_lvalue = expression
A.6.2 Procedural blocks and assignments
initial_construct ::= initial statement_or_null
always_construct ::= always_keyword statement
always_keyword ::= always | always_comb | always_latch | always_ff
final_construct ::= final function_statement
blocking_assignment ::= variable_lvalue = delay_or_event_control expression
| hierarchical_dynamic_array_variable_identifier = dynamic_array_new
| [ implicit_class_handle . | class_scope | package_scope ]
hierarchical_variable_identifier
select = class_new | operator_assignment
operator_assignment ::= variable_lvalue assignment_operator expression
assignment_operator ::= = | += | -= | *= | /= | %= | &= | |= | ^= | <<= | >>= | <<<= | >>>=
nonblocking_assignment ::= variable_lvalue <= [ delay_or_event_control ] expression
procedural_continuous_assignment ::= assign variable_assignment
| deassign variable_lvalue
| force variable_assignment
| force net_assignment
| release variable_lvalue
| release net_lvalue
variable_assignment ::= variable_lvalue = expression
A.6.3 Parallel and sequential blocks
action_block ::= statement_or_null
| [ statement ] else statement_or_null
seq_block ::= begin [ : block_identifier ]

21

SystemVerilog Reference

Formal Syntax

{ block_item_declaration }
{ statement_or_null }
end [ : block_identifier ]
par_block ::= fork [ : block_identifier ]
{ block_item_declaration }
{ statement_or_null }
join_keyword [ : block_identifier ]
join_keyword ::= join | join_any | join_none
A.6.4 Statements
statement_or_null ::= statement | { attribute_instance } ;
statement ::= [ block_identifier : ] { attribute_instance } statement_item
statement_item ::=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

blocking_assignment ;
nonblocking_assignment ;
procedural_continuous_assignment ;
case_statement
conditional_statement
inc_or_dec_expression ;
subroutine_call_statement
disable_statement
event_trigger
loop_statement
jump_statement
par_block
procedural_timing_control_statement
seq_block
wait_statement
procedural_assertion_statement
clocking_drive ;
randsequence_statement
randcase_statement
expect_property_statement

function_statement ::= statement


function_statement_or_null ::= function_statement | { attribute_instance };
variable_identifier_list ::= variable_identifier {, variable_identifier }
A.6.5 Timing control statements
procedural_timing_control_statement ::= procedural_timing_control statement_or_null
delay_or_event_control ::= delay_control
| event_control
| repeat ( expression ) event_control
delay_control ::= # delay_value
| # ( mintypmax_expression )
event_control ::=
|
|
|
|

@ hierarchical_event_identifier
@ ( event_expression )
@*
@ (*)
@ sequence_instance

event_expression ::=
|
|
|

[ edge_identifier ] expression [ iff expression ]


sequence_instance [ iff expression ]
event_expression or event_expression
event_expression, event_expression

22

SystemVerilog Reference

Formal Syntax

procedural_timing_control ::= delay_control


| event_control
| cycle_delay
jump_statement ::= return [ expression ] ;
| break ;
| continue ;
wait_statement ::= wait ( expression ) statement_or_null
| wait fork ;
| wait_order ( hierarchical_identifier {, hierarchical_identifier } ) action_block
event_trigger ::= -> hierarchical_event_identifier ;
| ->> [ delay_or_event_control ] hierarchical_event_identifier ;
disable_statement ::= disable hierarchical_task_identifier ;
| disable hierarchical_block_identifier ;
| disable fork ;
A.6.6 Conditional statements
conditional_statement ::= if ( cond_predicate ) statement_or_null [ else statement_or_null ]
| unique_priority_if_statement
unique_priority_if_statement ::= [ unique_priority ] if ( cond_predicate ) statement_or_null
{ else if ( cond_predicate ) statement_or_null }
[ else statement_or_null ]
unique_priority ::= unique | priority
cond_predicate ::= expression_or_cond_pattern { &&& expression_or_cond_pattern }
expression_or_cond_pattern ::= expression | cond_pattern
cond_pattern ::= expression matches pattern
A.6.7 case statements
case_statement ::= [ unique_priority ] case_keyword ( expression ) case_item { case_item } endcase
| [ unique_priority ] case_keyword ( expression ) matches case_pattern_item
{ case_pattern_item }
endcase
| [ unique_priority ] case ( expression ) inside case_inside_item
{ case_inside_item }
endcase
case_keyword ::= case | casez | casex
case_item ::= expression {, expression } : statement_or_null
| default [ : ] statement_or_null
case_pattern_item ::= pattern [ &&& expression ] : statement_or_null
| default [ : ] statement_or_null
case_inside_item ::= open_range_list : statement_or_null
| default [ : ] statement_or_null
randcase_statement ::= randcase randcase_item { randcase_item } endcase
randcase_item ::= expression : statement_or_null
A.6.7.1 Patterns
pattern ::= . variable_identifier
| .*
| constant_expression

23

SystemVerilog Reference

Formal Syntax

| tagged member_identifier [ pattern ]


| '{ pattern {, pattern } }
| '{ member_identifier : pattern {, member_identifier : pattern } }
assignment_pattern ::= '{ expression {, expression } }
| '{ structure_pattern_key : expression
{, structure_pattern_key : expression } }
| '{ array_pattern_key : expression {, array_pattern_key : expression } }
| '{ constant_expression { expression {, expression } } }
structure_pattern_key ::= member_identifier | assignment_pattern_key
array_pattern_key ::= constant_expression | assignment_pattern_key
assignment_pattern_key ::= simple_type | default
assignment_pattern_expression ::= [ assignment_pattern_expression_type ] assignment_pattern
assignment_pattern_expression_type ::= ps_type_identifier
| ps_parameter_identifier
| integer_atom_type
constant_assignment_pattern_expression ::= assignment_pattern_expression
assignment_pattern_net_lvalue ::= '{ net_lvalue {, net_lvalue } }
assignment_pattern_variable_lvalue ::= '{ variable_lvalue {, variable_lvalue } }
A.6.8 Looping statements
loop_statement ::= forever statement_or_null
| repeat ( expression ) statement_or_null
| while ( expression ) statement_or_null
| for ( for_initialization ; expression ; for_step )
statement_or_null
| do statement_or_null while ( expression ) ;
| foreach ( array_identifier [ loop_variables ] ) statement
for_initialization ::= list_of_variable_assignments
| for_variable_declaration {, for_variable_declaration }
for_variable_declaration ::= data_type variable_identifier = expression
{, variable_identifier = expression }
for_step ::= for_step_assignment {, for_step_assignment }
for_step_assignment ::= operator_assignment
| inc_or_dec_expression
| function_subroutine_call
loop_variables ::= [ index_variable_identifier ] {, [ index_variable_identifier ] }
A.6.9 Subroutine call statements
subroutine_call_statement ::= subroutine_call ;
| void ' ( function_subroutine_call ) ;
A.6.10 Assertion statements
procedural_assertion_statement ::= concurrent_assertion_statement | immediate_assert_statement
immediate_assert_statement ::= assert ( expression ) action_block
A.6.11 Clocking block

24

SystemVerilog Reference

Formal Syntax

clocking_declaration ::= [ default ] clocking [ clocking_identifier ] clocking_event ;


{ clocking_item }
endclocking [ : clocking_identifier ]
clocking_event ::= @ identifier | @ ( event_expression )
clocking_item ::= default default_skew ;
| clocking_direction list_of_clocking_decl_assign ;
| { attribute_instance } concurrent_assertion_item_declaration
default_skew ::= input clocking_skew
| output clocking_skew
| input clocking_skew output clocking_skew
clocking_direction ::=
|
|
|

input [ clocking_skew ]
output [ clocking_skew ]
input [ clocking_skew ] output [ clocking_skew ]
inout

list_of_clocking_decl_assign ::= clocking_decl_assign {, clocking_decl_assign }


clocking_decl_assign ::= signal_identifier [ = expression ]
clocking_skew ::= edge_identifier [ delay_control ] | delay_control
clocking_drive ::= clockvar_expression <= [ cycle_delay ] expression
| cycle_delay clockvar_expression <= expression
cycle_delay ::= ## integral_number
| ## identifier
| ## ( expression )
clockvar ::= hierarchical_identifier
clockvar_expression ::= clockvar select
A.6.12 Randsequence
randsequence_statement ::= randsequence ( [ production_identifier ] )
production { production }
endsequence
production ::= [ function_data_type ] production_identifier [ ( tf_port_list ) ] : rs_rule
{ | rs_rule };
rs_rule ::= rs_production_list [ := weight_specification [ rs_code_block ] ]
rs_production_list ::= rs_prod { rs_prod }
| rand join [ ( expression ) ] production_item production_item
{ production_item }
weight_specification ::= integral_number | ps_identifier | ( expression )
rs_code_block ::= { { data_declaration } { statement_or_null } }
rs_prod ::=
|
|
|
|

production_item
rs_code_block
rs_if_else
rs_repeat
rs_case

production_item ::= production_identifier [ ( list_of_arguments ) ]


rs_if_else ::= if ( expression ) production_item [ else production_item ]
rs_repeat ::= repeat ( expression ) production_item

25

SystemVerilog Reference

Formal Syntax

rs_case ::= case ( expression ) rs_case_item { rs_case_item } endcase


rs_case_item ::= expression {, expression } : production_item ;
| default [ : ] production_item ;
A.7 Specify section
A.7.1 Specify block declaration
specify_block ::= specify { specify_item } endspecify
specify_item ::=
|
|
|
|

specparam_declaration
pulsestyle_declaration
showcancelled_declaration
path_declaration
system_timing_check

pulsestyle_declaration ::= pulsestyle_onevent list_of_path_outputs ;


| pulsestyle_ondetect list_of_path_outputs ;
showcancelled_declaration ::= showcancelled list_of_path_outputs ;
| noshowcancelled list_of_path_outputs ;
A.7.2 Specify path declarations
path_declaration ::= simple_path_declaration ;
| edge_sensitive_path_declaration ;
| state_dependent_path_declaration ;
simple_path_declaration ::= parallel_path_description = path_delay_value
| full_path_description = path_delay_value
parallel_path_description ::= ( specify_input_terminal_descriptor [ polarity_operator ]
=> specify_output_terminal_descriptor )
full_path_description ::= ( list_of_path_inputs [ polarity_operator ] *> list_of_path_outputs )
list_of_path_inputs ::= specify_input_terminal_descriptor {, specify_input_terminal_descriptor }
list_of_path_outputs ::= specify_output_terminal_descriptor {, specify_output_terminal_descriptor }
A.7.3 Specify block terminals
specify_input_terminal_descriptor ::= input_identifier [ [ constant_range_expression ] ]
specify_output_terminal_descriptor ::= output_identifier [ [ constant_range_expression ] ]
input_identifier ::= input_port_identifier | inout_port_identifier |
interface_identifier.port_identifier
output_identifier ::= output_port_identifier
| inout_port_identifier
| interface_identifier.port_identifier
A.7.4 Specify path delays
path_delay_value ::= list_of_path_delay_expressions | ( list_of_path_delay_expressions )
list_of_path_delay_expressions ::= t_path_delay_expression
| trise_path_delay_expression, tfall_path_delay_expression
| trise_path_delay_expression, tfall_path_delay_expression, tz_path_delay_expression
| t01_path_delay_expression, t10_path_delay_expression, t0z_path_delay_expression,
tz1_path_delay_expression, t1z_path_delay_expression, tz0_path_delay_expression
| t01_path_delay_expression, t10_path_delay_expression, t0z_path_delay_expression,
tz1_path_delay_expression, t1z_path_delay_expression, tz0_path_delay_expression,

26

SystemVerilog Reference

Formal Syntax

t0x_path_delay_expression, tx1_path_delay_expression, t1x_path_delay_expression,


tx0_path_delay_expression, txz_path_delay_expression, tzx_path_delay_expression
t_path_delay_expression ::= path_delay_expression
trise_path_delay_expression ::= path_delay_expression
tfall_path_delay_expression ::= path_delay_expression
tz_path_delay_expression ::= path_delay_expression
t01_path_delay_expression ::= path_delay_expression
t10_path_delay_expression ::= path_delay_expression
t0z_path_delay_expression ::= path_delay_expression
tz1_path_delay_expression ::= path_delay_expression
t1z_path_delay_expression ::= path_delay_expression
tz0_path_delay_expression ::= path_delay_expression
t0x_path_delay_expression ::= path_delay_expression
tx1_path_delay_expression ::= path_delay_expression
t1x_path_delay_expression ::= path_delay_expression
tx0_path_delay_expression ::= path_delay_expression
txz_path_delay_expression ::= path_delay_expression
tzx_path_delay_expression ::= path_delay_expression
path_delay_expression ::= constant_mintypmax_expression
edge_sensitive_path_declaration ::= parallel_edge_sensitive_path_description = path_delay_value
| full_edge_sensitive_path_description = path_delay_value
parallel_edge_sensitive_path_description ::= ( [ edge_identifier ] specify_input_terminal_descriptor =>
( specify_output_terminal_descriptor [ polarity_operator ]
: data_source_expression ) )
full_edge_sensitive_path_description ::= ( [ edge_identifier ] list_of_path_inputs *> (
list_of_path_outputs [ polarity_operator ]
: data_source_expression ) )
data_source_expression ::= expression
edge_identifier ::= posedge | negedge
state_dependent_path_declaration ::= if ( module_path_expression ) simple_path_declaration
| if ( module_path_expression ) edge_sensitive_path_declaration
| ifnone simple_path_declaration
polarity_operator ::= + | A.7.5 System timing checks
A.7.5.1 System timing check commands
system_timing_check ::=
|
|
|

$setup_timing_check
$hold_timing_check
$setuphold_timing_check
$recovery_timing_check

27

SystemVerilog Reference
|
|
|
|
|
|
|
|

Formal Syntax
$removal_timing_check
$recrem_timing_check
$skew_timing_check
$timeskew_timing_check
$fullskew_timing_check
$period_timing_check
$width_timing_check
$nochange_timing_check

$setup_timing_check ::= $setup ( data_event, reference_event, timing_check_limit [, [ notifier ] ] );


$hold_timing_check ::= $hold ( reference_event, data_event, timing_check_limit [, [ notifier ] ] );
$setuphold_timing_check ::= $setuphold (reference_event, data_event, timing_check_limit,
timing_check_limit [, [ notifier ] [, [ stamptime_condition ]
[, [ checktime_condition ][, [ delayed_reference ]
[, [ delayed_data ] ] ] ] ] ] );
$recovery_timing_check ::= $recovery ( reference_event, data_event, timing_check_limit
[, [ notifier ] ] );
$removal_timing_check ::= $removal ( reference_event, data_event, timing_check_limit
[, [ notifier ] ] );
$recrem_timing_check ::= $recrem ( reference_event, data_event, timing_check_limit,
timing_check_limit [, [ notifier ] [, [ stamptime_condition ]
[, [ checktime_condition ] [, [ delayed_reference ]
[, [ delayed_data ] ] ] ] ] ] );
$skew_timing_check ::= $skew ( reference_event, data_event, timing_check_limit [, [ notifier ] ] );
$timeskew_timing_check ::= $timeskew ( reference_event, data_event, timing_check_limit
[, [ notifier ] [, [ event_based_flag ] [, [ remain_active_flag ] ] ] ] );
$fullskew_timing_check ::= $fullskew ( reference_event, data_event, timing_check_limit,
timing_check_limit [, [ notifier ] [, [ event_based_flag ]
[, [ remain_active_flag ] ] ] ] ) ;
$period_timing_check ::= $period ( controlled_reference_event, timing_check_limit [, [ notifier ] ] );
$width_timing_check ::= $width ( controlled_reference_event, timing_check_limit,
threshold [, [ notifier ] ] );
$nochange_timing_check ::= $nochange ( reference_event, data_event, start_edge_offset,
end_edge_offset [, [ notifier ] ] ) ;
A.7.5.2 System timing check command arguments
checktime_condition ::= mintypmax_expression
controlled_reference_event ::= controlled_timing_check_event
data_event ::= timing_check_event
delayed_data ::= terminal_identifier | terminal_identifier [ constant_mintypmax_expression ]
delayed_reference ::= terminal_identifier | terminal_identifier [ constant_mintypmax_expression ]
end_edge_offset ::= mintypmax_expression
event_based_flag ::= constant_expression
notifier ::= variable_identifier
reference_event ::= timing_check_event

28

SystemVerilog Reference

Formal Syntax

remain_active_flag ::= constant_mintypmax_expression


stamptime_condition ::= mintypmax_expression
start_edge_offset ::= mintypmax_expression
threshold ::=constant_expression
timing_check_limit ::= expression
A.7.5.3 System timing check event definitions
timing_check_event ::= [timing_check_event_control] specify_terminal_descriptor
[ &&& timing_check_condition ]
controlled_timing_check_event ::= timing_check_event_control specify_terminal_descriptor
[ &&& timing_check_condition ]
timing_check_event_control ::= posedge
| negedge
| edge_control_specifier
specify_terminal_descriptor ::= specify_input_terminal_descriptor
| specify_output_terminal_descriptor
edge_control_specifier ::= edge [ edge_descriptor {, edge_descriptor } ]
edge_descriptor ::= 01 | 10 | z_or_x zero_or_one | zero_or_one z_or_x
zero_or_one ::= 0 | 1
z_or_x ::= x | X | z | Z
timing_check_condition ::= scalar_timing_check_condition
| ( scalar_timing_check_condition )
scalar_timing_check_condition ::=
|
|
|
|
|

expression
~ expression
expression == scalar_constant
expression === scalar_constant
expression != scalar_constant
expression !== scalar_constant

scalar_constant ::= 1'b0 | 1'b1 | 1'B0 | 1'B1 | 'b0 | 'b1 | 'B0 | 'B1 | 1 | 0
A.8 Expressions
A.8.1 Concatenations
concatenation ::= { expression {, expression } }
constant_concatenation ::= { constant_expression {, constant_expression } }
constant_multiple_concatenation ::= { constant_expression constant_concatenation }
module_path_concatenation ::= { module_path_expression {, module_path_expression } }
module_path_multiple_concatenation ::= { constant_expression module_path_concatenation }
multiple_concatenation ::= { expression concatenation }
streaming_concatenation ::= { stream_operator [ slice_size ] stream_concatenation }
stream_operator ::= >> | <<
slice_size ::= simple_type | constant_expression

29

SystemVerilog Reference

Formal Syntax

stream_concatenation ::= { stream_expression {, stream_expression } }


stream_expression ::= expression [ with [ array_range_expression ] ]
array_range_expression ::=
|
|
|

expression
expression : expression
expression +: expression
expression -: expression

empty_queue ::= { }
A.8.2 Subroutine calls
constant_function_call ::= function_subroutine_call
tf_call ::= ps_or_hierarchical_tf_identifier { attribute_instance } [ ( list_of_arguments ) ]
system_tf_call ::= system_tf_identifier [ ( list_of_arguments ) ]
| system_tf_identifier ( data_type [, expression ] )
subroutine_call ::=
|
|
|

tf_call
system_tf_call
method_call
randomize_call

function_subroutine_call ::= subroutine_call


list_of_arguments ::= [ expression ] {, [ expression ] } {, . identifier ( [ expression ] ) }
| . identifier ( [ expression ] ) {, . identifier ( [ expression ] ) }
method_call ::= method_call_root . method_call_body
method_call_body ::= method_identifier { attribute_instance } [ ( list_of_arguments ) ]
| built_in_method_call
built_in_method_call ::= array_manipulation_call | randomize_call
array_manipulation_call ::= array_method_name { attribute_instance } [ ( list_of_arguments ) ]
[ with ( expression ) ]
randomize_call ::= randomize { attribute_instance } [ ( [ variable_identifier_list | null ] ) ]
[ with constraint_block ]
method_call_root ::= expression | implicit_class_handle
array_method_name ::= method_identifier | unique | and | or | xor
A.8.3 Expressions
inc_or_dec_expression ::= inc_or_dec_operator { attribute_instance } variable_lvalue
| variable_lvalue { attribute_instance } inc_or_dec_operator
conditional_expression ::= cond_predicate ? { attribute_instance } expression : expression
constant_expression ::= constant_primary
| unary_operator { attribute_instance } constant_primary
| constant_expression binary_operator { attribute_instance }
constant_expression
| constant_expression ? { attribute_instance } constant_expression:
constant_expression
constant_mintypmax_expression ::= constant_expression
| constant_expression : constant_expression : constant_expression
constant_param_expression ::= constant_mintypmax_expression | data_type | $

30

SystemVerilog Reference

Formal Syntax

param_expression ::= mintypmax_expression | data_type


constant_range_expression ::= constant_expression | constant_part_select_range
constant_part_select_range ::= constant_range | constant_indexed_range
constant_range ::= constant_expression : constant_expression
constant_indexed_range ::= constant_expression +: constant_expression
| constant_expression -: constant_expression
expression ::=
|
|
|
|
|
|

primary
unary_operator { attribute_instance } primary
inc_or_dec_expression | ( operator_assignment )
expression binary_operator { attribute_instance } expression
conditional_expression
inside_expression
tagged_union_expression

tagged_union_expression ::= tagged member_identifier [ expression ]


inside_expression ::= expression inside { open_range_list }
value_range ::= expression | [ expression : expression ]
mintypmax_expression ::= expression | expression : expression : expression
module_path_conditional_expression ::= module_path_expression ? { attribute_instance }
module_path_expression : module_path_expression
module_path_expression ::= module_path_primary
| unary_module_path_operator { attribute_instance } module_path_primary
| module_path_expression binary_module_path_operator
{ attribute_instance } module_path_expression
| module_path_conditional_expression
module_path_mintypmax_expression ::= module_path_expression
| module_path_expression : module_path_expression :
module_path_expression
part_select_range ::= constant_range | indexed_range
indexed_range ::= expression +: constant_expression
| expression -: constant_expression
genvar_expression ::= constant_expression
A.8.4 Primaries
constant_primary ::=
|
|
|
|
|
|
|
|
|
|
|

primary_literal
ps_parameter_identifier constant_select
specparam_identifier [ constant_range_expression ]
genvar_identifier
[ package_scope | class_scope ] enum_identifier
constant_concatenation
constant_multiple_concatenation
constant_function_call
( constant_mintypmax_expression )
constant_cast
constant_assignment_pattern_expression
type_reference

module_path_primary ::= number


| identifier

31

SystemVerilog Reference
|
|
|
|
primary ::=
|
|
|
|
|
|
|
|
|
|
|
|
|

Formal Syntax
module_path_concatenation
module_path_multiple_concatenation
function_subroutine_call
( module_path_mintypmax_expression )

primary_literal
[ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select
empty_queue
concatenation
multiple_concatenation
function_subroutine_call
( mintypmax_expression )
cast
assignment_pattern_expression
streaming_concatenation
sequence_method_call
this
$
null

time_literal ::= unsigned_number time_unit | fixed_point_number time_unit


time_unit ::= s | ms | us | ns | ps | fs | step
implicit_class_handle ::= this | super | this . super
bit_select ::= { [ expression ] }
select ::= [ { . member_identifier bit_select } . member_identifier ] bit_select
[ [ part_select_range ] ]
constant_bit_select ::= { [ constant_expression ] }
constant_select ::= [ { . member_identifier constant_bit_select } . member_identifier ]
constant_bit_select [ [ constant_part_select_range ] ]
primary_literal ::= number | time_literal | unbased_unsized_literal | string_literal
constant_cast ::= casting_type ' ( constant_expression )
cast ::= casting_type ' ( expression )
A.8.5 Expression left-side values
net_lvalue ::= ps_or_hierarchical_net_identifier constant_select
| { net_lvalue {, net_lvalue } }
| [ assignment_pattern_expression_type ] assignment_pattern_net_lvalue
variable_lvalue ::=
|
|
|

[ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select


{ variable_lvalue {, variable_lvalue } }
[ assignment_pattern_expression_type ] assignment_pattern_variable_lvalue
streaming_concatenation

A.8.6 Operators
unary_operator ::= + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_operator ::= + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **
| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
inc_or_dec_operator ::= ++ | -unary_module_path_operator ::= ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_module_path_operator ::= == | != | && | || | & | | | ^ | ^~ | ~^

32

SystemVerilog Reference

Formal Syntax

A.8.7 Numbers
number ::= integral_number | real_number
integral_number ::= decimal_number | octal_number | binary_number | hex_number
decimal_number ::=
|
|
|

unsigned_number
[ size ] decimal_base unsigned_number
[ size ] decimal_base x_digit { _ }
[ size ] decimal_base z_digit { _ }

binary_number ::= [ size ] binary_base binary_value


octal_number ::= [ size ] octal_base octal_value
hex_number ::= [ size ] hex_base hex_value
sign ::= + | size ::= non_zero_unsigned_number
non_zero_unsigned_number ::= non_zero_decimal_digit { _ | decimal_digit}
real_number ::= fixed_point_number
| unsigned_number [ . unsigned_number ] exp [ sign ] unsigned_number
fixed_point_number ::= unsigned_number . unsigned_number
exp ::= e | E
unsigned_number ::= decimal_digit { _ | decimal_digit }
binary_value ::= binary_digit { _ | binary_digit }
octal_value ::= octal_digit { _ | octal_digit }
hex_value ::= hex_digit { _ | hex_digit }
decimal_base ::= '[s|S]d | '[s|S]D
binary_base ::= '[s|S]b | '[s|S]B
octal_base ::= '[s|S]o | '[s|S]O
hex_base ::= '[s|S]h | '[s|S]H
non_zero_decimal_digit ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
decimal_digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
binary_digit ::= x_digit | z_digit | 0 | 1
octal_digit ::= x_digit | z_digit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
hex_digit ::= x_digit | z_digit
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
| a | b | c | d | e | f | A | B | C | D | E | F
x_digit ::= x | X
z_digit ::= z | Z | ?
unbased_unsized_literal ::= '0 | '1 | 'z_or_x 10
A.8.8 Strings

33

SystemVerilog Reference

Formal Syntax

string_literal ::= " { Any_ASCII_Characters } "


A.9 General
A.9.1 Attributes
attribute_instance ::= (* attr_spec {, attr_spec } *)
attr_spec ::= attr_name [ = constant_expression ]
attr_name ::= identifier
A.9.2 Comments
comment ::= one_line_comment | block_comment
one_line_comment ::= // comment_text \n
block_comment ::= /* comment_text */
comment_text ::= { Any_ASCII_character }
A.9.3 Identifiers
array_identifier ::= identifier
block_identifier ::= identifier
bin_identifier ::= identifier
c_identifier ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_ ] }
cell_identifier ::= identifier
class_identifier ::= identifier
class_variable_identifier ::= variable_identifier
clocking_identifier ::= identifier
config_identifier ::= identifier
const_identifier ::= identifier
constraint_identifier ::= identifier
covergroup_identifier ::= identifier
covergroup_variable_identifier ::= variable_identifier
cover_point_identifier ::= identifier
dynamic_array_variable_identifier ::= variable_identifier
enum_identifier ::= identifier
escaped_identifier ::= \ {any_ASCII_character_except_white_space} white_space
formal_identifier ::= identifier
function_identifier ::= identifier
generate_block_identifier ::= identifier
genvar_identifier ::= identifier

34

SystemVerilog Reference

Formal Syntax

hierarchical_block_identifier ::= hierarchical_identifier


hierarchical_dynamic_array_variable_identifier ::= hierarchical_variable_identifier
hierarchical_event_identifier ::= hierarchical_identifier
hierarchical_identifier ::= [ $root . ] { identifier constant_bit_select . } identifier
hierarchical_net_identifier ::= hierarchical_identifier
hierarchical_parameter_identifier ::= hierarchical_identifier
hierarchical_task_identifier ::= hierarchical_identifier
hierarchical_tf_identifier ::= hierarchical_identifier
hierarchical_variable_identifier ::= hierarchical_identifier
identifier ::= simple_identifier | escaped_identifier
index_variable_identifier ::= identifier
interface_identifier ::= identifier
interface_instance_identifier ::= identifier
inout_port_identifier ::= identifier
input_port_identifier ::= identifier
instance_identifier ::= identifier
library_identifier ::= identifier
member_identifier ::= identifier
method_identifier ::= identifier
modport_identifier ::= identifier
module_identifier ::= identifier
net_identifier ::= identifier
output_port_identifier ::= identifier
package_identifier ::= identifier
package_scope ::= package_identifier ::
| $unit ::
parameter_identifier ::= identifier
port_identifier ::= identifier
production_identifier ::= identifier
program_identifier ::= identifier
property_identifier ::= identifier
ps_class_identifier ::= [ package_scope ] class_identifier
ps_covergroup_identifier ::= [ package_scope ] covergroup_identifier

35

SystemVerilog Reference

Formal Syntax

ps_identifier ::= [ package_scope ] identifier


ps_or_hierarchical_net_identifier ::= [ package_scope ] net_identifier | hierarchical_net_identifier
ps_or_hierarchical_tf_identifier ::= [ package_scope ] tf_identifier | hierarchical_tf_identifier
ps_parameter_identifier ::= [ package_scope ] parameter_identifier
| { generate_block_identifier [ [ constant_expression ] ] . }
parameter_identifier
ps_property_identifier ::= [ package_scope ] property_identifier
ps_sequence_identifier ::= [ package_scope ] sequence_identifier
ps_type_identifier ::= [ package_scope ] type_identifier
sequence_identifier ::= identifier
signal_identifier ::= identifier
simple_identifier ::= [ a-zA-Z_ ] { [ a-zA-Z0-9_$ ] }
specparam_identifier ::= identifier
system_tf_identifier ::= $[ a-zA-Z0-9_$ ]{ [ a-zA-Z0-9_$ ] }
task_identifier ::= identifier
tf_identifier ::= identifier
terminal_identifier ::= identifier
topmodule_identifier ::= identifier
type_identifier ::= identifier
udp_identifier ::= identifier
variable_identifier ::= identifier
A.9.4 White space
white_space ::= space | tab | newline | eof

36

Evaluation Model

The simulation of SystemVerilog language is based on a discrete event execution model. Processes can be evaluated
and have their own state. They are concurrently scheduled. They are sensitive to update events. Every change of a
net or a variable generates an event (an update event). An evaluation of a process also generates an event (an
evaluation event).
Except for events, an important aspect of the simulation is the simulation time. The simulator maintains the time value
to model the actual time in the design being simulated. The simplest simulation time unit is called a time slot. The time
slot is divided into several regions where events can be scheduled. In appropriate regions of a time slot different kinds
of events are executed. Dividing a time slot into ordered regions helps to provide predictable interactions between the
design and testbench code.

Regions Observed, Reactive and Re-inactive were added to the simulation model by IEEE 1800-2005. The remaining
regions correspond to the IEEE 1364-2005 simulation model.
Evaluation of property expressions is executed in the Observed region.
The pass/fail code from the assertion/cover action blocks is scheduled in the Reactive region of the
current time slot.
A #0 control delay specified in a program block schedules the process for resumption in the Re-inactive
region.
Sampling of signals used in sequences and properties expressions is executed in Preponed region. Sampling of
signals with #1step input skew (see Clocking Blocks chapter) is also executed in the Preponed region.

37

Literals

Integer and Logic Literals


SystemVerilog allows specifying unsized literal single-bit values with a preceding apostrophe ( ' ), but without the base
specifier. All bits of the unsized value are set to the value of the specified bit. In a self-determined context, these
literals have a width of 1 bit, and the value is treated as unsigned.
reg
a =
b =
c =

[7:0] a,b,c;
'0;
'X;
'z;

Real Literals
The default type is real for fixed-point format and exponent format. A cast can be used to convert literal real values
to the shortreal type.
shortreal'(1.23)
shortreal'(1.23e0)

Time Literals
Time literals specify absolute time values, independent of the module timescale. Time literals are constructed from an
integer number followed by the name of time unit (s, ms, us, ns, ps, fs) without an intervening space. Time literals are
interpreted as realtime values
realtime rt;
initial
rt = 340ps;

String Literals
The string literal is enclosed in quotes. The length of a string literal is not limited.
A string literal can be assigned to an unpacked array of bytes.
byte a [0:21] = "It's a string literal\n";

SystemVerilog adds the following special string characters:

38

SystemVerilog Reference
Escape Sequence

Literals
Corresponding Character

\v

vertical tab

\f

form feed

\\

backslash (\)

\a

bell

\ddd

a hex number (each d symbolizes one octal digit (0-7)

\xdd

a hex number (each d symbolizes one hexadecimal digit (0-F)

Array Literals
Array literals are array assignment patterns or pattern expressions with constant member expressions. Nesting of
braces must follow the number of dimensions. Replicate operators can be nested.
int n[1:2][1:3] = '{'{0,1,2},'{3{4}}}; // same as '{'{0,1,2},'{4,4,4}}
int n[1:2][1:6] = '{2{'{3{4, 5}}}}; // same as '{'{4,5,4,5,4,5},'{4,5,4,5,4,5}}

Structure Literals
Structure literals are structure assignment patterns or pattern expressions with constant member expressions. A
structure literal must have a type. The type must be explicitly indicated with a prefix or implicitly indicated by an
assignment-like context.
typedef struct { logic a; shortint b; real c; } T;
T t1;
T t2 = '{1'b1, 22, 3.4};

Arrays of Unpacked Structures


typedef struct { logic a; shortint b; real c; } T;
T tab [0:1] = '{ '{0,13,2.7},'{1'bx,77,1.11}};

NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

39

Attributes

The attributes are properties that can be specified during declaration of the SystemVerilog objects, statements and
groups of statements containing additional information for simulation and synthesis tools.

Syntax
The Syntax is as follows:
attribute_instance ::= (* attr_spec { , attr_spec } *)
attr_spec ::= attr_name [ = constant_expression ]
attr_name ::= identifier

The attributes can appear in SystemVerilog code as a prefix attached to: declarations, module instances, statements
and port connections. The attributes can appear in SystemVerilog code as a suffix attached to: operators and function
calls. The attribute type is determined by the type of the assigned value. If no value is assigned, the attribute type is
bit with a value of 1.

Examples
The performance_opt attribute is specified as a prefix for a block statement. No value is assigned so the attribute
type is bit of a value 1.
always @(clk) (* performance_opt *) begin
// ...
end

In the below example, there are two attributes specified for a port connection .port_a(var_a). It is allowed to
specify more than two parameters within the attribute (* ... *) delimiters. The parameters need to be followed by
commas.
mod2 UUT ( (* drive_Ts, mode="ctl" *) .port_a(var_a), .port_b(var_b), .port_c(var_c) );

The attributes pertaining to the same statement can be also specified within separate delimiters, as it is shown below.
(* no_skew = 0 *)
(* sys_clk = 1 *)
clocking clk_blk @(posedge clk);
// ...
endclocking

The attribute specified for an operator follows the operator.


regA = exp1 -> (* mode = "exp1_implies_exp2" *) exp2;

40

Data Types

Integer Data Types


SystemVerilog introduces a 4-state logic type and several 2-state C-like types :
Type

Description

Language

shortint

2-state, 16-bit, signed integer

SystemVerilog
(C-like)

int

2-state, 32-bit, signed integer

SystemVerilog
(C-like)

longint

2-state, 64-bit, signed integer

SystemVerilog
(C-like)

2-state, 8-bit, signed integer or ASCII char

SystemVerilog
(C-like)

bit

2-state, user-defined vector size

SystemVerilog
(C-like)

logic

4-state, user-defined vector size

SystemVerilog

reg

4-state, user-defined vector size

Verilog

4-state, 32-bit, signed integer

Verilog

4-state, 64-bit, unsigned integer

Verilog

byte

integer
time

The 4-state types include zero, one, unknown (X) and high impedance (Z) values. The 2-state types include only zero
and one values. If a 4-state value is converted into a 2-state value, X and Z values are converted to zero.
In SystemVerilog, operators may be applied to 2-state values or to a mixture of 2-state and 4-state values. The result
is the same as if all values were treated as 4-state values and Verilog operators were applied. In most cases, if all
operand values are 2-state, the result is in the 2-state value set. The only exceptions involve operators where Verilog
produces an X result for operands in the 2-state value set, for example division by zero. (1/0 yields an X in the four
value set and 0 in the two value set.)

41

SystemVerilog Reference

Data Types

Non Integer Data Types

Real and Shortreal Type


The real type is a Verilog type. SystemVerilog introduces new shortreal type. It is the same as C float.

Void Data Type


The void data type represents nonexistent data. It can be used as the return type of functions to indicate no return
value. This type can also be used for members of tagged unions.

Chandle Data Type


The chandle data type represents storage for pointers passed using the DPI and corresponds to void * on the C
side. (See DPI.) The size of this data type is guaranteed to be large enough to hold a pointer.
Allowed operation on chandle variables include:
Testing for equality (==), inequality (!=), case equality (===), case inequality (!==). Testing can be performed
against another chandle or null.
Testing for a Boolean value. (0 if chandle is null and 1 otherwise.)
Assigning one chandle variable to another or assigning null to a chandle variable.
Passing chandle variables as arguments to subroutines.
Returning chandle variables from functions.
NOTE: The chandle data type is not fully supported in this release. Please contact Aldec Support to receive the latest
status.
The === and !== operators are not supported for the chandle data type.
Some issues are known related to referencing a chandle between a module and a package from separate
compilation units.
Declaring a chandle as a constant is not supported yet.

Event Data Type


The event data type in SystemVerilog extends Verilog named events idea. The event is a handle to a synchronization
object. It can be triggered and waited for. It has also a persistent triggered state that is maintained during the entire
time step.
Event variable can be assigned to another event variable or a null value.
event variable_name [= initial_value];

If an initial value is not specified then the event variable is initialized to a new synchronization object.
event strobe;
// A new event.
event strobe_1 = strobe; // strobe_1 is now an alias for strobe.

42

SystemVerilog Reference
event empty = null;

Data Types
// Empty event.

Classes
A class is a collection of data and a set of subroutines that operate on that data. A class can also be treated as a
specific data type. For more information about classes see Classes.

43

SystemVerilog Reference

Data Types

String Type
A string in SystemVerilog is an ordered collection of characters. The length of a string may vary during simulation. If a
string literal is assigned to a string variable during simulation, the size of the variable is adjusted so that neither the
literal is truncated nor the variable is padded with zeros.
A variable of type string is declared using the following syntax:
string str;

An initial value can be assigned in the declaration:


string str = "initial value";

Several sample assignments to a string variable are shown below:


str
str
int
str

=
=
i
=

"another value";
{"concatenation", " of", " strings"};
= 5;
{i{"replication "}};

The size of the string variable will be adjusted automatically.


You can use square brackets to select one character from the string. Square brackets can be used both on the left
and on the right side of the assignment, for example:
str1[1] = str2[0];

The indices of the string variable are numbered from 0 to N-1, where N is the length of the string. 0 corresponds to
the leftmost character in the string. A single character of a string variable is of type byte.
A string variable can be used in the $display statement, for example:
$display ("str = %s", str);

String literals can be assigned to arrays, for example:


reg [0:5][7:0] s1 = "string";

When the size of the variable where the string literal is assigned, is greater than the literal, the literal is left-padded
with zeros. When the literal is longer than the variable, the literal is truncated on the left.
reg [4*8-1:0] reg_1 = "string";
reg [4*8-1:0] reg_2 = "s";

The first declaration assigns value ring to variable reg_1. Note that the string is truncated on the left, not on the
right.
The second declaration assigns value s preceded with 0's (00000073h).

44

SystemVerilog Reference

Data Types

String Methods
SystemVerilog includes a number of special methods to work with strings. These methods use the built-in method
notation, i.e. they are invoked on the string object (see Example below).
Prototype

Return value or side effect

function int len()

Returns the length of the string, i.e., the number of characters in the string.

task putc(int i, byte c)

Replaces the i-th character in string with the given integral value.

function byte getc(int i)

Returns the ASCII code of the i-th character in string.

function string toupper()

Returns a new string with characters in str converted to uppercase; str


is not changed.

function string tolower()

Returns a new string with characters in str converted to lowercase; str


is not changed.

function int compare(string s)

Compares str and s, as in the ANSI C strcmp function with regard to


lexical ordering and return value.

function int icompare(string s)

Compares str and s, like the ANSI C strcmp function with regard to
lexical ordering and return value, but the comparison is case insensitive.

function string substr(int i, int j)

Returns a new string that is a substring formed by characters in position i


through j of str.

function integer atoi()

Returns the integer corresponding to the ASCII decimal representation in


str.

function integer atohex()

Returns the integer corresponding to the ASCII hexadecimal


representation in str.

function integer atooct()

Returns the integer corresponding to the ASCII octal representation in


str.

function integer atobin()

Returns the integer corresponding to the ASCII binary representation in


str.

function real atoreal()

Returns the real number corresponding to the ASCII decimal


representation in str.

task itoa(integer i)

Stores the ASCII decimal representation of i into str (inverse of atoi).

task hextoa(integer i)

Stores the ASCII hexadecimal representation of i into str (inverse of


atohex).

task octtoa(integer i)

Stores the ASCII octal representation of i into str (inverse of atooct).

task bintoa(integer i)

Stores the ASCII binary representation of i into str (inverse of atobin).

task realtoa(real r)

Stores the ASCII real representation of r into str (inverse of atoreal).

The example below shows usage of selected methods:

45

SystemVerilog Reference

Data Types

Example
string str = "aBc"; // declare string variables
string new_str;
initial begin
new_str = str.toupper();
new_str = str.tolower();
str.putc(0, "d");
str.putc(4, "d");
i = str.len();
j = str.getc(2);
k = str.icompare(new_str);

//
//
//
//
//
//
//
//

assigns ABC to new_str; str is not changed


assigns abc to new_str; str is not changed
changes str to dBc
has no effect, str is not expanded
returns the length of str (=3)
gets the character at position 2 (=c)
compares str to new_str;
the comparison is case insensitive

end

String Relational Operators


The following operators can be used for comparing strings: ==, !=, <, >, <=, and >=. Comparisons are case sensitive.

46

SystemVerilog Reference

Data Types

User-defined Type
SystemVerilog allows for defining new type using typedef construct as in C, for example:
typedef reg[15:0] bus;

Types can be defined outside the module context. Type definitions can be stored in a separate files and protected with
C-like include guards. For example:
`define _TYPES_VH
`ifdef _TYPES_VH
typedef integer number;
typedef real fraction;
`endif //_TYPES_VH

Such files can be then included with the `include directive.


Forward type declarations are allowed in SystemVerilog. For example:
typedef number;
number x;

The above type definition must be eventually resolved. For example:


typedef reg[7:0] number;

Forward declarations with an empty typedef statement are not allowed for enumeration values.
User-defined type identifiers have the same scoping rules as data identifiers, but the hierarchical reference to type
identifier is not allowed. References through ports to type identifiers defined within an interface are not considered
hierarchical and are allowed provided they are locally redefined before being used. This is shown in the example
below.
interface iface;
typedef integer number;
typedef real fraction;
//...
endinterface
module m( iface iface_i );
typedef iface_i.number number;
typedef iface_i.fraction fraction;
number x;
fraction z;
//...
endmodule

Interface iface contains a definition of two types: number and fraction. The interface is instantiated in module m
as iface_i. The two types are used in typedef statements; iface_i.number is redefined as number and
iface_i.fraction is redefined as fraction.
The typedef construct can be also used for class specialization.
class A #(int N = 1);
logic [N-1:0] a;
endclass
typedef A #(8) A8;

47

SystemVerilog Reference

Data Types

typedef A #(16) A16;

In the listing above, the typedef statement is used to declare two new types - A8 and A16 that are specializations of
class A.

48

SystemVerilog Reference

Data Types

Enumeration Types
SystemVerilog introduces the enumeration types. The example below shows how to declare variable rcvstate that
can be assigned either of the five enumerated values IDLE, SYNC, HEAD, DATA or CRC:
// declare variable rcvstate
enum {IDLE, SYNC, HEAD, DATA, CRC} rcvstate;

If the data type used with enumerated type in not explicitly declared the default type is int, as in the example above.
An enumeration encoding exceeding specified type range is illegal, as in the example below:
// Illegal enumeration encoding: hold
enum reg [1:0] {idle=2'b00, start=2'b01, hold=4'b1010, stop = 2'b11} states;

An enumerated type can be defined with the typedef construct, for example:
// declare type colors_t
typedef enum {red, yellow, green} colors_t;
// declare two variables of type colors_t
colors_t lightsRoadA, lightsRoadB;

Values in the enumerated type can be used in assignments, for example:


initial
lightsRoadA = red;

The string representation of the given enumeration value can be read with the name method, for example:
enum {RED, GREEN, BLUE} color;
initial begin
color = GREEN;
$display ("== %s ==", color.name);
end

The above example will display string GREEN.


The enumeration values can be cast to an integer type and incremented from an initial value of 0. This can be
overridden by an explicit assignment.
enum {RED=7, GREEN=8, BLUE=9} color;

Enumerated Type Ranges


The table below explains how enumeration elements are associated with values.
Notation
name

Behavior
Associates the next consecutive number with name.

name = C

Associates constant C with name.

name[N]

Generates N named constants in the sequence: name0, name1, ... name N-1. N must be a positive
integral number.

49

SystemVerilog Reference

Data Types

name[N]=C

Optionally, a constant can be assigned to the generated named constants to associate that
constant to the first generated named constant; subsequent generated named constants are
associated consecutive values. N must be a positive integral number.

name[N:M]

Creates a sequence of named constants starting with name N and incrementing or decrementing
until reaching named constant nameM. N and M must be nonnegative integral numbers.

Optionally, a constant can be assigned to the generated named constants to associate that
name[N:M]=C constant to the first generated named constants; subsequent generated named constants are
associated consecutive values. N and M must be nonnegative integral numbers.

Example
typedef enum {init=1, hold[2], count[4:6]=9,stop=12} fsm_states;

The enumerated type fsm_states assigns number 1 to enumerated constant init and creates two named
constants hold0 and hold1 and assigns values 2 and 3 to them. It also creates three named constants count4,
count5, and count6 and assigns values 9, 10 and 11 to them. Finally value 12 is assigned to the stop constant.
Elements of enumerated type variables can be used in numerical expressions. The value used in the expression is the
numerical value associated with the enumerated value.

Example
typedef enum {white=1, red=2, pink=3, yellow=4, blue=5,
orange=6, gray=7, violet=8} colors;
colors c;
int a,b;
initial begin
a = white + red; // integer value = 3 (pink)
b = blue;
c = colors'(a+b); // a+b=8 (violet)
end

Enumeration Methods
SystemVerilog introduces several methods to enable iterating over the values of enumerated types.
Prototype

Return Value

function enum first();

Returns the value of the first member of the enumeration.

function enum last();

Returns the value of the last member of the enumeration.

function enum next(int unsigned N = 1);

Returns the N-th next enumeration value (default is the next one)
starting from the current value of the given variable.

function enum prev(int unsigned N = 1);

Returns the N-th previous enumeration value (default is the previous


one) starting from the current value of the given variable.

function int num();

Returns the number of elements in the given enumeration.

50

SystemVerilog Reference
function string name();

Data Types
Returns the string representation of the given enumeration value.

51

SystemVerilog Reference

Data Types

Structures
A structure is a way of grouping several variables. Structures are defined with the struct keyword, for example:
struct {
reg [0:3] preamble;
reg [0:7] addr;
reg [0:63] data;
reg [0:7] crc;
} packet;

The above example defines variable packet. Variable packet is a structure consisting of four fields: preamble,
addr, data, and crc.
Instead of defining a variable directly, you can first define a type using the typedef keyword and then use that type to
define the required variable, for example:
typedef struct {
reg [0:3] preamble;
reg [0:7] addr;
reg [0:63] data;
reg [0:7] crc;
} packet_t;
packet_t srcpacket;
packet_t dstpacket;

You can refer to structure fields (members) using the dot notation, for example:
srcpacket.addr = 8'h0F;

SystemVerilog provides two types of structures:


Packed structures.
Unpacked structures.
They are declared and used differently.

Packed Structures
A packed structure is declared by using keyword packed following keyword structure.
typedef struct packed {
reg [0:3] preamble;
reg [0:7] addr;
reg [0:63] data;
reg [0:7] crc;
} packet_t;

Only structures where all members are packed can be declared packed. Unpacked (noninteger) members such as
type real or unpacked arrays are not allowed.
All fields in a packed structure are packed together in memory without gaps. Consequently, a packed structure can be
treated as a vector of values and used as an operand in arithmetic and logical expressions.

52

SystemVerilog Reference

Data Types

Structure members can be accessed as vector slices, for example:


srcpacket[80:73] = 8'h0F;

Signed and Unsigned Structures


Packed structures can be declared signed or unsigned. The signed or unsigned keyword is optional. When used, it
must follow the packed keyword. By default all structures are unsigned.

Unpacked Structures
Unpacked structures are structures declared without the packed keyword that contain unpacked fields, such as real,
realtime, or unpacked arrays as shown in the example below:
struct {
real a;
reg [7:0] b;
reg [7:0] c [3:0];
} us;

This structure cannot be declared as packed because it contains two unpacked members: a real number and an array
with an unpacked dimension. (The unpacked dimensions of an array are specified by indexes following the array
identifier.)

Member Initialization
Unpacked structures, unlike packed structures, can contain default assignments to individual members, for example:
typedef struct {
reg a = 1'b1;
real b = 7.1;
reg [7:0]c = 8'hFF;
} s_t;

If an explicit initial assignment is made to an unpacked structure, than the initial values specified at type declaration
are ignored, for example:
s_t s = '{ 0'b1, 8.1, 8'hAA };

Structure s will be assigned values specified in the literal ('{ 0'b1, 8.1, 8'hAA }) rather than the values from
the declaration.

Assignment
SystemVerilog allows assignments not only to an individual structure member but also assignments to a structure as a
whole. This is shown in the listing below.
struct {
bit b;

53

SystemVerilog Reference

Data Types

real r;
} s1;
struct {
bit b2;
real r2;
} s2;
initial
s1 = s2;

Assigning one unpacked structure to another unpacked structure is allowed if the following restrictions are satisfied:
Structure members are of the same type.
Structure members have the same declaration order.
Note that member names need not match.

Limitations
Initialization in the typedef struct statement has no effect on structures declared before the struct type
is resolved. (Such declarations are possible when forward typedef's are used.
Initialization of object handles using new has no effect.

54

SystemVerilog Reference

Data Types

Unions
A union specifies a set of variable values. The variable values are called members of the union. The union, unlike the
structure, can store only one member at a time.

Packed Unions
A packed union is a union declared with keyword packed. All members of a packed union must be packed structures,
packed arrays, or integer types. Moreover, their size must be the same. Otherwise, the union cannot be declared
packed.
An example of a packed union is shown below:
typedef union packed {
int a;
reg [31:0]b;
} u_t;

A packed union can be used as an operand for arithmetic and logical operators. Bits or slices of a packed union can
be selected as if the union were a packed array indexed from n-1 down to 0.
A packed union can be declared either signed or unsigned. By default, unions are unsigned.

Unpacked Unions
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.
Unpacked unions (i.e. unions declared without the packed keyword) that have only packed members of the same
size are packed automatically by the compiler. Whenever the compiler encounters such as a union, it prints the
VCP92013 message:
Unpacked unions are not supported in this release, this union is being treated as
packed. Please contact Aldec Support to receive the latest status.

Tagged Unions
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

55

SystemVerilog Reference

Data Types

Class
A class is a type that includes:
Data
Subprograms (tasks and functions) that operate on that data
Class data members are referred to as class properties. Subprograms that operate on that data are class methods.
Properties and methods define capabilities of some kind of an object. Objects can be dynamically created, deleted,
assigned, and accessed via object handles.
For more about classes see chapter Classes.

56

SystemVerilog Reference

Data Types

Casting
Casting converts an expression of one type to another type.

Static Casting
The data type can be statically changed by using the cast (') operator. The apostrophe must be prefixed with the type
of the expression. The expression itself must be enclosed in parentheses.
int i = int'(2.0 * 3.0);
shortint j = shortint'({8'hFA,8'hCE});

The example above shows casts to predefined types int and shortint. User-defined types are also allowed in
static casts. The listing below shows casting to the user-defined type my_reg.
module top;
typedef reg [3:0] my_reg;
my_reg a;
bit [1:0] b = 2'b10;
initial a = my_reg'(b);
endmodule

If a positive decimal number is used instead of a type name, then the cast changes the bit size, for example:
r = 10'(a+b-3)

The size of the expression in the example above is 10 bits. Changing the size does not affect signedness.
Signedness can be changed with signed and unsigned keywords:
rs = signed'(reg_vect_a)
ru = unsigned'(int_b)

Bit-stream Casting
A type casting can be applied to unpacked aggregate types. This can be done with the bit-stream casting which allows
you to convert between various bit-stream types, that is, between types which can be represented as a serial stream
of bits where each bit can be individually addressable. Following data types can be classified as bit-stream types:
Any integral, packed, or string type
Unpacked arrays, structures, or classes of the above types
Associative arrays, dynamic arrays and queues of any of the above types

Example 1
The example below shows how the bit-stream casting can be used to convert an integral type to a structure.
module top;
typedef struct {
logic[3:0] a[4];

57

SystemVerilog Reference

Data Types

shortint s;
integer i;
} T3;
T3 t1;
longint i3;
initial begin
i3 = 64'h0123456789abcdef;
t1=T3'(i3);
end
endmodule

Example 2
Here, the bit-stream casting is used to make a conversion between different aggregate data types.
module top;
typedef bit[7:0] T1[];
typedef struct {
logic[4:0] a[8];
shortint s;
byte b1;
} T3;
T1 t1 = new[8];
T3 t3;
initial

t1=T1'(t3);

endmodule

$cast Dynamic Casting


The $cast system task is a cast operation that performs a run-time check. As other cast operations, the dynamic cast
can be applied to variables that cannot be used in assignments because of the incompatibility of types. Apart from
that, it can be used in the conditional statements to check if the casting operation can be performed for the specified
arguments. The second application is feasible since the variable types are not checked until the run-time phase, so
the simulation can be run in cases where the use of the static cast would produce a code that cannot be compiled.
The dynamic cast can be called either as a task or a function and is allowed for objects of the class type (see Casting
in the Classes section for details) and all the other singular types. The syntax is as follows:
function int $cast( singular_type dest_var, singular_type src_expr );
task $cast( singular_type dest_var, singular_type src_expr );

The dest_var is a variable to which the assignment is made. The src_expr is an expression that is to be assigned
to the destination variable. When the dynamic cast is called as a task, it attempts to assign the source expressions to
the destination variable. If the type cannot be cast, the run-time error message is displayed and the destination
variable is left unchanged.
When the dynamic cast is called as a function, it attempts to assign the source expression to the destination variable.
If the assignment is legal, the function returns 1. If the assignment is illegal, no runtime error message is displayed,
the function returns 0 and the destination variable is left unchanged.

58

SystemVerilog Reference

Data Types

Example 3
In the example below, the value of the int type returned by the f1() function is cast on the variable enum1 of the
enumerated type. If the value cannot be assigned, that can happen when the enumerated type does not have a
named item that corresponds to the assigned value, the value of the enum1 variable is left unchanged and a warning
message is displayed.

function int f1(int arg_1);


return arg_1;
endfunction
module top;
enum int {e0 = 1, e1, e2, e3, e4, e5} enum1 ;
initial begin
enum1 = e3;
if (!$cast(enum1, f1(5))) $warning("$cast failed");
$display("enum1.name = %s", enum1.name);
end
endmodule

Const Casting
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

59

Arrays and Queues

Packed and Unpacked Arrays


SystemVerilog distinguishes between packed and unpacked arrays. A packed array is an array where all dimensions
are packed.

Packed and Unpacked Array Dimensions


The term packed dimension refers to dimensions declared before the object name. In Verilog, such dimensions were
called vector dimensions. Verilog allowed only one vector dimension for an object. In SystemVerilog, the number of
packed dimensions can be arbitrary.
The term unpacked dimension refers to dimensions declared after the object name. An arbitrary number of unpacked
dimensions is allowed.

Multiple Dimensions
In a multidimensional array, the packed dimensions, if any, always vary more rapidly than the unpacked dimensions.
Within the set of packed or unpacked dimensions, the dimensions to the right vary quicker than the dimensions on the
left.
The example below declares array arr with two packed dimensions ([3:0][7:0]) and one unpacked dimension
([15:8]). The unpacked dimensions vary quicker than the packed one. Of the two packed dimensions, the rightmost
one ([7:0]) varies quicker than the one the left ([3:0])
bit [3:0][7:0] arr [15:8];

The dimensions can also be specified with a single positive number designating the size of the array. The following
two declarations are synonymous.
int arr1 [8] [32]
int arr2 [0:7] [0:31]

Packed Array Properties


A packed array is represented in a memory as a contiguous set of bits. When a packed array appears as a primary, it
is treated as a single vector. (This is not true for unpacked arrays.)
Packed arrays can be made of:
The single bit data types (bit, logic, reg).
Enumerated types.

60

SystemVerilog Reference

Arrays and Queues

Other packed arrays and packed structures.


Signed packed array viewed as a single vector is signed. The individual elements of the array are unsigned unless
they are of a named type declared as signed. A part-select of a packed array is unsigned.

Unpacked Array Properties


Unpacked arrays can contain elements of any data type. Each dimension of an unpacked array can have a fixed or a
varying size. Fixed-size unpacked arrays can be multidimensional. If an unpacked array has one or more dynamic,
associative, or queued dimensions, it is considered a variable-size array.
The signed keyword in unpacked array declaration applies to the individual elements of the array.
When assigning to an unpacked array, the source and target must be arrays with the same number of unpacked
dimensions, and the length of each dimension must be the same.

Indexing, Part-selects, and Slices


In SystemVerilog the term part-select refers to a selection of one or more contiguous bits of a single dimension
packed array. The term slice refers to a selection of one or more contiguous elements of an array.
module top;
logic [3:0] [7:0] arr2 = '{1,2,3,4};
byte slice1;
initial slice1 = arr2[3]; // selects a single 8-bit element from arr1
endmodule

Parameters of Unpacked Array Type


Both one-dimensional and multidimensional arrays can be declared as a parameter. Parameters can be initialized
e.g., by assigning an array literal or a previously declared parameter:
parameter bit signed [31:0] p1 [2] = '{2{1}};
parameter int p2 [1:0] = p1,
p3 [2][3] = '{'{1,2,3},'{3{4}}};

Limitations
Overriding SystemVerilog module parameters by VHDL generics is not supported yet.

61

SystemVerilog Reference

Arrays and Queues

Dynamic Arrays
A dynamic array is an array whose size can be set during simulation run-time. The following syntax is used for
declaring dynamic arrays:
int arr [];

Note that the size of the array is not specified. No storage is allocated for the array until it is explicitly requested by
using the new function.

Dynamic Array Constructors


Dynamic arrays support the following methods: new, size, and delete. Two prototypes are available for the new
method.
Prototype

Description
Allocates storage for the number of elements specified by int_expr. The int_expr
must evaluate to a non-negative integer. Elements in the array are initialized to their
default values. This method can be used both to allocate a new array and to enlarge or
to shrink an existing array, for example:

arr = new[ int_expr ];


integer arr[];
arr = new[10];
arr = new[50];
arr = new[5];
arr = new[3]('{2,4,7});

arr = new[ int_expr


](expression);

// declare an array
// create an array with 10 elements
// grow the array
//shrink the array
// shrink the array and set values of the elements

Allocates storage for the number of elements specified by int_expr. The int_expr
must evaluate to a non-negative integer. An expression specifies an array with which to
initialize the new array arr. This array identifier must be a dynamic array of a data type
equivalent to the array on the left-hand side, but it need not be of the same size. If the
size of this array is less than the size of the new array, the extra elements shall be
initialized to their default value. If the size of this array is greater than the size of the new
array, the additional elements shall be ignored. An (expression) argument is useful when
growing or shrinking an existing array. In this situation, the value of (expression) is the
same as the left-hand side; therefore, the previous values of the array elements are
preserved. For example:
integer arr[];
// declare an array
arr = new[10];
// create an array with 10 elements
arr = new[20](arr); // double the array size, preserving previous values

Other Dynamic Array Methods


Prototype

Description

function int size();

Returns the number of items in the dynamic array or 0 if the array is empty.

function void delete();

Removes all elements from the dynamic array.

62

SystemVerilog Reference

Arrays and Queues

63

SystemVerilog Reference

Arrays and Queues

Associative Arrays
An associative array is a collection of unique keys and unique values, where each key is associated with one value.
The primary differences between associative arrays and regular arrays are as follows:
The type of the key in an associative array can be arbitrary, unlike in regular arrays, where the type of the key
is always an integer expression.
The storage for elements of an associative elements is not allocated until it is needed.
Associative arrays are best suited for sparse collections of data.

Syntax
element_type associative_array_id [ index_type ];

where

element_type
The type of elements that will be inserted into the associative array.
associative_array_id
The identifier of the array.
index_type
The type of the data to be used for indexing. The index type imposes the ordering of elements.
SystemVerilog also allows using * (a wildcard index) for index_type. Associative array with wildcard index may be
indexed with any integral expression and each index may be of different size. Indexes with the same numerical value
and differing only by width are treated as identical (leading zeros are removed). For example values 1'b0 and 2'b0
point to the same array item.
The following example demonstrates how to declare an associative array colors. The array is indexed by a 24-bit
value. The elements of the array are strings (color names). The initial value is assigned to the array by using an
associative array literal.
string colors [reg[23:0]] = '{
24'hF0F8FF : "Alice Blue",
24'hFAEBD7 : "Antique White",
24'h00FFFF : "Aqua",
24'h7FFFD4 : "Aquamarine",
24'hF0FFFF : "Azure",
24'hF5F5DC : "Beige",
24'hFFE4C4 : "Bisque",
24'h000000 : "Black",
24'hFFEBCD : "Blanched Almond",
24'h0000FF : "Blue"
};

Note that the array is sparse. Only ten 24-bit numbers have been used. The storage has been allocated only for
existing elements.
The default keyword allows defining a default value for nonexistent array elements. When the default is defined
the reference to an uninitialized array element returns the default value:

64

SystemVerilog Reference

Arrays and Queues

typedef enum {A,B,C,D,E,F,G} EnumType;


EnumType letters [byte] = '{
0 : A,
1 : B,
2 : C,
default : G
};
initial $display("letters[3]=%s",letters[3].name()); // displays letters[3]=G

If the default value is not specified, the value of an uninitialized array type is returned and a warning is printed to the
console:
typedef enum {A,B,C,D,E,F,G} EnumType;
EnumType letters [byte] = '{
0 : A,
1 : B,
2 : C
};
initial $display("letters[3]=%s",letters[3].name()); // displays letters[3]=A
// a warning will be printed: "Non-existent associative array entry. Returning default value."

An associative array can be written one entry at a time. The whole array contents can be replaced using an array
literal.
class CC;
int i;
function new(int i_);
i = i_;
endfunction
endclass
CC arr1 [EnumType];
CC obj1 = new(1), obj2 = new(2), obj3 = new(3);
initial begin
arr1[A] = obj1;
arr1[B] = obj2;
arr1[C] = obj3;
$display("arr1=", arr1); // displays: arr1='{A:'{i:1}, B:'{i:2}, C:'{i:3}}
arr1 = '{A:obj2, D:obj2}; // replaces previous contents of arr1
$display("arr1=", arr1); // displays: arr1='{A:'{i:2}, D:'{i:2}}
end

Each key in associative array literal can be used only once. Using the same key more than once triggers an error.
typedef int TA1 [string];
function int f1 (string idx, TA1 arr1 = '{"a":10,"b":20,"a":30});
return arr1[idx];
endfunction
// triggers an error about a duplicated key

SystemVerilog allows defining associative arrays that contain structure items. Array literals assigned to these arrays
may include nested structure literals.
typedef struct packed { reg a; EnumType b; } TS;
TS arr2 [byte] = '{0:'{a:1'b0,b:C},1:'{a:1'b1,b:D}};

65

SystemVerilog Reference

Arrays and Queues

Associative Array Methods


Associative arrays support the following methods: num, delete, exists, first, last, next, and prev. (Two
prototypes are available for the delete method.)
Prototype

Description

function num size();

Returns the number of items in the associative array or 0 if the array is


empty.

function num delete();

Removes all items from the associative array.

function num delete( input index );

Removes the item specified by index.

function int exists( input index );

Checks whether the element specified by index exists. Returns 1 if it does


or 0 if it does not.
Assigns the value of the smallest index in the array to the index variable.
Returns 0 if the variable is empty or 1 otherwise. Assuming that r is
declared as
reg[23:0] s;

function int first( ref index );


the following code could be used to check the smallest element in the
array colors:
if( colors.first( s ))
$display( "%s", colors[s] );

function int last( ref index );

Assigns the value of the largest index in the array to the index variable.
Returns 0 if the variable is empty or 1 otherwise.

function int next( ref index );

Finds the entry with the next index greater than the passed index. If no
such entry exists, returns 0. If the entry is found, returns 1 and assigns the
next index to the index variable.

function int prev( ref index );

Finds the entry with the previous index greater than the passed index. If no
such entry exists, returns 0. If the entry is found, returns 1 and assigns the
previous index to the index variable.

66

SystemVerilog Reference

Arrays and Queues

Queues
A queue is a variable-size, ordered collection of homogeneous elements. The queue can grow and shrink
automatically as elements are added or removed. Queues are declared similarly to arrays with the dollar sign ($) used
as the array dimension.
element_type queue_name [ $ ];

Queue Methods
Queues support the following methods: size, insert, delete, pop_front, pop_back, push_front, and
push_back. The prototype for each method and a brief description is provided below. element_t indicates the type
of the element inserted into the queue.
Prototype

Description

function int size();

Returns the number of items in the queue or 0 if the queue is


empty.

function void insert (input int index, input element_t


item);

Inserts the item at the position specified by the index.

function void delete (int index);

Deletes an element located at the specified position.

function element_t pop_front();

Removes the first element from the queue and returns it.

function element_t pop_back();

Removes the last element from the queue and returns it.

function void push_front (input element_t item);

Inserts the element at the front of the queue.

function void push_back (input element_t item);

Inserts the element at the end of the queue.

67

SystemVerilog Reference

Arrays and Queues

Limitations
This section lists limitations related to dynamic arrays, associative arrays, and queues. For brevity, dynamic arrays
and associative arrays are referred to as arrays.
Part-selection is not available for arrays.
Array and queue part-selections cannot be used as arguments for system tasks, e.g. the $display task.
Hierarchical references to arrays and queues are allowed only when the array/queue and the reference to it
reside in the same compilation unit (i.e. they are compiled in the same compiler run).
Elements of arrays and queues cannot be passed by reference.
Arrays cannot be concatenated with the concatenation operator.

68

SystemVerilog Reference

Arrays and Queues

Array Querying Functions


SystemVerilog introduces new functions returning information about arrays: $left, $right, $low, $high,
$increment, $size, $dimensions, and $unpacked_dimensions. These functions can be used to query regular
arrays, dynamic arrays, associate arrays, and queues.
Name

Arguments

$left

Returns the left bound (MSB) of the dimension. For queues and dynamic
array dimensions, returns 0.

$right

Returns the right bound (LSB) of the dimension. For empty queues and
empty dynamic or associative arrays, returns -1.

$low

Returns the minimum of $left and $right of the dimension.

$high

Returns the maximum of $left and $right of the dimension.

$increment

Returns 1 if $left is greater than or equal to $right and -1 if $left is


less than $right. For queues and dynamic array dimensions, returns -1.

$size

Returns the number of elements in the dimension. This is equivalent to


$high - $low +1.

$dimensions

For an array returns the total number of dimensions in the array (packed
and unpacked, static or dynamic). For the string data type or any other
non-array type that is equivalent to a simple bit vector type returns 1. For
any other type returns 0.

$unpacked_dimensions

Returns the total number of unpacked dimensions for an array (static or


dynamic). For any other type returns 0.

In references to multidimensional arrays the packed dimensions vary more rapidly than the unpacked dimensions . In
the list of packed dimensions the rightmost one varies most rapidly. The same rule applies to the list of unpacked
dimensions. This is shown in the listing below where the dimension [1:8] varies most rapidly (4), followed by [1:4]
(3), then [10:16] (@<2>), and then [1:2] (@<1>).
//
(3)
(4)
(1)
(2)
bit [1:4] [1:8] arr5 [1:2] [10:16];

For a fixed-size integer type (integer, shortint, longint, and byte), dimension 1 is predefined. For an integer N declared
without a range specifier, its bounds are assumed to be [$bits(N)-1:0].

69

SystemVerilog Reference

Arrays and Queues

Array Manipulation Methods


SystemVerilog provides several built-in methods that allow searching or reordering an array, or reducing contents of
an array to a value. The array manipulation methods can be applied to unpacked arrays. The return type, if any,
depends on the kind of a method.
The general syntax of the array manipulation methods is shown below:
array_name.array_method [(iterator_name)] [with (expression)]

The methods iterate over the array elements which are then evaluated by the expression specified in the with clause.
You can define the iterator_name to specify the name of the variable to designate subsequent array elements
inside the with clause at each iteration. Such defined iterator_name can be used only inside the with clause
expression. If the iterator_name is not specified, the default name item is used. The expression inside the with
clause should not modify the array contents; otherwise, the results may be unpredictable.

Array Locator Methods


Array locator methods search an array for elements that satisfy the specified expression. The methods can be applied
to any unpacked array, but their return type is always a queue. The returned queue contains all items that satisfy the
specified expression; if no items satisfy the expression, the returned queue is empty.
Regular locator methods return a queue of elements of the same type as the type of items stored in the array, while
the index locator methods return a queue of elements of the index type: the associative index type for associative
arrays or int for other arrays. The index locator methods cannot be applied to associative arrays with the wildcard
index type. The expression specified by the with clause should evaluate to a Boolean value.
The following array locator methods are available:

find()
The method returns a queue of elements satisfying the specified expression. The use of the with clause is
obligatory:
result = int_arr.find(x) with (x >= 3);

The same method used without the iterator_name explicitly defined (item is assumed by default):
result = int_arr.find() with (item >= 3);

find_index()
The method returns a queue of indices of elements satisfying the specified expression. The use of the with
clause is obligatory:
result = int_arr.find_index() with (item >= 3);

find_first()
The method returns a queue containing the first element satisfying the specified expression. The use of the
with clause is obligatory:
result = int_arr.find_first() with (item > 2);

70

SystemVerilog Reference

Arrays and Queues

find_first_index()
The method returns a queue containing the index of the first element satisfying the specified expression. The
use of the with clause is obligatory:
result = int_arr.find_first_index(x) with (x > 2);

find_last()
The method returns a queue containing the last element satisfying the specified expression. The use of the
with clause is obligatory:
result = int_arr.find_last() with (item < 2);

find_last_index()
The method returns a queue containing the index of the last element satisfying the specified expression. The
use of the with clause is obligatory:
result = int_arr.find_last_index() with (item < 2);

min()
The method returns a queue containing the element with the minimum value or whose expression evaluates
to a minimum:
result = int_arr.min();
s_res = s_arr.min(x) with (x.id); // criteria are 'id' fields of the array items

max()
The method returns a queue containing the element with the maximum value or whose expression evaluates
to a maximum:
result = int_arr.max();
s_res = s_arr.max(x) with (x.id); // criteria are 'id' fields of the array items

unique()
The method returns a queue containing all elements with unique values or whose expressions evaluate to
unique values. The returned queue contains only one entry for each of the values found in the array. The
ordering of the returned queue may not match the original ordering:
result = int_arr.unique();

unique_index()
The method returns a queue containing the indices of all elements with unique values or whose expressions
evaluate to unique values. The returned queue contains only one entry for each of the values found in the
array. The index returned for duplicate valued entries can be an index of any of the duplicates. The ordering of
the returned queue may not match the original ordering:
result = int_arr.unique_index();

Array Ordering Methods


Array ordering methods manipulate the order of elements stored in an array. The methods do not return any value, but
only reorder items in an array. The methods are available for any unpacked array except for associative arrays.
The following array ordering methods are supported:

71

SystemVerilog Reference

Arrays and Queues

sort()
Sorts an array in ascending order. If the with clause is specified, the array is sorted by the values of the
expression specified in the with clause:
s_arr.sort()

with (item.id);

Sorts the array by the values of the id fields of objects stored in the array.
rsort()
Sorts an array in descending order. If the with clause is specified, the array is sorted by the values of the
expression specified in the with clause:
s_arr.rsort() with (item.id);

Sorts the array by the values of the id fields of objects stored in the array.
reverse()
Reverses the order of elements stored in an array. Specifying the with clause is not allowed:
s_arr.reverse();

shuffle()
Randomizes the order of elements stored in an array. Specifying the with clause is not allowed:
s_arr.shuffle();

Array Reduction Methods


Array reduction methods allow reducing an unpacked array to a single value by applying a logic or an arithmetic
operation to elements stored in the array.
If the with clause is specified, the value of the with clause expression is evaluated for each of the array items, and
the reduction operation is applied to the values resulting from those evaluations.
The following reduction methods are available:

sum()
Returns the sum of all elements stored in an array. If the with clause is specified, returns the sum of values
returned by evaluation of the expression specified in the with clause for each of the array elements:
int array[] = '{ 1, 3, 5};
int result;
result = array.sum();
result = array.sum() with (item * 2);

// 1 + 3 + 5 = 9
// 1*2 + 3*2 + 5*2 = 18

product()
Returns the product of all elements stored in an array. If the with clause is specified, returns the product of
values returned by evaluation of the expression specified in the with clause for each of the array elements:
result = array.product();
// 1 * 3 * 5 = 15
result = array.product() with (item + 1); // 2 * 4 * 6 = 48

and()

72

SystemVerilog Reference

Arrays and Queues

Returns the logical conjunction (bitwise AND) of all elements stored in an array. If the with clause is
specified, returns the logical conjunction of values returned by evaluation of the expression specified in the
with clause for each of the array elements:
result = array.and();
result = array.and() with (item - 1);

// 1 & 3 & 5 = 1
// 0 & 2 & 4 = 0

or()
Returns the logical disjunction (bitwise OR) of all elements stored in an array. If the with clause is specified,
returns the logical disjunction of values returned by evaluation of the expression specified in the with clause
for each of the array elements:
result = array.or();
result = array.or() with (item - 1);

// 1 | 3 | 5 = 7
// 0 | 2 | 4 = 6

xor()
Returns the logical exclusive disjunction (bitwise XOR) of all elements stored in an array. If the with clause is
specified, returns the exclusive disjunction of values returned by evaluation of the expression specified in the
with clause for each of the array elements:
result = array.xor();
result = array.xor() with (item + 1);

// 1 ^ 3 ^ 5 = 7
// 2 ^ 4 ^ 6 = 0

Iterator Index Querying


The index() method allows accessing the actual index values and use them in the expressions under the array
manipulation methods. The syntax of the index() method is as follows:
function int_or_index_type index();

If the method is applied to indices of an associative array, the returned value is of the same type as associative array
indices. For other arrays, the function returns indices of the int type. The method cannot be used for associative
arrays with the wildcard index type.

Examples:
The example shows the index method used together with the array querying methods applied to unpacked and
associative arrays.
byte arr_unpacked[0:5] = '{0,1,2,8,8,8};
int arr_assoc[byte]
= '{20:0,0:1,1:2,2:8,4:8,25:8};
byte result[$],result_b;

The find() method returns the elements that indices are equal to their values.
// result is '{0,1,2};
result = arr_unpacked.find(x) with (x.index == x);

The find() method returns the elements that indices are bigger than 2.
// result is '{8,8,8};
result = arr_unpacked.find(x) with (x.index > 2);

73

SystemVerilog Reference

Arrays and Queues

The find_index() method returns the indices that are bigger than 2. The indices returned by the index method
and the whole find_index() method are of the byte type, since the arr_assoc index type is byte.
// result is '{4, 20, 25}
result = arr_assoc.find_index with (item.index > 2);

The unique() method returns elements that evaluate to a unique value. Since the with clause evaluates to the two
unique values: 0 for the indices: 0,1,2 and 1 for the indices: 3,4,5 the possible results are: '{0,8}, '{1,8}, or
'{2,8}.
// result is '{0,8}, '{1,8}, or '{2,8}
result = arr_unpacked.unique with (item.index > 2);

The sum() method below returns the number of even array indices. If the with clause is specified, the method
returns the sum of values returned by evaluation of the expression specified with the with clause. The expression
returns 1 for indices with the 0 value in the least significant bit position, that is, for even indices.
// result_b is 4
result_b = arr_assoc.sum(x) with (byte'(x.index[0]==0));

Limitations
The min(), max(), unique(), unique_index(), sort(), and rsort() methods are executed with an implicit
use of the relational operators: <, >, and ==. When a with clause is specified for one of these methods, the relational
operators must be defined for the type of the expression evaluated inside that clause. When the with clause is not
specified, the relational operators must be defined for the type of the elements stored in the array.
NOTE: Overloading the relational operators is not supported yet. Results returned by the min(), max(), unique(),
sort(), and rsort() functions for arrays containing class, event, or chandle variables are evaluated by comparing
the object addresses. For other data types that have no relational operators defined, e.g. unpacked structures, the
functions will not be executed and an error will be issued. Please contact Aldec Support to receive the latest status.

74

SystemVerilog Reference

Arrays and Queues

Array Assignment
Array assignments are allowed if arrays satisfy following restrictions:
The source and the target arrays have same number of dimensions. Each dimension has equal size.
The element types of the source and the target are equivalent. This means, arrays can be assigned to each
other not only if they are of the same type, but also if arrays are of different types and these types have the
same bit size, both are signed or unsigned and both are either 2-state or 4-state. (e.g. following pairs are
equivalent: bit signed [15:0] and shortint, real and realtime, integer and logic signed
[31:0], bit signed [7:0] and byte, etc.)
Equivalent types are also structures, unions and packed arrays of types that have the same bit size, both are
either signed or unsigned and both are either 2-state or 4-state. Moreover, unpacked fixed-size arrays,
dynamic arrays, queues and associative arrays of such types are also equivalent under certain conditions. For
more specific information refer to the Data Types | Type Compatibility section of IEEE Std 1800-2009.
NOTE: The continuous assignments of arrays of wires to arrays of variables and vice-versa are not supported yet.

Fixed-Size Arrays
byte arr1 [2] = '{1, 2};
byte arr2 [2] = '{3, 4};
initial
arr1 = arr2;

Both blocking and non-blocking assignments are allowed for fixed-size arrays.

Dynamic Arrays
The target of an assignment is resized to the size of the source.
byte dynarr1 [] = new[2]('{8'd1, 8'd2});
byte dynarr2 [] = new[3]('{8'd3, 8'd4, 8'd5});
initial
dynarr1 = dynarr2;

Non-blocking assignments are not allowed for dynamic arrays.

Associative Arrays
Assigning one associative array to another is allowed if arrays keys have the same type.
byte assocarr1 [string] = '{"a":8'd1, "b":8'd2};
byte assocarr2 [string] = '{"c":8'd3, "d":8'd4, "e":8'd5};
initial
assocarr1 = assocarr2;

75

SystemVerilog Reference

Arrays and Queues

Non-blocking assignments are not allowed for associative arrays.

Queues
The target of an assignment is resized to the size of the source.
byte queue1 [$] = '{8'd1, 8'd2};
byte queue2 [$] = '{8'd3, 8'd4, 8'd5};
initial
queue1 = queue2;

Non-blocking assignments are not allowed for queues.

Different Array Kinds in The Assignment


The following kinds of arrays can be used together in the single assignment: fixed-size array, queue and dynamic
array. Associative arrays are not allowed, since an associative array can be assigned only to another associative
array. Assignments are allowed if following conditions are met:
If a fixed-size array is the target of an assignment, a dynamic array or a queue that is the source of the
assignment must have the same number of elements as the target.
int dynarr[] = new[3] ('{21,-54,75});
bit signed [31:0] arr[3];
initial arr = dynarr; // dynamic array must be of the target size

If a target of an assignment is a dynamic array or a queue, the size of the source and the target may differ. If
size are different, the target will be resized to have the same number of elements as the source expression.
int dynarr[] = new[7], queue[$];
int arr[3] = '{124,3,94};
initial begin
dynarr = arr; //dynamic array is resized to 3
queue = dynarr; //uninitialized queue is resized to actual size of dynamic array dynarr (3)
end

Non-blocking assignments are not allowed if the target of an assignment is a queue or a dynamic array.

Overwriting Existing Elements


Assigning a dynamic array, associative array, fixed-size array or a queue to another array or a queue removes all
existing entries.
The example below shows an associative array arr_dst[int] with two elements: 1:2 and 2:2. After assigning
arr_src[int] containing 6:5, keys 1 and 2 are deleted.
byte arr_dst [int] = '{1:8'd2, 2:8'd2};
byte arr_src [int] = '{6:8'd5};
initial
// two elements are stored in arr_dst before the assignment:
// arr_dst[1] = 2 and arr_dst[2] = 2

76

SystemVerilog Reference

Arrays and Queues

arr_dst = arr_src;
// after the assignment arr_dst has one entry: arr_dst[6] = 5

Out-of-bounds Elements
The index expression is invalid if its value is out of array bounds or one or more of its bits is of the Z or X value.
Specifying an invalid index during the read operation, results in reading the values specified in the table below. The
values depends on the array type.
Type of array

Value

4-state integral type

'X

2-state integral type

'0

Enumeration

Value specified in this table for the base type of the enumeration.

real, shortreal

0.0

string

An empty string.

class

null

event

null

chandle

null

virtual interface

null

Unpacked struct

Each structure member has the value as specified in this table.

Fixed-size unpacked array

Array elements have values depending on the array type as specified in this table.

Dynamic array and queue

Array of zero size (no elements).

Associative array

Array of zero size (no elements) or the user-specified default value (if defined).

Writing a value to an element determined by an invalid index does not trigger any specific operation with the exception
of assigning a value to a next element of a queue [$+1] and creating a new element of an associative array which
are the legal operations.

Vectors and Unpacked Arrays


If a bit select address is invalid, then the value read from the specified address are X for 4-state and 0 for 2-state
types. The write operation has no effect.
If the part-select address is out of bounds then the values read from specified addresses are X for 4-state or 0 for
2-state types. The write operation has no effect.
If a part-select address is partially out of bounds, then the values read from the ranges exceeding the bounds are X
for 4-state and 0 for 2-state types. The write operation affects only the bits that are within the range.

77

Data Declarations

Constants
Constants are named data variables that never change. SystemVerilog provides elaboration time constants and
runtime constants.
The elaboration time constants are referred to as parameter constants. They include:
parameter's
localparam's
specparam's
Runtime constants are declared with the const keyword. A const constant, unlike parameter constants, can be set
during simulation run time, e.g. when an automatic task or function is executed.

Parameter Constants
SystemVerilog introduces a number of enhancements to parameter constants.

Parameter Port List


In SystemVerilog the keyword parameter can be omitted in a port list declaration. For example, the following module
declaration is a valid SystemVerilog code:
module m #(p = 1, k = 3);
endmodule

An error about a missing keyword would be reported if the declaration was compiled in Verilog mode.

Type Parameters
In SystemVerilog a parameter can also specify a data type. This allows creating multiple instances where the type is
set individually for each instance.
An example with type parameters is shown below. The first parameter (T) in the example is a type (byte), the other
parameter (M) is a value of type T;
module m #(parameter type T = byte, T M = 2);
endmodule

78

SystemVerilog Reference

Data Declarations

Omitting Default Parameter Values


A default value of a parameter can be omitted in a module and a program declaration. If so, the value must be
specified when the module is instantiated. IEEE Std 1800-2009 defines two forms of the parameter value
assignment: assignment by ordered list and assignment by name. See Verilog Reference Guide | Module Instantiation
for further information.
In the example below, the m1 instance of the mod module has parameters assigned by name. Since the parameters
P2 and P4 do not have a default parameter value assigned, these values must be specified at the instantiation.
Parameters with a default value may be omitted, as it is done for the P1 parameter. Though the P3 and P5 parameters
may be also omitted, their default values are overridden at the instantiation.
module mod #(parameter reg [7:0] P1 = 8'b10110011, bit [15:0] P2, int P3 = 6, byte P4, time P5 = 100);
endmodule
mod#(.P2(16'hA7F1), .P3(21), .P4(8'b10110011)) m1();

Assigning a parameter value by the ordered list implies to specify each parameter that precedes the parameter to be
assigned, since the parameter has to be on the same position in the declaration and in the instantiation.
mod#(8'b01111010,16'h930E,5,8'h7C) m2();

The instance m2 of the module mod, which is shown above, has ports assigned by the ordered list. Even though there
are only two parameters without default values: P2 and P4, parameters P1 and P3 have to be assigned once again
because P2 and P4 have to be placed in the proper position on the ordered list. Only the P5 parameter that is
preceded by the P4 parameter which is the last parameter without a default value, can be omitted.

$ as a Parameter Value
NOTE: $ as a parameter value is not supported in this release. Please contact Aldec Support to receive the latest
status.
$ represents unbounded range specification, where the upper index can be any integer. SystemVerilog introduces the
possibility to assign $ to parameters of integer types. A parameter to which $ is assigned can only be used wherever
$ can be specified as a literal constant.
parameter left_range = 0;
parameter right_range = $;
sequence s1(left_range,right_range);
@(posedge clk) a ##[left_range:right_range] b;
endsequence

SystemVerilog adds also a special system function $isunbounded that tests whether a constant expression is
unbounded ($).
$isunbounded(const_expression);

$isunbounded can be used as a condition in the generate statement.

79

SystemVerilog Reference

Data Declarations

Const Constants
A constant declared with the const keyword can be set to an expression of literals, parameters, local parameters,
genvars, enumerated names, a constant function of these, or other constants. Hierarchical names are allowed
because constants declared with the const keyword are calculated after elaboration.
An automatic constant declared with the const keyword can be set to any expression that would be legal without the
const keyword.
const int a = 9;
const logic q = top.uut.a;

An instance of class object can also be declared as const. If it is done so, the class instance (the object handle) acts
like a variable that cannot be overwritten. Its members, however, can be written unless they are declared as const.
const A a0 = new(7,8);

Localparam Constants
The local parameter is one of the three elaboration-time constants in SystemVerilog. The localparam construct
cannot be changed directly by the values assigned by the instance parameter or by the defparam statements.
The localparam construct can be defined in the parameter_port_list of a module. If a parameter is declared at the
end of the list or between the localparam and the parameter keywords, it will become a local parameter.
module mod1
#(localparam H_B=3, L_B=0)
(input wire [H_B:L_B] in,
input wire clk, set, strb,
output logic [H_B:L_B] out);
endmodule

NOTE: The localparam type declared in a compilation-unit scope, generate block, or package is not supported in
this release. Please contact Aldec Support to receive the latest status.

80

SystemVerilog Reference

Data Declarations

Variables
SystemVerilog provides two forms of variable declarations: with and without the keyword var.
The first form consists of a data type followed by an identifier, for example:
shortint a, b[3:0];

The second form begins with the keyword var, for example:
var shortint a, b[3:0];

When var is used, the data type is optional. When the data type is omitted, the assumed data type is logic. In the
example below i is declared to be of type int. No type is specified for l therefore l is assumed to be of type logic.
var int i;
var l;

A variable assignment at declaration is a procedural assignment, not a continuous assignment. (A variable cannot
have an implicit continuous assignment as a part of its declaration.)
SystemVerilog variables can be written by either one continuous assignment or by one or more procedural
statements. Multiple continuous assignments are illegal, so is a mixture of procedural and continuous assignments.
A variable cannot be connected to either side of an inout port.

81

SystemVerilog Reference

Data Declarations

Nets
A net declaration begins with a net type (wire, trireg, etc.) that determines how the values of the nets in the
declarations are resolved. The net declaration can include optional information, such as delay values and drive or
charge strength.
Several examples of net declarations are shown below. They include nets with unpacked (n2) and packed (n3)
dimensions and a net with a delay value (n4).
wire n1;
wire n2[10];
wire [7:0]n3;
wire #(3) n4;
trireg n5;

Specifying the Net Data Type


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.
Only nets of logic data type, which is default data type of nets, are currently supported. However, other data types will
be supported in future releases. These types will have to be 4-state data type. All integral types (integers, packed
structures, etc.) will be allowed. Unpacked structures and unpacked arrays will be also allowed as long as their
elements have a data type valid for a net.

82

SystemVerilog Reference

Data Declarations

Scope and Lifetime


Variables declarations outside a module, interface, task, or function are global in scope (can be referenced anywhere
after the declaration) and have a static lifetime (exist throughout the entire simulation). Variables declared inside a
module, a program, or an interface but outside a task, a function or a process are local in the scope and static in the
lifetime. Variables declared in an automatic task or a function are local in scope and have the lifetime of the call or
activation. Variables declared in static tasks, static functions or blocks have local scope and static lifetime.
Class methods and for loop variables are by default automatic.

Specifying the Lifetime of Local Variables


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.
SystemVerilog allows optional static and automatic modifiers to specify the default lifetime of all variables
declared in a task, a function or a block defined in a module, interface, package, or program.

83

SystemVerilog Reference

Data Declarations

Signal Aliasing
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

84

SystemVerilog Reference

Data Declarations

Type Operator
The construct is supported only in the initialization of the type parameter and type local parameter with the
data_type as an argument.
module m1;
parameter type T = type(bit [1:0]);
typedef int TT;
parameter type T1 = type(TT);
endmodule

85

Classes

Overview
A SystemVerilog class defines properties (data) and methods (behavior). Properties and methods grouped in a class
are inherent to all class instances. An instance of a class is called an object. Objects can be created and deleted
during simulation.
A simple class Point could have one data field (one property) x that stores the coordinate of a point. The coordinate
can be different for each instance of the class. Additionally, the class can provide methods to read, set, or change the
point coordinate, calculate the distance from the origin, etc.
A more complex class could define a USB data packet. A data packet will have a sync field, a PID field, a data field, a
CRC16 field, and an EOP field. Methods provided by the class could be used to send a packet, calculate the CRC for
the data field and compare it against the CRC16 field, etc.
Classes are declared with the class ... endclass keywords. A declaration of a simple class is shown below.
class Point;
int x;
function new (int initial_position);
x = initial_position;
endfunction
function void move (int dx);
x = x + dx;
endfunction
function void rnd_move;
x = $urandom;
endfunction
function int get_position;
return x;
endfunction
endclass

The declaration includes both data (variable x) and methods that operate on that data (functions move, rnd_move,
and get_position). Function new is the class constructor. The constructor is invoked whenever a new instance of
the class is created.
Classes can be declared in the compilation unit scope or in the unit scope (i.e. inside modules, programs, interfaces,
or other classes).

86

SystemVerilog Reference

Classes

Objects, Object Properties and Methods


A class defines a data type. An instance of that class is called an object. Object creation involves:
Declaring a variable of the class type. The variable will hold the object handle.
Creating an object of that class using the new function and then assigning it to the variable. The new function
can be called either at declaration or in a process, for example in an initial block.
The example below shows a declaration of class Point. Two instances of the class (or two objects) are then created
in module m. Object handles are stored in variables h1 and h2. The first handle (h1) is initialized at declaration, the
other (h2) is initialized in the initial block.
class Point;
int i;
function new( int _i );
this.i = _i;
endfunction
endclass
module m;
Point h1 = new(0);
Point h2;
initial
h2 = new (22);
endmodule

Objects in SystemVerilog can also be created by copying existing objects, for example:
initial
h2 = new h1;

The h2 object in the listing above is created by copying the h1 object (h2 = new h1). All properties of h1 are copied
to h2 except for properties that are objects themselves. If h1 contains a property that is an object, h2 will contain a
reference to the same object.

SystemVerilog Handles vs C Pointers


SystemVerilog handles differ significantly from C pointers. For example, arithmetic operations (incrementing,
decrementing, etc.) are not allowed for SystemVerilog handles, casting options are limited, arbitrary data cannot be
assigned to a handle, etc.

Object Properties and Object Parameters


The data fields of an object are called properties. Any legal data type can be used to declare a class property.
Properties are referenced by qualifying their name with the object (instance) name. The example below declares class
Point and two instances of that class: p1 and p2. Property x in either of the instances is accessed by specifying the
instance name (p1 or p2) followed by a dot and the property name.
class Point;
int x;

87

SystemVerilog Reference

Classes

endclass
Point p1 = new;
Point p2 = new;
initial begin
p1.x = 0;
p2.x = 22;
end

In parameterized classes (see Parameterized Classes) object parameters can also be accessed by qualifying the
parameter name with the instance name.
For a class declared as
class Point #(parameter step = 2);
endclass

and instantiated as p3, parameter step could be accessed as p3.step.

Object Methods
The syntax for accessing object methods is the same as the syntax for accessing class properties, i.e. the name of the
method must be prefixed with the name of the object followed by a dot (.), for example:
Point p;
initial begin
p = new;
p.move( 10 );
end

Each method can only access properties belonging to the object it is invoked against. (It cannot access properties of
other instances of the same class; however, it is possible to share data between all instances of the same class - see
Static Properties and Methods for details.)
The lifetime of methods declared as part of a class type is always automatic. Declaring a class method with a static
lifetime is illegal.

88

SystemVerilog Reference

Classes

Constructors
Whenever a new object (or a new instance of a class) is created, function new associated with the class is called.
A call to function new could look as follows:
Point p = new;

The actual implementation of function new can be provided in class Point, for example:
class Point;
int i;
function new( int _i = 2);
i = _i;
endfunction
endclass

The conventions for the constructor arguments are the same as for any other subroutine calls. The example in the
listing uses function new with one default argument. Consequently, specifying the argument for the constructor is
optional.
Point p = new;
// No actual argument provided; the default (2) will be used.
Point r = new(1); // 1 used as an argument for the constructor.

If a class does not contain a user-defined constructor, an implicit new method is provided automatically.
Object construction involves the following steps:
1. Memory is allocated for all dynamic object properties (local and inherited).
2. The object constructor (either user-defined or implicit) is called.
3. The constructor ports are initialized (if they exist).
4. Constructor local automatic variables are created and initialized (if they exist).
5. The base class constructor (super.new) is called (if the current class extends a base class). The constructor
in the base class can be either user-defined or implicit.
NOTE: The information about the base class constructor is a forward reference. For more information see:
Inheritance, Chaining Constructors, and Super.
6. Local object properties are initialized to their default values (i.e. values defined in the initialization at the
declaration).
7. Execution of the body of the constructor.
Referencing local or inherited dynamic variables prior to returning from the base class constructor triggers a compiler
warning.

89

SystemVerilog Reference

Classes

Inheritance
A class can be extended to form a new subclass. The new subclass will typically contain additional properties and
methods augmenting the base class. All properties and methods defined in the base class are inherited by the
subclass, as if they were defined directly in the subclass.
The example shows class ColorPoint that extends class Point. ColorPoint contains one new property (color),
and three methods to read color components.
class Point;
int pos;
function int get_distance;
if( this.pos < 0 )
return -this.pos;
else
return this.pos;
endfunction
endclass

class ColorPoint extends Point;


typedef bit[23:0] rgb_t;
rgb_t rgb;
function [7:0] get_red;
return rgb[23:16];
endfunction
function [7:0] get_green;
return rgb[15:8];
endfunction
function [7:0] get_blue;
return rgb[7:0];
endfunction
endclass

Property pos and method get_distance from the base class Point are also available in the derived class.
Note that neither the base class nor the derived subclass has a user-provided constructor. For information on how to
use constructors with extended classes, see Chaining Constructors.
A subclass in SystemVerilog can extend only one base class. This language feature is referred to as single
inheritance. Multiple inheritance (where a class inherits properties and methods from more than one class) is not
available.

90

SystemVerilog Reference

Classes

Chaining Constructors
Creation of an object that extends another class involves calling functions new (constructors) for all classes in the
inheritance hierarchy. The first action performed by function new from a subclass is calling method new() for the
superclass. The same rule is then applied to function new from the superclass, which may in turn call another
constructor from the class one level higher in the inheritance hierarchy. This approach ensures calling all constructors
in the proper order and creating objects begging with the root of the base class.
If a subclass does not have a user-defined constructor, a call to the constructor in the base class is inserted
automatically by the compiler. If the superclass does not have a user-defined constructor, the implicit constructor is
called.
If the constructor in the base class requires arguments and the default argument values are not provided, the call to
the constructor in the base class must be explicit (and include all required arguments). If the call is omitted, the
compiler reports an error.
The declaration of class P shown in the code below is invalid and will trigger a compiler error. Class P extends class
Point. The constructor for class Point requires an argument (_pos). Class P does not contain a user-defined
function new. The constructor is generated automatically by the compiler. It contains a call to the constructor in the
base class (Point::new) however, no arguments are passed to Point::new(). Therefore, an error is reported
about an unspecified argument for the formal argument _pos that does not have a default value.
class Point;
int pos;
function new( int _pos );
pos = _pos;
endfunction
endclass
class P extends Point;
endclass // Triggers an error about missing arguments.

Arguments for the base class constructor can be specified in the super.new call or in the extends clause.

Specifying Arguments in the super.new Call


A call to the constructor in the base class can be provided inside the body of the constructor of the derived subclass.
The constructor of the base class can be accessed with the super qualifier as super.new(). (For more information
on the super keyword, see Super.)
The listing below shows a declaration of class P1. The class contains a user-defined constructor (P1::new()). The
first executable statement in the constructor is a call to super.new(), i.e. the constructor of the base class
(Point::new()).
class P1 extends Point;
function new( int _i );
super.new( $random( _i ));
endfunction
endclass

Note that an argument passed to P1::new() is used in the invocation of Point::new().


A simpler example, where the value passed to Point::new() is constant is shown below.

91

SystemVerilog Reference

Classes

class P2 extends Point;


function new;
super.new( 16 );
endfunction
endclass

In this case, a user-defined function new() in class P2 can be omitted and the required arguments for
Point::new() specified in the extends clause.

Specifying Arguments in the extends Clause


Arguments for the base class constructor can be specified when the class is extended. They should be placed in the
extends clause after the name of the base class. An example is shown below. Class P3 extends class Point. Value
16 specified in the extends clause is passed to the constructor of class Point.
class P3 extends Point( 16 );
endclass

If multiple arguments are used, they must be separated with commas.

92

SystemVerilog Reference

Classes

Assigning, Renaming, Copying


Declaring a class variable does not create an object. The variable holds a handle to an object, however, before the
object constructor is called or an assignment is made to the variable, the variable value is null.

Assignment
The example shows class Point and two variables (A and B) that hold handles to objects of class Point.
class Point;
int x;
int y;
endclass
module m;
Point A, B;
initial begin
A = new;
B = A;
end
endmodule

The initial block calls the constructor (new) only once, for variable A. The constructor is never called for variable B.
Consequently, only one object is created. The assignment B = A; does not create a new object. Instead, it makes
variable B point to the same object as A.

Shallow Copy
A shallow copy is made when a new object is created by copying object properties from another object, as in the
following example:
class Segment;
int color;
Point A;
Point B;
endclass
module m;
Segment ab, cd;
initial begin
ab = new;
cd = new ab;
end
endmodule

All class properties (color, A, and B) of object ab are copied to object cd. However, objects of class Segment
contain two instances (A and B) of objects of class Point. A shallow copy does not copy those objects, only their
handles. Therefore, handles ab.A and cd.A point to the same object and not to separate copies of those objects. The
same applies to handles ab.B and cd.B.
Creating a shallow copy of an object with a null value is illegal and triggers a runtime error. See Full Copy for an
example.

93

SystemVerilog Reference

Classes

Full Copy
Creating a full copy where nested objects are also copied requires a user-defined subroutine. An example using such
a custom routine is shown in the listing below. The name of the routine (copy) is arbitrary.
initial begin
ab = new;
cd = new;
cd.copy( ab );
end

A simple implementation of the routine is shown below.


function void copy( Segment source );
this.color = source.color;
if( source.A ) this.A = new source.A;
if( source.B ) this.B = new source.B;
endfunction

You should note the following:


Before copying properties A and B a check is made to verify if the handles are not null. This is important,
because an attempt to create a shallow copy of an object that is null triggers a runtime error.
The copy routine in the example does not work recursively, i.e. if class Point contained instances of other
objects, only handles to those objects would be copied. In that case making a full copy would involve
implementing another copy method (inside class Point) and calling that method in Segment.copy.

94

SystemVerilog Reference

Classes

Static Properties and Methods


Class properties and class methods can be declared static. Such declarations begin with the keyword static.

Static Properties
A static variable is shared by all instances of a class.
Class Point shown in the listing has two instance properties (x and y) and one static property cnt. The static
property is incremented whenever a new object of class Point is created. Therefore, cnt contains a count of all
objects of class Point created during simulation.
class Point;
int x, y;
static int cnt = 0;
function new();
++cnt;
endfunction
endclass

A static class property can be accessed through an object handle, in the same manner instance properties are
accessed. However, a static property can also be accessed through a scope resolution operator (::), even if no
instance of a class has been created.
initial begin
repeat( 10 ) p = new;
$display( "%d", p.cnt );
$display( "%d", Point::cnt );
end

The initial block in the listing creates 10 instances of class Point. The cnt static property holding the number of
created instances in then displayed once. The first $display statement references the property through the p handle
(p.cnt), the other uses the class name and the class scope resolution operator (Point::cnt). Both references are
valid and both point to the same data item.
See Static Properties in Parameterized Classes for information on how class parameters affect static members.

Static Methods
A static method is subject to all the class scoping and access rules, but behaves like a regular subroutine that can be
called outside the class, even with no class instantiation.
A static method has no access to nonstatic members (properties or methods). It can only access static members of
the class where it is defined. Static methods cannot be virtual.
The example shows class Point with a static method get_cnt.
class Point;
int x, y;
static int cnt = 0;

95

SystemVerilog Reference

Classes

static function int get_cnt();


return cnt;
endfunction
function new();
++cnt;
endfunction
endclass

The static method accesses only static members (property cnt). It can be referenced either through an object handle
(p.get_cnt()) or through the class scope resolution operator (Point::get_cnt()) as shown in the listing.
initial begin
repeat( 10 ) p = new;
$display( "%d", p.get_cnt() );
$display( "%d", Point::get_cnt() );
end

The location of the static keyword is important. If it is moved behind the task or function keyword, then it refers
to the lifetime of arguments and variables within the task or function.
class C;
static task t1();
// ...
endtask // static class method with
// automatic variable lifetime
task static t2();
// ...
endtask // nonstatic class method with
// static variable lifetime
endclass

96

SystemVerilog Reference

Classes

This
Keyword this denotes a predefined object handle that refers to the object that was used to invoke the subroutine that
this is used within. Keyword this can be only used within nonstatic class methods.
In the example below, identifier this.x references property x in the instance of class Point. The unqualified
identifier (x) refers to the input argument of function new.
class Point;
int x;
function new (int x);
this.x = x;
endfunction
endclass

In the example below x was renamed to _x. Therefore, keyword this is no longer required to differentiate between
the function argument and the class property.
function new (int _x);
this.x = _x;
endfunction

However, keyword this improves code readability because it clearly indicates that the item that follows is a member
of the current object.

97

SystemVerilog Reference

Classes

Super
The super keyword refers to members of the parent class and is used from within a derived class. It is necessary to
use super to access members of a parent class when those members are overridden by the derived class.
A typical application of the super keyword is reaching for a constructor in the parent class, for example:
class Point2D;
int x, y;
function new( int _x, int _y );
this.x = _x;
this.y = _y;
endfunction
endclass
class Point3D extends Point2D;
int z;
function new( int _x, _y, _z );
super.new( _x, _y );
this.z = _z;
endfunction
endclass

Using super with the constructor (function new) involves a special limitation: super.new must be the first statement
executed in the constructor. (This is required to ensure a proper object construction order.)
The super keyword allows reaching only one level up in the inheritance hierarchy. super keywords cannot be
chained. (super.super followed by a member name is illegal).

98

SystemVerilog Reference

Classes

Casting
A class variable (handle) of one type can be cast to another type. Casting may succeed only for class types within one
inheritance hierarchy.
SystemVerilog provides both the $cast task and the $cast function. The function only checks if casting will succeed.
The actual casting is performed by the $cast system task. The task may fail at run time triggering a fatal error.
Therefore, you may invoke the function prior to the task and call the task only if the function return value indicates that
casting is possible.
Both the task and the function accept two arguments:
The source handle.
The destination handle.

When to Use $cast


Assigning a subclass variable to a variable of a class higher in the inheritance tree is always legal.
The listing below defines classes Point and CPoint. Class CPoint extends class Point.
typedef enum { yellow, red, green, blue, black } color_t;
class Point;
int x, y;
function new( int _x, int _y );
this.x = _x;
this.y = _y;
endfunction
endclass
class CPoint extends Point;
color_t c;
function new( int _x, int _y, color_t _c );
super.new( _x, _y );
this.c = _c;
endfunction
endclass

A handle to class CPoint (cp) can always be assigned to a handle to class Point because class Point is a
superclass of CPoint. No casting is required.
Point p;
CPoint pc;
initial begin
CPoint pc = new( 1, 2, blue );
p = pc; // It is always legal to assign a subclass variable
// to a superclass variable.
end

It is illegal to directly assign a superclass variable to a subclass variable. Such assignments must be performed with
the $cast task. The $cast task will succeed if the source handle refers to an object that is of the same type as the
destination handle or a subclass of a destination handle.
This is demonstrated in the listing below.

99

SystemVerilog Reference

Classes

Point p;
CPoint pc1;
CPoint pc2 = new( 8, 9, yellow );
initial begin
p = new( 3, 5 );
pc1 = new( 1, 2, blue );
if(! $cast( pc1, p ) ) begin
$display( "Cast will fail." );
$cast( pc1, p );
end
p = pc2;
if( $cast( pc1, p ) ) begin
$display( "OK to cast." );
$cast( pc1, p );
end
end

The $cast task in the first if statement fails because the source handle (p) is a handle to an object of class Point.
Point is a superclass of CPoint and cannot be assigned to CPoint.
The value of the source handle (p) is then assigned pc2 (and pc2 is a handle to an object of class CPoint). After the
assignment is made, p can be successfully cast to pc2.

100

SystemVerilog Reference

Classes

Data Hiding and Encapsulation


All class properties and methods are by default public. That means that anyone with an access to an object handle
can manipulate object internals. This is not always desirable.
The example below shows class CPoint. The class has four data fields:
x and y with Cartesian coordinates.
r and fi with polar coordinates.
class CPoint;
real x;
real y;
real r;
real fi;
endclass

The Cartesian coordinates and the polar coordinates carry the same information and one can be expressed in terms
of the other. If a coordinate in one system is updated, the coordinates in the other must be updated accordingly. If the
user of class CPoint has access to object properties, he can inadvertently corrupt the data in the object. This is
where data hiding comes into play.
You can declare all data properties in class CPoint local (using keyword local). This will prevent accessing the
properties from outside the body of the class. Then, provide methods get_x and set_x to read and write the
coordinate:
class CPoint;
local real x;
local real y;
local real r;
local real fi;
function real get_x();
return this.x;
endfunction
function void set_x( int _x );
/* Code omitted for brevity */
endfunction
endclass

While the get_x method has only to return the value of x, the set_x method must set the value of x and update the
planar coordinates (r and fi) accordingly.
This approach not only ensures data integrity. It also allows you to change the data structures used in the class
without affecting code using the class. For example, you could get read of data fields <x> and y and have method
get_x calculate x on the fly based on the values of r and fi.

Local and Protected Members


Keyword local limits access to members declared local to code inside the class. Such code can access members of
the current (this) instance or other instances of the same class. Members declared local in the base class are not
accessible inside classes that extend the base class. Members declared protected have the same characteristics
as members declared local, with one exception - they are visible in subclasses.

101

SystemVerilog Reference

Classes

Member access rules are demonstrated in the listing below. Lines marked with //Error are incorrect and will not
compile.
class C;
int m;
local int lm;
protected int pm;
function void test ( C _c );
$display( "%d", this.lm ); //OK to access members of the current instance (this)
$display( "%d", _c.lm );
//or any other instance of the same class.
endfunction
endclass
class D extends C;
function void test ( C _c );
$display( "%d", _c.lm ); //Error, cannot access a local member of the base class.
$display( "%d", _c.pm ); //OK, can access a protected member.
endfunction
endclass
module m;
C c;
initial begin
c = new;
$display( "%d", c.m ); //OK, can access a public member.
$display( "%d", c.lm ); //Error, cannot access a local member.
$display( "%d", c.pm ); //Error, cannot access a protected member.
end
endmodule

102

SystemVerilog Reference

Classes

Constant Class Properties


Class properties can be made constant using keyword const, similarly to other SystemVerilog variables. Two forms
of constant properties are available:
Global constants.
Instance constants.
Global constants are the same for all instances of the class. They can be assigned an initial value only in the
declaration.
Instance constants do not have an initial value in their declaration. They are marked by the const qualifier and can
be assigned to in the constructor, during simulation runtime. Assignments to instance constants outside the
constructor are illegal.
class Constants;
const int A;
const int B;
const int C = 10;
function new;
A = 10 + B; //B equals 0, A is assigned 10.
B = 10 + A; //A equals 10, B is assigned 20.
C = 10;
//Error. Illegal assignment to a global constant.
endfunction
endclass

103

SystemVerilog Reference

Classes

Overridden Members
The base class can override properties and methods from its subclasses. The example below shows two classes: C
and D. Class D extends class C. Method whoami is overridden.
class C;
function void whoami;
$display( "Class C." );
endfunction
endclass
class D extends C;
int x = 2;
function void whoami;
$display( "Class D." );
endfunction
endclass

The listing below contains instances of both the base class (C) and the subclass (D) and demonstrates the following:
Subclass objects are valid objects of their base classes, for example handle fp to class D can be assigned to
handle p1 of class C.
The type of the handle determines how references to overridden properties and methods are resolved. If the
type of the handle is that of the subclass (D), then the reference through the handle (p2.whoami()) points to
the subclass member (D::whoami()). If the type of the handle is of the base class (C), then the reference
(p1.whoami()) points to the member overridden in the base class (C::whoami()). The same principle is
used for resolving method references and property references.
See Virtual Methods for related information on virtual methods.
References to property x declared in subclass D are valid only if qualified by handle p2 of class D. Using
handle p1 of class C will trigger an error about an unresolved hierarchical reference. The error is reported at
simulation initialization. (The code compiles cleanly.)
module m;
D fp;
C p1;
D p2;
initial begin
fp = new;
p1 = fp;
p2 = fp;
p1.whoami(); // Displays "Class C.".
p2.whoami(); // Displays "Class D.".
//$display( "%d", p1.x ); // Illegal, would trigger an error at init.
$display( "%d", p2.x );
end
endmodule

Note that assigning a base class handle to a derived class handle (e.g. assigning p1 to fp) is illegal and triggers a
compilation error.

104

SystemVerilog Reference

Classes

Virtual Methods
Methods declared virtual can be overridden by methods in subclasses. This is shown in the listing below. Class D
extends class C. Method whereami from subclass C is declared virtual, therefore it can be overridden by methods
from subclasses, for example method whereami from class D.
class C;
virtual function void whereami();
$display( "Class C." );
endfunction
endclass
class D extends C;
function void whereami();
$display( "Class D." );
endfunction
endclass

In the following listing a handle to class C (i.e. the class with the virtual method) is assigned two handles: a handle to
an object of class C (q = c;) and a handle to an object of class D (q = d;).
module m;
C c = new;
D d = new;
C q;
initial begin
q = c;
q.whereami(); //Displays "Class C.".
q = d;
q.whereami(); //Displays "Class D.".
end
endmodule

This demonstrates a basic polymorphic construct. A call to method whereami qualified by the same handle q
(q.whereami()) calls method C::whereami() or D::whereami() depending on the type of the object assigned
to the handle. If method C::whereami were not declared virtual in class C, then the q.whereami() statement would
always resolve to method C::whereami() because q is a handle to an object of class C.
You should also note the following:
A method declared virtual remains virtual down the complete inheritance tree. If class D is extended by
another subclass, then a call to whereami through a handle of type C (where whereami is declared virtual)
can resolve to C::whereami, D::whereami, or whereami in either of D's subclasses.
Handles of all subtypes of class C are also affected by the fact that whereami is declared virtual in the
superclass (class C). For example, if class D is extended by class E, then a call to whereami through a
handle of type D can resolve either to D::whereami or E::whereami even though D::whereami is not
declared virtual.
The above principles are shown in the listing below. For brevity, function whereami is expanded from the WHEREAMI
macro.
`define WHEREAMI(_N) function void whereami(); $display( `"Class _N.`" ); endfunction
class C;
virtual `WHEREAMI(C)
endclass
class D extends C;
`WHEREAMI(D)

105

SystemVerilog Reference

Classes

endclass
class E extends D;
`WHEREAMI(E)
endclass
module m;
D d = new;
E e = new;
C q1;
D q2;
initial begin
q1 = e;
q1.whereami(); //Displays "Class E.".
q2 = d;
q2.whereami(); //Displays "Class D.".
q2 = e;
q2.whereami(); //Displays "Class E.".
end
endmodule

Default Values for Virtual Method Arguments


The listing below shows classes C and D. Class D extends class C and overrides virtual method say. The first call to
say in module m invokes C::say, the other D::say.
class C;
virtual function void say( string _str = "Hello" );
$display( "%s from class C.", _str );
endfunction
endclass
class D extends C;
function void say( string _str = "Bye" );
$display( "%s from class D.", _str );
endfunction
endclass
module m;
C c = new;
D d = new;
initial begin
c.say(); //Displays "Hello from class C.".
c = d;
c.say(); //Displays "Bye from class D.".
end
endmodule

The default values assigned to argument _str are hello and bye, respectively. In other words, if the call is routed to
method D::say, the default arguments are also read from the prototype of the D::say method. This behavior may
be surprising for C++ users. (The analogous code in C++ also calls methods C::say() and D::say(), however, the
default argument values are in either case read from C::say()).

106

SystemVerilog Reference

Classes

Abstract Classes and Pure Virtual Methods


A class declared with keyword virtual is an abstract class. An abstract class cannot be instantiated. Instead, it can
be extended; if the extending subclass is non-abstract, then an instance of that class can be created.
Abstract classes may contain pure virtual methods. A pure virtual method is a method declared with keywords pure
virtual and without a body. A pure virtual method specifies only the method interface; the actual method
implementation must be provided further down in the inheritance hierarchy.
The example below shows an abstract class Figure. The class is declared with keyword virtual. Two pure virtual
methods get_area and get_perimeter are declared inside the body of the class.
virtual class Figure;
pure virtual function real get_area();
pure virtual function real get_perimeter();
endclass

Any non-abstract class that extends class Figure must provide implementations of methods declared pure virtual in
the base abstract class. The example below shows class Circle that extends class Figure. Class Circle provides
implementation of the two pure virtual methods from class Figure.
typedef struct { real x; real y; } vertex_t;
class Circle extends Figure;
vertex_t middle;
real radius;
function new( vertex_t _a, real _r );
this.middle.x = _a.x;
this.middle.y = _a.y;
this.radius = _r;
endfunction
function real get_area();
return (this.radius ** 2) * `PI;
endfunction
function real get_perimeter();
return 2 * this.radius * `PI;
endfunction
endclass

An abstract class may also be extended to another abstract subclass. The subclass does not have to provide
implementations for all pure virtual methods. Implementations for the virtual methods must be available when the
abstract class is eventually extended to a non-abstract class that can be instantiated.

107

SystemVerilog Reference

Classes

Class Scope Resolution Operator


The class scope resolution operator :: is used for accessing identifiers within a particular class. For example, if type
colors_t is defined inside class Point, Point::colors_t can be used to access that type from outside the body
of the class.
class Point;
typedef enum { red, green, blue } colors_t;
endclass
module m;
Point::colors_t c; //A type reference.
initial begin
$display( "%d", Point::green ); //A reference to
//an enumeration type member.
end
endmodule

The class scope resolution operator :: can also be used to access static class members. They can be read, written
to, or triggered off in event expressions. A class scope can also be used as a prefix to a method call.
class C;
static int i;
static function void hello();
$display( "hello" );
endfunction
endclass
module m;
initial begin
C::hello(); //Call a static method.
#10;
C::i = 10; //Write a static property.
end
always @( C::i ) //Trigger an event.
$display( "%d", C::i ); //Read a static property.
endmodule

Accessing static class members is subject to data hiding rules (see Data Hiding and Encapsulation). Protected
members can only be accessed from derived classes. Access to local members is forbidden.
class C;
static int i;
protected static int j;
local static int k;
endclass
class D extends C;
function new;
$display( C::i ); //OK.
$display( C::j ); //OK.
$display( C::k ); //Error.
endfunction
endclass
module m;
initial begin
$display( "%d", C::i ); //OK.
$display( "%d", C::j ); //Error.
$display( "%d", C::k ); //Error.
end

108

SystemVerilog Reference

Classes

endmodule

The left side of the scope operator may be not only a class name but also a package, a covergroup type name, a
coverpoint name, or a cross name.

109

SystemVerilog Reference

Classes

Nested Classes
Classes in SystemVerilog can be nested. Nesting is useful when the inner class is a part of the implementation of the
outer class and is not intended to be used outside. Nesting can also prevent name collisions by hiding local names
within the outer class scope.
class TestEnv #(type T = int);
int TestQueue[$]; // Basic queue implementation.
class ExtendedTest;
class TestQueue #(type T = int);
// An extended implementation of the queue
// used only by the ExtendedTest class.
endclass
endclass
endclass

Nested classes have access to local and protected members of the nesting class and can access its static members
as well as parameters and local parameters. Direct access to non-static members of the enclosing class is not
allowed, the only way they can be accessed is through a handle.
class CNesting;
local
static
static

local

int
int
int
int

nonStaticPublicProperty;
nonStaticLocalProperty;
staticPublicProperty;
staticLocalProperty;

class CNested;
function void NestingClassAccess( CNesting handle );
staticPublicProperty = 1;
// Allowed.
staticLocalProperty = 1;
// Allowed.
nonStaticLocalProperty = 1;
nonStaticPublicProperty = 1;
handle.nonStaticLocalProperty = 1;
handle.nonStaticPublicProperty = 1;
endfunction
endclass
endclass

//
//
//
//

Not allowed.
Not allowed.
Allowed.
Allowed.

110

SystemVerilog Reference

Classes

Out-of-block Declarations
It is possible to move method definitions out of the body of the class declaration. Furthermore, such declarations can
be compiled independently of the class declaration and independently of the code that instantiates the class. If the
implementation of the method is changed but the method interface stays intact, only the implementation needs to be
recompiled.
To move the method body outside the class, do the following:
Specify the method prototype inside the class using the extern qualifier. A full argument list and other
qualifiers (if any) must be provided.
Provide the method declaration outside the body of the class. The method must be qualified with the class
name followed by a double colon. The argument list must be repeated verbatim and the qualifiers should be
omitted.
This is shown in the example below. The out-of-block method declaration matches the prototype declaration. It is
declared in the same scope as the class declaration.
class Packet;
typedef enum { OK, ERR } status_t;
extern function status_t check_crc();
endclass
function Packet::status_t Packet::check_crc();
status_t s;
//Calculate CRC...
return s;
endfunction

Note that type status_t declared inside the body of class Packet is available to the out-of-block declaration.
Furthermore, if another type status_t were defined outside the Packet class, then status_t used in the
out-of-block declaration would still resolve to Packet::status_t.

111

SystemVerilog Reference

Classes

Parameterized Classes
Class declarations can use parameters, similar to module declarations, for example:
class Buffer #(int size = 8);
reg [size-1 : 0] buff;
function integer get_size;
return $bits (buff);
endfunction
endclass

The declaration shown above declares class Buffer that uses one parameter (size). The default value of the
parameter is 8. This value can be overridden at instantiation. The listing below shows module test with the
instantiation of the class:
module m;
Buffer#(16) p;
initial begin
p = new;
$display ("Size = %d", p.get_size());
end
endmodule

The default value 8 of parameter size is overridden at instantiation with 16. Note that the syntax is consistent with
module instantiation and interface instantiation.
The combination of a generic class and the actual parameter values is called a specialization.
The listing below shows defining a new type (Buffer16 using the typedef statement and a specialization of class
Buffer.
typedef Buffer#(16) Buffer16;

Type Parameters in Parameterized Classes


A class can be parameterized with a type. The listing below shows class Buffer. Parameter T specifies the type of
elements stored in the Buffer, the return type for method pop and the argument type for method push. The default
type is int but any other type can be supplied.
class Buffer #( type T = int );
T buff[];
extern function T pop();
extern function void push( T elem );
endclass

Module m contains two instantiations of the Buffer class: one using Buffer specialized with the default type int
and the other with structure type s_t.
typedef struct {
int i;
real r;
} s_t;
module m;

112

SystemVerilog Reference

Classes

Buffer#( int ) buff_int;


Buffer#( s_t ) buff_str;
//...
endmodule

Omitting Default Parameter Values


A default value of a parameter can be omitted in a class declaration. If so, the value must be specified when a class is
instantiated. Otherwise, a compilation error will be triggered. IEEE Std 1800-2009 defines two forms of the
parameter value assignment: assignment by ordered list and assignment by name. See Verilog Reference Guide |
Module Instantiation for further information.
In the following example, the assignment by name is executed. Parameters without default values, such as P1 and
T2, must have a value assigned at the instantiation. Parameters with a default value may be omitted, as it is done for
the P2 parameter. Though the T1 parameter may be also omitted, its default value (real) is overridden at the
instantiation with the int type.
class A #(type T1 = real, parameter int P1, parameter byte P2 = 5, type T2);
endclass
A #(.P1(8), .T1(int), .T2(shortint)) cl_a = new();

Assigning a parameter value by ordered list implies to specify each parameter that precedes the parameter to be
assigned, since in the instantiation, the parameter has to be on the same position as in the declaration.
In the example below, there is a class instantiation with ports assigned by ordered list. Even though there is only one
parameter without a default value (P2), the parameters T1 and P1 have to be also specified since the P2 parameter
has to be placed on the proper position of the ordered list. Only the T2 parameter that follows after the P2 parameter,
can be omitted.
class B #(type T1 = real, parameter real P1 = 12.41, parameter byte P2, type T2 = reg[7:0]);
endclass
parameter real p = 8.71;
B #(real,p,8'b00110101) cl_b = new();

Equivalence of Specializations
Two class specializations are equivalent if their parameters are identical. The example below shows class C and two
specializations of the class: C1 and C2.
class C#( type T = int, int w = 1 );
endclass
typedef real r_t;
typedef C#( real, 2 ) C1;
typedef C#( r_t, 1+1 ) C2;

Because parameters used for both specializations are the same (although not lexicographically identical) classes C1
and C2 are equivalent. Therefore, a handle to C1 can be assigned to C2 and vice versa.

113

SystemVerilog Reference

Classes

Static Properties in Parameterized Classes


Each different specialization of a class has a separate set of static member variables. If the specializations are
equivalent, they share static members.
Different class specializations can share static members if those members are placed in a non-parameterized base
class.

Benefits of Parameterized Classes


Using parameterized classes allows you to write common code for objects that are different and not interchangeable.
You can create one generic version of a class and then specialize that class with different types and values without
having to duplicate (and maintain) the same code for each specialized version.
All class parameters are known at compile time. This improves type safety and allows the compiler to perform a
thorough source code checking. For example, if operator + is used inside class C for two operands of type T and class
C is then specialized with type T that happens to be an unpacked structure, the compiler will be able to detect that
unpacked structure operands cannot be used with the <+> operator.

Local Class Parameters


Class parameters can also be declared with the parameter and localparam keywords. (The two keywords are
synonymous as far as their usage inside a class is concerned.) An example is shown below:
class Buff;
parameter int size = 8;
reg [size-1 : 0] buff;
function integer get_size;
return $bits (buff);
endfunction
endclass

Parameters declared with the parameter and localparam keywords are local to the class and cannot be
overridden when instantiating the class (unlike parameters declared with the parameter port list syntax #(<type>
<name>=<value>)).

114

SystemVerilog Reference

Classes

Typedef Class
The typedef class statement should be used whenever a class variable has to be declared before a complete
class declaration. The example below shows such a scenario. Two classes Node and Root are used. Objects of type
Node contain property r of type Root. On the other hand, objects of type Root reference properties of type Node.
typedef class Root;
class Node;
Root r;
int id;
endclass
class Root;
Node n[];
endclass

The typedef class statement used at the beginning of the listing resolves the circular dependency. It indicates that
Root is a type that will be declared further down in the source code text. This allows a successful compilation of class
Node. A complete declaration of class Root must be provided in the same compilation unit after the declaration of
class Node.
Keyword class (in the typedef class statement) is optional. The example will compile cleanly also if you use
typedef Root; instead of typedef class Root;. However, using the class keyword improves code legibility
by indicating that the forward typedef'ed type is a class.

115

SystemVerilog Reference

Classes

Memory Management
Memory management in SystemVerilog is automatic. The simulator allocates memory when a new object is created.
The memory is reclaimed when the object is no longer needed, for example when it goes out of the scope or all
references to the object are destroyed.
The first listing shows an automatic task t. Whenever the task is called, it creates a new object f of type Frame.
When the task completes, variable f goes out of the scope so the simulator frees the memory allocated for f.
task automatic t( );
Frame f = new( 200, BULK );
f.fill();
#100;
f.send();
endtask

Another example shows an initial block with two instances of the Frame class. Two objects of type Frame are
created and then the handle stored in f is overwritten with the handle stored in g. At that point no handle points to the
first object; there is no way the user code can access that object so the simulator can delete it and reclaim the
memory.
Frame f, g;
initial begin
f = new( 200, HID); //The first object.
g = new( 100, BULK); //The second object.
f = g; //Both handles point to the second object.
//No handle points to the first object.
end

116

Assignment Statements

Assignment Patterns
Assignment patterns allows you to assign a set of values to elements of an aggregate data type. An assignment
pattern is a list of values separated by comas, enclosed in braces and prefixed with an apostrophe. The construct can
be used on both the left-hand or the right-hand side of an assignment if a self-determined data type is placed on the
opposite side.
module top;
int v,x,y,z;
int arr1[4] = '{6, 7, 8, 9};
int arr2[3] = '{1, 2, 3};
initial begin
arr1 = '{v, x, y, z};
'{x, y, z} = arr2;
end
endmodule

The replication operator can be used within the pattern assignment.


int z;
int n[1:3][5:6] = '{3{'{2{z}}}}; // same as '{'{z,z}, '{z,z}, '{z,z}}

It is allowed to use empty assignment patterns on the right-hand side of assignments. Such assignments clear the
contents of an aggregate and set its size to zero. SystemVerilog specification allows assigning empty patterns to
queues. Aldec Inc. extends this functionality to dynamic and associative arrays.
module top;
int que[$] = '{};
byte dyn[];
reg[15:0] asc[string];
initial begin
dyn = '{};
asc = '{};
end
endmodule

Note that assigning an empty pattern to a fixed-size array is not allowed. The assignment below shall trigger an error:
logic arr[4] = '{}; // error

Assignment Pattern Expressions


The assignment pattern expression is an assignment pattern preceded by the type name that determines the type of
the pattern. Unlike the pattern assignment, the pattern assignment expression is a self determined data type and it
does not require another self determined data type on the opposite side of the assignment.

117

SystemVerilog Reference

Assignment Statements

In the below example, an assignment pattern expression is used in the assignment to an assignment pattern. If the
assignment pattern was used instead of the assignment pattern expression an error would be triggered because none
of the assignment sides would determine the type.
module m;
typedef struct {bit [7:0] a; reg [7:0] b; int c;} R;
var byte a, b, c;
var int d;
initial R'{a, b, d} = '{2, 4, 6};
endmodule

It is possible to assign an empty assignment pattern expression to a queue, dynamic array or an associative array to
clean the contents of an aggregate and set its size to zero.
module top;
typedef int T;
typedef int QQ[$];
QQ que;
T dyn[];
T ass[int]=T'{};
initial begin
dyn = T'{};
que = QQ'{};
end
endmodule

Assignment Keys
Assignment keys are colon-separated statements that precedes consecutive values in an assignment pattern.
Assignment keys allows you to assign values to one or more aggregate fields or members.
To indicate a specific field of an array or a specific member of a structure use the index key or the member key,
respectively.
struct {real a1; int a2;} tss;
int arr[2];
initial begin
tss = '{a1:9.72,a2:321}; // member keys
arr = '{0:34,1:54};
// index keys
end

The type key assigns values to all fields or members of the specified data type.
struct {bit [31:0] a1; integer a2; int a3; int a4;} str;
initial str = '{int:12, a1:255, a2:7}; // 12 is assigned to all elements of the int type

Use the default key to assigning values to all aggregate elements that do not have a value specified with the type,
index or member keys.
typedef logic [15:0] T1;
int arr[10];
struct {bit [31:0] c1; int c2; T1 c3; shortint c4;} s1;
initial arr = '{default:5}; // sets all elements to 5
initial s1 = '{T1:11, c4:16 , default:3}; // sets c1 and c2 to 3

118

SystemVerilog Reference

Assignment Statements

If assignment keys are not specified, then the positional notation is used, that is, the position in a pattern assignment
determines to which field or member a value should be assigned.
integer arr[4] = '{1, 5, 8, 11}; // the positional notation

The positional notation and the notation with the assignment keys cannot be used together in one assignment pattern.

Assignment Keys Precedence


The assignment keys precedence is as follows (first in the list has the highest priority):
1. index and member
2. type
3. default
In the first assignment from the example shown below, the value assigned to a1 structure field is 6.7 since the type
key has higher priority than the default key.
In the second assignment, 8.1 will be assigned to the a1 structure member since the index key has higher priority
then type and default keys. To the a2 member that is of int type, 4 will be assigned because the type key has
the highest priority of all keys that pertains to the a2 member.
The default key has the lowest priority. Therefore, in both assignments, this key is assigned only to these members
that do not have another key.
module top;
typedef struct {real a1; int a2; reg [7:0] a3; logic [15:0] a4;} TS;
TS str;
initial begin
str = '{real:6.7, default:100}; // a1 = 6.7 , a2 = 100 , a3 = 100 , a4 = 100
str = '{a1:8.1, real:9.2, int:4, default:10}; // a1 = 8.1 ,a2 = 4, a3 = 10, a4 = 10
end
endmodule

Assignment Pattern on the left-hand side of an assignment


An assignment pattern on the left-hand side can be used to assign aggregate elements to variables placed in such
pattern. This allows more than one aggregate element to be assigned in the single statement.
module top;
int a,b;
struct {int a1; int a2;} str = '{1,2};
initial begin
'{a,b} = str;
end
endmodule

If an assignment pattern is used on the left side of an assignment, the following conditions must be met:
The positional notation must be used; It is not allowed to use assignment keys.
module top;
int ABC[2];

119

SystemVerilog Reference

Assignment Statements

int a,b;
initial '{1:a, 2:b} = ABC; // illegal keys on left-hand side are not allowed
initial '{a,b} = ABC;
// legal
endmodule

Each member expression must have a bit-stream data type which is assignment compatible with the
corresponding element on the left side of the assignment.
The number of bits of the corresponding elements must match.
NOTE: There are some differences in the way in which pattern assignments placed on the left-hand side of an
assignment are treated in the default mode and in the strict LRM mode. See User's Guide | SystemVerilog Simulation
| Strict LRM Mode | Assignment Patterns for details.

120

SystemVerilog Reference

Assignment Statements

Unpacked Array Concatenations


Unpacked array concatenation is used to assign values to unpacked arrays. It has to be a source expression of an
assignment-like context (e.g. continuous or procedural assignment, parameter declaration, port connection to an input
or output of a module interface or program, passing a value to subroutine, etc).
It can be only assigned to an array whose slowest-varying dimension is an unpacked fixed-size array, queue or
dynamic dimension. Note that a target of any other type, including associative array, is illegal.
The unpacked array concatenation is a comma-separated list, enclosed in braces similar to the assignment pattern.
However, in contrast to the assignment patterns, braces are not preceded by an apostrophe and there is no
assignment keys.
int arr[3]
arr = {5, 6, 7}; // an array concatenation
arr = '{7, 8, 9}; // a pattern assignment

In some cases, as in the preceding example, both forms give the same effect. Nevertheless, these two constructs
have different properties. The most significant difference is that an unpacked array concatenation can be composed of
both simple elements and arrays.
module top;
int arr1 [$] = '{0, 1, 2};
int arr2 [] = '{8, 9, 10};
initial
begin
arr1 = {arr1, arr2,100}; // '{0, 1, 2, 8, 9, 10,100}
arr2 = {arr1, arr2}; // '{0, 1, 2, 8, 9, 10, 100, 8, 9, 10}
end
endmodule

NOTE: Whole arrays as elements of concatenation are supported only for queues and dynamic arrays.
As in the case of the pattern assignments, unpacked array concatenations can be empty. Assigning an empty array
concatenation results in clearing the contents of an aggregate and setting its size to zero. SystemVerilog specification
allows assigning empty concatenations to queues. Aldec Inc. extends this functionality to dynamic arrays. It is not
allowed to assign an empty concatenations to fixed-size arrays.
module top;
int que[$] = {};
byte dyn[] = {2,3,4};
int arr[3];
initial begin
dyn = {};
arr = {}; // error: assigning empty concatenation
// to fixed-size array is not allowed
end
endmodule

The Following constructs and properties allowed in pattern assignment are forbidden in array concatenation:
a syntax resembling replications i.e
'{ n{element}}

121

SystemVerilog Reference

Assignment Statements

setting array to default values and setting default values for explicit type
int arr3[5] = '{default:2};

// gives arr3 = {2,2,2,2,2}

array concatenation cannot be used on the left-hand side of an assignment


only a positional notation is allowed

Limitations
Use of fixed-size arrays inside an array concatenation or as a target of such assignment is not supported in
the current release.

122

Tasks and Functions

Functions

Non-mandatory begin ... end or fork ... join Blocks


Statements inside the function body no longer have to be embraced by a begin...end or a fork...join block.
function f1;
$display( "Function f2 has no begin-end block." );
return 0;
endfunction

Formal Arguments
Function ports can be of type input, output, inout, and ref, similarly to task ports. If the direction is not specified
in the argument declaration, the default direction is the input direction. Once a direction is given, subsequent formals
default to the same direction.
function reg [3:0] f2( int a, b, output reg [3:0] c, d );
c = a[4:1];
d = b[9:6];
endfunction

SystemVerilog allows an array to be specified as a formal argument to a function.


The function with output, inout, or ref arguments cannot be called in an event expression, in an expression within
a procedural continuous assignment, or in an expression that is not within a procedural statement. (A const ref
function argument is legal in this context.)

Lifetime
Functions in Verilog can be either static or automatic. Task arguments and local variables are shared between all calls
to a static function and unique for each call to an automatic function.
SystemVerilog adds an additional level of flexibility by allowing you to declare:
Automatic variables within static functions.
Static variables within automatic functions.

123

SystemVerilog Reference

Tasks and Functions

Return Values and void Functions


SystemVerilog introduces functions of type void. Such functions do not have a return value.
function void vf;
$display( "This is a void function" );
endfunction

Parenthesis are optional in invocations of void functions that accept no arguments.


The nonvoid function can return value by assigning the function name to a value, or by using return statement with a
value. The return statement overrides any value assigned to the function name. The return statement in nonvoid
functions must be followed by an expression.
function int f3( input int a, b );
return a + b * 3;
endfunction

Discarding Function Return Values


The return value of a nonvoid function can be discarded by casting the function to the void type:
void'( my_funct() );

Constant Function Calls


In SystemVerilog a constant function may call any system function that may be called in a constant expression. This
includes $bits and the array query functions. A constant function may reference parameters defined in packages or
$unit.
SystemVerilog imposes the following restrictions on constant functions:
A constant function cannot not have output, inout, or ref arguments.
A void function cannot be a constant function.
An import "DPI" function cannot be a constant function.
A constant function may have default argument values, but any such default argument value must be a
constant expression.

Statements Allowed in Functions by SystemVerilog 2009


SystemVerilog 2009 (IEEE 1800-2009) allows statements that do not block to be used inside functions; specifically,
nonblocking assignments, event triggers, procedural assignments, clocking drives, and fork-join_none constructs
are allowed. For example:
reg[3:0] a;
event e;
reg[3:0] r;
int c;
bit clk;
clocking cb @(posedge clk);

124

SystemVerilog Reference

Tasks and Functions

output c;
endclocking
function void f_ext(reg[3:0] i);
assign a=i;
->e;
r <= i;
r <= #10 i+1;
->>e;
cb.c <= ##2 i;
r <= @e i+2;
endfunction

125

SystemVerilog Reference

Tasks and Functions

Tasks

Non-mandatory begin ... end or fork ... join Blocks


SystemVerilog adds the possibility to declare multiple statements in a task or function without requiring a
begin...end or fork...join block
task t;
$display( "This is task t" );
$display( "Task t has no begin-end block" );
endtask

Formal Arguments
Task ports can be of type input, output, inout, and ref. If there is no direction in function argument declaration,
the default direction is the input direction. Once a direction is given, subsequent formals default to the same direction.
task t1(a, b, output int c, v);
// ...
endtask

The task argument default type is logic.


task t2 (x, y, z);
// arguments x, y, z are of type logic
endtask

SystemVerilog allows an array to be specified as a task formal argument.

Lifetime
Tasks in Verilog can be either static or automatic. Task arguments and local variables are shared between all calls to
a static task and unique for each call to an automatic task.
SystemVerilog adds an additional level of flexibility by allowing you to declare:
Automatic variables within static tasks.
Static variables within automatic tasks.
task automatic t3;
static int x;
int y;
x++;
y++;
endtask

126

SystemVerilog Reference

Tasks and Functions

The return Statement


The return statement
The return statement can be used to exit the task before execution reaches the endtask keyword.
task t4();
if( i > 10 )
return;
$display( "Incrementing i." );
i++;
endtask

127

SystemVerilog Reference

Tasks and Functions

Passing Arguments to Tasks and Functions


SystemVerilog provides several enhancements in handling task and function arguments.
Arguments can be passed either by value or by reference.
Arguments can be bound by name or by position.
Arguments can be given default values, allowing function and task calls not to pass arguments.

Pass by Value
Pass by value works by copying each argument into the subroutine area. If the subroutine is automatic, then the
subroutine retains a local copy of the arguments in its stack. If the arguments are changed within the subroutine, the
changes are not visible outside the subroutine.

Pass by Reference
Passing an argument by reference requires preceding the argument declaration with the ref keyword, for example:
task automatic t( ref int i[1000] );

The actual subroutine call looks the same.


t( r );

Arguments passed by reference are not copied into the subroutine. Instead, the routines receives the reference and
can access the argument data via the reference. If the subroutine changes the argument data, that change is visible in
the calling context.
Passing by reference can be used to avoid copying large arguments to the subroutine. It also allows sharing a piece
of data that is not declared global.
If it is desired to prevent task or function from changing passed argument, reference can be declared as constant.
function automatic f(const ref int a);

Pass by reference is allowed for automatic subroutines only.

Limitations
Elements of unpacked arrays are not supported as ref arguments. This applies to fixed-size arrays as well
as dynamic arrays, associative arrays, and queues.

Default Argument Values


A default value for each singular argument is allowed in the subroutine declaration. The syntax to declare a default
argument in a subroutine is as follows:

128

SystemVerilog Reference

Tasks and Functions

subroutine( [ direction ] [ type ] argument = default_value );

The optional direction can be input, inout, or ref (defaults are not allowed for output ports). The default_value
expression is evaluated in the scope containing the subroutine declaration each time a call using the default is made.
If the arguments with default values are omitted in the subroutine call, then the default values are used. Omitting an
argument without a default value is illegal.
integer a, b, c;
task automatic t(
input integer _i = 2,
inout integer _j = a,
ref integer _k = b
);
_k = _i + _j;
_j = _i + 2;
endtask
initial begin
t( 1, a, b ); $display( "%0d %0d %0d\n", a, b, c ); // 3 x x
t( 1, a, c ); $display( "%0d %0d %0d\n", a, b, c ); // 3 x 4
t( , a,
); $display( "%0d %0d %0d\n", a, b, c ); // 4 5 4
end

Argument Binding by Name


Tasks and functions arguments can be bound by name.
task t( int i = 3, byte b = 1, real f );
//...
endtask
initial begin
t( .i(2), .b(1), .f(0.5) );
t( .i( ), .f(1.0) );
end

Both positional and named arguments mapping of subroutine call is allowed, but positional binding must precede
name binding.
t( 4, 0, .f(0.5) );

129

Operators and Expressions

An expression combines operands with operators to yield a result.

Operators Precedence and Associativity


The table lists SystemVerilog operators; operators with the highest precedence are located at the top of the table.
Operators
() [] :: .
+ - ! ~ & ~& | ~| ^ ~^ ^~ ++ --

Associativity and/or Arity


left
unary

**

left

*/%

left

+-

left, binary

<< >> <<< >>>

left

< <= > >= inside dist

left

== != === !== ==? !=?

left

&

left, binary

^ ~^ ^~

left, binary

left, binary

&&

left

||

left

?:

ternary conditional operator,


right

-> <->

right

= += -= *= /= %= &= ^= |= <<= >>= <<<= >>>= :=


none
:/ <=
{} {{}}

concatenation

Most operators (for example + and -) are left associative. Therefore


1 - 2 + 3

is equivalent to
(1 - 2) + 3

130

SystemVerilog Reference

Operators and Expressions

rather than
1 - (2 + 3)

Assignment Operators
SystemVerilog supports the simple assignment operator (=). Additionally, a number of C-like assignment operators
and special bitwise assignment operators are available: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, <<<=, and >>>=.
The assignment operator is semantically equivalent to a blocking assignment.
a += b;
c ^= d;

An expression in SystemVerilog can include a blocking assignment, provided it does not have a timing control. These
blocking assignments must be enclosed in parentheses. It is illegal to include an assignment operator in an event
expression, in an expression within a procedural continuous assignment, or in an expression that is not within a
procedural statement.
a = (b = c+5);

SystemVerilog includes increment and decrement assignment operators, both in the prefix and postfix forms: ++i,
--i, i++, and i--. They do not need parentheses when used in expressions. These operators also behave as
blocking assignments.

Wild Equality and Wild Inequality Operators


SystemVerilog includes wild equality (==?) and wild inequality operators (!=?). The operators treat X and Z values in
a given bit position in the right operand as wildcards. Such a wildcard matches any bit value (0, 1, Z, X) in the
corresponding bit in the left operand.
Operator

Usage

Description

==?

a ==? b a equals b, X and Z values in b act as wildcards.

!=?

a !=? b a does not equal b, X and Z values in b act as wildcards.

The following assignment will assign value 1 to res. (Z in the right operand is a wildcard that matches 0.)
res = (4'b1110 !=? 4'b111Z);

The ==? and !=? operators may result in X if the left operand contains an X or Z that is not being compared with a
wildcard in the right operand. For example:
res = (4'b111Z ==? 4'b1111);

The above statement assigns an X to register res.

131

SystemVerilog Reference

Operators and Expressions

Real Operators
The unary operators ++ and -- can have operands of type real and shortreal (the increment or decrement is by
1.0). The assignment operators +=, -=, *=, /= can also have operands of type real and shortreal.

Concatenation
The concatenation is expressed by using brace characters ({ and }) around expressions separated with commas, for
example:
{i, i[7:0], r, 8'h0F }

The result of the concatenation operation is the value resulting from joining together of bits from each expression.
Concatenation can be placed on either side of the assignment.
initial begin
int i, j, k;
k = 10;
{i, j} = {k, k};
end

Concatenation can also be performed on objects of type string. The result of the concatenation is a string if at least
one of the operands is of type string.
string s1
string s2
string s3
$display(

= " ";
= "string";
= {"This is", s1, s2, " s3."};
"%s", s3 ); // Displays 'This is string s3.'

String concatenation is not allowed on the left-hand side of an assignment.


Note that concatenation is different from array and structure literals. (In literals, the braces ({}) are prefixed with an
apostrophe ('); the apostrophe is not used in concatenation.)

Replication
A replication (also referred to as multiple concatenation) is created by prefixing a concatenation with a constant
expression and enclosing everything with another set of braces. The constant value should be positive. It must not
contain X or Z values.
The example below shows how to concatenate four copies of value 8'hE5. (The result is 32 bit wide.)
{ 4{ 8'hE5} }

A more elaborate example is shown below. The concatenation consists of three elements (r, arr, 1'b0); it is
replicated three times to yield a result that is 30 bit wide.
integer i;
reg r;
reg[7:0] arr;
i = { 3{ r, arr, 1'b0 }};

132

SystemVerilog Reference

Operators and Expressions

If object is of type string, the replication operator can be used with a non-constant multiplier, for example:
int i = 3;
string str = {i{"x y z"}}; // The result is: str = x y zx y zx y z

Tagged Union Expressions and Member Access


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

Aggregate Expressions
The following objects can all be used as aggregate expressions:
An unpacked structure.
An array data object.
An aggregate expression.
A multi-element slice of an unpacked array.
Aggregate expressions can be copied in an assignment, through a port, or as a subroutine argument. They can also
be compared with equality or inequality operators. To be copied or compared, the expressions must be of equivalent
types.

Operator Overloading
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

Streaming Operators (pack/unpack)


The streaming operators convert the bit-stream types, e.g. arrays, structures, classes, into sequences of bits; or vice
versa: convert the sequences of bits to the bit-stream types.
When used in the right hand side of an expression, the streaming operators pack the bit-stream types into sequences
of bits. When used in the left hand side of an expression, the streaming operators allow unpacking streams of bits to
variables. The streaming method is specified by specifying the streaming order and the slice size. The streaming order
specifies the sequence in which the slices of data will be streamed, i.e. left-to-right (>>) or right-to-left (<<). The slice
size determines the size of the processed data blocks. If not specified, the slice size of 1 bit is assumed; if a type is
specified, e.g. byte, then the slice size is the number of bits in that type.
The examples below show the packing and unpacking operations performed both in left-to-right and right-to-left
orders, with various slice sizes:
bit [7:0] array [4] = '{1,2,3,4};
int stream;
//
stream = { >> { array } };
//
stream = { << { array } };
//
stream = { << 8 { array } };
//

stream contents after the operation:


'h01020304
'h20C04080
'h04030201

133

SystemVerilog Reference

Operators and Expressions

bit [7:0] array [4];


int stream = 32'h01020304;
{ >> { array } } = stream;
{ << { array } } = stream;
{ << 8 { array } } = stream;

//
//
//
//

array contents after the operation:


array[0] = 1,
array[1] = 2,
array[2] = 3,
array[3] = 4
array[0] = 'h20, array[1] = 'hc0, array[2] = 'h40, array[3] = 'h80
array[0] = 4,
array[1] = 3,
array[2] = 2,
array[3] = 1

Conditional Operator
The conditional operator requires three operands separated by ? and ::
<condition> ? <expr> : <expr>

If <condition> is true, the operator returns the value of the first expression without evaluating the second. If it is
false, it returns the value of the second expression without evaluating the first. If <condition> evaluates to an
ambiguous value (i.e. x or z), then both expressions are evaluated and their results are combined bit by bit. A result
bit equals 0 if the respective bits in the first and the second expression equal 0. A result bit equals 1 if the respective
bits in the first and the second expression equal 1. All other bits are set to x.
Note that the conditional assignment and the if statement in the listing below are not equivalent. (The values
assigned to i may be different when cond evaluates to an ambiguous value.)
i = cond? a : b;
if( cond )
i = a;
else
i = b;

SystemVerilog allows using the conditional operator with nonintegral types and aggregate expressions. If both first
expression and second expression are of integral type, the operation proceeds as defined. If first expression or
second expression is an integral type and the opposing expression can be implicitly cast to an integral type, the cast is
made and proceeds as defined. For all other cases, the type of the first expression and second expression must be
equivalent.

Inside Operator
The inside operator checks whether the value of the expression from the left-hand side is present on the right-hand
side list.
The syntax is as follows:
<expr> inside {list}

The left-hand side expression has to be a singular expression (aggregate types are not allowed).
For nonintegral expressions, the inside operator uses the equality (==) operator to perform a comparison. If at least
one value on the list is equal to the left-hand side expression, the inside operator returns 1'b1. Otherwise, 1'b0 is
returned.
real rv = 9.66;
if ( rv inside {9.72, 14.1, 9.66, 1.683} ); // the result is 1'b1

134

SystemVerilog Reference

Operators and Expressions

integer dt = 12;
integer darr[] = new[3]('{11, 12, 16, 18});
if ( dt inside {7, darr} ); // arrays are allowed on the right-hand list

For integral expressions, the wildcard equality operator is used (==?), so that the x or z bits on the right-hand side of
the expression are treated as do-not-care values. On the left-hand side, the x or z bits are treated as they are.
reg [2:0] logvar;
while ( logvar inside {3'b1x1} ); // matches 3'b101, 3'b111, 3'b1x1, 3'b1z1
if ( logvar inside {3'bz01} );
// matches 3'bz01, 3'bx01, 3'b001, 3'b101

If no match is found, but some of the comparisons resulted in x, the inside operator will return 1'bx.
n = 3'b11x;
res = n inside {3'b1z1, 3'b010};

// res = 1'bx

When specifying members of the list, a range of values can be used. The list from the example below contains all
numbers from 2 to 4 and from 7 to 11.
int intvar;
logic logvar = intvar inside { [7:11], [2:4] };

If the left bound is higher than the right bound, the range contains no values.

Constraint Block Operators


For a list of operators supported in constraint blocks see Operators in the Constraints Block section.

135

Behavioral Statements and Control Flow

Selection Statements

Priority and Unique Keywords


SystemVerilog unique and priority keywords are added to the if and case selection statements.
The unique keyword in the if statement indicates that the conditions in the if statement are mutually exclusive and
can be safely evaluated in parallel. If more than one condition evaluates to true, the simulator reports an error. The
simulation continues even though an error has been reported.
The unique keyword in the case statement indicates that no more than one choice in the case statement matches.
If it does, the simulator reports an error without interrupting the simulation. If overlapping choices in the case
statement can be detected at the compilation stage, the appropriate warning is also generated by the compiler when
the file is compiled.
The priority keyword can be a hint for synthesis tools. It indicates that a series of if else conditions or case
choices should be evaluated in the order listed. If more than one condition is true or more than one choice matches,
priority logic may be required.
When either the unique or priority keywords are used, the simulator issues a warning if no condition is true or no
choice matches the expression.
unique if ((a==0) || (a==1))
x = 13;
else if (a == 2)
x = 0;
else if (a == 4)
x = 2;
priority case(a)
2'b00: task1();
2'b01: task2();
endcase

Keywords unique and priority can be also used with casex and casez constructs.

Set Membership Case Statement


The inside keyword allows you to indicate a set membership in the manner similar to the inside operator. The
condition expression is compared with lists of values specified for each statement. The result is 1'b1 if any of
specified values is equal to the case expression. The evaluated statement is the first statement whose condition result
is 1'b1. If all operations returns 1'b0 or 1'bx, none of statements is evaluated or, if specified, the default item
statement is evaluated.

136

SystemVerilog Reference

Behavioral Statements and Control Flow

See the Operators and Expressions section for information on how the inside operator is evaluated.
int q[$] = '{5,7};
initial
case (case_expr)
[2:4]
:
3, q
:
3'b?00, [1:3] :

inside
statement1;
statement2;
statement3;

//
//
//
//
default : default_statement; //
endcase

matches 3'b010, 3'b011 and 3'b100


matches 3'b011, 3'b101 and 3'b111
matches 3'b000, 3'b100, 3'bx00, 3'bz00,
3'b001, 3'b010, 3'b011
e.g.
3'b01x, 3'bxxx, 3'b110

Pattern Matching
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

137

SystemVerilog Reference

Behavioral Statements and Control Flow

Loop and Jump Statements

Loop Statements

do ... while Loop


SystemVerilog introduces the do ... while loop. Note that the first iteration of such loop is executed regardless of
how the condition evaluates.
// SystemVerilog Extension
integer i;
initial begin
i = 0;
do begin
$display (i);
i = i+1;
end
while (i<10);
end

for Loop Enhancements


SystemVerilog adds the possibility to declare a variable used to control the for loop inside the loop, for example:
for (integer i=1; i<10; i++) begin
$display ("%d", i);
end

Variables declared in the loop are local to the loop and they cannot be modified outside it.
The following syntax introduced in IEEE Std 1800-2012 is supported:
for ( [ for_initialization ] ; [ expression ] ; [ for_step ] )

The statements controlling the execution of the for loop that is: for_initialization, expression and
for_step are optional according to IEEE Std 1800-2012. For more information, see 12.7 in IEEE Std
1800-2012.

foreach Loop
There is a possibility to use the foreach loop in SystemVerilog. The foreach loop specifies an iteration over the
elements of an array. Each loop variable corresponds to one of the dimensions of the array.
foreach (vect_a [i])
vect_a[i] = i+1;
foreach ( arr1 [i,j,k])
arr1[i][j][k] = i+j+k;

138

SystemVerilog Reference

Behavioral Statements and Control Flow

The number of loop variables must match the number of dimensions of the array variable. Empty loop variables can
be used to indicate no iteration over that dimension of the array. Loop variables are automatic and read-only, and their
scope is local to the loop.

Jump Statements
Loops may include break and continue control statements. The break statement terminates the execution of the
enclosing loop. The continue statement terminates the current iteration of the enclosing loop (and resumes the next
iteration).
// SystemVerilog Extension
begin
i = 0;
forever begin
i = i+1;
if (i>5)
break;
if (i % 2)
continue;
end
end

The break and continue statements are not supported in Verilog'95 or Verilog 2001.
Tasks and functions may include the return statement. In a function returning a value, return must have an
expression of the correct type. The return statement can be also used without an expression in tasks and void
functions.
task t1(input byte i1, output string o1);
if (i1 < 5)
begin
o1 = "left";
return;
end
else if (5<=i1 && i1<9)
$fatal(0,"i1 in not allowed range. Exiting");
else
begin
o1 = "right";
return;
end
endtask : t1

139

SystemVerilog Reference

Behavioral Statements and Control Flow

Final Blocks
The final block is executed at the end of simulation time in zero time in a single simulation cycle. The final blocks
can only contain statements allowed in a function. This guarantees that the block will execute within a single
simulation cycle.

Example
assert property (CheckDataSeq) ++pass_count; else ++error_count;
final
begin : final_stat
$display("The CheckDataSeq property was executed %0d times",pass_count+error_count);
$error("The property fails %0d times",error_count);
$warning("The property passes %0d times",pass_count);
end : final_stat

140

SystemVerilog Reference

Behavioral Statements and Control Flow

Event and Level Control

iff Qualifier
The SystemVerilog iff qualifier enhances the event control, for example:
always @(Q iff EN==1)
D <= Q;

The event expressions triggers only if the condition after iff is true. The iff operator has precedence over or. Note
that in the example shown above, the expression is evaluated only when Q changes, not when EN changes. The event
expression can also denote a clocking block name (with no edge qualifier) to be triggered by the clocking event.

Sequence Events
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

Level-sensitive sequence controls


The event triggered property is used in SystemVerilog to delay an execution of procedural code until a sequence
termination status is true. The triggered property evaluates to true if the event has been triggered in the current
simulation time. Otherwise it is false. The triggered property can be used in wait statements:
wait (<eventname>.triggered)

The <eventname.triggered> property remains true throughout the time step. This allows preventing race conditions
such as the race shown in the listing below.
fork
@(e);
->e;
join

The fork-join statement may or may not complete depending on the order of execution of -e> and @(e)
statements. (The simulator is allowed to execute those statements in an arbitrary order.) The example re-written using
the e.triggered property is shown in the listing below:
fork
wait(e.triggered);
->e;
join

The wait (e.triggered) statement (contrary to the @(e) statement) will never block because the e.triggered
property remains true throughout the time step, regardless of the order of execution of the statements in the
fork-join block.

141

SystemVerilog Reference

Behavioral Statements and Control Flow

Event Control on Dynamic Class Members


An event control operator can also be applied to class properties and class methods. This page discusses three
distinct usage scenarios.

Waiting on a non-event Property


Let us assume that:
hnd is a class handle.
prop is an dynamic property defined inside the class pointed by hnd.
The type of prop is not an event.
If the event control operator is applied to hnd.prop, then hnd.prop behaves like an expression. The event triggers if
the value of the property changes. If handle hnd changes, then the new value of hnd.prop is compared against the
old value. The event triggers if the new value is different from the old one.
class C;
bit b;
endclass
module top;
C watch_me=new, c1=new, c2 = new;
always @(watch_me.b)
$display("Event triggered at time %0t.", $time);
initial begin
#10; watch_me=c1; // No event.
#10; c1.b=1;
// Changing the object triggers @.
#10; watch_me=c2; // Another event triggered
// because watch_me.b != c2.b.
#10 c1.b = 0;
watch_me = c1; // No event because watch_me.b == c1.b.
end
endmodule

Waiting on an Event Property


Waiting on a property that is an event works differently. After an event control statement is executed on hnd.e (where
hnd is a handle and e is a named event) it continues to monitor the event even after handle hnd changes. Only after
that event triggers, the event control starts monitoring events on the new handle.
class C;
event e;
endclass
module top;
C watch_me = new, c1 = new, c2;
always @(watch_me.e)
$display("Event triggered at time %0t.", $time);

142

SystemVerilog Reference

Behavioral Statements and Control Flow

initial begin
#1; c2 = watch_me;
#1; ->c2.e; // Event triggered.
#1; watch_me = c1; // Changing the handle does not trigger the event.
#1; ->c2.e; // Event triggered even though watch_me points now to c1.
#1; ->c1.e; // Event triggered. However, this event would not trigger
// should the previous statement be commented out.
end
endmodule

Note that assignment to the handle does not trigger the event.

Waiting on a Method
Let us assume that:
hnd is a class handle.
fn is a method defined inside the class pointed by hnd.
Method fn is not a static method.
If the event control operator is applied to hnd.fn then hnd.fn is treated as an expression.
The method is reevaluated whenever
Any dynamic member in the object pointed by hnd changes.
Any argument changes. (Same as for regular functions used under @.)
Note that changes to static members are ignored.
class C;
bit b1;
bit b2;
function bit fn;
$display("Function evaluated at time %0t.", $time);
return b2;
endfunction
endclass
module top;
C watch_me = new, c2 = new, c3;
always @(watch_me.fn)
$display("Event triggered at time %0t.", $time);
initial begin
c3 = watch_me;
#1; watch_me = c2; // Handle changed but event not triggered.
// (The value returned by watch_me.fn has not changed.)
#1; c2.b2 = 1;
// Function re-evaluated and event triggered.
#1; watch_me = c3; // Handle changed and event triggered again.
end
endmodule

NOTE: The description on this page applies to event control applied via an explicit class handle. It is irrelevant for
event control on the implicit this handle inside class methods.

143

SystemVerilog Reference

Behavioral Statements and Control Flow

Other Statements

Enhancement to Assignments Statements


In SystemVerilog it is allowed to be specify a time unit in the assignment statement.
#1ps a = b;
a = #1ps b;
a <= #1ps b;

It is illegal to make nonblocking assignments to automatic variables.

Named Blocks
The name of a block statement may be repeated when the block is closed. In the example below block names are
repeated for the fn1 function and the fj1 fork-join block.
// SystemVerilog Extension
function integer fn1 (input integer i);
//...
endfunction : fn1
initial begin
fork : fj1
//...
join : fj1
end

Statements Labels
All SystemVerilog statements (while, if, etc.) can be labeled. In the code below labels l1 through l9 have been
assigned to various behavioral statements.
// SystemVerilog Extension
module labels;
integer a,b,c,i,n;
initial
l1 : begin
l2 : if (a>b)
begin
l8 : c = a;
end
else
l3 : begin
l4 : c <= b;
end : l3
l5 : begin
l6 : for (i=0; i<n; i=i+1)
l7 : a = a+1;
end : l5
end : l1
endmodule

144

SystemVerilog Reference

Behavioral Statements and Control Flow

Labels can be used for code documentation.

Disable Statement
SystemVerilog allows using the disable statement with named blocks and labeled statements. Behavior for both
ways is the same. Disabling statement with label is not supported in this release. Please contact Aldec Support to
receive the latest status.

145

Processes

Always Processes
SystemVerilog introduces three new always processes:
always_comb
always_latch
always_ff
The suffixes (_comb), _latch, and _ff) indicate design intent (combinational, latched, or sequential logic) to
synthesis and formal verification tools.

always_comb and always_latch


The always_comb construct models combinational logic; always_latch models latched logic. Both always_comb
and always_latch blocks trigger automatically at time zero after all initial and always blocks have started.
Variables written to on the left-hand side of assignments cannot be written to by any other process. The sensitivity list
is inferred automatically.
// Inferred sensitivity list: a and b.
always_comb
a = b & c;
// Inferred sensitivity list: clk and d.
always_latch
if (clk) q <= d;

always_ff
The always_ff block models sequential logic, for example:
always_ff @(posedge clock iff reset == 0 or posedge reset) begin
r1 <= reset ? 0 : r2 + 1;
end

The always_ff block can contain only one event control and no blocking timing controls.

146

SystemVerilog Reference

Processes

Parallel fork-join Blocks


The fork-join construct creates concurrent processes from each of its parallel statements. Control passes out of the
block based on the type of join keyword.
Option

Description

join

The parent process blocks until all the processes spawned by this fork complete.

join_any

The parent process blocks until any one of the processes spawned by this fork completes.

join_none

The parent process continues to execute concurrently with all the processes spawned by the fork.
The spawned processes do not start executing until the parent thread executes a blocking statement.

A fork-join construct cannot be used inside a function. When used in a task, it must not contain the return statement.

147

SystemVerilog Reference

Processes

Process Control
SystemVerilog provides the following constructs that allow one process to terminate another process or wait for its
completion.
wait fork
disable fork
disable
The wait fork statement waits for completion of processes spawned with a fork statement. The disable fork
statement disables immediate child processes of the current process. The disable statement stops all activity within
a named block or a task without paying heed to parent-child relationships.

wait fork
The wait fork statement blocks the execution flow until all processes forked by the current process complete. The
descendants of forked processes (if any) are ignored and do not block execution.
fork
...
...
join_none
wait fork;

In the following example, the do_test task spawns processes and blocks until either of them (exec1 or exec2)
completes. Next, two more processes are spawned. The wait fork statement following the two fork-joins waits until
all processes in both the fork-join blocks finish execution.
task do_test;
fork
exec1();
exec2();
join_any
fork
exec3();
exec4();
join_none
wait fork; // block until exec1 ... exec4 complete
endtask

disable fork
The disable fork statement terminates recursively all processes forked-off by the current process.
fork
...
...
join_any
disable fork;

In the example below, task get_first spawns three versions of a task that wait for a particular device (1, 7, or 13).
Task wait_device waits for a particular device to become ready and then returns the device address. When the first
device becomes available, task get_first resumes execution and kills the outstanding wait_device processes.

148

SystemVerilog Reference

Processes

task get_first( output int adr );


fork
wait_device( 1, adr );
wait_device( 7, adr );
wait_device( 13, adr );
join_any
disable fork;
endtask

149

SystemVerilog Reference

Processes

Class process
Class process is a built-in class that allows one process to control another. The prototype for the process class is
shown below:
class process;
typedef enum { FINISHED, RUNNING, WAITING, SUSPENDED, KILLED } state;
extern
extern
extern
extern
extern
extern
endclass

static function process self();


function state status();
function void kill();
task await();
function void suspend();
function void resume();

The user can declare variables of type process and use them in his code, for example:
module top;
process p1;
std::process p2;
initial begin
p1 = process::self();
p2 = process::self();
//...
end
endmodule

Note that it is not possible to create objects of type process. (The process class cannot be instantiated with
operator new.) Neither it is possible to extend the process class.

Process Methods
Prototype

Description

self()

A function that returns a handle to the current process.


A function that returns the status of a process. The status is one of:

status()

FINISHED - the process is terminated.


RUNNING - the process is currently running.
WAITING - the process is waiting.
SUSPENDED - the process is stopped and waiting for resume().
KILLED - the process has been killed or disabled.

kill()

A function that terminates a process and all its subprocesses.

await()

A task that allows the current process to wait for the completion of another process.

suspend()

A function that suspends a given process.

resume()

A function that restarts a previously suspended process.

In the example below, the initial block forks three processes. Process handles are stored in the parr array. The
block controls the processes with kill, suspend, and resume methods. The status of all processes is printed by the

150

SystemVerilog Reference

Processes

show_status task.
module top;
parameter numproc = 3;
process parr[0:numproc-1];
task show_status;
process::state status;
for( int i = 0; i < numproc; ++i ) begin
status = parr[i].status();
$display("Process num %0d, status at time %0t - %s.", i, $time, status.name);
end
endtask
initial begin
for ( int i = 0; i < numproc; ++i ) begin
fork begin
automatic process me = process::self();
parr[i] = me;
#35;
end
join_none
#0;
end
#10;
#10; parr[0].kill;
#10; parr[1].suspend;
#10; parr[1].resume;
end
endmodule

show_status;
show_status;
show_status;
show_status;

//
//
//
//

All
0 0 0 -

processes
KILLED; 1
KILLED; 1
KILLED; 1

151

WAITING.
- WAITING;
2 - WAITING
- SUSPENDED; 2 - WAITING
- RUNNING;
2 - FINISHED

Constrained Random Value Generation

Overview
The SystemVerilog constrained random generation feature allows generating complex random stimulus. The user
defines a container for data alongside constraints for data values. The constraints must be observed (or solved) by the
generation process.
The mechanism is based on SystemVerilog classes. Each class member can be marked as a random variable by
using rand or randc modifiers. Constraints are defined in constraint blocks, which are named items declared
inside the class body. An instance of a class with random members and constraints can be randomized by calling the
randomize method against the class handle.
The example below shows class Packet with two properties marked with rand modifiers. The constraint block
inside the class specifies constraints for property address. The randomize method will observe the constraints and
randomize addr with values less than 8'h0f. No constraints are assigned to property data so it will be randomized
with all possible values.
class Packet;
rand reg [7:0] addr;
rand reg [7:0] data;
constraint addr_dist {
addr < 8'h0f;
}
endclass
module top;
Packet p;
initial begin
p=new;
repeat(10)
#10 p.randomize();
end
endmodule

Constraints can be manipulated by the user; for example he can turn them on or off to achieve the desired stimulus.
SystemVerilog supports a wide variety of data types and operators for randomization.

152

SystemVerilog Reference

Constrained Random Value Generation

Rand, randc Modifiers


Class properties and structure members have to be defined with the rand or randc modifier to be randomized.

Rand Modifier
Variables declared with the rand modifier are randomized with a uniform distribution.
class packet;
rand int m_rdata; //random variable
int m_data;
endclass
typedef struct {
rand int f_ra; //random variable
int f_a;
} Ts;

Randc Modifier
Variables declared with the randc modifier are random-cyclic. It means that the variable will not be assigned the
same randomized value until all available values form the declared range are randomized. See the example given
below. Each object instance has its own randc sequence calculated independently for each variable declared with
randc modifier. These sequences are calculated during the first randomization of each variable declared randc. All
types allowed to be declared rand can also be declared randc. Exceptions are unpacked structures and object
handles. Declaring randc any of these will trigger an error.
class C;
randc bit[1:0] a;
endclass
module top;
C c = new;
initial begin
repeat(4) begin
c.randomize();
$display(c.a); // possible values randomized in successive iterations of the loop: 1-2-0-3
end
// for the given example permutation like 1-2-2-3 will never occur
end
endmodule

It is suggested to use randc modifier wisely - randomizing variables wider than 8 bits may drastically slow down the
simulation.

Disabling Random Variables - rand_mode


Each SystemVerilog class has a built-in rand_mode method. This method allows you to control whether a random
variable is active and should be randomized or it is inactive and should be treated as a state variable when the
randomize method is called. Note that a random variable is a variable declared with the rand or randc modifier. The
rand_mode method can be called as a statement or as a function. When it is called as a statement, it sets the

153

SystemVerilog Reference

Constrained Random Value Generation

rand_mode state of the random variable. In this case, the rand_mode argument is obligatory. The argument for
rand_mode can be:
1 turns the variable 'ON' (the random variable is active, all random variables are active by default prior to
calling rand_mode on them).
0 turns the variable 'OFF' (the random variable is inactive, it will be treated as a state variable).
If rand_mode is invoked as a function (in expression context) then it returns the current state of the random variable.
When called in expression context then rand_mode should not have arguments.
class C;
rand int x;
endclass
module top;
C c = new;
initial begin
c.x.rand_mode(0);
variable
c.randomize();
$display(c.x.rand_mode());
inactive now
end
endmodule

// rand_mode called as statement. It will set c.x to inactive random


// variable 'x' will not be randomized
// rand_mode called in expression context. It will return 0 as c.x is

If rand_mode is called as a statement, it can be called only on random variables or object handles. If it is called on the
object handle then rand_mode sets the state of all random variables defined inside the object. If rand_mode is called
as a function, it can be called only on singular random variables.
Rand mode, as a statement, can be called on a random variable (declared rand or randc) of type:
Unpacked array - it will change the state of all array elements.
Unpacked array element - it will affect the state of the selected element only.
Unpacked struct - it will change the state of the unpacked struct variable and all its members.
Unpacked struct member - it will change the state of the selected member only.
Object handle - it will change only the state of this handle.
A compile error will occur, if the specified variable does not exist or it exists but it is NOT a random variable (declared
rand or randc, object handles are exceptions to this rule). See the example below:
class B;
rand int i;
int j;
endclass
class C;
int x;
B b;
rand B b_r;
endclass
module top;
C c = new;
initial begin
c.y.rand_mode(1); // An error will occur, variable does not exist
c.x.rand_mode(0); // An error will occur, variable is not declared rand or randc
c.b.rand_mode(0); // This call is correct. b is not a random variable but it is an object handle so
this call sets c.b.i rand state
c.b_r.rand_mode(0); // The object handle is a random variable - such call will affect only the

154

SystemVerilog Reference

Constrained Random Value Generation

object's handle rand state,


// c.b_r.i rand state will not be changed
$display(c.b.rand_mode());
//An error will occur, rand_mode called as a function while c.b is
not a random variable
end
endmodule

If a variable declared rand or randc is static, its rand_mode state is also static. Changing the variable to be active or
inactive will change its behavior in all instances of the base class.
NOTE: The rand_mode() method is built-in and cannot be overridden.

155

SystemVerilog Reference

Constrained Random Value Generation

Random Variables
Random variables are variables randomized with the randomize function. A variable becomes a random variable if it
is passed as an argument to the randomize function or declared with the rand modifier in a class or an unpacked
structure. Types allowed for random variables in SystemVerilog are listed below.

Random Integral Types


Variables of all integral types can be randomized. Integral types include:
All packed arrays.
All integer atom types.
Packed structures.
Packed unions.
Enumerated types.
Time.
Integral type variables can be passed to the randomize function.
int i;
reg [3:0] vec;
initial
randomize( i, vec ) with {i inside {0,10}; vec < 10; };

Integral type variables can be declared as rand/randc class properties and randomized with the randomize class
method.
class C;
rand int i;
rand reg [3:0] vec;
endclass

Unpacked Arrays
Unpacked arrays are supported for randomization. This can be done by calling the std::randomize() function with
an array identifier on the argument list or by invoking the randomize() class method. For the latter case, the array
as a class member can be declared with the rand or randc modifier. An unpacked array being an unpacked
structure member can be declared with the rand or randc modifier as well. Randomization of multidimensional
arrays is allowed. As a result, all array elements are randomized.
Example for Unpacked Arrays:
class C;
rand int x[1:0][3:0];
endclass
module top;
reg[3:0] y[7:0];
C c = new;
initial begin

156

SystemVerilog Reference
std::randomize(y);
c.randomize();
end
endmodule

Constrained Random Value Generation


// all 'y' array elements are randomized
// all 'x' array elements are randomized

Limitations:
Unpacked arrays of class handles and unpacked arrays of unpacked structures are not supported for
randomization yet.

Dynamic Arrays
Dynamic arrays are supported for randomization. This can be done by calling the std::randomize() function with
an array identifier on the argument list or by invoking the randomize() class method. For the latter case, the array
as a class member can be declared with the rand or randc modifier. A dynamic array being an unpacked structure
member can be declared with the rand or randc modifier as well. Randomization of multidimensional arrays is
allowed. As a result, all array elements are randomized.
Example for Dynamic Arrays:
class C;
rand int a[];
rand int b[][];
function set_size(longint x, longint y);
longint i;
a = new [x];
b = new [x];
for ( i = 0; i < x; i++ ) begin
b[i] = new [y];
end
endfunction
endclass
module top;
int i;
int a[] = new [4];
C c = new;
initial begin
c.set_size(2,4);
std::randomize(a); // all 'a' array elements are randomized
c.randomize();
// all array elements in 'c' are randomized
std::randomize(a) with {a[1] > 0;}; // a[0] must be greater than 0
c.randomize() with {a[0] != a[1];}; // c.a[0] and c.a[1] must not be equal
end
endmodule

Limitations:
Dynamic arrays of class handles and dynamic arrays of unpacked structures are not supported for
randomization yet.
Using whole dynamic arrays inside constraints is not supported yet.
Using dynamic array slices inside constraints is not supported yet.

157

SystemVerilog Reference

Constrained Random Value Generation

Queues
Queues are supported for randomization. This can be done by calling the std::randomize() function with a queue
identifier on the argument list or by invoking the randomize() class method. For the latter case, the queue as a
class member can be declared with the rand or randc modifier. A queue being an unpacked structure member can
be declared with the rand or randc modifier as well. Randomization of multidimensional queues is allowed. As a
result, all queue elements are randomized.
Example for Queues:
class C;
rand int a[$] = '{1, 2, 3};
endclass
module top;
int a[$] = '{4, 5, 6};
C c = new;
initial begin
std::randomize(a); // all 'a' queue elements are randomized
c.randomize();
// all queue elements in 'c' are randomized
std::randomize(a) with {a[1] > 0;}; // a[0] must be greater than 0
c.randomize() with {a[2] != a[1];}; // c.a[2] and c.a[1] must not be equal
end
endmodule

Limitations:
Queues of class handles and dynamic arrays of unpacked structures are not supported for randomization yet.
Using whole queues inside constraints is not supported yet.
Using queue slices inside constraints is not supported yet.

Associative Arrays
Associative arrays are supported for randomization. This can be done by calling the std::randomize() function
with an associative array identifier on the argument list or by invoking the randomize() class method. For the latter
case, the associative array as a class member can be declared with the rand or randc modifier. An associative array
being an unpacked structure member can be declared with the rand or randc modifier as well. Randomization of
multidimensional associative arrays is allowed. As a result, all associative array elements are randomized.
Example for Associative arrays:
class C;
rand int a[int] = '{1:1, 2:2, 3:3};
endclass
module top;
int a[*] = '{1:4, 2:5, 3:6};
C c = new;
initial begin
std::randomize(a); // all 'a' associative array elements are randomized
c.randomize();
// all associative array elements in 'c' are randomized
std::randomize(a) with {a[1] > 0;}; // a[0] must be greater than 0
c.randomize() with {a[2] != a[1];}; // c.a[2] and c.a[1] must not be equal
end

158

SystemVerilog Reference

Constrained Random Value Generation

endmodule

Limitations:
Associative arrays of class handles and dynamic arrays of unpacked structures are not supported for
randomization yet.
Using whole associative arrays inside constraints is not supported yet.

Randomized Class Objects


The randomize method can be called against a class handle. Randomization of a handle does not affect which
object the handle points to, instead it randomizes class properties declared with the rand/randc modifiers.
Random properties are randomized according to class constraints if such constraints are declared inside the class.
A class property can be declared with the rand/randc modifier only if randomization is allowed for its type. Class
handles cannot be declared with the randc modifier.
The example below shows class C2 randomized with a call to std::randomize() and with a call to the randomize
class method. In the first call, the class handle is passed as an argument. Any constraints defined inside the class are
ignored. The second call invokes the method against the class handle. In this case the constraints from the class are
used.
class C1;
rand int i;
endclass
class C2;
rand int ri;
int i;
rand C1 c1 = new;
constraint rest1 { ri < i; }
endclass
C2 hnd=new;
initial begin
std::randomize( hnd ); // Ignore constraints.
hnd.randomize();
// Satisfy constraints.
end

Random Unpacked Structures


A complete unpacked structure can be randomized. It can be passed as an argument to the randomize function or
declared as a rand member of another unpacked structure or a class.
An unpacked struct cannot be declared with the randc modifier. A structure member can be declared with the
rand/randc modifier only if randomization is allowed for its type.
Members of an unpacked struct can be declared as rand or randc and only those rand or randc members are
randomized when the structure is being randomized. Other members are state variables and are not affected by
randomization.
If the rand modifier is not used for a member of an unpacked struct type then its members are not randomized
even if they have rand modifiers. Similarly, when an unpacked struct member of an unpacked struct type is

159

SystemVerilog Reference

Constrained Random Value Generation

declared as rand but has no rand members, then nothing is randomized.


A packed structure cannot have members declared as rand. (The compiler flags this as an error.) Packed structures
are always randomized as an entire packed vector.
The example shows an unpacked structure passed to the randomize function. Type point has random members
rgb and lum. Members x, y are not random and will not be randomized. All other members are random variables.
typedef struct {
rand byte r;
rand byte g;
rand byte b;
} rgb_t;
typedef struct {
rand rgb_t rgb;
rand byte lum;
int x,y;
} point_t;
// A variable of type point_t
// can be used directly in std::randomize call:
point_t p;
initial begin
repeat ( 10 )
#10 randomize (p); // A call to std::randomize randomizes p.
end

160

SystemVerilog Reference

Constrained Random Value Generation

Constraints Block
A constraint is an expression affecting generation of random values with the randomize method. The solver must
select random values that satisfy constraints (or return an error if this is impossible). A constraint block is a set of
expressions nested inside a class and designated by keyword constraint. The block must be named.
Expressions in the constraints block can use random variables, state variables, and constants. Random variables are
randomized and assigned in the randomize call. State variables are sampled during randomization, they are not
assigned. State variables can have different values in each randomize call. Constants (literals, parameters, const's)
are sampled during randomization, their values are constant in each randomization call.
class packet;
rand int m_rdata, m_rdata1; //random variables
int m_data;
//non random variable
const int c = 10;
//constant
//both m_rdata and m_rdata1 are random
constraint data1_less_data2 { m_rdata < m_rdata1; }
//m_rdata is a random variable, m_data is a state variable
constraint less_than_m_data { m_rdata < m_data; }
//m_rdata is a random variable, c is a constant
constraint less_than_c { m_rdata < c; }
//m_rdata is a random variable, 0 is a literal (also a constant)
constraint greater_than_0 { m_rdata > 0; }
endclass

When a class object is randomized with the std::randomize function (rather than the randomize method) then the
constraint blocks defined in this class are ignored.

External Constraint Blocks


Constraint blocks can be specified outside their respective classes. This can be realized by specifying the constraint
prototype inside the class, and the constraint body in an external constraint block.
There are two forms of prototypes allowed: with and without the extern keyword. If the extern keyword is omitted,
the body of the constraint is not obligatory. The constraint will be treated as an empty one and a proper warning will
appear. An external constraint block shall appear in the same scope as the class containing its prototype. It shall also
be declared after the declaration of the corresponding class. An external constraint block body is declared using class
scope resolution operator. See the below example for details.
class C;
rand int a,b;
constraint con1;
extern constraint con2;
endclass
constraint C::con1{a<100;}
constraint C::con2{b==a;}

161

SystemVerilog Reference

Constrained Random Value Generation

Constraint Inheritance
Constraint blocks follow general rules for inheritance:
Constraints can be inherited from the base class.
Constraints can be overridden in a child class.
New constraints can be added in a child class.
Constraints themselves are not virtual, but method randomize is virtual and always uses constraints from the object
for which randomize was called.
class CBase;
rand int a;
rand int b;
constraint greater_0 {a>0;}
constraint cc {a<b;}
endclass
class CChild extends CBase;
// Constraint "greater_0" is inherited from the base class.
constraint less_10 {a<10;} // Constraint "less0" is a new constraint
// added in this CChild class.
constraint cc {a+b==10;}
// Constraints "c" from CBase is overridden in CChild.
endclass
CBase b=new;
CChild c=new;
initial begin
// greater_0 and c constraints are valid as b points to the CBase class object.
// Constraint c equals {a<b;}.
b.randomize();
b=c;
//greater_0, less_10, and c are valid as handle b points to the CChild class object.
//The meaning of c has changed, it points to "a+b==10".
b.randomize();
//The same constraints are in effect as handle c points CChild class object.
c.randomize();
end

Constraints in virtual (abstract) classes can be declared as pure constraints. Pure constraints do not have actual
constraint defined it just declares the constraint name. Non-virtual class have to override all pure constraints which
they inherits from base abstract classes.
virtual class CBase;
pure constraint base_constraints;
endclass
class CChild extends CBase;
rand int a;
//CChild class is not virtual so constraint "base_constraints"
//have to be overridden. Otherwise an error will occur.
constraint base_constraints {a>0;}
endclass

Operators
Most SystemVerilog expression are allowed in constraints block. Forbidden operators include:

162

SystemVerilog Reference

Constrained Random Value Generation

4-state operators: === !== ==? !=?.


Operators with side effects i.e.: ++, --.
All expressions allowed in the constraints block can also be used in the with clause.
The listing below shows several sample constraint expressions.
constraint
constraint
constraint
constraint

constr_expr1
constr_expr2
constr_expr3
constr_expr4

{
{
{
{

v1 + v2 < v3; v3 > 0;}


v1 - v2 <= v3; }
v1 == v2 && v3 != v1; }
! (v1*v2 > 10); }

Currently, the following operators are not yet supported:


<->.
In complex expressions several issues are known with signed/unsigned extensions.

Set Membership
Set membership operator inside can be used in constraints to define a set of values for a random variable.
constraint constr_inside{ v1 inside { [v2:v3] } ;} // v1 >= v2 and v1 <= 3
// If v2 > v3 then the set is empty.

If arrays are used in the open_range_list of the inside operator, then all their members define the set of correct
values for the inside left-hand side expression. Consider the following example:
typedef enum {START, SYNC, RESET, TRANSMIT32, TRANSMIT64, NEGOTIATE, IDLE} Tstate;
class C;
rand Tstate state;
Tstate mystates[$]='{TRANSMIT32, NEGOTIATE, SYNC};
constraint c_mystates { state inside {mystates}; }
endclass
module top;
C c = new;
initial begin
c.mystates.push_back(START);
repeat(10) begin
assert(c.randomize) else $error("Randomization failure.");
$display(c.state.name);
end
end
endmodule

Implication
With the implication operator (->) the user can define a condition that implies constraints.
constraint constr_implic{ v1_greater_v2 -> v1 > v2; } // If v1_greater_v2 is true then
// v1 should be greater than v2.

163

SystemVerilog Reference

Constrained Random Value Generation

Distribution
Statistical distribution of the values which a randomized variable can assume can be specified by using the distribution
operator in the form of a distribution list:
std::randomize(a) with { a dist { [12:15]:=4, [8:11]:/4, 7:=2, 6:=1, 5:=0, 4:=2 }; };

The distribution list is a comma-separated list of ranges or integral values an expression can assume. Each item in the
list can have its weight specified, which corresponds to the probability for the variable to accept the corresponding
value during randomization. The weights can be assigned to particular items by using the := or :/ operators. If an
item is a range, the := operator assigns the specified weight to each value in the range, while the :/ operator assigns
the specified weight to the range as a whole. In the latter case, the weight is distributed equally between all the values
in the range. For example, the expression [12:15]:=4 assigns each value from the range 12:15 the weight of 4,
while the expression [8:11]:/4 assigns the weight of 4 to the whole range, thus particular values from the range are
assigned the weight of 1.
Values that are not listed in the distribution list will never be assumed by a random variable.
If no other constraints are specified, the probability that a value in a distribution list will match corresponds to its
specified weight. Otherwise, if any constraint contradicts an item in the distribution list, only the constraint will be
satisfied, for example:
std::randomize(b) with { b dist { 1:=1, 2:=3, 7:=1 }; b > 5; }; // b can only assume the value 7

NOTE: The distribution operator does not work as expected when used in the implication or in the if-else construct.

if-else Constraints
It is possible to use if-else style constraint.
constraint constr_ifelse{
if (v1_greater_v2) // If v1_greater_v2 is true then
v1 > v2;
// v1 should be greater than v2,
else
v1 <= v2; }
// otherwise v2 should be greater than v1 or equal.

Iterative Constraints
NOTE: Iterative constraints are not supported in this release. Please contact Aldec Support to receive the latest
status.

Global Constraints
Member objects of a given class that are declared as rand and that themselves are objects of another class subject
to randomization along with the other members of the given class. When a constraint defined in a given class is
applied to a randomized field of its object member, then such a constraint is called a global constraint.
When an object of a given class is to be randomized, i.e. the randomize() method is to be executed on that object,
first, the set of all its active rand fields is determined and then, if the members themselves contain active rand fields,
these are also added to the randomized set. This operation is performed recursively, as long as given objects contain
randomized members. Next, all of the active constraints that apply to the set of randomized objects are gathered.

164

SystemVerilog Reference

Constrained Random Value Generation

After the constraints are resolved, thus collected objects are randomized.
Consider two classes - class A that contains two randomized fields one of which is constrained within that class:
class A;
rand int i, j;
constraint con_a { i > 10; }
endclass

and class B that contains an object of class A, declared as rand. Within the class B, a constraint is defined that is
applied to a member field of the class A object:
class B;
rand A a = new;
constraint con_b { 10 < a.j && a.j < 20; }
endclass

Randomization of the object of class B results in applying the constraints defined in the class B to member fields of
the object of class A:
B b = new;
initial begin
b.randomize();
end

As a result, b.a.i will have a value larger than 10 (according to the constraint defined in the class A), and b.a.j will
have a value between 10 and 20 (according to the constraint defined in the class B).

Variable Ordering
The solve...before construct changes the probability of occurrence of values specified by a constraint block
without changing the set of possible values. This is done by changing the order in which expressions from a constraint
are solved.
In the below constraint, the j value is equal 0 only when i value is false. Although the expression if(i==0) j==0;
else j!=0 suggest that j is determined by i, in fact, the values are determined independently, because the solver
assures the uniform distribution over legal value combinations.
class A;
rand bit i;
rand bit [15:0] j;
constraint c { if(i==0) j == 0; else j != 0;}
endclass

The total number of legal combinations for the {i,j} pair is 216 but i is false for only one of them so the probability of
the occurrence of i=0, and thus, {i,j}={0,'h0000} is 1/216. The following table lists each of the legal value
combinations and their probabilities:
i value j value Probability
0

'h0000

1/216

'h0001

1/216

'h0002

1/216

165

SystemVerilog Reference

Constrained Random Value Generation

...

...

'hfffe

1/216

'hffff

1/216

The solve...before construct allows you to change the distribution of values by determining the order in which
variables are solved.
class B;
rand bit i;
rand bit [15:0] j;
constraint c { if(i==0) j == 0; else j != 0;}
constraint order { solve i before j; }
endclass

The order {solve i before j;} constraint forces the i value to be solved independently with a uniform
distribution before the j randomization. In this case, the probability that the i value is false and {i,j}={0,'h0000}
is 50%. As it can be seen in the table below, the order constraint does not change the set of the legal values
combinations, but changes the probability of their occurrences.
i value j value

Probability

'h0000

0.5

'h0001

0.5 * 1/(216 - 1)

'h0002

0.5 * 1/(216 - 1)

...

...

'hfffe

0.5 * 1/(216 - 1)

'hffff

0.5 * 1/(216 - 1)

Variable ordering can be used to make a value that is randomized with a relatively small probability to appear more
frequently without changing the solution space.

Static Constraint Blocks


NOTE: Static constraint blocks are not supported in this release. Please contact Aldec Support to receive the latest
status.

Function Calls in Constraints


Functions used in constraints are called before constraints are solved. Values returned from functions in constraint
blocks are later treated as state variables when constraints are solved. When random variables are used as
arguments, these variables are randomized before functions are called. As a result, the randomization is divided into
the following steps:
First, arguments of functions are randomized with respect to constraints that are using only these arguments.
Subsequently, the function values are calculated for the previously randomized arguments.

166

SystemVerilog Reference

Constrained Random Value Generation

Eventually, the remaining variables are randomized according to their constraints and calculated function
values.
Such an approach is also called variable ordering. This case of implicit variable ordering may lead to a randomization
failure if random arguments are connected by constraints with other random variables. Note, that additional steps may
be required if random function arguments are used in expression with other function calls, for instance:
(a==f(b); b==f(c);)

Multiple steps may cause circular dependencies to occur. In such cases, randomization fails. The following restrictions
apply to functions that are inside constraint expressions:
They cannot modify constraints.
They cannot have output, input of ref arguments.
They should be automatic.
class C;
function int countones ( bit[3:0] w );
return $countones(w);
endfunction
rand int ones; //If the variable "ones" is not random, the randomization process may fail because
of variable ordering.
rand bit[3:0] rv;
constraint c_ones { ones == countones( rv ) ; }
endclass
module top;
C c =new;
initial repeat(10) begin
assert(c.randomize) $display("%b %d %d",c.rv, c.ones, $countones(c.rv)); else
$error("Randomization failure.");
end
endmodule

Limitations
Function calls are supported with the following restrictions:
Only integral types are supported as arguments.
Only single level of variable ordering is supported.
System functions are treated in the same way as other function calls but the $countones function is not
supported.
Please contact Aldec Support to receive the latest status.

Controlling Constraints - constraint_mode


SystemVerilog provides method constraint_mode to control constraint blocks within class objects. The method can
be used in two ways:
As a task, to enable or disable particular constraint blocks in a given object.
As a function, to check the status of a given constraint block (enabled or disabled).

167

SystemVerilog Reference

Constrained Random Value Generation

If constraint_mode is used as a task, then it requires one argument - 0 or 1 - to disable or enable a constraint block.
See the example below:
class C;
rand bit[3:0] b;
constraint c1 {b >= 2;}
constraint c2 {b <= 7;}
endclass
C c = new;
initial begin
c.c1.constraint_mode(0); // Constraint block c1 is now disabled.
c.randomize; // Randomized value for c.b will be in the [0:7] range.
c.c1.constraint_mode(1); // Constraint block c1 is now enabled.
c.randomize; // Randomized value for c.b will be in the [2:7] range.
end

If constraint_mode acts as a function, then it accepts no arguments and returns the status of a given constraint
block: 0 if the constraint block is disabled or 1 if the constraint block is enabled. See the example below:
class D;
rand bit[3:0] b;
constraint c1 {b >= 2;}
endclass
D d = new;
initial begin
d.c1.constraint_mode(0); // Constraint block c1 is now
$display(d.c1.constraint_mode()); // Check and display
// block c1. (0 will
d.c1.constraint_mode(1); // Constraint block c1 is now
$display(d.c1.constraint_mode()); // Check and display
// block c1. (1 will
end

disabled.
the status of constraint
be displayed.)
enabled.
the status of constraint
be displayed.)

When constraint_mode is used as a task then the constraint block name can be omitted; the task will then enable
or disable all constraint blocks in the object.

Constraint Guards
A mechanism is implemented that prevents null pointer references during calls to the randomize method on a class
handle. If the randomization algorithm determines that the class handle is null, then it excludes such a handle from
randomization without reporting a null pointer access during simulation runtime.
class Member;
rand int b;
endclass
class C;
rand int a;
rand Member memb;
endclass
C c = new;
initial
begin

168

SystemVerilog Reference

Constrained Random Value Generation

randomize(c);
end

In the example above, class handle c.memb is null and it will be ignored during randomization. Note that this
mechanism does not safeguard against accessing a constraint through a null handle, i.e. if the user code attempts to
access such a constraint, then a null pointer access error will be reported during simulation runtime.
To avoid such issues, the if-else construct must be used as a constraint guard. In example below, handle cc is
checked first (if(cc!=null)) and constraint cc.a < 10 is applied only if cc != null.
class CC;
rand int a;
endclass
CC cc;
initial
begin
randomize(cc) with {if(cc!=null){cc.a < 10;}};
end

A failure to add a guard would make the call to randomize unsafe. Such a call would trigger a null pointer access
runtime error if handle cc equaled null.

Debugging Constraints
To facilitate the process of debugging, a message about the cause of randomization failure is printed to the Console.
For more information, refer to the Debugging Randomization Failures section in the Randomization and Seed Control
topic.

169

SystemVerilog Reference

Constrained Random Value Generation

Randomization Methods

Randomize Method
Class objects are randomized by calling the randomize method against the handle. All user-defined classes have a
built-in virtual randomize method. Randomization is successful if all random variable values are assigned values
satisfying the constraints. Randomization fails if the solver is unable to solve the constraints, or if the time elapsed for
solving the constraints exceeds the timeout defined with rc_timeout variable. The randomize method returns 1 if
randomization was successful or 0 if randomization failed.
Additionally, the reason of randomization failure may be printed to the console if the verbosity level is set to 1 or 2 in
the rc_verbose variable.
The example shows the C class with the constraint block cnstr. The class contains one property (data) with the
rand modifier. The constraint expressions in the cnstr block use two data properties (min and max) that are
assigned to before each call to randomize.
The first call will succeed and the random variable will be assigned a value from range 5-10. The second call will fail
because no number exists that could meet the constraints, i.e. to be both greater than and less than 10.
module top;
class C;
rand int data;
int min, max;
constraint cnstr { data > min; data < max; }
endclass
C hnd;
initial begin
hnd = new;
hnd.min = 5; hnd.max = 10;
assert (hnd.randomize()); //This call succeeds.
//The random variable data will be assigned a new value from range 5-10.
hnd.min =10; hnd.max=10;
assert (hnd.randomize()); // This call fails.
//No value exists that could fulfill the constraints.
end
endmodule

Inline Constraints
Additional constraints can be included to the already existing object set of constraint blocks by invoking the
hnd.randomize() with{} method. These constraints must be enclosed in braces ({}).
class C;
rand byte b1, b2;
constraint cc {b1 > b2;};
endclass
module top;
C c = new;

170

SystemVerilog Reference

Constrained Random Value Generation

initial
c.randomize() with {b1 < 10; b2 < 10;};
endmodule

In the above example, during the c.randomize() method calling, the inline constraints {b1 < 10; b2 < 10} are
considered along with the cc constraint block.

In-line Random Variable Control


Inline random variable controlling allows choosing which members in particular object will be randomized during
invoking the randomize() method. It is achieved by invoking the randomize() method with parameters being the
names of the object members. In this case, only members included in the list of method arguments will be
randomized. Other members will be state even if they have the rand qualifier in their declarations.
class C;
rand byte b1;
byte b2;
endclass
module top;
C c = new;
initial
c.randomize(b2);
endmodule

In the above example, during the c.randomize method calling, only b2 is considered as random member. In this
case, b1 will be treated as the state member.

Inline Constraint Check


Checking constraints for a particular object without changing member values is allowed by invoking the randomize()
method with null as its argument. In this case, all object members are state and all constraints, including inline
constraints, act as checkers. When the member values satisfy all constraints then the randomize() method returns
1. Otherwise, it returns 0.
class C;
rand byte b1, b2;
constraint cc {b1 > b2;};
endclass
module top;
C c = new;
int i;
initial
begin
c.b1 = 20; c.b2 = 110;
i = c.randomize(null) with {b1 < 10; b2 < 10;};
$display(i); // constraints are not satisfied, 0 shall be displayed
c.b1 = 2; c.b2 = 1;
i = c.randomize(null) with {b1 < 10; b2 < 10;};
$display(i); // constraints are satisfied, 1 shall be displayed
end
endmodule

171

SystemVerilog Reference

Constrained Random Value Generation

In the above example, during the c.randomize() method calling, the current member values are considered when
constraints checking. No new values are assigned to members.

local:: Scope Resolution


Names used within inline constraints can reference to either members of an object calling the randomize method or
variables in a scope where the method is called. At the beginning, the simulator checks whether an appropriate name
matches a member within object calling the randomize method. If it does, the member is considered during
constraint expression resolution. If specified name cannot be found inside the object, then the identifiers are searched
inside the scope where the randomize method is called. SystemVerilog provides a mechanism that limits resolving
variable names used within inline constraints for the scope where the randomize method is called.
class C;
bit
endclass

[3:0] b;

module top;
bit
[3:0] b = 6;
C c1 = new;
initial
begin
c1.randomize(b) with {local::b >= 5;}; // <--- local used to consider 'b' from top instead of 'b'
from c1
c1.randomize(b) with {b >= 5;}; // <--- 'b' from c1 is used
$finish;
end
endmodule

Restricted inline constraint block


If an inline constraint is prefixed with an optional, parenthesized identifier list then such constraint block is considered
to be restricted. It means that all variables which appear on the list are resolved into the randomize object class; all
other variables used within inline constraint will resolve into the local scope where randomize method was called. If
the parenthesized list is present and the scope resolution local:: qualifier is used then no matter if the qualified
variable identifier is on the list - it will always resolve into the scope containing randomize method call.
class C;
rand int a,b;
endclass
module top;
C c = new;
int b;
initial begin
c.randomize() with(a){a<10; b<20;}; // variable 'a' will resolve into the class object,
// while variable 'b' will resolve into the local scope containing randomize call
end
endmodule

172

SystemVerilog Reference

Constrained Random Value Generation

Pre_randomize and post_randomize Methods


The pre_randomize and post_randomize methods are built-in class methods, similar to the randomize method.
A call to the randomize method on an object involves the following steps:
Execute the pre_randomize method on the object and all its random members.
Perform randomization.
Call the post_randomize method on the object and all its random members and return.
NOTE: If methods are overridden, the pre_randomize and post_randomize methods from the base class need
to be called explicitly. They are not called automatically.
module top;
class Base;
rand int data;
/* The Base class overrides the pre_randomize and post_randomize methods.
User-defined actions to be performed before and after randomization
are shown below */
function void pre_randomize();
$display("Base data value before rand=%0d", data);
endfunction
function void post_randomize();
$display("Base data value after rand=%0d", data);
endfunction
endclass
class Child extends Base;
/* This class does not override the built-in pre_randomize and post_randomize
methods. Built-in methods perform only a call to the base class pre_randomize
and post_randomize methods. The built-in methods look as shown below:
function void pre_randomize();
super.pre_randomize();
endfunction
function void post_randomize();
super.post_randomize();
endfunction */
endclass
class GrandChild extends Child;
rand int data_extra;
function void pre_randomize();
/* This call needs to be placed in the user-defined pre_randomize method.
Otherwise, pre_randomize from the base class will not be called. */
super.pre_randomize();
$display("Child data_extra value before rand=%0d", data_extra);
endfunction
function void post_randomize();
/* This call needs to be placed in the user-defined post_randomize method.
Otherwise, post_randomize from the base class will not be called. */
super.post_randomize();
$display("Child data_extra value after rand=%0d", data_extra);
endfunction
endclass
endmodule

173

SystemVerilog Reference

Constrained Random Value Generation

Randomization of Scope Variables std::randomize()


The scope randomize function std::randomize() enables randomizing data in the current scope without having to
resort to classes (i.e. defining a class with rand/randc members and instantiating that class).

Syntax
scope_randomize ::= [ std:: ] randomize( [ variable_identifier_list ] ) [ with constraint_block ]

Arguments to this function specify the variables that are to be assigned random values.
module top;
int i;
byte j;
int ok;
initial begin
ok = std::randomize(i,j);
$display( "%d", ok );
end
endmodule

The std::randomize() function returns 1 if it successfully sets all random variables to valid values; otherwise, it
returns 0. If it is called without arguments, then it returns a status.

Randomization of Scope Variables std::randomize() with Constraints


The user can specify constraints for generated random variables by using the with form.
int x;
task gen_t(int min, max);
int ok;
ok = std::randomize(x) with {x > min; x < max; };
endtask

The with clause supports the same operators are the constraints block. See Operators for a complete list.
Calling the std::randomize function with no arguments will check the constraints from the with clause. If
constraints are true, then the function returns 1, otherwise 0 is returned.
//This call only checks if i > 0 without randomizing anything.
assert (randomize() with { i > 0; } );

Extensions to std::randomize()
Aldec's simulator provides the following extensions to the std::randomize() call:
Elements of unpacked arrays can be randomized. For example:

174

SystemVerilog Reference

Constrained Random Value Generation

module m;
reg r[][4] = new[3];
bit ok;
initial
// only the first and the last element of the second row is randomized
ok = std::randomize( r[1][0], r[1][3] );
endmodule

Unpacked structure members can be randomized. For example:


module n;
struct {reg r[7:0];
byte res;

bit ok;} s1;

initial
res = std::randomize( s1.r );
endmodule

Class members can be randomized. For example:


module sn;
class A;
int var1;
endclass
A a = new;
int res;
initial
res = std::randomize (a.var1) with { a.var1>5; a.var1<50; };
endmodule

A hierarchical name can be used as an argument to std::randomize(). For example:


module sm;
int i;
endmodule
module top;
sm uut();
initial
std::randomize( uut.i ) with { uut.i>0; };
endmodule

175

SystemVerilog Reference

Constrained Random Value Generation

System Functions and Methods

$urandom()
The function returns a new 32-bit unsigned random number each time it is called.
function int unsigned $urandom [ (int seed ) ] ;

The seed is an optional argument that determines the sequence of random numbers generated.

$urandom_range()
The function returns an unsigned integer within a specified range.
function int unsigned $urandom_range( int unsigned maxval, int unsigned minval = 0 );

The function returns an unsigned integer in the range of maxval ... minval. If minval is omitted, the function
returns a value in the range of maxval ... 0. If maxval is less than minval, the arguments are automatically
reversed so that the first argument is larger than the second argument.
x = $urandom_range( 5 );
y = $urandom_range( 2, 19 );

srandom()
The method sets object randomization seed to value given as argument.
function void srandom( int seed );

This method is a dynamic method built into each SystemVerilog class object.
class C;
rand int i;
endclass
C c;
initial begin
c = new;
c.srandom( seed );
end

get_randstate()
The method returns the Random Number Generator state of an object or a process. The state returned by
get_randstate is a string, similar to a hexadecimal number.
function string get_randstate();

176

SystemVerilog Reference

Constrained Random Value Generation

The method usage is presented below:


objRNGstate = c.get_randstate;
procRNGstate = p.get_randstate;
$display("c1.get_randstate = %s", objRNGstate);
$display("p.get_randstate = %s", procRNGstate);

set_randstate()
The method sets the Random Number Generator state of an object or a process. The state is passed to
set_randstate as string. It is guaranteed that the RNG state is properly set only when the argument passed to the
method is taken from the get_randstate result. In other cases, the behavior of the set_randstate method is
undefined.
function void set_randstate(string state);

The example use of the method is presented below:


c.set_randstate(objRNGstate);
p.set_randstate(procRNGstate);

$get_sv_seed
Returns the seed for SystemVerilog random number generator. The seed can be set with the -sv_seed argument for
the asim command (that is the command that initializes simulation).
The function usage is presented below:
s = $get_sv_seed;
$display ("$get_sv_seed = %d", s);

This function is Aldec's proprietary extension.

$get_random_seed
Returns the seed for the SystemVerilog $random function. This seed can be set either with the -random_seed
argument for the asim command or the random_seed command.
The function usage is shown below:
s = $get_random_seed;
$display ("$get_random_seed = %d", s);

This function is Aldec's proprietary extension.

177

SystemVerilog Reference

Constrained Random Value Generation

Random Weighted Case


The randcase statement randomly selects one of its branches. The randcase item expressions are non-negative
integral values that constitute the branch weights. An item's weight divided by the sum of all weights gives the
probability of taking that branch.
randcase
4: x = 0;
4: x = 1;
2: x = 2;
endcase

If a branch specifies a zero weight, then that branch is not taken. If all randcase items specify zero weights, then no
branch is taken.

178

SystemVerilog Reference

Constrained Random Value Generation

Random Sequence Generation


The randsequence statement randomly creates a sequence of tokens based on the specified grammar. The
construct is useful for randomly generating structured sequences of stimulus.
The randsequence grammar is composed of one or more productions. Production is defined by its name and
consists of production items. There are two of them - terminals and nonterminals. Nonterminals are defined via
terminals and other nonterminals. Terminal is indivisible and should be defined with a code block. A production list
contains the succession of production items that should be streamed in sequence.
If randsequence keyword is not followed by a production name, the first production is treated as top-level one.
Otherwise, specified name indicates top-level production.
Multiple production lists within the production definition may be separated with | symbol that implies choices that are
taken randomly when sequence is generated.
randsequence (main)
main: prod1 | prod2 {$display("1");};
prod1: prod1_1 | {$display("2");};
prod1_1: {$display("3");};
prod2: {$display("4");};
endsequence

In the example above, the definition of the production main consists of two parts. The first part is a choice of
non-terminal prod1 and terminal prod2 which is taken randomly. The second part is a code block.
Non-negative integral value can be assigned to production list in order to specify its weight. A list weight divided by the
sum of all weights within the production gives the probability of taking that list. If no weight is specified, it is equal to 1.
randsequence ()
main:
prod1 | prod2 prod3 := 3 | {$display("1");} := 6;
prod1: {$display("2");};
prod2: {$display("3");};
prod3: {$display("4");};
endsequence

Production main is defined as alternative of three production lists. According to the specified weights probability of
selection list prod1 is 10%, prod2 prod3 is 30% and {$display("1");} is 60%.
The randsequence statement creates an automatic scope. All productions identifiers are local to scope. Each code
block creates an anonymous automatic scope. Hierarchical references to the variables declared within the code block
are not allowed. Static variables are declared using static prefix.
When the randsequence statement is executed, grammar-driven stream of random productions is generated.

Production Statements
Production list may be generated conditionally and iterated specified number of times. if-else, case and repeat
production statements are provided for such facilities.
if-else production statement in the example below generates prod1 when i<5 and prod2 otherwise.
randsequence ()
main:
if(i<5) prod1 else prod2;

179

SystemVerilog Reference

Constrained Random Value Generation

prod1: {$display("1");};
prod2: {$display("2");};
endsequence

case production statement is analogous to procedural case statement. Consider the following example:
randsequence ()
main:
case(i)
1, 3 : prod1;
7, 8 : prod2;
default : prod3;
endcase;
prod1: {$display("1");};
prod2: {$display("2");};
prod3: {$display("3");};
endsequence

When i is equal to 1 or 3 production prod1 is generated, when i is equal to 7 or 8 production prod2 is generated. In
all other cases production prod3 is taken.
The repeat production statement iterates production item specified number of times (it should be integral
non-negative number). For example:
randsequence ()
main:
repeat(3) prod1;
prod1: {$display("1");};
endsequence

The repeat production statement cannot be terminated prematurely.

Aborting Productions
Production generation may be terminated using break and return procedural statements.
The break statement is executed from within code block and aborts the sequence generation.
randsequence ()
main:
prod1 prod2 prod3;
prod1: {$display("1");};
prod2: {if(i<5) break; else $display("2");};
prod3: {$display("3");};
endsequence
$display("4");

In the above example when i < 5 execution of the statement brakes after prod1 generation and execution
continues with the next statement ($display("4");).
If break statement is called from loop scope, it terminates the smallest enclosing loop statement.
The return statement is also executed from within a production code block but it terminates current production
generation.
randsequence ()
main:
prod1 prod2 prod3;
prod1: {$display("1");};
prod2: {$display("2");} {if(i<5) $display("3"); else return;} {$display("4");};
prod3: {$display("5");};
endsequence

180

SystemVerilog Reference

Constrained Random Value Generation

The sequences generated by the above example are the following:


i < 5 => prod1 {$display("2");} {$display("3");} {$display("4");} prod3
i >= 5 => prod1 {$display("2");} prod3

Interleaving Productions
The rand join production control is used for random interleaving of production lists. At each sequence generation
step one of the left-most items of all interleaved production lists is randomly taken.
randsequence ()
main:
rand join prod1 prod2;
prod1: {$display("1");} {$display("2");};
prod2: {$display("3");} {$display("4");};
endsequence

The following sequences may be generated from the above description:


1
1
1
3
3
3

2
3
3
4
1
1

3
2
4
1
2
4

4
4
2
2
4
2

The optional expression following the rand join keyword is a real number in the range of 0.0 to 1.0 (default 0.5 if
unspecified). The value represents the degree of production length influence on the production item selection
probability.
If the expression value is in the range [0.0 : 0.5), the shortest production has the highest probability.
randsequence ()
main:
rand join (0.0) prod1 prod2;
prod1: {$display("1");};
prod2: {$display("2");} {$display("3");};
endsequence

The above description leads to generation of one of the following sequences (sequences are arranged in the
probability descending order):
1 2 3
2 1 3
2 3 1

If the expression value is in the range (0.5 : 1.0], the longest production has the highest probability.
randsequence ()
main:
rand join (1.0) prod1 prod2;
prod1: {$display("1");};
prod2: {$display("2");} {$display("3");};
endsequence

The above description leads to generation of one of the following sequences (sequences are arranged in the
probability descending order):
2 3 1
2 1 3
1 2 3

181

SystemVerilog Reference

Constrained Random Value Generation

Value Passing between Productions


Productions can accept data before they are generated and then return data to the non-terminal symbol that triggered
production generation. A production that accepts data contains a formal argument list and the syntax for declaring the
arguments to a production is similar to a task prototype. The syntax for passing data is the same as for a task call.
As the production creates a scope, which encloses all its rules and code blocks, arguments passed to the production
are available throughout the production.
In the following example, a is an input argument and o is an output argument of the prod production. prod is
generated with different input argument depending on the choice selected randomly when sequence is generated. A
value of the output argument is assigned to the s variable.

string s;
initial
randsequence ()
main : prod(1,s) | prod(2,s) := 2 | prod(3,s) := 3;
prod(int a, output string o) : {
case(a)
1: o = "first";
2: o = "second";
3: o = "third";
endcase
};
endsequence
always @(s)
$display(s);

The production that returns a value requires a type specification before the production name. If the type is omitted
then a production return type is void. The return statement with an expression is used to return a value from a
production. The expression should have a type corresponding to the production type. The production that triggered
the generation of the production returning value can read this value. The return value can be accessed within the code
block via production name and an optional indexing expression. Each rule production that return a value leads to an
implicit variable declaration. The type of the implicit variable is an array, where the element type is the production
return type. The array index is in the range from 1 to the number of the production appearances within the rule and
follows the order of production occurrences.
In the example below, the generation of the main production causes generation of the arg production that returns the
random value in the range from 1 to 10. The repeat statement uses this random number (returned by the arg
production) to iterate the prod production. The prod production returns a queue of random values, which is used by
the run function.
typedef int arr [$];
arr q;
initial
randsequence ()
main : arg repeat(arg[1]) prod {run(prod[1]);};
arr prod : arg arg {q.push_back(arg[1]);
q.push_front(arg[2]);
return q;};
int arg: {return $urandom_range(1,10);};
endsequence

182

SystemVerilog Reference

Constrained Random Value Generation

NOTE: There are restrictions of the following LRM requirements for production return value access:
Each production that return a value leads to implicit variable declaration. If a production appears once in a
rule, the type of an implicitly declared variable is the same as the production return type. If the production
appears multiple times, the type of the implicit variable is an array where the element type is the production
return type and the index is in the range from 1 to the number of the production appearances within the rule.
Aldec simulator always generates an array where the element type is the production return type. An element
with index 0 exists and stores a default value of the corresponding type.
A production variable can be read-only when the production is generated. Aldec simulator does not produce
any error when this condition is not satisfied.

183

SystemVerilog Reference

Constrained Random Value Generation

Random Stability

Initialization of The Random Number Generator


In the design structure, each module, interface, program, and package has a random number generator (RNG). The
generator is seeded with a default seed and used in the creation of static processes and static initializers.
The default seed does not change between subsequent simulation runs. This guarantees that simulation results are
reproducible. If it is desired to run the simulation with another seed to acquire different results, the seed can be
specified with the -sv_seed argument for the asim command. Note that the reproducibility cannot be assumed for
simulations run by different tools. (The default seed is implementation dependent.)

Thread Stability
Each thread has an independent RNG for randomization calls invoked from that thread. The threads are seeded
hierarchically:
The RNG for a dynamic thread is seeded with the next random value from its parent thread.
The RNG for a static thread (process) is seeded with the next value from the initialization RNG from the unit
containing the thread.
Thread stability can be achieved when the order of thread creation and the order of number generation do not change.

Object Stability
Each class instance has an independent RNG for all randomization methods in the class. An object created using new
has the RNG seeded with the next random value from the thread that creates the object. When a class object is
created by a static declaration initializer its RNG is seeded with the next random value of the initialization RNG of the
containing unit (module, interface, program, or package).
Object stability can be achieved when the order of thread creation and the order of number generation do not change.

Manual Seeding
Random number generators that are not used for initialization can be manually seeded using a call to srandom().
The example below demonstrates seeding class C.

Example 1
class C;
rand int i1;
endclass
C c1;
initial begin

184

SystemVerilog Reference

Constrained Random Value Generation

c1 = new;
c1.srandom(100); // Seed c1 with 100.
//...
end

The other example shows seeding a process. Note how the process handle is acquired through the predefined
process class.

Example 2
process p1;
initial begin
p1=process::self();
p1.srandom(100);
//...
end

// Get a handle to the current process.


// Seed RNG of the process with seed 100.

Maintaining Random Stability


Threads and objects have their own Random Number Generators(RNGs). Dependencies between individual
randomizing statements do not span over the whole design; they are rather localized to the nearest RNG resource.
Thus, the SystemVerilog introduces properties such as: the thread stability and the object stability.
Threads and objects are randomly stable if random values generated within them are identical in subsequent
simulation runs. Having all objects and threads stable guarantees the random stability, that is, the reproducibility of the
results in consecutive simulation runs.
In General, SystemVerilog projects are typified by the random stability. However, the simulation results reproducibility
can be lost in certain circumstances:

Changes in The Project Hierarchy


The RNGs are seeded during initialization, or later, in a strictly defined procedure called the hierarchical seeding. The
hierarchical seeding starts from the sv_seed value to initialize the root RNG. Then, the RNGs of all instances in the
design hierarchy are seeded with values initiated from the root RNG and projected onto the instance's hierarchical
path.

185

SystemVerilog Reference

Constrained Random Value Generation

The instances' RNGs, in turn, are used to create the RNGs associated with objects and processes within instances.
Therefore, the random stability may be affected by changes in the project hierarchy; particularly, by changes that
modifies the instance's hierarchical path. The instance stability is not affected as long as the hierarchical path of an
instance does not change. Adding or removing an instance in another design region will not change randomization
results, but moving or renaming instances that are in the instance's hierarchical path will affect the stability.

Rearrangement of The Code


RNGs for threads of static processes located in the certain instance, e.g. threads of procedural blocks such as
always or initial declared in the same module instance, are evaluated on the basis of the RNG of that particular
module instance. The relative order of procedural blocks affects the evaluation of their RNGs. Adding, removing or
changing their order have an influence on the generated values.
Objects initialized at declarations outside procedural blocks, similarly to procedural blocks themselves, have RNGs
depended on the current instance RNG and the order in which these objects are declared and initialized.

186

SystemVerilog Reference

Constrained Random Value Generation

Code Execution Order


The RNG state depends on the order in which statements that uses the RNG appears in the code, thus adding or
removing such statements affects the RNG state of succeeding statements. In consequence, the number and order of
statements operating on the particular RNG, e.g. random statements in the same procedural block, have an influence
on results.
Objects that are created inside a procedural block, have RNGs based on the procedural block RNG and their values
depend on the order of random statements within the block.

Changes within Object Declarations


Objects are typified by significant stability. If a class RNG is seeded with the same seed in subsequent simulation
runs, random values inside are not affected by hierarchy changes and rearrangements of the code outside the class
declaration. However, random values can be affected by changes within class declaration. When adding, removing, or
changing the order of fields inside a class, random values might change.

Preventing Random Stability Loss


SystemVerilog has a mechanism for random stability, but its usability is limited. Changes in source code, parameter
values, etc. may cause that stability to suffer. In cases where stability is important, the user has to develop his own
stability mechanism using the srandom function (such as a mechanism included in the UVM library).
Problems related to changing the code layout can be, to some extent, minimized by adding new procedural blocks
and object declarations at the end of the project. This, however, may be practically impossible to apply in many cases.
The most effective way of maintaining stability could be the use of the srandom() method. This method can set a
seed for objects. Using the srandom method in an object declaration, as it is shown on the Example 1 from the
Manual Seeding section above, will ensure the random stability for its members. Placing an srandom call in the object
constructor and calculate its argument basing on some stable values could be a good idea.
The srandom method can also be used to specify the seeds for threads, and as a consequence, to set the seeds for
procedural blocks. On the Example 2 from the Manual Seeding section above, the seed is set for the thread executed
at the moment, that is, to the thread of the actual procedural block. The srandom() method needs to be used for
every block and object separately, since its effect does not apply to regions' subinstances.
Similar effects can be achieved with the srandom macro command. The srandom command allows you to set a seed
for a whole design region. Random values within the region where the seed is specified will not be affected by
hierarchy changes. As with the srandom command, the srandom() method needs to be used for every block and
object separately.
The srandom command description may be found in the User's Guide | Macro Command Reference | srandom
command section.

187

Interprocess Synchronization

Semaphores
Semaphore is a built-in class. It can be used for mutual exclusion, to control the access to the shared resources and
for synchronization.
When new semaphore object is created, the set of specified number of keys is created. The process using
semaphore gets key(s) and then can continue the execution. After finishing operations controlled by the semaphore
the process returns the key(s). If more then one process use the declared semaphore processes must wait for free
keys.
The semaphore class includes the following methods:
new()
get()
put()
try_get()
The example below shows two processes synchronized via semaphore data_sem and its put() and get()
methods. The call to get() in one process can block if the other process has already acquired the semaphore with
another call to get(). (The call blocks until the other process releases the semaphore using put().)
semaphore data_sem = new(1);
always @(posedge clk)
if (IN0) begin
data_sem.get(1);
dump_data(data_in);
data_sem.put(1);
end
always @(posedge clk)
if (IN1) begin
data_sem.get(1);
read_data(data_out);
data_sem.put(1);
end

Note that compilation of a module using the semaphore class will yield (at least) two library units: the module itself
and the semaphore class.

Semaphore Methods
Method

Description

new()

Semaphore object constructor. The argument to the constructor specifies the number of keys initially
allocated to the semaphore. The default value of the keys is zero.

188

SystemVerilog Reference

Interprocess Synchronization

function new(int keyCount = 0 );

The new() function returns the semaphore handle or, if the semaphore cannot be created, null.
Gets a specified number of keys from the semaphore.
task get(int keyCount = 1);

get()

The keyCount specifies the required number of keys to obtain from the semaphore. The default is 1.
If the specified number of keys is available, the method returns and execution continues. If the
specified number of keys is not available, the process blocks until the keys become available.
The semaphore waiting queue is first-in first-out (FIFO). This does not guarantee the order in which
processes arrive at the queue, only that their arrival order is preserved by the semaphore.
Returns keys to the semaphore.
task put(int keyCount = 1);

put()

The keyCount specifies the number of keys being returned to the semaphore. The default is 1.
When the semaphore.put() task is called, the specified number of keys is returned to the semaphore.
If a process has been suspended waiting for a key, that process shall execute if enough keys have
been returned.
Gets a specified number of keys from a semaphore, but without blocking.
function int try_get(int keyCount = 1);

try_get()
The keyCount specifies the required number of keys to obtain from the semaphore. The default is 1.
If the specified number of keys is available, the method returns a positive integer and execution
continues. If the specified number of keys is not available, the method returns 0.

189

SystemVerilog Reference

Interprocess Synchronization

Mailboxes
A mailbox is a built-in class that provides a mechanism of exchanging messages between processes. Data can be
sent to a mailbox by one process and retrieved by another. If there is no data in the mailbox, the retrieving process
can wait for data or continue execution and try to retrieve data at the next attempt.
A mailbox is a FIFO. A message put into the mailbox as first goes out from the mailbox first. The number of messages
in the mailbox can be limited or unlimited. The limit, if any, is specified in the constructor. A bounded mailbox (that is, a
mailbox with a limited number of messages) becomes full when it contains the maximum allowed number of
messages.
The type of the messages stored in the mailbox must be specified in its declaration.
The mailbox class provides the following methods:
new()
put()
try_put()
get()
peek()
try_get()
try_peek()
num()
The example below shows two processes posting and retrieving messages to/from a mailbox. The first process blocks
when the mailbox is full; the other when the mailbox is empty. The time required for each put() and get() operation
is displayed on the Console.
mailbox #(int) MBox = new(2);
initial begin
int i = 0; int delay = 1;
repeat( 12 ) begin
time start;
#( ++delay );
start = $time;
MBox.put( i++ );
$display( "Message posted in %0d time unit(s).", $time - start );
end
end
initial begin
int m; int delay = 10;
repeat( 10 ) begin
time start;
#( --delay );
start = $time;
MBox.get(m);
$display( "Message retrieved in %0d time unit(s).", $time - start );
end
end

190

SystemVerilog Reference

Interprocess Synchronization

Mailbox Methods
Method

Description

new

Mailbox constructor. An optional argument to the constructor specifies the maximum number of
messages in a mailbox. This number must be positive.
function new(int bound = 0);

Places a message in a mailbox.


put()

task put(singular_message);

If the mailbox was created with a limited number of messages, then the process suspends until there
is enough room in the queue.
Attempts to place a message in a mailbox.
function int try_put(singular_message);

try_put()
If the mailbox is not full, then the specified message is placed in the mailbox, and the function returns
a positive integer. If the mailbox is full, the method returns 0. For unbounded mailboxes, this method is
not meaningful.
Gets a message from a mailbox.
task get(ref singular_message);

get()
Removes one message from the mailbox queue. If the mailbox is empty, the process blocks until a
new message is put into the mailbox. If the type of the message variable is not equivalent to the
message type a run-time error is generated.
Tries to retrieve a message from a mailbox; without blocking. Returns a positive integer on success or
zero otherwise.
try_get()

function int try_get(ref singular_message);

If the mailbox is empty, try_get does not block. (It returns 0 immediately.)
Copies a message from a mailbox without changing the mailbox state.
peek()

task peek(ref singular_message);

If the mailbox is empty, the current process blocks until a message appears in the mailbox.
The try_peek() method tries to copy a message from a mailbox without removing the message from
the queue.
function int try_peek( ref singular message );

try_peek()
If the mailbox is empty, 0 is returned. Otherwise, a positive integer is returned. If the type of the
message variable is not equivalent to the type of the message in the mailbox, the method returns a
negative integer. If a message is available and its type is equivalent to the type of the message
variable, the message is copied, and the method returns a positive integer.
num()

The num() method returns the number of messages in a mailbox.


function int num();

191

SystemVerilog Reference

Interprocess Synchronization

The returned value should be used with care because it can be invalidated when method get(),
try_get(), put(), or try_put() is executed on the mailbox. These methods can be executed by
other processes; therefore the validity of the returned value depends on the time that other methods
start and finish.

Parameterized Mailboxes
The type of messages to be stored in the mailbox is specified at declaration. Any mismatches between the message
type and the argument types for put(), try_put(), peek(), try_peek(), get(), and try_get() methods are
detected by the compiler.

Non-parameterized Mailboxes
Non-parameterized mailbox can store messages of an arbitrary type. This is very useful mechanism, but it can also
cause run-time errors. When a message type and the type of variable used to retrieve the message are not equivalent
error is generated.
mailbox MBox = new;
initial begin
MBox.put(2.3);
MBox.put("short string");
MBox.put(311);
MBox.put(4'b01xz);
end
real x_real;
string x_string;
int x_int;
reg [3:0] x_reg;
initial begin
MBox.get(x_real);
$display( "Message retrieved
MBox.get(x_string);
$display( "Message retrieved
MBox.get(x_int);
$display( "Message retrieved
MBox.get(x_reg);
$display( "Message retrieved
end

in %0d time unit(s). Message is %f", $time, x_real );


in %0d time unit(s). Message is %s", $time, x_string );
in %0d time unit(s). Message is %0d", $time, x_int );
in %0d time unit(s). Message is %b", $time, x_reg );

192

SystemVerilog Reference

Interprocess Synchronization

Events
Events provide means for describing the communication and synchronization between processes. The triggered state
of an event persists throughout the time step in which the event is triggered. Events can be passed as arguments to
tasks, can be assigned to one another or compared.

Triggering an Event
Named events can be triggered via the -> operator. Triggering an event unblocks all processes currently waiting on
that event. When triggered, the trigger state itself is not observable, only its effect. (For example, the if (e)
statement, where e is an event, is illegal.)
Named events can be also triggered using the nonblocking event operator ->>. The effect of the ->> operator is that
the statement executes without blocking and creates a nonblocking assign update event in the time in which the delay
control expires or the event control occurs.
The nonblocking trigger (unlike the blocking trigger) cannot trigger events that are declared as dynamic class
properties.

Waiting for an Event


Waiting for the triggered event can be realized using the @ operator.
@named_event;

The calling process is blocked until the named event is triggered.

triggered Property
The triggered property represents the state of the named event. The property evaluates to true if the given event
has been triggered in the current time step and false otherwise. If event_identifier is null, then the triggered
event property evaluates to false.
The triggered method can be used with the wait statement:
wait(named_event.triggered);

The calling process in blocked until the wait executes before or at the same simulation time as the trigger
operation.

wait_order()
The wait_order() construct suspends the calling process until all of the specified events are triggered in the given
order (left to right) or any of the untriggered events is triggered out of order and thus causes the operation to fail.

193

SystemVerilog Reference

Interprocess Synchronization

wait_order ( hierarchical_identifier { , hierarchical_identifier } ) action_block

The wait_order() succeeds if all untriggered events happen in the prescribed order. Initially, all events are
untriggered and wait_for waits for the first event in the list. If any other event from the list is triggered instead, then
wait_order() fails. After the first event has triggered, wait_for() starts waiting for the second event from the list.
This event must be untriggered or else wait_order() would have already failed. Waiting is repeated until all event
are triggered. Note that events that have already triggered in the correct order are no longer monitored. They may be
triggered again, without causing wait_order() failure.
The wait_order() statement can include the else statement in the action block. If the wait_order() fails, the
action in the else statement is executed. If the wait_order() statement does not include else statement the
failure generates a run-time error.
wait_order( a, b, c ) else $error( "The events a,b,c out of order" );

Merging Events
Two events are merged when one event is assigned to another. After the merge, triggering one event also triggers the
other.
class C;
event a, b;
endclass
initial begin
C c = new;
c.a = c.b; // Events are merged.
-> c.a; // Also triggers b.
-> c.b; // Also triggers a.
end

Reclaiming Events
To break the synchronization queue of the event, assigning the null the event can be used. The resources of the
queue become available for reuse.
Triggering a null event has no effect. Waiting on a null event generates a run-time error.
event a;
initial begin
a = null;
@ a; // undefined: might block forever or not at all
wait( a.triggered ); // undefined
-> a; // no effect
end

Event Comparison
Event variables can be compared against other event variables or the special value null. The following operators are
allowed for comparing event variables:
==

194

SystemVerilog Reference

Interprocess Synchronization

!=
===
!==
An event can be compared with another event or with null.

195

Clocking Blocks

Clocking Block Declaration


A clocking block in SystemVerilog identifies clock signals and captures the timing and synchronization requirements. It
separates timing and synchronization details from structural, functional and procedural elements of a testbench.
A clocking block gathers signals that are synchronous to a particular clock and makes their timing explicit.
Clocking blocks can be defined in a module, program or interface. Each of these units can include one or more
clocking blocks. Only one default clocking block can be declared in a module, program or interface.

Clocking Block Syntax


clocking_declaration ::=
[ default ] clocking [ clocking_identifier ]clocking_event ;
{ clocking_item }
endclocking [ : clocking_identifier ]
clocking_item ::=
default default_skew ;
| clocking_direction list_of_clocking_decl_assign ;
| { attribute_instance } concurrent_assertion_item_declaration
default_skew ::= input clocking_skew
| output clocking_skew
| input clocking_skew output clocking_skew
clocking_direction ::=
input [ clocking_skew ]
| output [ clocking_skew ]
| input [ clocking_skew ] output [ clocking_skew ]
| inout
list_of_clocking_decl_assign ::= clocking_decl_assign { , clocking_decl_assign }
clocking_decl_assign ::= signal_identifier [ = expression ]
clocking_skew ::= edge_identifier [ delay_control ] | delay_control

Example
clocking cl_bl_1 @(posedge clk);
default input #10ns output #2ns;
input data, ready, enable = top.mem1.enable;
output negedge ack;
input #1step addr;
endclocking

196

SystemVerilog Reference

Clocking Blocks

Clocking event in a clocking block can be for example, a clocking expression including a posedge or negedge
identifier, it can also be an event variable. Hierarchical identifiers can be assigned to the clocking block inputs. Output
signals in a clocking block cannot be read, input signals cannot be driven.

Clocking Block Scope and Lifetime


A clocking block has a static lifetime and a scope local to an enclosing module, interface, or program. It is both the
declaration and the instance. The clocking block signals are available via the clocking block name and the dot (.)
operator. Clocking blocks cannot be nested. They cannot be declared inside tasks, functions and packages, or outside
declarations in a compilation unit.

197

SystemVerilog Reference

Clocking Blocks

Input and Output Skews


Input (or inout) signals are sampled at the designated clock event. If an input skew is specified, then the signal is
sampled at skew time units before the clock event.
Output or inout signals are driven at the designated clock event. If an output skew is specified the output (or inout)
signals are driven skew simulation time units after the corresponding clock event.

A skew must be a constant expression. It can be specified as a parameter. If the skew does not specify a time unit,
the current time unit is used. If a number is used, the skew is interpreted using the timescale of the current scope.
Default input skew is #1step. Default output skew is #0. #1step means that the signal is sampled at the end of the
previous time step, just before the corresponding clocking event. #0 skew for the input signals means that the signals
are sampled at the same time as the clocking event, but in the Observed region. #0 skew for the output signals means
that they are driven at the same time as the clocking event, in the NBA region.

Input Sampling
Clocking block inputs and inouts are sampled at the corresponding clocking event. The signals declared with explicit
#0 input skew are sampled in the Observed region. The signals without explicit #0 skew are sampled in the Postponed
region. Sampled signals values are used when the signal from the clocking block appears in the expression. When the
same signal is an input to multiple clocking blocks, each clocking block samples the corresponding signal with its own
clocking event.
An event associated with the clocking block name is updated in the Observed region. It is made to eliminate potential
races which can occur if values sampled in clocking block are altered by a non-blocking assignment in the same
simulation time. If value is used in process that waits for clocking block, it is guaranteed that expressions inside this
process will use the newly-updated values.
bit clk;
reg v;
clocking cb @(negedge clk);
input v;
endclocking
always @(cb) $display(cb.v);

The next example, as distinct from the first, has a potential risk of races, since values sampled in clocking block can
be changed by concurrent non-blocking assignment.
always @(negedge clk) $display( cb.v);

NOTE: In the Verilog and the SystemVerilog standards preceding IEEE Std 1800-2009 there were no distinction
between these two examples. Both of them worked as the latter one.

198

SystemVerilog Reference

Clocking Blocks

Cycle Delay Operator


Cycle delay operator ## delays the execution of a process by a specified number of clocking events or clock cycles.

Syntax
cycle_delay ::=
## integral_number
| ## identifier
| ## ( expression )

The expression must evaluate to positive integer number. The default clocking event determines the clock cycle or
clocking event used in the delay. If no default clocking block is declared the usage of cycle delay operator is illegal.

Example
default clocking cl_1 @(negedge clk);
endclocking
initial begin
a = 0;
##1; // wait one clock clk cycle
a = 1;
##3; // wait three clock clk cycles
b = 5;
// ...
end

199

SystemVerilog Reference

Clocking Blocks

Default Clocking
In a SystemVerilog one clocking can be specified as the default for all cycle delay operations within a given module,
interface, or program.
Specifying a default clocking more than once in the same program or module is illegal.
A default clocking is valid only within the scope containing the default clocking specification. This scope includes
the module, interface, or program that contains the declaration as well as any nested modules or interfaces. It
does not include instantiated modules or interfaces.
default clocking d_clk @(posedge clk);
endclocking
initial begin
##1;
a =1;
##1;
a = 0;
##1;
a = 1;
end

200

SystemVerilog Reference

Clocking Blocks

Events and Drives

Clocking Block Events


The clocking event of a clocking block can be used by referencing the clocking block name.
clocking clk_bl1 @(posedge clk);
endclocking
always @(clk_bl1)
q = d;

Synchronous Drives
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

201

SystemVerilog Reference

Clocking Blocks

Clocking Properties
The clocking block can include sequences and properties declarations. These sequences and properties are
clocked with the corresponding clocking block event. The signals in sequences and properties expressions are
sampled in the Preponed region.
clocking cl1 @(posedge clk);
input a,b,c,d;
sequence s1;
a ##1 b ##[1:$] c;
endsequence
property p1;
s1 |-> (##[1:5] !d);
endproperty
endclocking

The clocking event from the default clocking block specifies a clocking event for the sequences and properties,
which have no explicit clock (in corresponding scope).
default clocking cl2 @(negedge clk);
endclocking
property p2;
a -> b;
endproperty

The property p2 is clocked with negedge clk.

202

Program

Program blocks are used to model the design verification environment. A program block provides an entry point to
the execution of testbenches, creates a scope that encapsulates programwide data, tasks, and functions.
A sample program definition is shown below:
program
input
input
input
inout
);

tst_prg(
clk,
[15:0] addr,
EN,
[8:1] data

clocking cblk @(posedge clk);


input EN;
input #2 output #5ps data;
endclocking
initial begin
// program begins here
...
//you can access cblk.data , cblk.EN
end
endprogram

A program can be instantiated within modules or interfaces.


module top;
logic clk;
wire [8:1] data;
logic [15:0] addr;
tst_prg main( clk, addr, EN, data);
mem UUT1( clk, addr, EN, data );
endmodule

A program block can only contain initial and final blocks. UDPs, modules, interfaces, always blocks, or other
programs are not allowed.

$exit Task
Calling the $exit() system tasks explicitly terminates a program. All processes spawned by the current program are
terminated. When all initial blocks in a program finish the program implicitly calls $exit.

Anonymous Programs
Anonymous programs allow you to declare data, tasks and functions accessible only by other programs and
unreachable outside the program blocks. Anonymous programs can be declared inside the packages or compilation
unit scopes. The items declared in these programs share the same name space as the package or compilation unit
scope in which they are declared. Therefore, the identifiers used inside an anonymous program cannot be used in

203

SystemVerilog Reference

Program

declarations placed outside the program but inside the package or compilation unit scope in which the program is
declared.

Example
In the below example, there are two declarations of anonymous programs: the first is declared in the pckg package
and the second is declared in the compilation unit scope. The pckg package is imported to the top program so the C
class and ff function declared in anonymous programs are visible in the program top.

package pckg;
program; // anonymous program declared in package
class C;
int x;
endclass
endprogram
endpackage
program;
// anonymous program declared in compilation scope
function int ff(int y);
return 2*y;
endfunction
endprogram
program top;
import pckg::*;
C c = new;

// instantiating class from anonymous program

initial
begin
// calling function from anonymous program
c.x = ff(5);
end
endprogram

204

Assertions

Assertion Evaluation Model


The assertion evaluation model is based on a clock. (The only exception to this rule are Immediate Assertions.) A
concurrent assertion is evaluated only at clock ticks. (A clock tick can be, for example, a positive or a negative edge of
a clock expression.) The values of signals and variables from the assertion expression used in the evaluation are
sampled in the Preponed region of a time slot, i.e. before any assignments. Assertions are evaluated in the Observed
region, after assignments. (Detailed information about scheduling semantics and time slot regions is available in
clause 9.3 of IEEE Std 1800-2005.) The same variable used in the clock expression and in the assertion expression
can have different values during assertion evaluation - the current value is used for the clock expression and the
sampled value for the assertion expression. Similarly, the sampled value will be read for a variable that changes
exactly on the clock tick.
The result of the assertion evaluation is true or false. It can be differently interpreted and reported, depending on the
verification directive in the assertion. If the assertion works as a checker (assert directive has been used) true result
means that the design works correctly, according to the description in the assertion. False result indicates an error in
the design behavior. If the assertion works as a monitor for the functional verification (cover directive) true means
that the required scenario of events happened during simulation, false means that this scenario was not covered
during simulation.

Example

property HndShk_1;
@(posedge clk) $rose(RECEIVE)|-> ##2 $fell(RECEIVE);
endproperty
assert property (HndShk_1) else $error("RECEIVE pulse incorrect");

The property HndShk_1 is tied to clock clk. The clock tick for this property is the rising edge of this clock. The
RECEIVE signal is sampled in the Preponed region of each time slot, in which the rising edge of clk appears.
Changes on the signal between clock ticks (for example between the 5-th and 6-th clock tick in the figure above) are
ignored. Signal RECEIVE rises at clock tick 7 exactly on at the positive clock edge. The sampled value of this signal
for clock tick 7 equals zero.

205

SystemVerilog Reference

Assertions

Assertions Building Blocks

Overview
The basic element in Assertion Based Verification is a Boolean expression. Boolean expressions together with
sequence operators create sequences. The sequences can be also built using other sequences and sequence
instances. All aforementioned elements can be combined to build a property. A property can also include other
properties, property instances, and property operators. The properties describe design behavior but are only
declarations. To use properties in the verification during simulation, the verification directives must be used. The
evaluation of assertions is based on a clock (except for immediate assertions), so the clock expressions are also
important elements of assertions.

Keywords
Keywords are predefined identifiers that are used to define SystemVerilog constructs.

List of Keywords
and
assert
assume
bind
cover
disable iff
ended
endproperty
endsequence
first_match
if ... else
intersect
matched
not
or
property
sequence
throughout

206

SystemVerilog Reference

Assertions

within

Identifiers
Identifiers in SystemVerilog consist of a letter, followed by zero or more alphanumeric characters; each subsequent
alphanumeric character may optionally be preceded by a single underscore character. Additionally, hierarchical
names are allowed for referencing selected HDL objects.

Example

Example 1
BusyPrinter
Check_Full_after_Write4
tb.UUT

All identifiers above are valid.

Example 2
8ones
two__underscores

All identifiers above are invalid.

Hierarchical References
HDL signals, functions and scopes can be referenced using hierarchical path names.

Syntax
hierarchical_identifier ::= [ $root . ] { identifier constant_bit_select . } identifier
constant_bit_select ::= { [ constant_expression ] }

$root provides unambiguous reference to the top level instance, or to an instance path starting from the root of the
instantiation tree.

Boolean Expressions
Boolean expressions are interpreted in the same way as expressions in a condition of a procedural if statement. If
the expression evaluates to X, Z, or 0, then it is interpreted as being false. Otherwise, it is true.
The boolean expression can include a function call, the function must be automatic.

207

SystemVerilog Reference

Assertions

Boolean expressions are used in sequences and in top-level statement disable iff.

Restrictions
The following restrictions apply:
string, event, handle, and class types are not allowed in expressions.
Associative or dynamic arrays are not allowed in expressions.
Variables used in expressions must be static.
Assignment operator, increment operator, and decrement operator are not allowed.

Built-in Functions
The SystemVerilog includes several built-in functions, which facilitate building sequences and properties - sampled
value functions $sampled, $rose, $fell, $stable, and $past and system functions $onehot, $onehot0,
$isunknown, and $countones.

Sampled value functions


The following sampled value functions can be used to sample the current expression value, to sample the expression
value in the past and to detect changes in the expression value.

Syntax
$sampled(expression [, clocking_event])
$rose( expression [, clocking_event])
$fell( expression [, clocking_event])
$stable( expression [, clocking_event])
$past( expression1 [, number_of_ticks] [, expression2] [, clocking_event])

$sampled
Function $sampled returns the value of the expression sampled exactly before the last occurrence of the clocking
event. When $sampled is invoked prior to the occurrence of the first clocking event, the value of X is returned.
The use of $sampled in assertions is redundant, the result of the function is identical to the sampled value of the
expression itself used in the assertion. $sampled can be also used in other, non-assertion expressions.

208

SystemVerilog Reference

Assertions

Example 1
property Load_Data_1;
@(negedge Load) $sampled(QOut)==$sampled(DataIn);
endproperty
property Load_Data_2;
@(negedge Load) QOut==DataIn;
endproperty

The property Load_Data_1 works exactly the same like the property Load_Data_2.

Example 2
Check_Load:
assert property (Load_Data)
else
$display(
"Time=%0t Programmable Counter : Load - violation! QOut=%0d DataIn=%0d",
$time, $sampled(QOut), $sampled(DataIn)
);

In the example 2 $sampled is used in action block of the assert statement, in $display task that displays a
message when the property fails. Here, the $sampled function is very useful. The $display task displays the values
of signals in the postponed region of the timeslot, the signal values for the assertion are taken from the preponed
region of the time slot. If the signal changes at the clocking event, the signal value used for evaluating assertion and
the value displayed in the failure message will be different. When $sampled is used, the correct signal value is
displayed in the message (i.e. the value that was used when the assertion was evaluated).

$rose, $fell, $stable


$rose, $fell, and $stable functions detect changes on a signal. The signal value sampled at the current clocking
event is compared with the value of the signal from the previous clocking event. If the signal value toggles an even
number of times between the clock ticks of the clocking event the change on the signal will be ignored. When these
functions are called at or before the first clock tick of the clocking event, the results are computed by comparing the
current sampled value of the expression to X.
$rose returns true if the LSB of the expression changed to 1. Otherwise, it returns false.
$fell returns true if the LSB of the expression changed to 0. Otherwise, it returns false.
$stable returns true if the value of the expression did not change. Otherwise, it returns false.

Example 3
property D2_Pulse_Active;
@(posedge CLK) $fell(D1) |-> $rose(D2);
endproperty

The property D2_Pulse_Active checks that whenever the D1 signal changes to a low value, signal D2 should be set
high in the same clock cycle.

209

SystemVerilog Reference

Assertions

In the figure above the falling edge of the D1 signal is detected on the 2-nd and on the 7-th clock tick. The falling edge
between the 4-th and 5-th clock tick is not detected because the value of the D1 signal is the same at the 4-th and the
5-th clock edge. The rising edge of the D2 signal is detected on the second clock tick.

Example 4
property Active_TXD_1;
@(negedge clk) SEND |-> !$stable(TXD);
endproperty

Signal TXD should change at each clock cycle, always when SEND is active. In the figure below, TXD is stable at the
7-th clock tick.

$past
The past values of the signal can be accessed using the $past function. By default $past returns the signal value
from the previous clocking event, if the number_of_ticks argument is specified, the function returns signal value
that was present number_of_ticks clock cycles in the past.

Example 5
property Count_Down;
@(posedge clk) (!Load & Enable) |-> QOut == $past(QOut)-1;
endproperty

The property in the example 4 describes the behavior of a simple counter. The counter counts down when the
Enable signal is active and Load is not enabled.

210

SystemVerilog Reference

Assertions

System functions
The functions $onehot, $onehot0, $isunknown, $countones, $inset and $insetz check specific features of a
Boolean expression in the current clock tick.
$onehot(expression) returns true if 1 and only 1 bit of expression is high.
$onehot0(expression) returns true if at most 1 bit of expression is high.
$isunknown(expression) returns true if any bit of the expression is X or Z. This is equivalent to
^expression === 'bx.
$countones (expression) counts the number of ones in a bit vector expression. An X and a Z value of a
bit is not counted towards the number of ones.
$inset(expression {, expression }) returns the true value if the first expression is equal to at least
one of remaining expressions.
$insetz(expression {, expression }) acts as the $inset function, but it treats the high-impedance
value Z (sometimes signified by '?') as the do-not-care value.

Example 6
property Incorrect_FSM_State;
@(posedge clk) $isunknown(Current_State);
endproperty
assert property (not Incorrect_FSM_State);

The Incorrect_FSM_State rule reports violation when the FSM register includes X, Z values.

Example 7
property Counter_Fast_Check;
@( posedge Clk ) $fell( Enable ) |-> $countones( Q % 2 ) == 0;
endproperty

Example 7 shows the rule for a simple parity checker - when receiving is finished the number of ones in the counter
should be even.

211

SystemVerilog Reference

Assertions

Sequences

Sequence Declaration
A sequence statement describes a sequence of events changing over time. The sequence is not evaluated
continuously but at discrete time points designated by clocking events. Therefore, it describes design behavior in
consecutive clock ticks.
A simple sequence can be built from Boolean expressions and the cycle delay operator. The cycle delay operator
indicates a shift between clock ticks, for example:
sequence Simple_Seq;
@( posedge clk ) Req ##1 Start ##1 Send ##1 Stop;
endsequence

The sequence starts with a high value on signal Req. In the next clock cycle, signal Start is high. It is then followed
by a high SEND and a high Stop in the next two consecutive clocks.

In the figure above the sequence Simple_Seq starts at clock cycle 2 and completes at clock cycle 5, the second
sequence starts at clock cycle 4 and completes at clock cycle 7. Signal values are checked at positive clock edge.
As shown in the figure, sequences can overlap. This feature allows catching all sequences, even if the evaluation of
the previous sequence is not finished.
To describe more refined behavior, use the Sequence Operators.
A sequence can be declared in a module, in an interface, in a program, in a clocking block, in a package and in a
compilation-unit scope.

Syntax
sequence_declaration ::=
sequence sequence_identifier [ ( [ sequence_port_list ] ) ] ;
{ assertion_variable_declaration }
sequence_expr [ ; ]

212

SystemVerilog Reference

Assertions

endsequence [ : sequence_identifier ]
sequence_port_list ::= sequence_port_item {, sequence_port_item}
sequence_port_item ::= { attribute_instance } [ local [ sequence_lvar_port_direction ] ]
sequence_formal_type formal_port_identifier {variable_dimension} [ = sequence_actual_arg ]
sequence_lvar_port_direction ::= input | inout | output
sequence_formal_type ::= data_type_or_implicit | sequence | untyped

Sequence Instance
Named sequence can be instantiated in other sequences and properties. It increases the readability of the code and
allows building hierarchical, reusable sequences.

Example 1
sequence StartEvent;
!WR && READY ##1 ADDR == ValidAdd;
endsequence
sequence StopEvent;
( Data == 0 )[*2] ##1 !WR_Req & !RD_Req;
endsequence
sequence Window;
StartEvent.triggered ##[1:$] StopEvent.triggered;
endsequence
sequence TrueInWindow;
MinMaxLimit( Counter ) throughout Window;
endsequence

The sequence Window includes the instances of sequences StartEvent and EndEvent used with method
triggered. The sequence TrueInWindow uses the instance of Window sequence and user-defined function

213

SystemVerilog Reference

Assertions

MinMaxLimit.

Parameterized Sequences
A sequence can be declared with the formal arguments. The actual arguments in the sequence instantiations can be
any of the following:
literal
identifier
expression
event control expression
sequence expression
the $ symbol
The data types allowed in the expressions are denoted in the Boolean Expressions section.

Untyped Arguments
A formal argument is said to be untyped if there is no type specified for the given argument in the sequence
declaration or the untyped keyword is used. The type of the references to the untyped formal argument is
determined by the type of the actual argument.

Example 2
In the example below, the two instantiations of the StableAfterChange parameterized sequence checks whether
the MemCL and IN1 signals are stable during the specified time after the value change.
sequence StableState(clk,data,min,max);
@clk $stable(data)[*min:max];
endsequence
sequence StableAfterChange(clk,data,min,max);
@clk $changed(data) ##1 Stablestate(clk,data,min,max);
endsequence
MemCLCov: cover sequence(StableAfterChange(posedge clk,MemCL,1,5));
Data1Cov: cover sequence(StableAfterChange(negedge clk,IN1,3,4));

Typed Arguments
The typed formal arguments can be one of the following types:
data type (the allowed types are denoted in the Boolean Expressions section)
event
sequence

214

SystemVerilog Reference

Assertions

Example 3
The example below is the Example 2 with the typed formal arguments in the sequence declarations.
sequence StableState(event clk,byte data,int min,max);
@clk $stable(data)[*min:max];
endsequence
sequence StableAfterChange(event clk,byte data,int min,max);
@clk $changed(data) ##1 Stablestate(clk,data,min,max);
endsequence
MemCLCov: cover sequence(StableAfterChange(posedge clk,MemCL,1,5));
Data1Cov: cover sequence(StableAfterChange(negedge clk,IN1,3,4));

The formal and the actual argument types must be cast compatible. If the actual and formal arguments are of the
same types, each assignment to a reference to the formal argument will be treated as though there was a subsequent
assignment of the formal argument to the actual argument. If the actual and formal arguments are of different types,
the actual argument will be cast to the type of the formal argument before being used as a substitute for a reference to
the formal argument.

Example 4
In the example below, the actual argument w1 of the 8 bit size is assigned to the formal argument word. Before the
assignment, the w1 actual is extended to 16 bits. Similarly, the actual i argument is truncated to the size of the formal
argument idx.
sequence CompareBit( logic [0:15] word, bit [0:3] idx);
@(posedge clk) $past(word[idx]) === word[idx];
endsequence
reg [0:7] w1;
int i;
sequence Check;
@(posedge clk) enable and CompareBit(w1,i) and CompareBit(w1,i+1);
endsequence

Example 5
The example below shows the Range sequence with the two formal arguments of the event and the sequence type
and a one untyped argument. The keyword untyped is obligatory if an untyped argument is specified on the
argument list along with typed arguments.
There are two instances of the Range sequence. In the first instance, in the CheckAck assertion declaration, the
values returned by the $fell function calls are mapped to the s1 and s2 arguments of the sequence type. The
untyped argument n is assigned with the $ symbol as an actual argument so that the argument is used in the
sequence as the upper bound of the cycle delay constant range expression (##). In the second instance, in the
CheckReq assertion declaration, the actual arguments s1 and s2 are the sequence expressions and the integer
literal constant (2) is assigned to the untyped argument n.
sequence Range(event clk, sequence s1,s2, untyped n);
@clk s1 ##[0:n] s2;
endsequence

215

SystemVerilog Reference

Assertions

CheckAck: assert property(Range(.clk(posedge clk),.s1($fell(Strobe)),.s2($fell(Ack)),.n($)));


CheckReq: assert property(Range(.clk(posedge clk),.s1($rose(Req) ##1 Req),.s2(Busy throughout
(!Ack[*3:8])),.n(2)));

Local Variable Formal Arguments


The typed formal arguments can be declared as local variables by specifying the local keyword before the argument
declaration. For more information about local variables, refer to the Using Dynamic Variables in a Sequence section.
The formal arguments declared as local variables have the following characteristics:
You can specify default values of the input or inout formal arguments.
If the formal argument declared as a local variable of the input or inout direction is assigned to an actual
argument in the argument list of an instance and this actual argument references a local variable, then the
value of the actual argument corresponding to this formal argument has to be set before a reference to this
actual argument occurs.
The triggered and the matched sequence methods cannot be applied to named sequences containing the
formal arguments declared as the local variable of one of the directions: input and inout.
The actual argument of an output local variable formal argument must be a local variable declared in the
body of the sequence declaration.
The formal argument of the output direction declared as a local variable cannot be assigned with any value
when a sequence evaluation attempt begins. The argument has to be assigned before the end of the
successful evaluation.
The sequence with the local variables of the inout and output directions cannot admit an empty match.
The copies of each formal argument declared as a local variable are created at the beginning of each
evaluation attempt of a sequence instance.
All multiple threads of the evaluation of the named sequence instance have their own copy of each actual
argument declared as a local variable.

Example 6
In the below example, there is a declaration of the s1 sequence. The sequence has the formal arguments declared as
a local variables on its port list. In the first clock cycle of the s1 sequence evaluation, the sequence checks whether
the a variable holds. In the next cycle, the sequence checks whether the b variable and the x variable are equal and
in the next cycle, the sequence checks whether the c variable holds, saves its value to the y variable and the current
simulation time to the z variable.
sequence s1(local input byte x, local output time z, local output byte y);
@(posedge clk) a ##1 b==x ##1 (c,z=$time,y=c);
endsequence
sequence s2;
byte v1=1,v2;
time t1;
@(posedge clk) (d,v2=d) ##0 (s1(.x(v1),.y(v2),.z(t1)),$display(v2,t1));
endsequence
a1: cover sequence(s2);

Sequence Operators
SystemVerilog includes several sequence constructs and operators that facilitate describing the design behavior and
allow creating more sophisticated rules.

216

SystemVerilog Reference

Assertions

Syntax
sequence_expr ::=
cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
| sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
| expression_or_dist [ boolean_abbrev ]
| ( expression_or_dist {, sequence_match_item } ) [ boolean_abbrev ]
| sequence_instance [ sequence_abbrev ]
| ( sequence_expr {, sequence_match_item } ) [ sequence_abbrev ]
| sequence_expr and sequence_expr
| sequence_expr intersect sequence_expr
| sequence_expr or sequence_expr
| first_match ( sequence_expr {, sequence_match_item} )
| expression_or_dist throughout sequence_expr
| sequence_expr within sequence_expr
| clocking_event sequence_expr
cycle_delay_range ::= ## integral_number
| ## identifier
| ## ( constant_expression )
| ## [ cycle_delay_const_range_expression ]
sequence_match_item ::= operator_assignment
| inc_or_dec_expression
| subroutine_call
sequence_instance ::= ps_sequence_identifier [ ( [ list_of_arguments ] ) ]
actual_arg_expr ::= event_expression | $
boolean_abbrev ::= consecutive_repetition
| non_consecutive_repetition
| goto_repetition
sequence_abbrev ::= consecutive_repetition
consecutive_repetition ::= [* const_or_range_expression ]
non_consecutive_repetition ::= [= const_or_range_expression ]
goto_repetition ::= [-> const_or_range_expression ]
const_or_range_expression ::= constant_expression | cycle_delay_const_range_expression
cycle_delay_const_range_expression ::= constant_expression : constant_expression | constant_expression :
$
expression_or_dist ::= expression [ dist { dist_list } ]

Sequence Operator Precedence

Operator

Associativity

[*] [=] [->]


##

left

throughout

right

217

SystemVerilog Reference
within

left

intersect

left

and

left

or

left

Assertions

Cycle Delay Operator ##


The Cycle Delay operator is the most basic operator in sequences. It describes a shift between clock ticks. The shift
can be defined with a range - limited or unlimited.

Syntax
sequence_expr ::=
cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
| sequence_expr cycle_delay_range sequence_expr { cycle_delay_range sequence_expr }
...
cycle_delay_range ::= ## integral_number
| ## identifier
| ## ( constant_expression )
| ## [ cycle_delay_const_range_expression ]

Examples

Example 1
sequence FSM_Cycle_1;
@(posedge clk) `Buffer_Empty ##2 `Wait_For_Free ##2 `Set_Strobe ##2 `Wait_For_Ack ##2 `Shift_Fifo ##2
`Buffer_Empty;
endsequence

The sequence FSM_Cycle_1 describes one of several possible cycles in the finite state machine in a printer buffer.
The device stays in each state for two clock cycles.

218

SystemVerilog Reference

Assertions

Example 2
sequence Next_Ack_Limit;
@(posedge clk) !Ack ##[1:5] $fell(Ack) ;
endsequence
assert property (not Next_Ack_Limit);

The next acknowledge cannot happen earlier than 6 cycles after the previous acknowledge. Otherwise the buffer will
not react and will not shift the next value. The sequence Next_Ack_Limit describes incorrect behavior. Such
behavior should not happen during simulation. This is indicated in the assert statement. The falling edge of the Ack
signal cannot happen one, two, three, four, or five clock cycles after the previous acknowledge !Ack.
In the figure below the first acknowledge happens at clock 3 and is followed by another acknowledge at clock 9, i.e.
six ticks after the acknowledge at clock 3. This behavior is correct. The acknowledge in clock cycle 13 happens too
early after the acknowledge in clock 9. The assertion violation in clock 13 is marked with a red triangular mark.

Example 3
sequence Printer_Ack;
@(posedge clk) $fell(Strobe) ##[2:$] $fell(Ack) ;
endsequence

The printer must send an acknowledge after the Strobe signal. The time when the acknowledge should appear is not
determined precisely, it must happen at least 2 clock cycles after the strobe and not later than the end of simulation
($).

Repetitions
The repetition is a construct that facilitates describing recurrent events. SystemVerilog offers three kinds of repetitions:
consecutive repetitions, nonconsecutive repetitions and goto repetitions. Nonconsecutive and goto repetition
operators can be used only with Boolean expressions, consecutive repetition operator can be used also with
sequences.

Syntax
sequence_expr ::=
...

219

SystemVerilog Reference

Assertions

| expression_or_dist [ boolean_abbrev ]
| ( expression_or_dist {, sequence_match_item } ) [ boolean_abbrev ]
| sequence_instance [ sequence_abbrev ]
boolean_abbrev ::= consecutive_repetition
| non_consecutive_repetition
| goto_repetition
sequence_abbrev ::= consecutive_repetition
consecutive_repetition ::= [* const_or_range_expression ]
non_consecutive_repetition ::= [= const_or_range_expression ]
goto_repetition ::= [-> const_or_range_expression ]
const_or_range_expression ::= constant_expression | cycle_delay_const_range_expression
cycle_delay_const_range_expression ::= constant_expression : constant_expression | constant_expression :
$
expression_or_dist ::= expression [ dist { dist_list } ]

Consecutive Repetition
Consecutive repetition specifies finitely many iterative matches of the operand sequence, with a delay of one clock
tick from the end of one match to the beginning of the next. The overall repetition sequence matches at the end of the
last iterative match of the operand. If a sequence is built only from one Boolean expression the consecutive repetition
repeats this Boolean expression at the specified number of consecutive clock ticks.
The effect of consecutive repetition of a subsequence within a sequence can be achieved by explicitly iterating the
subsequence.

Examples

Example 1
sequence Send_Period;
@(negedge XTAL) $rose(SEND) ##1 SEND[*7] ##1 $fell(SEND);
endsequence

The SEND signal must be active for 8 machine cycles and then should drop to zero.
The equivalent sequence with delay range operator is as follows:
sequence Send_Period_1;
@(negedge clk) $rose(SEND) ##1 SEND ##1 SEND ##1 SEND ##1 SEND ##1 SEND ##1 SEND ##1 SEND ##1
$fell(SEND);
endsequence

220

SystemVerilog Reference

Assertions

Example 2
sequence Busy_Length;
@(posedge clk) Busy[*1:4] ##1 !Busy;
endsequence

The maximal busy period takes 4 clock cycles. The minimal busy period takes 1 clock cycle. The consecutive
repetition with a range helps to specify the rule in a convenient way. The equivalent sequence for Busy[*1:4] is
specified below:
Busy
| (Busy ##1 Busy)
| (Busy ##1 Busy ##1 Busy)
| (Busy ##1 Busy ##1 Busy ##1 Busy)

The completion of each of aforementioned sequences causes that the sequence Busy[*1:4] is treated as completed.
The simulator reports always only first completed sequence.

Example 3
$rose(Req) ##1 Req[*1:3] ##1 !WR

In the figure above sequence $rose(Req) ##1 Req[*1:3] is completed at clock ticks 6, 7, 12, 13, 14. The whole
sequence $rose(Req) ##1 Req[*1:3] ##1 !WR is completed at clock tick 7 (evaluation starting at clock 5) and
at clock ticks 13 and 14 (evaluation starting at clock tick 11). In the case of the second evaluation starting at clock tick
11, the simulator reports only the first completion of the full sequence.

221

SystemVerilog Reference

Assertions

Example 4
It is also possible to declare a repetition with an unlimited range using the $ symbol, for example:
$rose(State==Wait_For_Traffic) ##1 (Traffic_Detected==0)[*1:$] ##1 Traffic_Detected==1

The sequence above describes a situation where the device goes into the Wait_For_Traffic state and waits for
the signal denoting traffic detection. This signal can stay low for any time, until the end of simulation. No time limit is
imposed.

Example 5
sequence TXD_Seq;
@(posedge clk) ($rose(TXD) ##1 TXD[*2] ##1 !TXD[*2])[*3];
endsequence

The sequence ($rose(TXD) ##1 TXD[*2] ##1 !TXD[*2]) is repeated 3 times in the figure above.

Nonconsecutive Repetition
Nonconsecutive repetition specifies finitely many iterative matches of the operand Boolean expression, with a delay of
one or more clock ticks from one match of the operand to the next successive match and no match of the operand
strictly in between. The overall repetition sequence matches at or after the last iterative match of the operand, but
before any later match of the operand.

Example 6
sequence Write_4;
@(negedge clk) (!WR & RD) [=4];
endsequence

The Write_4 sequence describes 4 not necessarily consecutive writes to memory.

There are many sequences with defined (!WR & RD)[=4] repetition in the figure above. The most intuitive are:

222

SystemVerilog Reference
Start Clock

Assertions

Completion Clock

12

13

The sequence (!WR & RD)[=4] can also start or complete at clock cycle, in which expression (!WR & RD) is false:
Start Clock

Completion Clock

10

11

12

12

13

13

14

14

The nonconsecutive repetition can also be defined with a range, either limited or unlimited.

Example 7
sequence Low_Level;
@(posedge clk) IN[=1:3];
endsequence
sequence Medium_Level;
@(posedge clk) IN[=4:6];
endsequence
sequence High_Level;
@(posedge clk) IN[=7:9];
endsequence
sequence Level;
(Low_Level and Level=1) or (Medium_Level and Level=2) or (High_Level and Level=3);
endsequence

223

SystemVerilog Reference

Assertions

The counter counts elements thrown to the container at any time during the simulation. (A high value on the IN signal
denotes the arrival of a new element to a container). The number of these elements is divided into ranges : 0
elements - Level=0, 1-3 elements - Level=1, 4-6 elements - Level=2 and 7-9 elements - Level=3. The sequence
Level describes the correct relation between the number of elements and the Level signal.

Goto Repetition
Goto repetition specifies finitely many iterative matches of the operand Boolean expression, with a delay of one or
more clock ticks from one match of the operand to the next successive match and no match of the operand strictly in
between. The overall repetition sequence matches at the last iterative match of the operand.
The differences between nonconsecutive repetition and goto repetition is, that the sequence with the goto repetition
must always complete on an expression match.

Example 8
sequence Write_4_Goto;
@(negedge clk) (!WR & RD) [->4];
endsequence

The figure above presents Write_4_Goto sequences:


Start Clock

Completion Clock

12

13

12

12

13

13

And operator

224

SystemVerilog Reference

Assertions

The binary operator and is used when both operands are expected to match, but the end times of the operand
sequences can be different. The two operands of and are sequences. Both the operands must match. The operand
sequences start at the same time. When one of the operand sequences matches, it waits for the other to match. The
end time of the composite sequence is the end time of the operand sequence that completes last.

Syntax
sequence_expr ::=
...
| sequence_expr and sequence_expr

Example 1
sequence Count_Down;
@(posedge clk) (Counter == $past(Counter)-1)[*4:8];
endsequence
sequence Start_Seq;
@(posedge clk) $rose(State==Start) ##2 $rose(State==Wait);
endsequence
sequence Count_In_Wait;
StartSeq and CountDown;
endsequence

The sequence Start_Seq starts at clock 2, completes successfully at clock 4 and waits for the sequence
Count_Down. The sequence Count_Down starts at clock 2 and completes successfully at clock 9. The sequence
Count_In_Wait starts at clock 2 and succeeds at clock 9.
The length of the "anded" sequences can be different or it can be the same, but they must start at the same clock
cycle.

Intersect Operator
The binary operator intersect is used when both operand sequences are expected to match, and the end times of the
operand sequences must be the same. The two operands of intersect are sequences. Both the operands must match
and the lengths of the two matches of the operand sequences must be the same.
An attempted evaluation of an intersect sequence can result in multiple matches. The results of such an attempt can
be computed as follows:

225

SystemVerilog Reference

Assertions

1. Matches of the first and second operands that are of the same length are paired. Each such pair results in a
match of the composite sequence, with length and end point equal to the shared length and end point of the
paired matches of the operand sequences.
2. If no such pair is found, then there is no match of the composite sequence.

Syntax
sequence_expr ::=
...
| sequence_expr intersect sequence_expr

Example
sequence Window;
@(posedge clk) $rose(StartEvent) ##[1:$] $rose(StopEvent);
endsequence
sequence Input_Seq;
@(posedge clk) IN0[*2:8];
endsequence
sequence IN0_Window;
Input_Seq intersect Window;
endsequence

The sequence Window can have any length, it is limited only with the appearance of StartEvent and StopEvent.
The length of the sequence Input_Seq is also variable and can take from 2 to 8 clock cycles. The sequence
IN0_Window matches only when Window and Input_Seq have the same length. In the figure above successful
IN0_Window sequence starts at clock cycle 10 and completes at clock cycle 14. The evaluation, which starts at clock
cycle 2 fails at clock cycle 8.

Or Operator
The operator or is used when at least one of the two operand sequences is expected to match. The two operands of
or are sequences.

Syntax
sequence_expr ::=
...
| sequence_expr or sequence_expr

226

SystemVerilog Reference

Assertions

Example

Example 1
sequence Forbidden_Changes_from_Normal;
@(posedge clk) (Normal_State ##1 Red_1_State) or (Normal_State ##1 Red_2_State) or (Normal_State ##1
Yellow_Red_State);
endsequence

The sequence above describes forbidden transactions from one of state of finite state machine in a traffic lights
controller. If any of the three forbidden sequences happen the sequence Forbidden_Changes_from_Normal
matches.

Example 2
sequence Seq_1;
@(posedge clk) (IN0==0 ##2 Data0==8'hff) or (IN1==0 ##1 Data1==8'hff) or (IN2==1 ##2 Data2=8'b0);
endsequence

In example 1 the transitions are mutually exclusive and only one sequence can match. In example 2 all three
sequences used as operands of the or operator can match at the same time. (Obviously, for the or operator it is
enough if only one operand matches.)
If more than one of the or'ed sequences starts evaluating at the same clock cycle (in the figure above this happens in
cycles 1, 5, and 11) and the sequences complete at different times, only the first match will be reported. In other
words, sequence Seq_1 matches, when the first of the or'ed components matches.
For the evaluations started at clock 1 and at clock 2, sequence Seq_1 matches at clock cycle 3. For the evaluation
started at clock 5 the match happens at clock 6, and for the evaluation started at clock 11, at clock cycle 12.

Throughout Operator
The composite sequence, exp throughout seq, matches along a finite interval of consecutive clock ticks provided seq
matches along the interval and exp evaluates to true at each clock tick of the interval. This statement is convenient to

227

SystemVerilog Reference

Assertions

define some condition that must be true while processing a transaction or to define assumptions, under which the
sequence must occur. The equivalent temporal expression for the sequence exp throughout seq is
(exp) [*0:$] intersect seq

Syntax
sequence_expr ::=
...
| expression_or_dist throughout sequence_expr

Example
sequence RXD_Active;
@(posedge XTAL) RXD !== 1'bz throughout (Transmit[*8] ##1 $rose(SEND) );
endsequence

RXD_o data output signal is active during transmission, or otherwise it should have the Z value.

The sequence RXD_Active starts at clock 2 and matches at clock 10 - RXD is active during the sequence
Transmit[*8] ##1 $rose(SEND), then next transmission starts at clock cycle 13 and at the same clock fails
because RXD equals 1'bZ.

Within Operator
The composite sequence seq1 within seq2 matches along a finite interval of consecutive clock ticks provided seq2
matches along the interval and seq1 matches along some subinterval of consecutive clock ticks. The construct seq1
within seq2 is equivalent to the following temporal expression:
(1[*0:$] ##1 seq1 ##1 1[*0:$]) intersect seq2

This construct helps to easily define containment of a sequence within another sequence.

Syntax
sequence_expr ::=
...
| sequence_expr within sequence_expr

228

SystemVerilog Reference

Assertions

Examples
sequence Window;
@(posedge clk) $rose(StartEvent) ##[1:$] $rose(StopEvent);
endsequence
sequence Input_Seq;
@(posedge clk) IN0[*2:8];
endsequence
sequence IN0_Window;
InputSeq within Window;
endsequence

The example 1 includes a similar sequences as the example 1 for the Intersect Operator, but the IN0_Window
sequence includes the within operator instead of the intersect operator. In the within operator, the start point
of the Input_Seq must be no earlier than the start point of the Window sentence and the end point of the
Input_Seq must be no later than the end point of the Window sentence. (In the intersect operator, both
sequences must start and end at the same time.)
In the figure above sequence IN0_Window matches twice, at clock 8 and 14.
Sequence Window starts at clock 2 and completes at clock 8, InputSeq also starts at clock 2 and completes at clock
7. Therefore, InputSeq is contained within Window. (It does not intersect with Window because the intersect
operator, contrary to the within operator, requires that both sequences start and complete at the same time.)
Sequence Window starts again at cycle 10 and completes at cycle 14, InputSeq starts later than Window, at clock
cycle 12 and completes earlier than Window, at clock 14. InputSeq is again contained within Window.

First_match Operator
Some of the sequence operators, for instance ##[N:M] or [*N:M] are able to generate multiple matches for a single
sequence start point. The first_match operator discards all sequence matches except the first one. This is
especially useful for the implication operator which by default checks if for all matches on the left-hand side (LHS)
sequence the right-hand side (RHS) property holds. By using the first_match implication, the operator can be
restricted to check just the first match of LHS. For more information, see 16.9.8 in IEEE Std 1800-2012.

Example
module m;
reg clk=0;
always #10 clk=!clk;
reg req=0, data=0, ack=0;
initial begin

229

SystemVerilog Reference
repeat(2)@(negedge
req=1;
@(negedge clk) ;
req = 0;
repeat(3)@(negedge
data=1;
repeat(4)@(negedge
data=0;
repeat(4)@(negedge
$finish;
end

Assertions

clk) ;

clk) ;
clk) ;
clk) ;

initial begin
repeat(7)@(negedge clk) ;
ack=1;
@(negedge clk);
ack=1;
@(negedge clk);
ack=0;
end;
check_req_fm: assert property(@(posedge clk) first_match(req ##[1:$] data) |=> ack);
check_req: assert property(@(posedge clk) (req ##[1:$] data) |=> ack);

endmodule

The assertion check_req_fm tests the following scenario: if the asserted req object is followed by the asserted
data object then the assertion checks if the ack is asserted one clock cycle later. The first_match operator on the
LHS of the implication guarantees that the acknowledge ack is checked only when the data bit is asserted for the first
time. All subsequent clock cycles where the data bit is asserted are ignored. Such case is presented in the figure
below.

Figure 1. The check_req_fm assertion with the first_match operator and the check_req assertion without the
operator.

End Point of a Sequence


The end point of a sequence is reached whenever the ending clock tick of a match of the sequence is reached,
regardless of the starting clock tick of the match. The reaching of the end point can be tested by using the method
triggered.
The result of triggered operation is true or false. When method triggered is evaluated in an expression, it tests
whether its operand sequence has reached its end point at that particular point in time. The result of triggered does
not depend upon the starting point of the match of its operand sequence.
The ending clock of the sequence instance to which triggered is applied must be the same as the clock in the
context where the application of method triggered appears.

230

SystemVerilog Reference

Assertions

Syntax
sequence_instance.triggered

Example
sequence Sending;
@(posedge XTAL) $rose(SEND) ##1 SEND[*7] ##1 $fell(SEND);
endsequence
sequence TI_Pulse;
@(posedge XTAL) !TI[*9] ##1 Sending.triggered ##0 $rose(TI) ##2 $fell(TI);
endsequence

TI signal is low and when the sending finishes it is set for two clock cycles and then drops again to zero. In the
TI_Pulse sequence only the point of the completion of the Sending sequence is important so the method
triggered is used.

The evaluation of TI_Pulse sequence starts at first clock cycle, TI is low for 9 cycles, in the next clock is a check if
the Sending sequence is completed, in the same clock cycle the signal TI rises, is high in the next clock cycle and
drops to zero.
The behavior described by the sequence
@(posedge XTAL) !TI[*9] ##1 Sending ##0 $rose(TI) ##2 $fell(TI)

(without the triggered method) is shown in the figure below:

The evaluation of the TI_Pulse sequence starts at first clock cycle, TI is low for 9 cycles and then in the next clock
cycle starts evaluation Sending sequence, after 9 clock cycles Sending sequence is completed and TI rises.
NOTE: IEEE Std 1364-2005 defined the two keywords corresponding to the current meaning of the triggered
keyword: triggered and ended. The ended keyword applied to the sequence method to which currently the
triggered word applies, and the triggered keyword was used in the other contexts. In the IEEE Std 1800-2009
standard, the triggered keyword is allowed to be used in the sequence context and the ended keyword is
deprecated. In the default compilation (the IEEE Std 1800-2009 mode), the ended method is allowed, but it triggers a
warning message informing that the method is obsolete. You may enforce the strict LRM mode (the -j argument for
the alog command) to block the compilation of the code containing the ended keyword or use the -v2k5 argument
to work in the IEEE Std 1364-2005 compatibility mode.

231

SystemVerilog Reference

Assertions

NOTE: Using the triggered sequence method in the procedural context (e.g. in the wait statement inside the
begin...end block) is not supported yet.

End Point of a Sequence in Multiclock Context


Detecting the end point of a sequence when the clock of the source sequence is different from the destination
sequence is possible via the method matched used on the source sequence. The end point of a sequence is reached
whenever there is a match on its expression.
The matched method returns true or false. Unlike triggered, matched uses synchronization between the two
clocks, by storing the result of the source sequence match until the arrival of the first destination clock tick after the
match. The result of matched does not depend upon the starting point of the source sequence.

Syntax
sequence_instance.matched

Example
sequence Sending;
@(posedge XTAL) $rose(SEND) ##1 SEND[*7] ##1 $fell(SEND);
endsequence
sequence TI_Pulse;
@(posedge SysClk) !TI[*3] ##1 Sending.matched ##0 $rose(TI) ##2 $fell(TI);
endsequence

The Sending sequence is completed at tick 10 of the XTAL clock. The evaluation of the TIPulse sequence starts at
the first tick of clock SysClk, then TI is low for the first 3 cycles of the SysClk clock. There is a check if Sending
sequence is completed in the next SysClk cycle (cycle 4). In the same cycle TI rises and is high for the next SysClk
cycle, then drops at the 6-th SysClk clock. This completes the TI_Pulse sequence.

Using Dynamic Variables in a Sequence


SystemVerilog allows declarations of variables which are local to and used within a particular transaction check that
can span an arbitrary interval of time and can overlap with other transaction checks. Such variables can be declared
inside a named sequence or property or can be a formal argument in a sequence declaration.

232

SystemVerilog Reference

Assertions

Assertion Variables Declared in a Named Sequence or Property


Local variables can be declared in a declarative part of a sequence or a property.

Declaration Syntax
sequence_declaration ::=
sequence sequence_identifier [ ( [ sequence_port_list ] ) ] ;
{ assertion_variable_declaration }
sequence_expr ;
endsequence [ : sequence_identifier ]
property_declaration ::=
property property_identifier [ ( [ property_port_list ] ) ] ;
{ assertion_variable_declaration }
property_statement_spec
endproperty [ : property_identifier ]
assertion_variable_declaration ::= var_data_type list_of_variable_decl_assignments ;

The data type of the local variable must be one of the types allowed within assertions. The initial value of the local
variable can be applied using the declaration assignment. The initial expression need not be constant.
A new copy of a local variable is created at the beginning of each evaluation of an instance of a named sequence or
property.
The initialization assignment is executed (if present) in the Observed region, the variables are initialized in the order
that they appear in the sequence or property declaration.
If non-local variables are used in the local variable initialization expression then the Preponed values of non-local
variables from the time slot in which the evaluation attempt begins are used.
Local variables do not have default initial values. If a local variable is declared without an initialization assignment it is
unassigned at the beginning of the evaluation attempt.
Local variables can be assigned and re-assigned within the body of the sequence or property where they are
declared, in the sequence match item.
sequence s1;
int x=0;
@(posedge clk) (a,x=1) ##1 (b,x++)[*2:4]
endsequence

##1 (x>=3)&&(x<=5);

Assignment Syntax
sequence_expr ::= // from A.2.10
...
| ( sequence_expr {, sequence_match_item} ) [ sequence_abbrev ]
...
sequence_match_item ::=
operator_assignment
| inc_or_dec_expression
| subroutine_call

233

SystemVerilog Reference

Assertions

The local variable assignments are performed in the order that they appear in the list specified in a sequence match
item at the end of any non-empty match of the subsequence.
It is not allowed to attach a local variable assignment to a subsequence that can have an empty match, for example
(a[*0:1],x=1).
Local variables cannot be referenced outside the sequences of properties where they are declared. They are not
visible in the context where the sequence or property is instantiated.
It is not allowed to reference a local variable after the point from which it does not flow until after it has again been
assigned a value.
Local variable bit-selects and part-selects can be used in expressions. Local variables can be also used as array
indices.

Local Variable Flow out Rules


Variables assigned on parallel threads cannot be accessed in sibling threads.
sequence s3;
int x;
@(posedge clk) (a ##1 (b, x = data) ##1 c) or (d ##1 (e==x)); // illegal
endsequence

If a composite sequence includes an or operator, the local variable flows out of this sequence if it flows out
from each of the operand sequences. If the local variable is not assigned before the start of the composite
sequence and it is assigned in only one of the operand sequences, then it does not flow out of the composite
sequence.
sequence s4_i;
bit x;
@(posedge clk) (a ##1 (b,x=1)) or (c ##1 d) ##1 (e>=x);
endsequence

// illegal

sequence s4;
bit x;
@(posedge clk) (a ##1 (b,x=1)) or (c ##1 (d,x=0)) ##1 (e==x); // legal
endsequence

Each thread for an operand of an or that matches its operand sequence continues as a separate thread. Each
thread has its own local variables values, not necessary consistent to other threads variables.
If a composite sequence includes an and/intersect operator the local variable flows out of this sequence if it
flows out of at least one operand of the composite sequence unless it is blocked. A local variable is blocked if
The local variable is assigned in and flows out of each operand of the composite sequence, or
The local variable is blocked from flowing out of at least one of the operand sequences.
sequence s5;
reg x;
@(posedge clk) ((a ##1 (b,x=1)) and (c ##1 d)) ##1 (e>=x); // legal
endsequence
sequence s5_i;
reg x;
@(posedge clk) (a ##1 (b,x=1)) and (c ##1 (d,x=0)) ##1 (e==x); // illegal
endsequence

234

SystemVerilog Reference

Assertions

Calling Subroutines on Match of a Sequence


A successful, non-empty sequence match can trigger a subroutine call. The subroutine call must appear in the comma
separated list that follows the sequence. The subroutine is said to be attached to the sequence, for example:
sequence s1;
@(posedge CLK)
(REQ ##[4:16] GNT, $display( "Sequence matched at time %0t.", $time ));
endsequence

The sequence and the list must be enclosed in parentheses.


It is possible to pass arguments to a subroutine call, either by value as input or by reference.
task t( int linenum );
$display( "Sequence in line %0d matched at time %0t.", linenum, $time );
endtask
sequence s2;
@(posedge CLK)
(REQ ##[4:16] GNT, t( `__LINE__ ));
endsequence

Local sequence variables must be passed by value.


task automatic t( int d );
$display( "Matched at time %0t for data = %0d.", $time, d );
endtask
sequence s3;
int tmp;
( A ##1 (!A, tmp = DIN) ##1 !B[*0:15] ##1 B && (DOUT == tmp), t( tmp ));
endsequence

235

SystemVerilog Reference

Assertions

Properties

Property Declaration
A property describes design behavior. The property declaration is more extensive than the sequence declaration and
describes more complex temporal relations between events.
A property can be declared in a module, in an interface, in a program, in a clocking block, a package and in a
compilation-unit scope.
A property can be used for verification as an assumption - with assume directive, as a checker - with assert directive,
or as a coverage specification - with cover directive. A property declaration by itself does not produce any result.
The result of a property is true or false.
The simplest property can be Boolean expression or the simplest sequence.

Syntax
property_declaration ::=
property property_identifier [ ( [ property_port_list ] ) ] ;
{ assertion_variable_declaration }
property_spec [ ; ]
endproperty [ : property_identifier ]
property_port_list ::=
property_port_item {, property_port_item}
property_port_item ::=
{ attribute_instance } [ local [ property_lvar_port_direction ] ] property_formal_type
formal_port_identifier {variable_dimension} [ = property_actual_arg ]
property_lvar_port_direction ::= input
property_formal_type ::=
sequence_formal_type
| property
property_spec ::=
[clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr

Example 1
property Data_Low_Limit;
@(posedge Clk) Data>=4'b0011;
endproperty
property HndShk;
@(posedge Clk) Req ##2 Ack;
endproperty

236

SystemVerilog Reference

Assertions

Property Instance
A named property can be instantiated in another property, but with one restriction. The instantiated property cannot
include a reset expression (disable iff statement). The possibility of creating property instances allows you to
easily build complex properties and facilitates code maintenance.

Example 2
In the below example, the listed properties Start_Seq, Rd_Transaction, Wr_Transaction, Stop_Seq can be
instantiated in other properties. If any changes to the listed properties are necessary, only their declarations need to
be changed. The code where the properties are instantiated does not need to be touched.
sequence Start_WR;
@(posedge clk) $fell(WR);
endsequence
sequence Start_RD;
@(posedge clk) $fell(RD);
endsequence
property Valid_Addr;
@(posedge clk) ~RD|~WR |-> Addr<8'hc;
endproperty
property RD_Transaction;
@(posedge clk) (!RD && Data==OUT1)[*4];
endproperty
property WR_Transaction;
@(posedge clk) (!WR && Data==IN1)[*4];
endproperty
property Full_RD_Transaction;
@(posedge clk) Start_RD |-> ##[1:$] RD_Transaction ;
endproperty
property Full_WR_Transaction;
@(posedge clk) Start_WR |-> ##[1:$] WR_Transaction ;
endproperty
property No_Idle_Mode;
@(posedge clk) ~Idle |->
endproperty

Full_RD_Transaction or Full_WR_Transaction;

Reset Expression
property_spec ::= [clocking_event ] [ disable iff ( expression_or_dist ) ] property_expr

The expression of the disable iff in a property_spec is called the reset expression. It is tested independently
for different evaluation attempts of the property_spec. If the reset expression becomes true, the overall evaluation
of the property_spec is true, even if the evaluation of property_expr is not finished or failed. If the reset
expression is false the evaluation of property_spec is the same as that of the property_expr.
Nesting of disable iff clauses, explicitly or through property instantiations, is not allowed.
If a sampled value function is used in the reset expression, the sampling clock must be explicitly specified in its actual

237

SystemVerilog Reference

Assertions

argument list. The sequence methods matched and triggered and local variables cannot be used in the reset
expression.
For more clarity, the simulator can print special "DISABLED" messages when the reset expression becomes true and
the whole property_spec is also true. To see "DISABLED" messages, use the -dbg argument for compilation and
enable pass messages using the following command:
assertion pass -enable -log on

Example 3
property Not_To_Early_Ack;
@(posedge Clk) disable iff (!Rst) $rose(Req) |-> !Ack[*1:3] ##1 $rose(Ack);
endproperty

The acknowledge Ack cannot appear earlier than 4 clock cycles after request Req. If reset signal becomes low the
whole property Not_To_Early_Ack is disabled (true).

In the figure above the evaluation of the property starts at clock 1 and succeeds at clock 5 - Ack is true 4 clock cycles
after Req, then the evaluation starts at clock 7 and fails at clock 9 - active Ack happens too early. The next evaluation
starts at clock 11, at the negative edge of the clock 12 the Rst signal drops to zero and makes the property true
(without reset it would fail because Ack happens too early). The simulator reports the DISABLED message at the
negative edge of the reset signal and then at the active clock (posedge Clk).

Parameterized Properties
A property can be declared with formal arguments (typed and untyped). Such a parameterized property can be
instantiated with actual arguments, which can be any of the following:
literal
identifier
expression
event control expression
sequence expression
property expression
the $ symbol
The data types allowed in the expressions are denoted in the Boolean Expressions section.

238

SystemVerilog Reference

Assertions

Untyped Arguments
A formal argument is said to be untyped if there is no type specified for the given argument in the property declaration
or the untyped keyword is used. The type of the references to the untyped formal argument is determined by the
type of the actual argument.

Example 4
The below example, shows how the untyped arguments can be used to create generic properties thanks to the fact
that the types are not specified in the property declaration. These properties are then used to rewrite the declarations
from the Example 2.
The parameterized property CondCheck declares behavior that the scheme statement is tested if the condition
statement is true. The both arguments: condition and scheme are untyped, so the actuals can be of any type. The
RepeatScheme sequence executes the sequence specified with the scheme argument the number of times specified
with the number argument. As in the case of the CondCheck property, the both arguments of the RepeatScheme
sequence are untyped.
property CondCheck(condition,scheme);
@(posedge clk) condition |-> scheme;
endproperty
sequence RepeatScheme(scheme,number);
@(posedge clk) scheme [*number] ;
endsequence

The properties Valid_Addr, Full_RD_Transaction, Full_WR_Transaction and No_Idle_Mode from the


Example 2 can now be declared using the CondCheck and RepeatScheme statements.
In the below declaration of the Valid_Addr property, the actual arguments of the CondCheck property are the
boolean expressions.
property Valid_Addr;
CondCheck(~RD|~WR,Addr<8'hac);
endproperty

In the Full_RD_Transaction declaration, the actual arguments of the CondCheck property for the condition
and the sequence formals are a sequence and a parameterized sequence, respectively.
property Full_RD_Transaction;
CondCheck(Start_RD,RepeatScheme(!RD && Data==OUT1,4));
endproperty

In the Full_WR_Transaction property declaration, the actual arguments of the CondCheck property for the
condition and the scheme formals are a boolean expression returned by a function call and a sequence
expression, respectively.
property Full_WR_Transaction;
CondCheck($fell(WR),(!WR && Data==IN1)[*4]);
endproperty

In the No_Idle_Mode declaration, the subsequent actuals for the CondCheck property are boolean and property
expressions.
property No_Idle_Mode;
CondCheck(~Idle,Full_WR_Transaction or Full_RD_Transaction);

239

SystemVerilog Reference

Assertions

endproperty

Typed Arguments
The types of formal arguments can be explicitly specified in the property declaration. The arguments can be one of the
following types:
data type (the allowed types are denoted in the Boolean Expressions section)
event
sequence
property
The typed arguments restricts the use of a property to the specified types.

Example 5
In the following example, the CondCheck property and the RepeatScheme sequence from Example 4 are declared
using the typed arguments.
property CondCheck(logic condition,property scheme);
@(posedge clk) condition |-> scheme;
endproperty
sequence RepeatScheme(sequence scheme,shortint number);
@(posedge clk) scheme [*number] ;
endsequence
assert property(CondCheck(WR[*4],nexttime(Data==IN1))); // Error: WR[*4] sequence used instead of logic
assert property(CondCheck(!WR,nexttime(Data==IN1)));
// OK: !WR expression is of the logic type
assert property(RepeatScheme(Ack ##1 !Ack,2));

Local Variable Formal Arguments


The rules for the local variable formal arguments of the properties and their corresponding actual arguments are the
same as the rules pertaining to the local variable formal arguments of the sequences, except for the following
difference: the only allowed direction of the local variable formal argument of the property is input. It is illegal to
specify the output or inout direction.

Property Operators
There are several operators that can be used with properties to describe more complex design features.

Syntax
property_expr ::=
sequence_expr
| ( property_expr )
| not property_expr

240

SystemVerilog Reference
|
|
|
|
|
|
|

Assertions

property_expr or property_expr
property_expr and property_expr
sequence_expr |-> property_expr
sequence_expr |=> property_expr
if ( expression_or_dist ) property_expr [ else property_expr ]
property_instance
clocking_event property_expr

Property Operator Precedence

Sequence
operators

Property
operators

Associativity

[*], [=], [->]


##

Left

throughout

Right

within

Left

intersect

Left
not

and

and

Left

or

or

Left

if...else

Right

|->, |=>

Right

Not Operator
Negation of a property is used when the property describes an undesirable behavior.
The negation has the following form:

Syntax
not property_expr

The keyword not states that the evaluation of the property returns the opposite of the evaluation of the underlying
property_expr. Thus, if property_expr evaluates to true, then not property_expr evaluates to false; if
property_expr evaluates to false, then not property_expr evaluates to true.

Example
property EN_Pulse_1;
@(posedge clk) (En[*2:$]);

241

SystemVerilog Reference

Assertions

endproperty
Check_Max_EN_Length: assert property (not EN_Pulse_1);

The property checks if EN remains high for longer than one clock cycle.

The assertion Check_Max_EN_Length fails at clock 7 and at clock 12 because the En pulse is longer than 1 clock
cycle.

And Operator
The and operator is used to define a conjunction of a properties.

Syntax
property_expr1 and property_expr2

The property evaluates to true if, and only if, both property_expr1 and property_expr2 evaluate to true.

Example
The following properties describe the implementation of an LRC (longitudinal redundancy check) module.
The LRC check is performed for each record cycle (CMP=1). If the calculated LRC is not equal to the LRC read from
data downloaded data (CMPR==0), the ERR output turns HIGH until the next LRC check.
property LRCErrDurationProp;
@(posedge clk) disable iff (CLR) !CMPR && CMP |=> (ERR[*1:$] ##1 !ERR && CMP);
endproperty

Property CmprLogicProp is used for the comparator submodule:


property CmprLogicProp;
@(posedge clk) (CMPR === &(~LRCC ^ LRCR));
endproperty

Reading LRC from input : (High and Low byte) control


property RLCLEProp;
@(posedge clk) (LRCLE==2) |-> ##2 (LRCLE==1);
endproperty

LRC general check using the and operator:


property LRCProp;
LRCErrDurationProp and CmprLogicProp and RLCLEProp;
endproperty

242

SystemVerilog Reference

Assertions

CheckLRC: assert property (LRCProp) else $error("LRC module works incorrectly");

If any of properties LRCErrDurationProp, CmprLogicProp and RLCLEProp fails at any time during simulation the
CheckLRC assertion reports a failure.

Or Operator
The or operator is used to define a disjunction of a properties.

Syntax
property_expr1 or property_expr2

The property evaluates to true if, and only if, at least one of property_expr1 and property_expr2 evaluates to
true.

Example
property Connect_When_Send;
@(posedge XTAL) SEND |-> RXD_o == SBUF_o[0];
endproperty
property Connect_When_Receive;
@(posedge XTAL) RECEIVE |-> RXD_o == SI;
endproperty
property Disconnect;
@(posedge XTAL) !SEND && !RECEIVE |-> RXD_o === 1'bz;
endproperty
property Connect_RXD;
@(posedge XTAL) Connect_When_Send or Connect_When_Receive or Disconnect;
endproperty
Check_Connect_RXD : assert property (Connect_RXD);

RXD output in a buffer device is connected to SBUF output register during sending, to serial input SI during receiving
or has value Z when there is no transmission. Only one property from the properties Connect_When_Send,
Connect_When_Receive, Disconnect should be successful in one time for the correct behavior of the RXD port.

Implication Operators
The implication statement is used to precondition monitoring of a property expression. The result of the implication is
either true or false.

Syntax
property_expr ::= ...
| sequence_expr |-> property_expr
| sequence_expr |=> property_expr

243

SystemVerilog Reference

Assertions

From a given start point, the left sequence_expr can have zero, one, or more than one successful match.
If there is no match of the left sequence_expr from a given start point, then evaluation of the implication from that
start point succeeds vacuously and returns true.
For each successful match of left sequence_expr, the right property_expr is separately evaluated. The end point
of the match of the left sequence_expr is the start point of the evaluation of the right property_expr.
From a given start point, evaluation of the implication succeeds and returns true if, and only if, for every match of the
left sequence_expr beginning at the start point, the evaluation of the right property_expr beginning at the end
point of the match succeeds and returns true.
Two forms of implication are provided: overlapped using operator |-> and nonoverlapped using operator |=>.
sequence_expr |=> property_expr

is equivalent to the following:


sequence_expr ##1 'true |-> property_expr

Examples

Example 1
property RI_Seq;
@(posedge clk) $rose(RECEIVE) ##1 RECEIVE[*7] ##1 $fell(RECEIVE) |-> $rose(RI);
endproperty

Received flag is set when receiving transaction is completed.

In the figure above the evaluation of RI_Seq starts at first clock, but because there is no rising edge of RECEIVE
signal the evaluation succeeds vacuously. The next evaluation starts at clock 2 and the positive edge of RECEIVE is
detected - the evaluation of the left (antecedent) sequence is successfully completed at clock 10. This causes the
check of the right (consequent) side of the implication operand - the rising edge of RI signal is detected and the whole
property holds. At the next clock cycle shown in the figure the property holds vacuously because there has been no
rising edge on the RECEIVE signal.

Example 2
property RI_Seq_1;
@(posedge clk) $rose(RECEIVE) ##1 RECEIVE[*7] ##1 $fell(RECEIVE) |=> $rose(RI);
endproperty

244

SystemVerilog Reference

Assertions

RI_Seq_1 includes nonoverlapped operator |=>. This causes that the rising edge of the RI signal is checked one
clock after a successful completion of the left sequence. This situation is shown in the figure below.

Implies Operator
The property evaluates to true if, and only if, either property_expr1 evaluates to false or property_expr2
evaluates to true.

Syntax
property_expr1 implies property_expr2

If property_expr1 result is false, the implies operator returns true. If property_expr1 result is true,
property_expr2 is evaluated immediately after the evaluation of property_expr1, that is, in the same simulation
time in which the property_expr1 evaluation is completed.

Example
If the left-hand side(LHS) expression of the below property is false, the property returns the value true and the
assertion r passes vacuously. Otherwise, the evaluation of the right-hand side(RHS) expression begins. Since the
LHS operand contains the cycle delay operator (##), the evaluation of the LHS expression lasts one clock cycle. The
RHS evaluation begins after the LHS evaluation completion, so the expressions are evaluated in different simulation
times.
property p;
(a ##1 b) implies (c ##1 d);
endproperty
r: assert property (p);

The example shows how the above property is evaluated when it is applied to the code below. The values for the
property are sampled in the preponed region, that means, if a signal changes in a particular time, the sampled value is
a value that signal had before a value change.
reg clk = 0;
always #5 clk = ~clk;
default clocking @(posedge clk);
endclocking
reg a,b,c,d;
initial begin
a = 1; b = 0; c = 1;
@(posedge clk);

d = 1;

245

SystemVerilog Reference

Assertions

c = 0;
@(posedge clk);
b = 1; c = 1;
repeat (2) @(posedge clk);
d = 0;
repeat (2) @(posedge clk);
d = 1;
end
initial #70 $finish;

The figure below shows the waveform for the assertion r and for the signals a, b, c, and d used in the p property
expression.

The signal values for an assertion check that begins in the 5 time unit are as follows:
time
5
15
15
25

signal value
a is 1
b is 1 from 0
c is 1 from 0
d is 1

a ##1 b is false

The value a at the 5 unit is 1 and the value b at the 15 unit changes from 0 to 1. Hence, the preponed value of b is 0
and the a ##1 b expression, which is evaluated as the logical and function of preponed a and b values in specified
simulation time, is false. The property evaluates to true without checking the RHS expression, and the assertion
passes vacuously.
In the 15 simulation unit, the values of signals in the assertion property expression are as follows:
time
15
25
25
35

signal value
a is 1
b is 1
c is 1
d is 0 from 1

a ##1 b is true
c ##1 d is true

The true value of the LHS expression does not determine the implies operator result, and, therefore, the RHS
expression has to be evaluated. The RHS evaluation begins in the time of the LHS evaluation completion (25 time
unit) and evaluates to true, since the preponed values of the both: c and d signals are 1. If the RHS expression is
true, the implies operator evaluates to true and the assertion r passes nonvacuously.
The preponed signal values used to evaluate the assertion property in the 25 time unit are:
time
25
35
35

signal value
a is 1
b is 1
c is 1

a ##1 b is true

246

SystemVerilog Reference
45

d is 0

Assertions
c ##1 d is false

The preponed signal values used to evaluate the assertion property from the 35 time unit are:
time
35
45
45
55

signal value
a is 1
b is 1
c is 1
d is 1 from 0

a ##1 b is true
c ##1 d is false

For the assertion checks from 25 and 35 time units, the implies operator returns false and the assertion r fails,
since in both assertion checks neither the LHS operand is false nor RHS is true.

iff Property
The property iff evaluates to true, if either both property_expr1 and property_expr2 evaluates to false or both
property_expr1 and property_expr2 evaluates to true.

Syntax
property_expr1 iff property_expr2

Example
property p;
!b[*2] iff ##[4:8] c;
endproperty

The property evaluates to true if either the b signal holds the 0 value during two subsequent clock ticks and the c
signal holds the value 1 within the [4:8] cycle range or there are no two subsequent clock ticks in which the b signal
is 0 and the c signal does not hold the 1 value within the specified range.
NOTE: The iff operator is supported only for boolean expressions in this release. Please contact Aldec Support to
receive the latest status.

Followed-by Property
The followed-by property evaluates to true if there is at least one successful evaluation of the first expression followed
by a successful evaluation of the second expression.

Syntax
The followed-by property evaluates to true if the sequence_expr has at least one successful match and the
property_expr evaluates to true starting from the end point of some successful evaluation of the sequence_expr
expression.

247

SystemVerilog Reference

Assertions

property_expr ::= ...


| sequence_expr #-# property_expr
| sequence_expr #=# property_expr

There are two forms of the followed-by property: the overlapped and non-overlapped indicated by the #-# and #=#
operators, respectively. The difference between these two forms lies in the time considered as the start point of the
property_expr evaluation. For the overlapped property, the property_expr evaluation start point is the end point
of the sequence_expr evaluation and for the non-overlapped property is the next clock tick after the end point of the
sequence_expr evaluation.

Examples
The property p1 contains the overlapped following-by operator, which means that the evaluation of the right-hand side
expression will start at the same clock tick in which the successful evaluation of the left-hand side expression has
ended. The p1 property is evaluated to true if the following sequence of events occurs: b is 1 after one clock tick since
the time when a was 1, and in the same clock tick begins another sequence in which d is 1 after two clock ticks since
the time when c was 0.
property p1;
(a ##1 b ) #-# ( !c ##2 d);
endproperty

The following property contains the non-overlapped following-by operator, which means that the evaluation of the
right-hand side expression will start in the next clock tick after the successful evaluation of the left-hand side
expression. The signal values are checked at positive edges of the clock signal clk. The left-hand side expression
will be evaluated to true if the sequence: a is equal 1 followed by b is equal 0 is repeated twice. The right-hand side
expression, whose successful evaluation has to be started at the next clock tick, says that if c is true then d must hold
during two cycles starting with the cycle in which c is true. If c is false, then the right-hand side expression is true
regardless of the d value.
property p;
@(posedge clk) (a ##1 !b)[*2] #=# (c |=> d[*2]);
endproperty

always, nexttime, and eventually Properties

always Property

Syntax
The always property evaluates to true when the expression following the always keyword evaluates to true in the
current and every future clock ticks. There are three variants of the always property:

weak always property


The property evaluates to true if, and only if, property_expr holds at every current or future clock tick.
always property_expr

ranged form of always property

248

SystemVerilog Reference

Assertions

The property evaluates to true if, and only if, property_expr holds at every current or future clock ticks that
are within the range of clock ticks specified by constant_range. It is not required that all clock ticks within
this range exist.
always [constant_range] property_expr

ranged strong form of s_always property


The property evaluates to true if, and only if, all current or future clock ticks specified by constant_range
exist and property_expr holds at each of these clock ticks.
s_always [constant_range] property_expr

Complete description: Language Reference Manual IEEE 1800-2012, 16.13.11

Example
The p1 property evaluates to true providing that if b and the value of c occurring after two clock ticks after b are true
or a is true, then d will be false at every clock tick until the simulation end.
property p1;
(a or b ##2 c) |=> always !d;
endproperty

The p2 property evaluates to true, if the property nexttime(c) holds in the range that begins after two clock ticks
from the time when property a ##1 b was evaluated to true and lasts until the simulation end. To the successful
evaluation, it is not required that all clock ticks within the range exist.
property p2;
@(posedge clk) (a ##1 b) |=> always[2:$](nexttime(c));
endproperty

The p3 property evaluates to true if all clock ticks specified by the range [3:7] exist and the a property is true at
each clock tick occurrence in the specified range.
property p3;
s_always [3:7] a;
endproperty

nexttime Property

Syntax
The nexttime property is true when the property following the nexttime keyword evaluates to true in the next clock
tick or in a specified future clock. There are four variants of the nexttime property:

weak nexttime property


The property evaluates to true if, and only if, either property_expr evaluates to true beginning at the next
clock tick or there is no further clock ticks.
nexttime property_expr

249

SystemVerilog Reference

Assertions

indexed weak nexttime property


The property evaluates to true if, and only if, either there are not const_expr clock ticks or property_expr
evaluates to true beginning at the last of the next const_expr clock ticks.
nexttime [const_expr] property_expr

strong nexttime property


The property evaluates to true if, and only if, there exists a next clock tick and property_expr evaluates to
true beginning at that clock tick.
s_nexttime property_expr

indexed strong nexttime property


The property evaluates to true if, and only if, there exist const_expr clock ticks and property_expr
evaluates to true beginning at the last of the subsequent const_expr clock ticks.
s_nexttime [const_expr] property_expr

Complete description: Language Reference Manual IEEE 1800-2012, 16.13.10

Example
The p1 property evaluates to true if the a property is true at every positive clock edge beginning with the next edge or
there are no further positive clock edges.
property p1;
@(posedge clk) nexttime always a;
endproperty

The p2 property evaluates to true in a given simulation time if the property a evaluates to true at the second clock tick
counting from that simulation time or there is no clock ticks during the two forthcoming clock signal periods.
property p2;
nexttime[2] a;
endproperty

The p3 property evaluates to true if the next clock tick exists and the property a evaluates to true at the beginning of
that clock tick.
property p3;
s_nexttime a;
endproperty

The p4 property evaluates to true if clock ticks exist in the three forthcoming time units and the property a evaluates to
true at the beginning of the last of these clock ticks.
property p4;
s_nexttime[3] a;
endproperty

250

SystemVerilog Reference

Assertions

eventually Property

Syntax
The eventually property evaluates to true if there exists at least one current or future clock tick in which the
property expression following the eventually keyword evaluates to true. There are three variants of the
eventually property:

strong eventually property


The property evaluates to true if there exists a current or future clock tick at which property_expr evaluates
to true.
s_eventually property_expr

ranged weak eventually property


The property evaluates to true if, either there exists a current or future clock tick within the range specified by
constant_range at which property_expr evaluates to true or not all the current or future clock ticks
within the range specified by constant_range exist. The range for a strong eventually cannot be
unbounded.
eventually [constant_range] property_expr

ranged strong eventually property


The ranged strong eventually property s_eventually [cycle_delay] property_expr evaluates to
true if, and only if, there exists a current or future clock tick within the range specified by cycle_delay at
which property_expr evaluates to true. The range for a strong eventually may be unbounded.
s_eventually [cycle_delay] property_expr

Complete description: Language Reference Manual IEEE 1800-2012, 16.13.13

Example
The p1 property evaluates to true if, and only if, there exists a current or a future clock tick in which the sequence: the
true value on the a signal followed by the false value on the signal b occurs.
sequence s1;
@(posedge clk) a ##1 !b;
endsequence
property p1;
@(posedge clk) s_eventually s1;
endproperty

The p2 property evaluates to true, if there exists at least one positive edge of the clk signal for which the property
p2a is true in the specified [2:5] range, that is, if the a property holds the 0 value until the b variable is 1. or not all
the clock ticks within the range exist.
property p2a;
@(posedge clk) !a until b;
endproperty
property p2;

251

SystemVerilog Reference

Assertions

@(posedge clk) eventually [2:5] p2a;


endproperty

The p3 property evaluates to true in a given simulation time if there exists at least one clock tick in which the p3a
property is true in the range from the second clock tick after that simulation time to the simulation end.
property p3a;
@(posedge clk) a ##1 b |=> c;
endproperty
property p3;
@(posedge clk) s_eventually [2:$] p3a;
endproperty

If Else Statement
An if-else property syntax:
if (expression_or_dist) property_expr1

or
if (expression_or_dist) property_expr1 else property_expr2

In the first case the if property evaluates to true if expression_or_dist is false or when expression_or_dist is
true together with property_expr1. In the second case the property evaluates to true if expressions_or_dist is true
together with true property_expr1 or when expression_or_dist is false together with true property_expr2.

Example
sequence Start;
@(posedge clk) IN_0 ##1 !IN0;
endsequence
property Check_Start;
@(posedge clk)
if (!Strobe)
Start
else
Wait == 2'b00;
endproperty

Case Statement
The case property statement tests whether a Boolean expression matches any of the specified case items and
executes the statement associated with the case item that matches.

Syntax
property_expr ::=
...
| case ( expression_or_dist ) property_case_item { property_case_item } endcase
...

252

SystemVerilog Reference

Assertions

property_case_item ::=
expression_or_dist { , expression_or_dist } : property_expr [ ; ]
| default [ : ] property_expr [ ; ]

The default item is optional. If none of the case items match and the default item is specified, then the default property
statement is executed. If none of the case items match the expression and the default item is not specified, the case
property statement succeeds and returns true (vacuously).

Example
In the following example, the overlapped implication operator (|->) is used in the expression if the mode value is 0, or
the nonoverlapped operator (|=>), if the mode value is 1. If the mode variable has a different value, the m_select
property returns 0.
property m_select(logic [1:0] mode);
case (mode)
2'b0 : (a ##1 b) |-> (!c ##1 d);
2'b1 : (a ##1 b) |=> (!c ##1 d);
default: 0;
endcase;
endproperty

Recursive Properties
NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

Abort Properties
The following abort properties are available in SystemVerilog
accept_on ( expression_or_dist ) property_expr
reject_on ( expression_or_dist ) property_expr
sync_accept_on ( expression_or_dist ) property_expr
sync_reject_on ( expression_or_dist ) property_expr

If during the evaluation of properties with accept_on and sync_accept_on operators, the abort condition becomes
true, then the overall evaluation of the property results in true. Otherwise, the overall evaluation of the property is
equal to the evaluation of the property_expr.
If during the evaluation of properties with reject_on and sync_reject_on operators, the abort condition becomes
true, then the overall evaluation of the property results in false. Otherwise, the overall evaluation of the property is
equal to the evaluation of the property_expr.
The operators accept_on and reject_on represent asynchronous resets and are evaluated at the granularity of
the simulation time step. Their abort condition is evaluated using sampled value as a regular boolean expression in
assertions.

253

SystemVerilog Reference

Assertions

The operators sync_accept_on and sync_reject_on represent synchronous resets and are evaluated at the
simulation time step when the clocking event happens, unlike disable iff, accept_on and reject_on. Their abort
condition is evaluated using sampled value as for accept_on and reject_on.
The nesting of abort operators (accept_on, reject_on, sync_accept_on, sync_reject_on) is allowed. Nested
accept_on, reject_on, sync_accept_on and sync_reject_on operators are evaluated in the lexical order (left
to right).
property hndshk;
@(posedge clk) accept_on (!rst) req |-> ##[1:5] ack;
endproperty
check_hndshk : assert property (hndshk);

The abort conditions may contain sampled value functions. Abort conditions cannot contain any reference to local
variables and the sequence methods triggered and matched.

254

SystemVerilog Reference

Assertions

Immediate Assertions
The immediate assertion statement is a test of an expression performed when the statement is executed in the
procedural code. Contrary to the concurrent assertions, an immediate assertion cannot be placed outside procedural
block, is evaluated independently of the clock signal events and cannot check dependencies between logical values
from different points of the simulation time. The immediate assertion expression is evaluated similarly to the
expression of the if statement: if the expression evaluates to X, Z, or 0, then it is interpreted as being false, and the
assertion is said to fail. Otherwise, the expression is interpreted as being true, and the assertion is said to pass or,
equivalently, to succeed. The immediate assertion statements can perform one of the following verification functions:
assert - the statement is treated as a checker that verifies whether the design behavior is correct.
assume - the statement is treated as an assumption for the design.
cover - the statement evaluation is monitored for the functional coverage.

Syntax
procedural_assertion_statement ::=

...
| immediate_assertion_statement
...
immediate_assertion_statement ::= simple_immediate_assert_statement
| simple_immediate_assume_statement
| simple_immediate_ cover_statement
simple_immediate_assert_statement ::= assert ( expression ) action_block
simple_immediate_assume_statement ::= assume ( expression ) action_block
simple_immediate_cover_statement ::= cover ( expression ) statement_or_null
action_block ::= statement _or_null | [ statement ] else statement

Examples
The immediate assert statement below specifies that if CLR is active (reset), the counter's value should equal zero.
always @(posedge CLK or posedge CLR)
begin
if (CLR)
begin
Check_CLR: assert (Q==0);
end
end

In the below example, the immediate assume statement specifies that the expr_1 should be evaluated to 1.
According to the expr_1 result, the proper message is displayed.
initial begin
as1: assume (expr_1)
$info("Immediate assume condition for expr_1 satisfied at %0t time unit", $time);
else
$warning("Immediate assume condition for expr_1 failed at %0t time unit", $time);
end

In the code below, the statements are covered if they are evaluated to one during occurrence of the falling edge of the
CLK signal.

255

SystemVerilog Reference

Assertions

always @(negedge CLK)


begin
cover (!a|1'b0^b&c~^a||(~|b)||c&&1'b1&&(~&a));
cover ((a|b)&(a^c) == 1 );
end

256

SystemVerilog Reference

Assertions

Concurrent Assertions

Overview
Concurrent assertion is a general name for a property with a verification directive. The verification directive instructs
the verification tool how to process the property. SystemVerilog includes three verification directives - assert,
assume and cover. When the assert directive is used, the property is treated as a checker that verifies if the design
behavior is correct. The assume directive converts the property to an assumption for the design. The cover directive
causes the property to be evaluated for functional coverage.

Syntax
procedural_assertion_statement ::= concurrent_assertion_statement | immediate_assert_statement
concurrent_assertion_item ::= [ block_identifier : ] concurrent_assertion_statement
concurrent_assertion_statement ::= assert_property_statement
| assume_property_statement
| cover_property_statement
assert_property_statement::= assert property ( property_spec ) action_block
assume_property_statement::= assume property ( property_spec ) ;
cover_property_statement::= cover property ( property_spec ) statement_or_null

A concurrent assertion statement can be used outside of a procedural context. It can be used within a module, an
interface, or a program. A concurrent assertion statement is an assert, an assume, or a cover statement. Such a
concurrent assertion statement uses the always semantics. The following two forms are equivalent:
assert property ( property_spec ) action_block
always assert property ( property_spec ) action_block ;

Similarly, the following two forms are equivalent:


cover property ( property_spec ) statement_or_null
always cover property ( property_spec ) statement_or_null

Assert Statement
The assert statement is used to inform the verification tool that a property should be processed as a checker. When
the property in the assert statement is evaluated to be true, the pass statements of the action_block are
executed. Otherwise, the fail statements of the action_block are executed. If no statement is specified for else,
then $error is used as the statement when the assertion fails.
By default, execution of both pass and fail action blocks is enabled for both vacuous and nonvacuous evaluations of
assertions. You can control the execution of pass and/or fail action blocks for assertions that are evaluated vacuously
and/or nonvacuously by using the assertion action control tasks.

257

SystemVerilog Reference

Assertions

NOTE: The distinction between vacuously and nonvacuously failed evaluations of assertions is a proprietary
extension to SystemVerilog developed by Aldec. Depending upon the simulation options specified by the user, this
feature can either be enabled or disabled.

Syntax
assert_property_statement::= assert property ( property_spec ) action_block
action_block ::= statement_or_null | [ statement ] else statement_or_null

Example
assert property (Ack_Max_Cycle) begin
$display("Ack_Max_cycle passed at time ",$time);
pass_count++;
end
else
begin
$error("Acknowledge is not asserted within specified maximum max_ack_cycle cycles from request");
fail_count++;
if (failed_count > `ACK_FAILURE_LIMIT)
activate_additional_tests(Ack,5);
end

In the example above property Ack_Max_Cycle is checked. The assert statement includes the action block. If the
property succeeds, the pass message is displayed ($display task) and the variable pass_count is increased. If
the property fails, the error message is displayed and the variable fail_count is increased. If the failure number
exceeds `ACK_FAILURE_LIMIT, the additional tests are activated (using task activate_additional_tests).
The action block allows user to define an action for assertion pass and failure. This can be used for creating smart
testbenches that will react flexibly to different simulation errors.

Cover Statements
The properties and sequences used for functional coverage have the same syntax as properties created for checkers
but the usage rationale is different. Different processing of these properties during simulation is forced by the cover
sequence and cover property statements. The design is monitored during the simulation, if the scenarios of
events described in sequences / properties happen during simulation, the sequences / properties are covered by the
testbench and pass. Otherwise they are not covered.

Syntax
cover_property_statement::= cover property ( property_spec ) statement_or_null
cover sequence ( [clocking_event ] [ disable iff ( expression_or_dist ) ] sequence_expr )
statement_or_null

The difference between cover sequence and cover property is that for sequence coverage, all matches per evaluation
attempt are reported, whereas for property coverage the coverage count is incremented at most once per evaluation
attempt.

258

SystemVerilog Reference

Assertions

Example
sequence Full_Event;
@(posedge clk) Full[*1:$];
endsequence
sequence Empty_Event;
@(posedge clk)Empty[*1:$];
endsequence
sequence Read_Event;
@(posedge clk) RD[*1:$];
endsequence
sequence Write_Event;
@(posedge clk) !WR[*1:$];
endsequence
sequence Read_Write_Event;
@(posedge clk) !WR[*1:$]};
endsequence
property LongWaitAck; @(posedge Clk) $fell(Strobe) ##1 Ack[*15:$] ;endproperty
Check_Full_Event : cover sequence (Full_Event) $display("Full FIFO happened");
Check_Full_Event_Bis : cover property (Full_Event) $display("Full FIFO happened");
Check_Empty_Event : cover sequence (Empty_Event) $display("Empty FIFO happened");
Check_Read_Event : cover sequence(Read_Event) $display("FIFO read happened");
Check_Write_Event : cover sequence (Write_Event) $display("FIFO write happened");
Check_Read_Write_Event : cover sequence (Read_Write_Event) $display("FIFO write happened");
Check_LongWaitAck : cover property (LongWaitAck) $display("Acknowledge after very long time happened");

The example above includes sequences with typical events for a FIFO buffer - buffer full, buffer empty, write to buffer,
etc. All these events should happen during simulation, otherwise the buffer functionality will not be tested well during
simulation. Each match of the sequences will be reported and counted as covered. For example, if the signal Full will
repeat for five clock cycles: 1, 2, 3, 4 and 5, the cover sequence statement will report the following covered results:
Start
(cycle)

Matched
(cycle)

Full[*1:$]

Full[*1]

Full[*2]

Full[*3]

Full[*4]

Full[*5]

Full[*1]

Full[*2]

Full[*3]

Full[*4]

Full[*1]

Full[*2]

259

SystemVerilog Reference

Assertions

Full[*3]

Full[*1]

Full[*2]

Full[*1]

The cover property results will be:


Start
(cycle)

Matched
(cycle)

Full[*1:$]

Full[*1]

Full[*1]

Full[*1]

Full[*1]

Full[*1]

The cover property statement reports the first matched result for an evaluation.

Embedding Concurrent Assertions in Procedural Code


A concurrent assertion statement can also be embedded in a procedural block. If the statement appears in an always
block, the property is always monitored. If the statement appears in an initial block, then the monitoring is performed
only on the first clock tick.

Example
property Reset_Check;
Q==0;
endproperty
always @(posedge CLK or posedge CLR)
begin
if (CLR)
begin
// If CLR is active (reset), the counter's value should equal zero
CheckCLR: assert property (Reset_Check);
end
else
begin
// CLE signals activates loading from determined input bits to some bits of the counter
if (CLE==2'b01)
begin
CheckCLE1: assert property ((##1 Q[3:0]==D[3:0]));
end
else if (CLE==2'b10)
begin
CheckCLE2: assert property ((##1 Q[5:4]==D[1:0]));
end
end
end

260

SystemVerilog Reference

Assertions

The clock in the property is interfered from the event control of an always block, clock expression must be placed as
the first term of the event control as an edge specifier (posedge expression or negedge expression). The variables in
expression must not be used anywhere in the always or initial block.
There is also possibility to put property definition explicitly to the assert statement.
When a property is placed in an if...else block or a case block the enabling condition from these blocks is used as the
antecedent of the property.
property Reset_Check;
Q==0;
endproperty
...
if (CLR)
begin
// If CLR is active (reset), the counter's value should equal zero
CheckCLR: assert property (Reset_Check);
end

The above part of code is equivalent to


property Reset_Check;
@(posedge CLK) CLR |-> Q==0;
endproperty
CheckCLR: assert property (Reset_Check);

Vacuity Feature
An evaluation attempt of a property is either vacuous or nonvacuous.
property p1;
@(posedge clk) a |-> b ##1 c;
endproperty
property p2;
@(posedge clk) c ##1 d |-> e ##2 f;
endproperty
as1: assert property (p1);
as2: assert property (p2);

The example above includes two properties with suffix implication. For these properties the vacuity feature can be
described as follows: if left side of the implication is false the whole property succeeds vacuously. If left side of the
property is true and the right side of the property is true then the whole property succeeds nonvacuously. In other
words the second success is a real success of the evaluation. In the first case, when implication condition fails
vacuously, the property on the right side is just not evaluated and this is named vacuous success.
The table below presents the vacuity feature for the sequence and properties operators.
Operator

Vacuity

sequence

"An evaluation of the sequence is always nonvacuous."

not

"An evaluation of a property of the form not property_expr is nonvacuous if, and
only if, the underlying evaluation attempt of property_expr is nonvacuous."

261

SystemVerilog Reference

Assertions

or

"An evaluation attempt of a property of the form property_expr1 or


property_expr2 is nonvacuous if, and only if, either the underlying evaluation
attempt of property_expr1 is nonvacuous or the underlying evaluation attempt of
property_expr2 is nonvacuous."

and

"An evaluation attempt of a property of the form property_expr1 and


property_expr2 is nonvacuous if, and only if, either the underlying evaluation
attempt of property_expr1 is nonvacuous or the underlying evaluation attempt of
property_expr2 is nonvacuous."

if ()

"An evaluation attempt of a property of the form if ( expression_or_dist )


property_expr1 is nonvacuous if, and only if, expression_or_dist evaluates to true
and the underlying evaluation attempt of property_expr1 is nonvacuous."

if () ... else ...

"An evaluation attempt of a property of the form if ( expression_or_dist )


property_expr1 else property_expr2 is nonvacuous if, and only if, either
expression_or_dist evaluates to true and the underlying evaluation attempt of
property_expr1 is nonvacuous, or expression_or_dist evaluates to false and the
underlying evaluation attempt of property_expr2 is nonvacuous."

|->

"An evaluation attempt of a property of the form sequence_expression |->


property_expr is nonvacuous if, and only if, there is a successful match of the
antecedent sequence_expression and the evaluation attempt of property_expr
that starts at the end point of the match is nonvacuous."

|=>

"An evaluation attempt of a property of the form sequence_expression |=>


property_expr is nonvacuous if, and only if, there is a successful match of the
antecedent sequence_expression and the evaluation attempt of property_expr
that starts at the clock event following the end point of the match is nonvacuous."

instance of a property

"An evaluation attempt of an instance of a property is nonvacuous if, and only if,
the underlying evaluation attempt of the property_expr that results from
substituting actual arguments for formal arguments is nonvacuous."

accept_on/sync_accept_on

"An evaluation attempt of a property of the form accept_on(expression_or_dist)


property_expr is nonvacuous if, and only if, the underlying evaluation attempt of
property_expr is nonvacuous and expression_or_dist does not hold in any time
step of that evaluation attempt."

reject_on/sync_reject_on

"An evaluation attempt of a property of the form reject_on(expression_or_dist)


property_expr is nonvacuous if, and only if, the underlying evaluation attempt of
property_expr is nonvacuous and expression_or_dist does not hold in any time
step of that evaluation attempt."

disable iff

"An evaluation attempt of a property of the form disable iff (expression_or_dist)


property_expr is nonvacuous if, and only if, the underlying evaluation attempt of
property_expr is nonvacuous and expression_or_dist does not hold in any time
step of that evaluation attempt."

262

SystemVerilog Reference

Assertions

Clocks
Concurrent assertion is always tied to a clock. Usually the clock expression includes the negedge or the posedge
operator.
The clock can be specified explicitly in the sequence or property declaration.

Examples

Example 1
sequence Write_4_and_Not_Read;
@(negedge SysClk) (!WR && RD)[*4];
endsequence
property Inactive_TXD;
@(posedge clk) !Rst & !SEND & !RECEIVE |-> TXD;
endproperty

The sequences and properties can also use clock from the default clocking block. In such case, the explicit clock in
the sequence or property is not necessary.

Example 2
default clocking Sys_Clock @(posedge SysClk);
property Load_Prop;
Load |-> QOut==1;
endproperty
endclocking
property Count_Down;
disable iff(!Rst) (!Load & Enable) |-> QOut == $past(QOut)-1;
endproperty
property Load_Data;
@(negedge Load) disable iff (!Rst) (QOut==DataIn);
endproperty

The property LoadProp is clocked by the SysClk, because is located in default clocking block. The property
CountDown is clocked with posedge SysClk clock from the default Sys_Clock clocking block. The sequence or
property can have also another explicitly specified clock expression even if there is default clocking block declaration like in the LoadData property;

Example 3
clocking Block_1_Clock @(negedge Clk1);
sequence Start_Addr;
$rose(TX_H) ##1 $rose(TX_L) ##1 Addr==8'hf0;
endsequence

263

SystemVerilog Reference

Assertions

endclocking

If the sequence or property is declared inside a clocking block, the clocking expression is always inherited from this
clocking block. The sequences and properties inside clocking blocks cannot have an explicitly defined clock
expression.

Example 4
always @(negedge clk)
begin
IN0 = data;
assert property (data==8'hff ##1 data==8'h0);
end

The clock expression can be inferred from a procedural block. The property in the example 4 is clocked with negedge
clk from the always statement.

264

SystemVerilog Reference

Assertions

Multiclock Support
SystemVerilog allows defining multiclock sequences and properties. Several restrictions apply.

Multiclock sequences
In multiclock sequences, only the single-delay concatenation operator ##1 can be used. This operator is
nonoverlapping and synchronizes the clocks of two sequences. The single delay indicated by ##1 is understood to be
from the end point of the first sequence, which occurs at a tick of the first clock, to the nearest strictly subsequent tick
of the second clock, where the second sequence begins.
None of the concatenated multiclock sequences can be empty. Sequence
@(posedge clk0) sig0 ##1 @(posedge clk1) sig1[*0:1]

is illegal because of the possibility of an empty match of sig1[*0:1]. Such empty matches would make it impossible
to determine the starting and ending clocking events.

Example 1
sequence Multi_Seq;
@(posedge clk1) sig1 ##1 @(posedge clk2) sig2
endsequence

The sequence starts with sig1 on a posedge clk, then ##1 moves time to the nearest posedge clk2 and then sig2
is checked.

Multiclock properties
The Boolean property operators (not, and, or) and the nonoverlapping implication operator |=> can be used freely to
combine singly clocked and multiclock properties.
Because |-> overlaps the end of left sequence with the beginning of the right property, the clock for the end of the left
sequence must be the same as the clock for the beginning of the right property.
The if/if...else operators overlap the test of the Boolean condition with the beginning of the if clause property and, if
present, the else clause property. Therefore, whenever using if or if...else, the if and else clause properties must begin
on the same clock as the test of the Boolean condition.

265

SystemVerilog Reference

Assertions

Example 2
property Send_Cycles;
@(negedge ClkS1P1) $rose(SEND)|=> SEND[*7];
endproperty
property TI_Pulse_Set;
@(negedge XTAL) $fell(SEND) |=> TI;
endproperty
property Send;
Send_Cycles and TI_Pulse_Set;
endproperty

The SEND signal is high for 8 machine cycles. When the falling edge of SEND is detected (on the negedge XTAL clock)
then, in the next clock cycle (negedge XTAL), TI is high.

266

SystemVerilog Reference

Assertions

Encapsulating Assertions in Design Units


In SystemVerilog (contrary to PSL and OVA), there is no special verification unit that encapsulates declarations of
sequences and properties and assertions statements.
Sequences and properties can be declared in a module, in an interface, in a program, in a clocking block, in a
package and in a compilation-unit scope.
An assertion statement can be specified in an always block or initial block as a statement, wherever these blocks
can appear, in a module, in an interface, or in a program outside of a procedural context.
Assertions can be mixed with Verilog code and, additionally, work as executable documentation. They can also be
encapsulated in separate modules or interfaces including only assertions and cover statements, creating
independent assertions monitors.

Example

Example 1
This example is based on file i_pcounter.v. (See examples/assertions/mix/simple_uart)
interface i_PCounter_asrt (input Clk, ... output Counted);
default clocking i_PCounter_cl @(posedge Clk);
endclocking
sequence RstSeq;
(!Rst) and !(Counted==0 && QOut==0);
endsequence
CheckRst: assert property(not RstSeq)
else $warning(": during reset output different than zero, Counted=%b", $sampled(Counted));
property LoadData;
@(negedge Load) disable iff (!Rst) (QOut==DataIn);
endproperty
CheckLoad: assert property (LoadData)
else
$warning(" Time=%0t Programmable Counter : Load - violation! Rst=%b QOut=%0d DataIn=%0d ", $time,
$sampled(Rst), $sampled(QOut), $sampled(DataIn));
property CountDown;
disable iff(!Rst) (!Load & Enable) |-> QOut == $past(QOut)-1;
endproperty
CheckCountDown: assert property (CountDown)
else $warning( " Time=%0t Programmable Counter : count down - violation! Load=%b Enable=%b QOut=%0d
previous(QOut)=%0d",
$time, $sampled(Load), $sampled(Enable), $sampled(QOut), $past(QOut) );
endinterface

i_PCounter_asrt is a specialized interface used only for debug purposes. It includes only assertions for design
checking.

267

SystemVerilog Reference

Assertions

Example 2
This example is based on file counter.v. (See examples/assertions/sva/verilog/traffic_lights_controller)
module Counter #(parameter N=4,... DIR=1) (input Clk,... output [N:0] QOut);
...
// ---- Specification ---------------------------------------------------------------------property ResetProperty;
@(negedge Clk) not Rst & (QOut != 0);
endproperty
property LoadProperty;
@(negedge Clk) Load |=> (QOut == DataIn);
endproperty
Reset_Check: assert property (ResetProperty) // No failure
// Failure, during resetting the counter's output different than zero
else $error("time=%0d Reset failure", $time);
Load_Check: assert property (LoadProperty) // Loading was done correctly
// Failure, during loading the counter's output different the DataIn input
else $error("time=%0d Loading failure", $time);
// ---- Implementation --------------------------------------------------------------------always @(negedge Clk , posedge Rst , posedge Load) begin : Counter_body
if (Rst)
q = 0;
else if (Load)
q = DataIn;
else if ( Enable && (!EN_Q0 || (EN_Q0 && (q>0))))
begin : Counting_block
if (DIR)
q++;
else
q--;
end : Counting_block
end : Counter_body
assign QOut = q;
endmodule

The listing shows a counter implementation. Assertions are treated as checkers and as documentation of the counter
features.

268

SystemVerilog Reference

Assertions

Binding Assertions to Modules or Instances


It is possible to specify properties and bind them to specific modules or instances. This allows verification engineers to
run the verification process with minimum changes to the design code and files. It also provides a convenient
mechanism for attaching verification monitor (IP) to a module or an instance.
With this feature, the user can specify assertions in a module, interface or program instance (in a separate file) and
bind them to a module or a module instance.

Syntax
bind_directive ::= bind bind_target_scope [: bind_target_instance_list] bind_instantiation
| bind bind_target_instance bind_instantiation ;
bind_target_scope ::= module_identifier | interface_identifier
bind_target_instance ::= hierarchical_identifier constant_bit_select
bind_target_instance_list ::= bind_target_instance { , bind_target_instance }
bind_instantiation ::= program_instantiation | module_instantiation | interface_instantiation

Example
bind DAT_CNT DAT_CNT_check DAT_CNT_check_Inst(.CLK(SysCLK), .CLR(Rst), .CLE(CLE), .CE(CE), .D(D),
.Q(Q));

The example shows binding assertions in the DAT_CNT_check module to the DAT_CNT design module.

The format of the target name decides if a bind statement is bound to a module or instance. If the target is a simple
identifier then it is bound to a module (scope). If the target is a hierarchical identifier then this bind statement is
bound to an instance. For a top-level, use $root.<top_module_name> to bind to an instance.

269

SystemVerilog Reference

Assertions

Binding to Specific Instance


An assertion can be bound to a specific instance by using the bind statement. Consider the following example:

Example 1
module bindex (clk, a, b, d1, d2, d);
input logic clk, a, b;
input logic [4:0] d1, d2;
output logic [4:0] d;
always@(negedge clk)
begin
if(a)
d <= d1;
if(b)
d <= d2;
end
endmodule
module mtx_chk(a, b, clk);
input logic a, b, clk;
property p_check;
@(negedge clk) not (a && b);
endproperty
a_mtx: assert property (p_check);
endmodule
module topex;
logic clk=0;
always #10 clk=!clk;
logic a,b;
logic [4:0] d1, d2;
logic [4:0] du1;
bind topex.uut mtx_chk i2 (a, b, clk);
bindex uut (clk, a, b, d1, d2, du1);
initial begin
d1 = 0;
d2 = 0;
#200;
$finish;
end
logic [0:1] temp=0;
always @(posedge clk) temp++;
assign {a,b}=temp;
endmodule

The bind statement binds the p_check property to the instance of the topex module. The assertion p_check is
checked on a negative edge of a clock. The assertion will fail in the 4th and 8th clock cycle in the simulation unit

270

SystemVerilog Reference

Assertions

scope topex.uut.i2.

Example 2
In the following example, the bind statements are used at the end of the file. When the bind statement is bound to
an instance, an additional top-level module containing the checker mapping and bound instance is created. To see the
assertions during the simulation, it has to be initialized by using the asim command with $root or all top-level modules
have to be specified in the asim command.
module bindex (clk, a, b, d1, d2, d);
input logic clk, a, b;
input logic [5:0] d1, d2;
output logic [5:0] d;
endmodule
module mtx_chk(a, b, clk);
input logic a, b, clk;
property p_mtx;
@(negedge clk) not (a && b);
endproperty
a_mtx: assert property (p_mtx);
endmodule
module topex;
logic clk=0;
always #10 clk=!clk;
logic
logic
logic
logic

a,b;
c,d;
[5:0] d1, d2;
[5:0] du1,du2;

bindex uut1 (clk, a, b, d1, d2, du1);


bindex uut2 (clk, c, d, d1, d2, du2);
initial begin
d1 = 0;
d2 = 0;
#200;
$finish;
end
logic [0:1] temp1=0,temp2=3;
always @(posedge clk) begin temp1++; temp2++; end
assign {a,b}=temp1;
assign {c,d}=temp2;
endmodule
bind topex.uut1 mtx_chk i1 (a, b, clk);
bind topex.uut2 mtx_chk i2 (.a($root.topex.c), .b($root.topex.d), .clk);
bind topex.uut2 mtx_chk same_as_i2 (.a, .b, .clk);

271

SystemVerilog Reference

Assertions

Binding SystemVerilog Assertions to VHDL


It is also possible to bind a SystemVerilog module to a VHDL design (to an entity or to an instance) by using the bind
statement that can be placed in a separate SystemVerilog file. The bind statement can exist without the module. The
following configurations are available:
The checker module bound to an entity in a VHDL design.
The checker module bound to a VHDL instance in a VHDL design.
The checker module bound to a VHDL or SystemVerilog instance in a mixed design.
To initialize the simulation with the bind statement connected to an instance, the VHDL top-level along with {$root} or
the name of the top-level created by the bind statement has to be defined in the asim command. Otherwise, it is
enough to specify the top-level name of a design in the asim command. If the bin statement is bound to an instance,
the VHDL top-level along with {$root} or the name of the top-level created by the statement has to be defined in the
asim command.
If the bind statement is used inside the module construct, the simulation can be initialized by specifying the name of
a VHDL top-level along with $root. It is also possible to initialize the simulation by defining the name of a VHDL
top-level with the name of a module containing the bind statement as a second top-level.
For more information, see the SystemVerilog bind Statement topic in User's Guide.

Example 1
The following example presents how to bind a SystemVerilog checker module to a VHDL instance. In this case, the
bind statement is not placed inside the module construct. The simulation is initialized by using the asim command
with the name of the VHDL top-level and {$root}.
library ieee;
use ieee.std_logic_1164.all;
entity sub1 is
port (
clk : in std_logic;
a: in std_logic;
b: in std_logic );
end entity;
architecture rtl of sub1 is
begin
...
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity top is
end entity;
architecture rtl of top is
signal
signal
signal
signal
signal

clk : std_logic;
a: std_logic;
b: std_logic;
c: std_logic;
d: std_logic;

component sub1 is

272

SystemVerilog Reference
port (
clk
a
b
end component;

Assertions

: in std_logic;
: in std_logic;
: in std_logic );

begin
...
end process;
sub1_i : sub1
port map(
clk => clk,
a
=> a,
b
=> b );
end architecture;

The checker sv_chk is bound to the VHDL instance of the sub1 entity on the following ports: clk, a, and b. The
used bind statement is presented below:
bind top.sub1_i sv_chk ch_i1 (.clk(clk),.a(a),.b(b));

273

SystemVerilog Reference

Assertions

Expect Statement
The expect statement allows for waiting on a property evaluation. The process execution is blocked until the property
evaluates (with success or with failure). The statement following expect is executed in Observed region.
property Go_To_Idle;
@(posedge clk) $rose(IN_0) |-> ##2 State==Idle;
endproperty
initial begin
rst = 1'b1;
##3;
rst = 1'b0;
##10;
expect (Go_To_Idle) begin
idle=1'b1;
$display("Idle state reached");
Idle_Process(data);
end
// ...
end

It is allowed to use the expect statement any procedural code, including tasks or class methods. Because it is a
blocking statement, the property can refer to automatic variables as well as static variables.

274

Coverage

Overview
Functional coverage provides metrics that show how much of the design specification, as enumerated by features in
the test plan, has been exercised. Interesting scenarios, corner cases, design states and any other test plan features
can be defined in SystemVerilog and checked for coverage during simulation.
The metrics are based on the design specification and define the project designer intent. They are independent of the
actual design code or its structure.
Using SystemVerilog coverage constructs allows you to check coverage of variables and expressions, as well cross
coverage between them. Checked value ranges or transactions of values can be conveniently specified by using
coverage bins. Filtering conditions can be applied at multiple levels in coverage definitions. Sampling of coverage
variables and expressions can be done using clocking events, clocking blocks, or named blocks. It can be automatic
or triggered procedurally. The operation of coverage models can be controlled by a set of options.

275

SystemVerilog Reference

Coverage

Covergroup
The covergroup construct is used to encapsulate definition of a coverage model. It may include an event that triggers
sampling of coverage points and crosses. It can also assign values to coverage options. Covergroup definition may
include one or more formal arguments.
typedef enum {Idle, Start, Count, Wait, Stop} States;
States state;
int i;
covergroup cg1 (int n) @(posedge clk);
option.auto_bin_max = n;
c1 : coverpoint state;
c2 : coverpoint i;
endgroup
cg1 cg1_inst = new( 256 );

A covergroup can be instantiated multiple times. A covergroup instance is created using operator new. A covergroup
can be declared in a module, program, interface, class, or package.
When formal arguments are specified in the covergroup declaration, instances must provide values to all arguments
that have no default value assigned. input or ref argument directions are allowed. input arguments use the value
passed to new operator when the instance is created. ref arguments point directly to the originally passed object and
always read the current value. In the covergroup context ref is automatically treated as const ref.
logic [1:0] a1,a2;
covergroup cg2 (ref logic [1:0] arg1);
a: coverpoint arg1;
endgroup
cg2 cg2_1 = new( a1 );
cg2 cg2_2 = new( a2 );
initial begin
a1 = 1;
a2 = 2;
cg2_1.sample();
cg2_2.sample();
a1 = 0;
a2 = 3;
cg2_1.sample();
cg2_2.sample();
end

In the example above two instances with different argument values are declared. The cg2_1 instance defines
coverpoint for signal a1. The cg2_2 instance defines coverpoint for signal a2. After simulation of the example is
finished values 1 and 0 will be sampled for cg2_1.a and values 2 and 3 - for cg2_2.a.
The triggering event defines the moment when the coverage points from the covergroup should be sampled. If the
event is omitted from the covergroup declaration, then the user must procedurally trigger the sampling by using the
built-in sample() method.
The strobe option may be used to modify sampling scheduling region. When the strobe option is false, then
sampling may happen multiple times within a time slot. Setting the option to true results in scheduling sampling in the
Postponed region. Consequently, a coverpoint will be sampled only once per time slot.

276

SystemVerilog Reference

Coverage

A covergroup can be also triggered by the start or by the end of execution of a given named block, a task, a function,
or a class method. When a covergroup is triggered at the start of a named block, the sampling takes place
immediately before the first statement in the block is executed. When the end of a named block triggers a covergroup,
sampling is performed after the execution of the last statement in the named block.
A coverage point can be a variable or an expression of integral type. Each coverage point includes a set of bins
associated with its sampled values or value transitions. The bins can be explicitly defined by the user or automatically
created by the tool.

Using Covergroups in Classes


One or more covergroups can be embedded in a class. This facilitates defining functional coverage of class
properties.
When a covergroup is declared in a class, then an instance variable of an anonymous type is declared implicitly. An
instance name is the same as used within the covergroup definition. Explicit declarations of embedded covergroup
variables are not allowed.
A covergroup should be explicitly instantiated in the parent class constructor. Otherwise, the covergroup is not created
and no data will be sampled.
class A;
int i;
bit enable;
logic [9:0] b;
covergroup cg3 @enable;
coverpoint i;
coverpoint b;
option.per_instance = 1;
endgroup
function new();
cg3 = new;
endfunction
endclass
module top;
A inst1 = new();
A inst2 = new();
initial begin
#5;
inst1.enable = 1;
inst2.enable = 1;
#5;
inst1.enable = 0;
end
endmodule

Any class properties can be used to declare a coverpoint. The coverpoint may reference any property of the parent
class regardless of access qualifier (local, protected).
An event dependent on non-static members of enclosing class triggers covergroup sampling individually per each
object. Considering an example above inst1.cg3 samples values twice, while inst2.cg3 - three times.

277

SystemVerilog Reference

Coverage

Coverage Points
A coverage point specifies which variable or expression value or sequences of values transitions should be tracked
during the simulation. Each coverage point includes a set of bins associated with its sampled values or its value
transitions. The bins can be explicitly defined by the user or automatically created by the simulator. A coverage point
can be optionally labeled. If the label is omitted and the coverage point is associated with a single variable, then the
variable name becomes the name of the coverage point. Otherwise a name for a coverage point is generated
automatically for reporting purposes.
A coverage point can sample the values by specifying a clocking block signal. If the clocking block specifies a skew of
#1step, the variable/expression in the coverpoint statement is sampled in the Preponed region. If the clocking block
specifies a skew of #0, the sampling is executed in the Observed region.
The coverage point can include a guard expression, when this expression evaluates to false, the coverpoint is
ignored.
covergroup cov1 @(posedge clk);
coverpoint x iff (!rst);
endgroup

A coverage point bin associates a name and a hit count with a set of values or a sequence of value transitions. The
count is incremented every time the coverage point matches one of the values in the set or the entire sequence of
value transitions. The user can define bins for a coverpoint or the bins can be defined automatically. The option
auto_bin_max controls the number of the automatically created bins.

Specifying Bins for Values


The default specification defines a bin that is associated with none of the defined value bins. The default bin catches
the values of the coverage point that did not hit any of the defined bins. However, the coverage calculation for a
coverage point must not take into account the hits captured by the default bin. The default bin is also excluded from
cross coverage. The default is useful for catching unplanned or invalid values.
It is possible to create a separate bin for each value in the given range list or for a range of values.
An open array of bins can be used to create a separate bin for each unique value:
bins b1[] = { [1:2], 3, [4:19], 20, 21 };

To create a fixed number of bins for a set of values, a number can be specified inside the square brackets.
bins b2[5] = { [1:2], 3, [4:19], 20, 21 };

The fixed number is used to specify the set of values associated with a bin shall be constant expressions, instance
constants (for classes only), or non-ref arguments to the coverage group. If the number of bins exceeds the number of
values, then some of the bins will be empty. If the number of values is not divisible by the number of bins, then the last
bin will include the remaining items.
The expression within the iff construct enables/disables sampling the values for the bin. If the expression is false at
a sampling point, the count for the bin is not incremented.
logic [3:0] x;
covergroup my_cg @(posedge clk);

278

SystemVerilog Reference

Coverage

coverpoint x {
bins a = { [0:6],7 };
bins b[] = { [8:10],[11:12] };
bins c[] = { 13,14,15 };
bins others[] = default;
}
endgroup

In order to exclude bins from coverage the ignore_bins construct is used. Specified values are excluded from
coverage even if they are included in another bins. When ignore bin is hit, runtime warning is produced. Bins may be
also marked as illegal using illegal_bins construct. When value from illegal bin is sampled, runtime error is
produced. Bins marked as illegal take precedence over any other bins.
logic [3:0] x;
covergroup my_cg @(posedge clk);
coverpoint x {
bins a = { [0:6],7 };
ignore_bins ignore_them[] = { [8:10],[11:12] };
illegal_bins illegal[] = { 13,14,15 };
bins others[] = default;
}
endgroup

Wildcard Specification for Coverage Point Bins


When a bin definition includes an X or Z the comparison is doing using ===. This behavior is the default one for any
user-defined bin. A wildcard bin definition causes all X, Z, ? to be treated as wildcards for 0 or 1.
logic [3:0] x;
covergroup my_cg @(posedge clk);
coverpoint x {
wildcard bins wb[] = { 4'b00zz, 15};
ignore_bins ignore_them = { 0, 5 };
}
endgroup

In the example above bin wb defines the following values: 0, 1, 2, 3, 15, but value 0 is specified within ignore bin
definition and is excluded. Therefore, bin wb is hit with values 1, 2, 3 and 15.
A wildcard bin definition only considers 2-state values. Sampled values containing X or Z are excluded.
Wildcard cannot be used for range specification of bins definition.

Specifying Bins for Transitions


The transition bins, which are a part of functional coverage, are useful for verifying if the intended change of the
specified variable has occurred.
module top;
reg clk = 1'b0;
reg rst = 1'b0;
typedef enum { IDLE,SEND_PACKET,CRC,SUSPEND } DEV_STATES;

279

SystemVerilog Reference

Coverage

DEV_STATES dev_sm;
covergroup cg_dev_sm @(posedge clk);
cp: coverpoint dev_sm iff
{
bins dev_started
=
bins dev_whole_packet =
bins dev_suspended
=
bins dev_resumed
=
}

(rst==1'b0)
(IDLE =>
(IDLE =>
(IDLE =>
(SUSPEND

SEND_PACKET);
SEND_PACKET[*2:1023] => CRC[*2] => IDLE);
SUSPEND[*2000]);
=> IDLE);

endgroup
endmodule

The example above, which contains four transition coverage bins, shows how to check the transitions in a state
machine. The following sequence is associated with the bin dev_started: IDLE => SEND_PACKET. The next bin
construct, dev_whole_packet, waits for the sequence of the following states: IDLE and SEND_PACKET for the
range of repetitions from 2 to 1023 and then the simulator waits for 2 clock cycles of CRC and ends with the IDLE
state. The third bin construct, dev_suspended, waits for the following sequence: IDLE and stays in the SUSPEND
state for 2000 clock cycles. The last sequence is associated with the bin dev_resumed: SUSPEND => IDLE.
For more information about transition bins, see 19.5.1 in IEEE Std 1800-2009.

Limitations
Cross coverage for transition bins is not supported yet.
Transition bins declared inside class templates are not supported yet.

Automatic Bin Creation for Coverage Points


If no bins are explicitly declared in a coverpoint, SystemVerilog automatically creates state bins. Automatically created
bins only comprise 2-state values; sampled values containing X or Z are ignored. Each automatically created bin will
have a name in the form of auto(value), where value is either a single coverage point value or a range of coverage
point values included in the bin in the form low:high. For enumerated types, the value is the enumerated name
associated with a particular enumerated value.
NOTE: When only ignore or illegal bins are defined within a coverpoint, the simulator still generates bins
automatically, excluding values marked as ignore or illegal.

280

SystemVerilog Reference

Coverage

Cross Coverage
Cross coverage between multiple coverage points or variables is defined with the cross construct. If variable is used
in cross, implicit coverpoint is declared for this variable. Expression may not be specified directly in the cross
definition, but coverpoint should be declared for the expression first. Crossing coverpoints is allowed only if they are
defined within the same covergroup.
Crossing any number of coverage points is the coverage of all bins combinations belonging to these coverage points
(Cartesian product of coverage points bin sets). Default, ignore and illegal coverpoint bins are not included to the
cross coverage products. The following example defines cross of single bit variables, therefore four cross bins are
generated.
bit x,y;
covergroup cov1 @(posedge clk);
coverpoint x;
coverpoint y;
cross x,y;
endgroup

Generated cross products: bin <auto(0), auto(0)>, bin <auto(0), auto(1)>, bin <auto(1),
auto(0)>, bin <auto(1), auto(1)>
Total number of automatically generated cross bins may not exceed 2^31.
Cross coverage guard expression is specified with iff clause. Used at the cross level it disables cross evaluation
when the expression is false. Used at cross bin level, guard expression controls hitting of particular bin.

Specifying Bins for Cross Coverage


The binsof operator allows specifying user-defined cross coverage bins. Any coverage point or its user-defined bin
may be used to specify cross bin expression. The obtained bins set may be constrained with intersection operation:
cross a, b {
bins my_bins = binsof (a) intersect {[0:3]};
}

Cross products may be excluded from coverage computation or marked as illegal. In order to exclude coverage
products ignore_bin is used.
cross a, b {
bins my_bins = binsof (a) intersect {[0:3]};
ignore_bins ignore_them = binsof (a) intersect {[4:7]};
}

Illegal bins are specified by illegal_bin construct:


cross a, b {
bins my_bins = binsof (a) intersect {[0:3]};
illegal_bins my_illegal_bins = binsof (b) intersect {0};
}

When ignore bin is hit, runtime warning is produced. When illegal bin is hit, runtime error is issued.

281

SystemVerilog Reference

Coverage

Coverage Options
The SystemVerilog defines a set of options for the coverage. They control the behavior of the covergroup, coverpoint
and cross. They can be applied to a specific instance of a covergroup or to covergroup type as a whole. Specifying
value for determined option more than once in the covergroup declaration scope is not allowed.

Instance-specific Options

Option

LRM
default
value

Simulator
default
value

Description

weight=number

Specifies the weight of this covergroup instance for


computing the overall instance coverage of the simulation
for the covergroup syntactic level. Specifies the weight of
a coverpoint (or cross) for computing the instance
coverage of the enclosing covergroup for the coverpoint
(or cross).

goal=number

100

100

Specifies the target goal of a covergroup instance or for a


coverpoint or for a cross from determined covergroup
instance.

name=string

unique
name

unique name

comment=string

""

""

Specifies a comment that appears with a covergroup


instance or coverpoint or cross of the covergroup instance
in the coverage report.

at_least=number

Minimum number of hits for each bin. A bin with a hit count
that is less than the number is not considered covered.

detect_overlap=boolean

Forces a warning generation when there is an overlap


between the range list (or transition list) of two bins of a
coverpoint.

auto_bin_max=number

64

64

Specifies the maximum number of automatically created


bins for coverpoint when no bins are declared explicitly.

cross_num_print_missing
=number

Specifies the number of not covered cross product bins


that should be included into the coverage report.

per_instance=boolean

When true, coverage data for covergroup instances is


included into the coverage report.

Applies when the merge_instances type option is set.


When true, instance coverage is calculated by
get_inst_coverage method. When false, the method
return value is equal to the value returned by
get_coverage method.

get_inst_coverage=boolean

Specifies a name for the covergroup instance. If not


specified, name is generated automatically by the tool.

The syntax of specifying options in the covergroup:

282

SystemVerilog Reference

Coverage

option.option_name = expression ;

Constant expression only may be used to assign an option value. Covergroup arguments may also be used within an
expression.
The identifier option is a built-in member of any coverage group.
covergroup cov @(posedge clk);
option.per_instance = 1;
coverpoint a {
option.auto_bin_max = 32;
}
endgroup

The per_instance and get_inst_coverage options can only be set in the covergroup definition. The
auto_bin_max and detect_overlap options can only be set in the covergroup or coverpoint definition. Other
options can be set procedurally after a covergroup has been instantiated.
covergroup cov1 @(posedge clk);
cx : coverpoint x;
cy : coverpoint y;
endgroup
// ...
cov1 cov1_inst0 = new;
cov1_inst0.option.comment ="cov1_inst0 instance";
cov1_inst0.x.option.weight = 3;

All instance options can be specified at the covergroup level. Except for the weight, goal, comment, and
per_instance options, all other options set at the covergroup syntactic level act as a default value for the
corresponding option of all coverpoints and crosses in the covergroup during its definition. Individual coverpoints or
crosses can overwrite these default values. When set at the covergroup level, the weight, goal, comment, and
per_instance options do not act as default values to the lower syntactic levels.

Type Options

Option

weight=constant_number

Standard
default
value

Simulator
default
value

Description

For the covergroup syntactic level specifies the weight of


this covergroup for computing the overall cumulative (or
type) coverage of the saved database. For the coverpoint
(or cross) syntactic level specifies the weight of a
coverpoint (or cross) for computing the cumulative (or
type) coverage of the enclosing covergroup.

100

Specifies the target goal for a covergroup type or for a


coverpoint or cross of a covergroup type.

goal=constant_number

100

comment=string_literal

""

""

Specifies a comment that appears with a covergroup type


or with a coverpoint or cross of the covergroup type in the
coverage report.

strobe=boolean

When true, all samples happen at the end of the time slot,
like the $strobe system task.

283

SystemVerilog Reference

merge_instances=boolean

Coverage

When true, cumulative (or type) coverage percentage is


calculated by merging instances together. Otherwise,
cumulative coverage is the weight average of instances.

The syntax for specifying type options in the covergroup :


type_option.option_name = expression ;

Constant expression only may be used to assign an option value.


The identifier type_option is a built-in member of any coverage group. It is not allowed to assign different values to
type options in different instances of a covergroup.
The strobe type option can only be set in the covergroup definition. Other type options can be set procedurally at
any time during simulation.
covergroup cov1 @(posedge clk) ;
cx : coverpoint x;
cy : coverpoint y;
endgroup
...
cov1::type_option.comment = "Comment";
cov1::x::type_option.weight = 3;
cov1 cov1_inst0 = new;

284

SystemVerilog Reference

Coverage

Coverage Methods
The predefined coverage methods are provided for the covergroup and can be invoked procedurally at any time.
Method

covergroup

coverpoint

cross

yes

no

no

Triggers sampling of the


covergroup

yes

yes

yes

Calculates type coverage


number (0...100)

yes

yes

yes

Calculates type coverage


number (0...100)

yes

yes

yes

Calculates the coverage


number (0...100)

void set_inst_name(string)

yes

no

no

Sets the instance name to the


given string

void start()

yes

yes

yes

Starts collecting coverage


information

void stop()

yes

yes

yes

Stops collecting coverage


information

void sample()

Description

real get_coverage()
real get_coverage(ref int, ref
int)
real get_coverage(ref int, ref
int)
real get_inst_coverage()
real get_inst_coverage(ref int,
ref int)

The get_coverage() method is a static method. It is available for types via :: operator and for instances via .
operator. The get_inst_coverage() method is available only for a specific instance via . operator. Both methods
can be invoked with optional set of arguments (passed by reference). When the optional arguments are specified, the
get_coverage() and get_inst_coverage() methods assign to the first argument the value of the covered bins
and to the second argument the total number of bins for the given coverage item. These two values correspond to the
numerator and the denominator used when calculating the particular coverage percentage (the return value before
scaling by 100).

Overriding build-in sample method


Build-in sample() method may be overridden in order to trigger sampling coverage data other then covergroup
declaration defines. It may be used to sample various data by passing different arguments to covergroup from an
automatic functions, particular process, assertions, etc.
The formal arguments of the overridden sample() method may be used only within coverpoint expression or
conditional guard expression. The arguments belong to the same scope as covergroup formal arguments, therefore
an error is produced if same names are specified within sample() method and covergroup arguments lists.
covergroup cov1 with function sample (int arg);
coverpoint arg;
endgroup
int x = 3;

285

SystemVerilog Reference

Coverage

cov1 cov1_inst = new();


initial begin
cov1_inst.sample(x);
cov1_inst.sample(5);
end

In the example above integer values 3 and 5 are sampled by passing actual arguments to an instance sample()
method call.

286

SystemVerilog Reference

Coverage

Coverage System Tasks and Functions


The following tasks and functions are available in SystemVerilog coverage :
Name

Description

$set_coverage_db_name(name)

Sets the filename of the coverage database into which coverage information
is saved at the end of a simulation run.

$load_coverage_db(name)

Loads from the given filename the cumulative coverage information for all
coverage group types.

$get_coverage()

Returns as a real number in the range of 0 to 100 with the overall coverage
of all coverage group types (cumulative coverage).

287

SystemVerilog Reference

Coverage

The Structure of option and type_option Members


The option and type_option members of a covergroup, coverpoint, and cross are implicitly declared structures.
They are presented below:
struct { // covergroup option declaration
string name;
int weight;
int goal;
string comment;
int at_least;
int auto_bin_max;
int cross_num_print_missing;
bit detect_overlap;
bit per_instance;
bit get_inst_coverage;
} option;
struct { // coverpoint option declaration
int weight;
int goal;
string comment;
int at_least;
int auto_bin_max;
bit detect_overlap;
} option;
struct { // cross option declaration
int weight;
int goal;
string comment;
int at_least;
int cross_num_print_missing;
} option;
struct { // covergroup type_option declaration
int weight;
int goal;
string comment;
bit strobe;
bit merge_instances;
} type_option;
struct { // coverpoint and cross type_option declaration
int weight;
int goal;
string comment;
} type_option;

288

SystemVerilog Reference

Coverage

Coverage Computation
The cumulative coverage is calculated using the contribution of covergroup types.
The cumulative coverage - C - is the weighted average of the coverage of all covergroup types:

where:
g - set of covergroup types.
Wg - the weight associated with type g.
Cg - the coverage of type g.

Coverpoint Coverage Computation


If coverpoint bins are defined by a user, then the coverpoint coverage computation is as follows:

where:
|bins| - the cardinality of the set of bins defined.
|bins covered| - the cardinality of the covered bins - the subset of all (defined) bins that are covered.
If the bins are automatically generated the computation uses the following equation:

where:
|bins covered| is the cardinality of the covered bins - the subset of all (auto-defined) bins that are covered.
M - the minimum number of bits needed to represent the coverpoint.
auto_bin_max - the value of the auto_bin_max option in effect.
The cumulative coverage considers the union of all significant bins; it includes the contribution of all bins (including
overlapping bins) of all instances.

289

SystemVerilog Reference

Coverage

Cross Coverage Computation


The cross coverage is calculated according to the formula:

where:
j - belongs to a set of crossed coverpoints.
Bj - the cardinality of coverpoint with j number.
Bc - the number of auto-cross bins.
Bu - the number of user-defined cross bins excluding ignore_bing and illegal_bins, i.e. bins that are relevant
for coverage percentage.
Bb - the number of cross products that includes all user-defined cross bins.

Type Coverage Computation


Type coverage is calculated in either of the two following ways depending on the type_option.merge_instances
value.
When true, type coverage percentage is calculated by merging instances together.
Otherwise, type coverage is the weighted average of instances.
When cumulative coverage is computed as the weighted average of instances, only covergroup type instances
contribute to the coverage, not its coverpoints or crosses.

where:
Wi - the weight option of the instance.
Ii - the instance coverage.
Coverpoint or cross type coverage is computed in the same way using coverpoint or cross coverage of each instance.
The return values of get_coverage(ref int, ref int) method are also computed according to the formula
above when type_option.merge_instances is false.

290

SystemVerilog Reference

Coverage

When type_option.merge_instances is true, instances are merged and cumulative coverage is obtained
computing all bins from all instances. When bin name overlapping occurs among instances, cumulative coverage
count of the bin is the sum of the bin counts in all instances containing the bin.
Following formula is used for coverage computation when instances are merged:

where:
i - set of coverage items (coverpoints and crosses).
Wi - the weight associated with item i.
Ci - the coverage of item i.

291

Hierarchy

Packages
SystemVerilog packages are used to group type definitions, data declarations (variables and nets), functions, tasks,
sequence and properties. Packages cannot contain any processes. Wire declarations with implicit continuous
assignments are not allowed.
An example of a package is shown below. The package groups several type definitions and conversion functions.
package colors;
typedef reg [3*8 -1 :0] RGB_t;
typedef reg [3*8 -1 :0] CMY_t;
typedef reg [4*8 -1 :0] CMYK_t;
typedef enum { WHITE, YELLOW, ORANGE, RED, GREEN, BLUE, BLACK } COLORS_t;
function CMY_t rgb2cmy( RGB_t i );
rgb2cmy[23:16] = 8'hFF - i[23:16];
rgb2cmy[15:8] = 8'hFF - i[15:8];
rgb2cmy[7:0] = 8'hFF - i[7:0];
endfunction
function CMYK_t cmy2cmyk( CMY_t i );
reg[7:0] min;
min = i[7:0];
min = (min < i[15:8] ) ? min : i[15:8];
min = (min < i[23:16]) ? min : i[23:16];
cmy2cmyk[31:24] = i[23:16] - min;
cmy2cmyk[23:16] = i[15:8] - min;
cmy2cmyk[15:8] = i[7:0] - min;
cmy2cmyk[7:0] = min;
endfunction
function CMYK_t rgb2cmyk( RGB_t i );
rgb2cmyk = cmy2cmyk( rgb2cmy( i ));
endfunction
endpackage

Packages are declared at the outermost level of source code, alongside modules, interfaces, programs and
user-defined primitives.
It is not allowed to use hierarchical references in packages. Packages can include parameters, nets and variables.
Variable declaration assignments within the package shall occur before initial, always, always_comb,
always_latch, or always_ff processes.

Utilizing Package Contents

292

SystemVerilog Reference

Hierarchy

Referencing Package Contents with Scope Operator


Declarations from packages can be utilized using the scope operator (::), for example:
colors::RGB_t r;
colors::CMYK_t c;
initial begin
r = 24'hFF0055;
c = colors::rgb2cmyk( r );
end

The package must be compiled before it is referenced with the scope operator. Otherwise the compiler will report an
error.

Importing Package Contents


Package declarations can also be made visible in the current scope with the import keyword. After a declaration is
imported, it can be used without the package name qualifier. You can either import one declaration or all declarations
using the wildcard.
// Import one declaration only
import colors::RGB_t;
// Import all declarations
import colors::* ;

The scope where the import keyword is used may contain local declarations that hide declarations from packages.
An explicit import is not allowed if the imported identifier is declared in the same scope or explicitly imported from
another package. Importing an identifier from the same package multiple times is allowed.
The contents of a package can be referenced in a module, an interface, or a program by an import in the header of
such a unit. The contents of such imported packages are visible throughout the unit, including its port and parameter
declarations:
module RGB_2_CMY import colors::*;
// Contents of 'colors' are visible in module's port declarations:
(
output CMY_t out,
input RGB_t in,
input clk
);
// ... and in the module's body:
always @(posedge clk) out = rgb2cmy( in );
endmodule: RGB_2_CMY

Description

Scope containing
a declaration of
Scope
Scope not
the same
containing the
containing the
local declaration local declaration identifier
imported using
of the same
of the same
another package,
identifier, for
identifier, for
for example:
example var1
example var1
o_pckg::var1

293

Scope containing
a declaration of
the same
identifier
imported using
another package
and * symbol, for
example:
o_pckg::*

SystemVerilog Reference

A reference to
package identifier
via the scope
operator ::, for
example my_pckg
:: var1

A package
identifier is
visible in any
scope

Hierarchy
Direct reference
to var1 refers to
the identifier
declared locally.
my_pckg::var1
refers to the
identifier from
package
my_pckg

Direct reference to
var1 refers to the
Direct reference
identifier from the
is illegal.
other package
my_pckg::var1
(o_pckg::var1)
refers to the
my_pckg::var1
identifier from
refers to the
package
identifier from
package my_pckg

Direct reference to
var1 refers to the
identifier from the
other package
(o_pckg::var1)
my_pckg::var1
refers to the
identifier from
package my_pckg

A reference to
package identifier
using import
keyword, for
example import
my_pckg::var1

All package
identifiers are
potentially
directly
Error
visible in the
importing
scope.

Direct reference
to var1 refers to
the identifier
imported from
package
my_pckg.

It is not allowed to
import an identifier
defined in the
importing scope.

The import of
my_pckg::var1
makes any prior
reference to var1
illegal. Otherwise,
direct reference to
var1 refers to the
var1 imported from
package
my_pckg.

A reference to
package identifier
using import
keyword and *
symbol, for
example: import
my_pckg::*;

Imported
identifier is
directly
visible in the
importing
scope.

Direct reference
to var1 refers to
the identifier
imported from
package
my_pckg.

Direct reference to
var1 refers to the
identifier from the
other package
(o_pckg::var1)

It is illegal to
reference var1, it is
undefined.

Direct reference
to var1 refers to
the identifier
declared locally.

Exporting Previously Imported Items


By default, the declarations imported into a package are not available to subsequent imports. To make such contents
available, the export construct is provided. Two forms of export are available:

export package_name::item [, package_name::item ]


Makes the specified items available to subsequent imports. An export of the form package_name::* exports
all declarations that were actually imported from package_name within the exporting package. The items that
are candidates for import but were not actually imported will not be exported.
export *::*
Exports all imported items from all packages from which imports occurred available to subsequent imports.
A package export may precede a corresponding package import.
It is allowed to specify multiple exports that export the same actual declaration. Importing a declaration that was made
available through an export is equivalent to importing the original declaration. Thus, it is not an error to import the
same declaration by means of multiple exported paths:
package p1;
int x, y;
endpackage
package p2;
import p1::x;

294

SystemVerilog Reference

Hierarchy

export p1::*;
endpackage
package p3;
import p1::*;
import p2::*;
export p1::x;
export p2::x;
endpackage

// p1::x and p2::x reference the same item


// thus, they are allowed.

295

SystemVerilog Reference

Hierarchy

Compilation Unit and Top-level Instance

Compilation Unit
Compilation unit refers to a set of files compiled together. Compilation-unit scope is local to the compilation unit. It
contains all declarations that lie outside of any other scope. The name $unit used to explicitly access the identifiers
in the compilation-unit scope.
All files on a given compilation command line build a single compilation unit. In this case the declarations within those
files are accessible anywhere else within the constructs defined within those files. Each file is a separate compilation
unit. In this case the declarations in each compilation-unit scope are accessible only within its corresponding file.
Items defined in the compilation-unit scope cannot be accessed by name from outside the compilation unit. Access to
the items in a compilation-unit scope can be accessed using the PLI, which must provide an iterator to traverse all the
compilation units.

Example
const integer i = 1;
module m;
const integer i = 2;
initial $display( "%0d %0d", i, $unit::i );
endmodule

Constant i is declared outside module m. Another constant named i is declared inside module m. The declaration
inside the module scope hides the declaration at the compilation unit scope. However, the declaration at the
compilation unit scope can still be accessed with the $unit:: prefix. When the code shown in the listing is simulated,
the display statement will print 2 1, i.e. the value of the module-local constant i (2) followed by the value of the
constant i declared in the compilation unit scope (1).

Scoping Rules
The compiler sets the compilation unit scope to all files specified on the command line. Assuming that files f1.sv, f2.sv,
and f3.sv are compiled with the following command
alog f1.sv f2.sv f3.sv

then the compilation unit comprises all three files and the compilation unit scope ($unit::) is shared between all
three files. Files included with the `include directives (if any) are also a part of this compilation unit.
To make each file a separate compilation unit (and have a separate compilation unit scope for each file), compile the
files with separate commands, for example:
alog f1.sv
alog f2.sv
alog f3.sv

Each compiler run will use a different compilation unit consisting of the file specified on the command line and files
included with the `include directive (if any).

296

SystemVerilog Reference

Hierarchy

Top-level Instance
SystemVerilog introduces name $root to unambiguously refer to a top-level instance or to an instance path starting
from the root of the instantiation tree. $root is the root of the instantiation tree. $root allows explicit access to the
top of the instantiation tree.

Example
$root.A.B // item B within top instance A
$root.A.B.C // item C within instance B within instance A

297

SystemVerilog Reference

Hierarchy

Nested and Extern Modules

Nested Modules
SystemVerilog introduces a possibility to declare a module within another module. The outer name space is visible to
the inner module so that any name declared there can be used, unless is hidden by a local name. Nesting of modules
can be used to create logical partitioning of a module without using ports. It can be also used to create a library of
modules that is local to a part of a design.
module device1();
module block1;
interrupts inst1();
reg_block inst2();
always @(posedge clk) o1 = vc[0:3];
endmodule
module block2;
transmitter inst ();
reg_block inst2 ();
assign s1 = t1 & r3;
endmodule
block1 block1_inst ();
endmodule

Binding PSL Units to Nested Modules


Binding PSL vunits to nested modules uses separator :: in the reference to the nested module. The following PSL
vunit v1 is bound to the module block1, which is nested in the module device1. So the vunit v1 references to
device1::block1 name. PSL vunit can be also bound to the nested module instance. The nested module block1
is instantiated in the module device1 with instance name block1_inst. The PSL vunit v2 references to this instance in
the following example.
vunit v1 (device1::block1) {
asrt1: assert always (vc!=0)@rose(clk);
}
vunit v2 (tb.UUT.block1_inst) {
asrt1: assert always (vc!=0)@rose(clk);
}

Extern Modules
Extern modules are introduced to facilitate separate compilation. For regular, non-extern modules, signal connections
are established during the project elaboration when all instances have already been declared. The extern module
declaration allows you to declare a module port list without declaring a module itself, and perform the connection
check earlier, when the project is compiled.
If an instance port does not match an extern module declaration, a warning message is reported:

298

SystemVerilog Reference

Hierarchy

extern module exm(input byte w, input byte x, output byte z);


module top;
byte w,x,z;
exm mm0 (w,x); // warning: unconnected ports
endmodule

When instantiating a module, the wildcard pattern .* may be used in the same way as in the case of non-extern
modules. The following instantiations are equivalent:
exm mm1 (.*);
exm mm2 (w,x,z);

Names, positions, and variable types of the extern and actual module declarations must match. When specifying
module contents, you may use the wildcard pattern .* instead rewriting variable names:
extern module exm(w, x, z);
extern module expm #(parameter width0 = 8, parameter width1 = 4)
(input wire [width0-1:0] a, output bit [width1-1:0] b);
module exm(.*);
input byte w,x;
output byte z;
//...
endmodule
module expm(.*);
//...
endmodule
// above declarations are equivalent to:
module exm(w, x, z);
input byte w,x;
output byte z;
//...
endmodule
module expm #( parameter width0 = 8, parameter width1 = 4)
(input wire [width0-1:0] a, output bit [width1-1:0] b);
//...
endmodule

The extern modules can appear at any hierarchy level, but are visible only within the region where declared.

299

SystemVerilog Reference

Hierarchy

Ports Declarations and Mapping

Ports Declarations
In SystemVerilog, a port may contain declarations of an interface, an event, a variable or net of any allowed data type
including an array, a structure or a union.
typedef enum {start,go,await,stop} states_type;
typedef struct {int a; reg b;} struct_type;
module m (input int i,input states_type state, output struct_type structure);
// ...
endmodule

If no type and direction is specified in the first port, the declaration of type and direction must be located after the ports
list.
module m (a,b,c);
input int a,b;
output reg [3:0] c;
// ...
endmodule

If first port declaration includes the type but there is no direction, the default assumed direction is inout.
module m (wire logic[31:0] a, wire logic[7:0] b);
assign b = a[7:0] & a[15:8];
endmodule

If first port declaration includes the direction but the type is omitted, the wire type is assumed as default.
module m(input a, output b);
// ...
endmodule

If subsequent ports declarations include no type and direction, the type and direction is inherited from the previous
declaration.
module m(input byte a1,a2,a3);
// ...
endmodule

If subsequent ports include type but direction is omitted, it is inherited from the previous port declaration.
module m(input byte a, reg b, int c);
// ...
endmodule

If subsequent ports type include direction but type is omitted the assumed type is wire.
module m(input a, input b, output c);
// ...
endmodule

300

SystemVerilog Reference

Hierarchy

List of Port Expressions


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

Ports Mapping
SystemVerilog expands Verilog facilities related to port mapping.

Implicit Mapping by Name


SystemVerilog introduces implicit .name port connections :
module m (output o, input i);
// ...
endmodule
module top (output o, input i);
// ...
m U1(.i, .o);
endmodule

The .name syntax can be used if the name and size of a port in the instantiated module matches the name and size of
the connecting port or variable. Note that this eliminates the requirement to list a port name twice while still listing all
ports of the instantiated module.

Implicit Mapping by Wildcard


Next additional type of port connections in SystemVerilog is implicit .* port connection:
module m (output o, input i);
// ...
endmodule
module top ();
wire o, i;
m U1(.*);
endmodule

A .* syntax can be used for all ports in the instantiated module where the name and size of a port matches the name
and size of the connecting port or variable.
Implicit .* port connections can be mixed with named port connections:
module m (output o, input i1, i2);
endmodule
module top;
wire w, i1, i2;
m U1 (.o(w), .*);
endmodule

The .* token can be placed anywhere in the port list but it can only appear at most once in the port list, when it is
mixed with named port connections.

301

SystemVerilog Reference

Hierarchy

A named or implicit .name connection can be mixed with a .* connection in one instance.

302

SystemVerilog Reference

Hierarchy

Parameters in Hierarchical Path Name


Parameters and local parameters can be used in hierarchical names. It is useful when dealing with units declared with
loop generate constructs. In following example, generate block is used to create an array of instances within another
array of instances.

module sub;
int k;
endmodule
module top;
int a;
localparam M=2;
parameter J=7;
genvar i;
generate
for(i=0;i<4;i++)
begin:gen
sub s[i:J]();
initial #0 s[J-i].k=i;
end
endgenerate

//parameter & genvar

initial #5 a = gen[M].s[J-M].k;
endmodule

Parameters can be used in hierarchical paths to variables declared inside these module instances. It can be done
inside generate block or outside of it. Loop index variables, which are always declared as genvar, also can be used in
such hierarchical references.

303

SystemVerilog Reference

Hierarchy

Timeunit and Timeprecision


Module timeprecision and timeunit can be specified with the new timeprecision and timeunit keywords, for example:
// SystemVerilog Extension
module m();
timeprecision 1ps;
//...
endmodule
module m();
timeunit 1ns;
//...
endmodule

The Verilog standard (IEEE Std 1364) requires using the `timescale directive:
`timescale 1ns / 1ps

304

SystemVerilog Reference

Hierarchy

Configurations
Configurations are described in Verilog Reference. Additionally, SystemVerilog supports setting parameters in
configurations. For more information, refer to 33.4 in IEEE Std 1800-2009.

Example
config cfg1;
localparam S = 24;
design lib_top.top;
instance top.a1 use
instance top.a2 use
instance top.a3 use
instance top.a4 use
endconfig

#(.W(16),.D(512));
#(.W());
#();
#(.W(S));

For the a1 instance, the use clause sets the values for the W and D parameters.
In the a2 instance, the use clause sets the W parameter to its default value.
In the instance a3, the clause sets the default values for all instance parameters.
The clause applied in the instance a4 assigns the localparam value to the W parameter.

Important Notes
The parameter specified by a configuration will have a priority even if the value of the defparam statement is
passed.
It is impossible to refer to any constructs which are under the generate statement by using the configuration.
Passing parameters in configuration can only be done by name.

305

SystemVerilog Reference

Hierarchy

Type Parameters in Parameterized Design Elements


SystemVerilog provides a possibility of defining type parameters in the design elements such as modules, interfaces,
programs, etc. This feature extends value-based parameterization known from Verilog and it allows writing more
generic units which can be later specified by defining the type parameters in a unit instantiation, for example:
module adder#( parameter type T =integer)(output
always_comb
o = i1+i1;
endmodule
module top;
reg[3:0] r1,r2,r3;
int i1,i2,i3;
adder #(reg[3:0]) adder_vector4val(r1,r2,r3);
adder #(int) adder_int2val(i1,i2,i3);
endmodule

T o, input T i1,i2);

The following constructs are supported:


templates of interfaces, modules and programs
variable declarations
port declarations
net declarations
continuous assignments
nested classes
task and function declarations
always/initial processes
procedural statements
submodule instantiations
NOTE: To receive the latest status on supported constructs, contact Aldec Support.

306

Interfaces

Interface Declaration
SystemVerilog interface encapsulates communication between blocks. The interface can be accessed as a single
port item; using it reduces the size of description and improves the code maintainability.
Using parameters, constants, variables, functions, tasks, assertions, covers and processes in the interface enhances
its functionality isolated from module and can be useful for system-level modeling and testbench applications.
The example below shows a declaration of interface itf.
interface itf;
reg a;
reg b;
reg [1:0] c1;
reg [1:0] c2;
endinterface: itf

An interface can contain a smaller interface and can be passed through ports. It can be used in a declaration of a
module, for example:
module mod1(itf if1, input en);
// ...
endmodule
module mod2(itf if2, input clk);
// ...
endmodule

Interfaces can be instantiated hierarchically, like modules, with or without ports. They can also be nested in a module
instantiation, for example:
module top;
logic clk = 0;
//interface instance
itf sv_itf();
// connect the interface by position
mod1 UUT1(sv_itf, clk);
// or by name
mod2 UUT2(.if2(sv_itf), .clk(clk));
endmodule

Note that only one change in the source code is required if the interface between modules changes. You only need to
edit the declaration of itf. Module declarations and module instantiations will stay intact. Variables declared in the
interface can be referenced by using the dot (.) operator.
module mod1(itf if1, input en);
always @(posedge if1.a)
if1.c1 = if1.c2;
// ...
endmodule

307

SystemVerilog Reference

Interfaces

Interface Ports
Nets and variables declared within the interface can be only used to connect to a port with the same nets and
variables. If the external net variable must be shared using an interface, the port declaration must be used. The
interface ports can be connected externally by name or position when the interface is instantiated.

Example
interface itf ( input clk, input a, input b, output c);
endinterface
module mod1(itf i1);
// ...
endmodule
module top;
logic clk,x,y,z;
itf itf_1 ( .clk,.a(x),.b(y),.c(z));
mod1 mod1_i1 (.i1(itf_1));
// ...
endmodule

308

SystemVerilog Reference

Interfaces

Modports
SystemVerilog introduces modport construct. It provides direction information for module ports and to control the use
of tasks and functions within particular modules.
interface itf;
wire a, b, c, d;
modport master (input a, b, output c, d);
modport slave (output a, b, input c, d);
endinterface
module m (itf.master i);
// ...
endmodule
module s (itf.slave i);
// ...
endmodule
module top;
itf i();
m u1(.i(i));
s u2(.i(i));
endmodule

The modport can also be specified in the port connection with the module instance, where the modport name is
hierarchical from the interface instance.
module m (itf i);
//...
endmodule
module s (itf i);
//...
endmodule
module top;
itf i();
m u1(.i(i.master));
s u2(.i(i.slave));
endmodule

All of the names used in a modport declaration must be declared by the same interface as the modport itself. In
particular, the names used shall not be those declared by another enclosing interface, and a modport declaration shall
not implicitly declare new ports.

Modport Expressions
You can specify the elements of arrays and structures, concatenations of elements, and assignment pattern
expressions of elements declared inside an interface as the modport items. The modport items declared as one of
these constructs are called the modport expressions.
The modport expressions are explicitly named with a port identifier which is accessible only through the modport
connection. The port identifiers exist in their own name space for each modport list. If a modport expression is a
simple port identifier, that identifier is used as both the port identifier and the reference to a variable declared in the
interface. It is not allowed to specify multiple port identifiers of the same name in the modport declaration.

309

SystemVerilog Reference

Interfaces

Example
In the following example, there are two modport expressions: the first one, denoted by the p1 port identifier, is an
element of the a two-dimensional array. The second one, denoted by the p2 port identifier, is a part-select of the b
logic vector.
interface I;
integer a [3:0][2:1];
logic [3:0] b;
modport mp (input .p1(a[0][1]), output .p2(b[1:0]));
initial a[0][2:1] = {36,78};
endinterface
module top;
I I();
m1 m1(I.mp);
endmodule
module m1(I i);
initial begin
i.p2 = '1;
#1 $display("i.p1 = %0d, i.p2 = %0b",i.p1, i.p2);
end
endmodule

Clocking Blocks and Modports


For synchronization requirements use clocking block on modport.

interface itf(input clk);


wire a, b, c, d;
clocking cb @(posedge clk);
output c,d;
input a,b;
endclocking
modport master (clocking cb);
modport slave (output a, b, input c, d);
endinterface
module M(itf.master i);
logic val;
initial i.cb.c <= ##3 val;
//....
endmodule

310

SystemVerilog Reference

Interfaces

Tasks and Function in Interfaces


Tasks and functions can be defined in interfaces. A Module which is connected to an interface, can use tasks and
functions declared within that interface.
interface itf (input clk, input ce,input wr, inout [7:0] data);
task read;
// ...
endtask : read
task write;
// ...
endtask : write
endinterface
module mod1(interface any_itf);
always @(posedge any_itf.clk)
if (~any_itf.ce & any_itf.wr)
any_itf.read;
else if (~any_itf.ce & ~any_itf.wr)
any_itf.write;
endmodule

Tasks and Functions in Modports


In a modport, the import construct can either use function or task prototypes or use just the identifiers. The only
exceptions are when a modport is used to import a function or task from another module and when default
argument values or argument binding by name is used, in which cases a full prototype shall be used. It is illegal when
a modport contains a task prototype that does not match the full task description (i.e. different number of ports).
Following example shows how tasks can be used in modports. Since sb instance uses modport A, it has only access
to send task.
interface itf;
bit from_A_to_B;
modport A (output from_A_to_B,
import task send(input byte data));

modport B (input from_A_to_B,


import receive);

// Full task prototype

// Task identifier only

task send (input byte data);


// ...
endtask : send
task receive (output byte store);
// ...
endtask : receive
endinterface

311

SystemVerilog Reference

Interfaces

module sub(itf a);


byte temp;
initial a.send(temp);

// Call task "send" from interface itf

endmodule

module top();
itf iface();
sub sb(iface.A);

// Instance uses modport A

endmodule

Task Export in Modport


NOTE: The export constructs are not supported in this release. Please contact Aldec Support to receive the latest
status.

Multiple Tasks Exports


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

312

SystemVerilog Reference

Interfaces

Parameterized Interfaces
The interface declaration can be parameterized as a module or program declaration.

Example
interface itf
#(parameter byte WIDTH = 8, int MIN = 0, int MAX = 10)
(input clk, input ce,input set,inout [WIDTH-1:0] data);
endinterface
module m(interface any_itf);
endmodule
module top;
itf #(4,1,12) itf_i (.set(ld),.*);
m m_inst(.any_itf(itf_i));
// ...
endmodule

NOTE: An interface assignment to another interface with different actual parameters is not allowed in the IEEE Std
1800-2009. You can use this construct, however, in the IEEE Std 1800-2005 compatibility mode (the -sv2k5
acom argument).
virtual itf #(5,3,14) itf_v1;
initial itf_v1 = itf_i;

Above, a virtual interface of the type defined in previous example is initialized with the itf_v1 interface. The
interfaces have different actual parameters. This assignment will trigger an error unless the IEEE Std 1800-2005
compatibility mode is in use.

313

SystemVerilog Reference

Interfaces

Interfaces and Specify Blocks


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

314

SystemVerilog Reference

Interfaces

Virtual Interfaces
A virtual interface is a variable that represents an interface instance. Virtual interfaces provide a mechanism for
separating abstract models and test programs from the actual signals that make up the design. By using virtual
interfaces, you can construct a subprogram that operates on different parts of a design, and dynamically control the
set of signals associated with the subprogram.

Syntax
virtual_interface_declaration ::= virtual [ interface ] interface_identifier
list_of_virtual_interface_decl ;
list_of_virtual_interface_decl ::= variable_identifier [ = interface_instance_identifier ]
{ , variable_identifier [ = interface_instance_identifier ] }
data_declaration ::= ... | virtual_interface_declaration
data_type ::= ... | virtual [ interface ] interface_identifier

Virtual interface variables can be arguments of tasks, functions, or methods.


A virtual interface must be initialized before it can be used; it has the value null before it is initialized. It is not allowed
to use an uninitialized virtual interface.
The following operations are allowed on virtual interface variables:
Assignment of another virtual interface of the same type.
Assignment of an interface instance of the same type.
Assignment of null.
Comparison (== or !=) to another virtual interface of the same type.
Comparison (== or !=) to an interface instance of the same type.
Comparison (== or !=) to null.
Virtual interfaces cannot be used as ports, interface items, or union members.
The components of the underlying interface instance are directly available to the virtual interface via the dot notation.
These components can only be used in procedural statements, including event control statements; they cannot be
used in continuous assignments.
interface itf;
logic a;
logic b;
endinterface
module top;
itf i1();
virtual itf vi = i1;
initial begin
#10 i1.a = 0;
#10 i1.a = 1;
end
always @(vi.a) begin
vi.b = !vi.a;
end

315

SystemVerilog Reference

Interfaces

//...
endmodule

Virtual interfaces can be declared as class properties, which can be initialized procedurally or by an argument to
new().
interface itf;
logic req, ack;
endinterface
class C;
virtual itf itf_var;
function new(virtual itf itf_in);
itf_var = itf_in;
endfunction
task request();
itf_var.req = 1'b1;
endtask
endclass
module device (itf i);
//...
endmodule
program prog (itf i);
C c = new(i);
initial begin
//...
c.request();
end
endprogram
module top;
logic req, ack;
itf itf_inst ();
device devinst (itf_inst);
prog proginst (itf_inst);
endmodule

Virtual interfaces and clocking blocks


If interface signals are synchronized using a clocking block construct, a testbench program may use all advantages
offered by this synchronization feature.

interface itf(input clk);


logic req,ack;
clocking cb@(posedge clk);
output req,ack;
endclocking
endinterface
class C;
virtual itf itf_var;
function new(virtual itf itf_in);
itf_var = itf_in;

316

SystemVerilog Reference

Interfaces

endfunction
task request();
itf_var.cb.req <= ##2 1'b1;
endtask
endclass

Virtual interface modports and clocking blocks


To restrict testbench access, modport construction may be used:

interface itf(input clk);


logic req,ack;
clocking cb@(posedge clk);
output req,ack;
endclocking
modport TBasync(output req,ack);
modport TBsync (clocking cb);
endinterface
class C;
virtual itf.TBasync itf_var_async;
virtual itf.TBsync itf_var_sync;
function new(virtual itf itf_in);
itf_var_async = itf_in;
itf_var_sync = itf_in;
endfunction
task request(bit sync);
if(sync) itf_var_sync.cb.req <= 1'b1;
else
itf_var_async.req = 1'b1;
endtask
endclass

317

System Tasks and Functions

Display Tasks and Functions

Overview

Name

Syntax

Description
When one of the display tasks is invoked, it simply prints
its arguments. The $display task adds a new line
character at the end of the output. The display tasks are
very similar to the print functions in the ANSI C language.

$display

$display [(arguments)]

$displayb

$displayb [(arguments)]

$displayh

$displayh [(arguments)]

$displayo

$displayo [(arguments)]

An argument can be an expression that returns a value,


and a quoted string. The order of printed arguments is the
same as the order that appears in the argument list.
The display tasks have a special character (%) to indicate
that the information about signal value is needed. When
using a string, the compiler recognizes the % character
and knows that the next character is a format specification
(%d, %b, %h, %o, %c, %v, %m, %s, %t, %p). The
%p format specifier can be used by $display system
task for displaying objects with unpacked structure data
types such as unpacked structures, arrays, and unions.
See Printing Aggregates Using %p and %0p Formats for
details.
When one of the write tasks is invoked, it simply prints its
arguments. The write tasks are very similar to print
functions in the ANSI C language.

$write

$write [(arguments)]

$writeb

$writeb [(arguments)]

$writeh

$writeh [(arguments)]

$writeo

$writeo [(arguments)]

The $write task works in the same way as $display


task and the only difference is that the $display task
adds a new line character at the end of the output.
An argument can be an expression that returns a value,
and a quoted string. The order of printed arguments is the
same as the order that appears in the argument list.
The $write task supports all format specifiers supported
by $display task.

$fdisplay
$fwrite

$fdisplay (output_var,
format_string [ ,
list_of_arguments ])

The $fdisplay and $fwrite functions append data to


a file and work in the same way as their corresponding
display tasks.

318

SystemVerilog Reference
$fwrite (output_var,
format_string [ ,
list_of_arguments ])

System Tasks and Functions


The only difference is a file descriptor that appears as the
first argument in the function argument list.
Another arguments can be an expression that returns a
value, and a quoted string. The order of printed arguments
is the same as the order that appears in the argument list.
The $fdisplay and $fwrite tasks supports all format
specifiers supported by $display.
The $sformat task is similar to the $write task, but
always interprets its second argument, and only its
second argument, as a format string. The $sformat is
similar to $sformat task, but places the string result in
the first argument. See $sformat system task for details.

$sformat

$sformat (output_var,
format_string [ ,
list_of_arguments ])

The format argument can be a string literal, such as "data


is %d", or may be an expression of integral, unpacked
array of byte, or string data types whose content is
interpreted as the formatting string. The $sformat
supports all format specifiers supported by $display
task, except %p format specifier used for displaying
objects with unpacked structure data types such as
unpacked structures, arrays, and unions.
The $sformatf function behaves like $sformat system
task except that the string result is passed back as the
function result value. See $sformatf system function for
details.

$sformatf

$psprintf

$sformatf ( format_string
[ , list_of_arguments ])

$psprintf ( format_string
[ , list_of_arguments ])

The format argument can be a string literal or expression


of integral, unpacked array of byte, or string data types
whose content is interpreted as the formatting string. The
$sformat supports all format specifiers supported by
$display system task.
The $psprintf function is described in the Verification
Methodology Manual for SystemVerilog, albeit is not
included in the Language Reference Manual. The
$psprintf function is an extension to IEEE 1800-2005.
It is used in several open source verification libraries.
The $psprintf function works in the same way as
$sformatf system function. The $psprintf function
can be used everywhere where string is allowed. The
string result is passed back to the user as the function
return value.
Unlike other system tasks and functions, $psprintf
function cannot be overridden by a user-defined system
function in the PLI. See $psprintf function for details.
The format argument can be a string literal or expression
of integral, unpacked array of byte, or string data types
whose content is interpreted as the formatting string. The
$psprintf function supports format specifiers supported

319

SystemVerilog Reference

System Tasks and Functions


by $display. The %p format specifier cannot be used by
$psprintf system task for displaying objects with
unpacked structure data types such as unpacked
structures, arrays, and unions.

$display system task


The $display task prints specific information from the simulator. The task displays its arguments in the same order
as they appear in the argument list using the corresponding format specification. The escape sequences are used for
format specifications.
When using a string with % character, the compiler recognizes the % character and knows that the next character is a
format specification. When $display system task is executed it displays the string, and the format specifier is
replaced with a corresponding expression value.
The $display task also supports additional escape sequence used for the format specification.

Example
module top;
int r1;
initial begin
r1 = 10;
$display( "Default printing - :%d: :%h:", r1,r1 );
$display( "Printing with minimum size - :%0d: :%0h:", r1,r1 );
$display( "Printing with defined size - :%4d: :%4h:", r1,r1 );
$display( "Printing with defined size (leading zeros for decimal format added) - :%04d: :%04h:", r1,r1
);
end
endmodule

NOTES:
The escape sequence %0<N> works only for the decimal format specifier. For other specifiers, 0 after the %
character is ignored.
For the list of available escape sequences for format specifications, see 21.2.1.2 in IEEE Std 1800-2012.

$sformat system task


The $sformat system task is similar to the $swrite system task, with one major difference. Unlike the display and
write family of output system tasks, $sformat always interprets its second argument, and only its second argument,
as a format string. This format argument can be a string literal, such as "data is %d", or may be a an expression of
integral, unpacked array of byte, or string data types whose content is interpreted as the formatting string. No other
arguments are interpreted as format strings. $sformat supports all the format specifiers supported by $display.

Syntax
variable_format_string_output_task ::=
$sformat ( output_var , format_string [ , list_of_arguments ]);

320

SystemVerilog Reference

System Tasks and Functions

Example
byte dynamic_arr [] = new[2]('{8'd1, 8'd2});
byte assoc_arr [string] = '{"a":8'd1, "b":8'd2};
int intvar = 140;
string a,b,c;
initial begin
$sformat(a, "%p", dynamic_arr);
$sformat(b, "%p", assoc_arr);
$sformat(c, "%d", intvar);
end

$sformatf system function


The system function $sformatf behaves like $sformat system task except that the string result is passed back as
the function result value for $sformatf, not placed in the first argument as for $sformat. Thus $sformatf function
can be used where a string value would be valid.

Syntax
variable_format_string_output_function ::=
$sformatf ( format_string [ , list_of_arguments ])

Example
byte dynamic_arr [] = new[2]('{8'd1, 8'd2});
byte assoc_arr [string] = '{"a":8'd1, "b":8'd2};
int intvar = 140;
initial begin
$sformatf("%p", dynamic_arr);
$sformatf("%p", assoc_arr);
$sformatf("%d", intvar);
end

$psprintf function
The $psprintf function works in the same way as $sformatf system function. The string result is passed back to
the user as the function return value.
The $psprintf function can be used where a string is valid. Note that at this time, unlike other system tasks and
functions, $psprintf cannot be overridden by a user-defined system function in the PLI.

Syntax
variable_format_string_output_task ::=
$psprintf ( format_string [ , list_of_arguments ]);

321

SystemVerilog Reference

System Tasks and Functions

Example
function void ovm_report_warning(string id,
string message,
int verbosity = OVM_MEDIUM,
string filename = "",
int line = 0);
ovm_top.ovm_report_warning(id, message, verbosity, filename, line);
endfunction
ovm_report_warning("CRFLD", $psprintf("The create method failed for %s,
object cannot be cloned", get_name()));

Printing Aggregates Using %p and %0p Formats


SystemVerilog allows printing complex data structures such as arrays, structures, or classes in a straightforward
manner using the %p or %0p format specifiers. The %p specifier formats the output into a form similar to an assignment
pattern. The %0p specifier allows presenting the data stored in an aggregate in a simplified form, as a list of values.
The %p and %0p formats are used with the $display and $write families of tasks.

Arrays
Given the following array definition:
reg [7:0] arr [3:0] = '{ 8'bxxxxxxxx, 8'd5, 8'b00zz11zz, 8'b00xx11zz };

you could display the array arr using the following $display statement:
$display( "%p", arr );

The output will look as an array literal:


'{x, Z, 6, X}

You could also use the %0p format specifier:


$display( "%0p", arr );

which would print a simple list of the array items:


x 5 Z X

The value of each element is printed using the %d format, therefore:


A small x indicates a value consisting entirely of x's. Likewise, a small z indicates a value consisting entirely
of z's.
A capital X is used when the displayed value contains at least one x (alongside other values).
A capital Z is used for values with at least one z (alongside 0's and 1's and no x's).
Finally, when there are no unknown values (x or z), a numeric value in the decimal notation is shown.
Below are examples of different types of arrays and different types of output:

322

SystemVerilog Reference

System Tasks and Functions

int unpacked_arr [3] [2]= '{'{1, 2}, '{3, 4}, '{5, 6}};
bit [2] packed_arr = '{'b1, 0};
byte dynamic_arr [] = new[2]('{8'd1, 8'd2});
byte assoc_arr [string] = '{"a":8'd1, "b":8'd2};
initial begin
$display("unpacked array = %p", unpacked_arr);
$display("packed array = %p", packed_arr);
$display("dynamic array = %p", dynamic_arr);
$display("assoc array = %p", assoc_arr);
end
unpacked array = '{'{1, 2}, '{3, 4}, '{5, 6}}
packed array = 2
dynamic array = '{1, 2}
assoc array = '{"a":1, "b":2}

Structures
The output of %p format for values that are structures is printed in a form similar to an assignment pattern with named
elements. For example, given the following definition:
typedef struct {
int a;
reg [7:0] arr [7:0];
} s_t;
s_t strt;

the following $display statement:


$display( "%p", strt );

would yield the following output:


'{a:0, arr:'{x, x, x, x, x, x, x, x}}

Names of structure elements (a and arr) are followed by values. Name-value pairs are separated by commas.
Using the %0p format specifier:
$display( "%0p", strt );

prints the structure data in a format similar to a positional notation of an assignment pattern. Additionally, the array
contents are printed as a simple list:
'{0, x x x x x x x x}

Packed Unions
Using the %p format specifier for a packed union prints the name of the first field of the union and then the actual
value. The %0p format specifier prints only the actual value of a union in a format similar to an assignment pattern.
For example, given the following definition:
typedef union packed {
reg [7:0] r1;

323

SystemVerilog Reference

System Tasks and Functions

reg [7:0] r2;


} un;
un u1;

the following $display statements:


initial begin
u1.r1 = 8'h00;
u1.r2 = 8'hff;
$display("%p", u1);
$display("%0p", u1);
end

would yield the following output:


'{r1:255}
'{255}

Class Handles
Uninitialized class handles or handles that have been assigned null are shown by using the string null. Class
handles that are not null are printed similarly to structures, by using name-value pairs.
Given the following definitions:
typedef struct {
int a;
reg [7:0] arr [7:0];
} s_t;
s_t str;
class C;
s_t strt;
reg [7:0] r;
endclass

the following code:


C c1;
C c2;
initial begin
c2 = new;
$display( "%p", c1 );
$display( "%p", c2 );
end

would produce the following output:


null
'{strt:'{a:0, arr:'{x, x, x, x, x, x, x, x}}, r:x}

Note that the contents are printed recursively.


A class can contain properties that are themselves class handles. The contents of member handles are also printed
by default. For example, given the following definitions:
class C;
int foo;
int bar[2];

324

SystemVerilog Reference

System Tasks and Functions

endclass
class D;
int i = 1;
C c1 = new;
C c2 = new;
C c3;
endclass
D d = new;

the $display("%p", d) task would produce the following output:


'{i:1, c1:'{foo:0, bar:'{0, 0}}, c2:'{foo:0, bar:'{0, 0}}, c3:null}

Limiting Output with %0p


Instead of using %p, you can use %0p as the format specifier. This limits the output for class handles.
Properties that are themselves class handles are not printed recursively. Instead, the simulator outputs
<class handle> or null (depending on whether the member handle is null or not).
Property names are not printed, only their values.
Given the following definitions:
class C;
int foo;
int bar[2];
endclass
class D;
int i = 1;
C c1 = new;
C c2 = new;
C c3;
endclass
D d = new;

the $display("%p", d) and $display("%0p", d) tasks would produce the following output:
'{i:1, c1:'{foo:0, bar:'{0, 0, 0, 0}}, c2:'{foo:0, bar:'{0, 0, 0, 0}}, c3:null}
'{1, <class handle>, <class handle>, null}

Circular References
Class handles can contain circular references to each other. Consider a class C containing two properties: an int and
a handle to C.
class C;
function new( int id );
this.id = id;
endfunction
int id;
C next;
endclass

325

SystemVerilog Reference

System Tasks and Functions

Three instances of the class are created. The handle c1 contains a reference to c2, c2 references c3, and c3
references c1, which makes a circular reference.
C c1 = new(1);
C c2 = new(2);
C c3 = new(3);
initial begin
c1.next = c2;
c2.next = c3;
c3.next = c1;
$display( "%p", c1 );
end

To prevent an infinite loop, the simulator makes sure that each handle is printed only once: The $display statement
will produce the following output:
'{id:1, next:'{id:2, next:'{id:3, next:<circular reference, class already printed>}}}

Truncating %p Field
For large data structures, the text for the %p field could be very large. The simulator imposes a hard-coded limit and
truncates the output when the limit is exceeded. This results in the following message on the console:
Warning: RUNTIME_0195 dty_pformat_ex3.sv (26): The output for the %p field
exceeded the maximum allowed length and was truncated to 69918 characters. If the
output contains class handles, you can limit excessive output by using %0p
instead of %p. (%0p prevents recursive class printing.)

Default Mode
If the format specifier is omitted, %p format is used by default. However, in the case of packed structures and unions,
there are some differences between %p and the default mode.
Printing the contents of a packed structure with or without the format specifier, for example:
struct packed {
reg r1;
reg [7:0] r2;
} s1;
s1.r1=1'b1;
s1.r2=8'hff;
$display("%p",s1);
$display(s1);

yields different types of output:


'{r1:1, r2:255}
511

Note that in the case of the default output (%p not used), the representation of bits stored in separate fields of the
structure has been merged into a single vector.
Similarly, printing the contents of a union with and without the format specifier:

326

SystemVerilog Reference

System Tasks and Functions

union packed {
reg [7:0] r1;
reg [7:0] r2;
} u1;
u1.r1=1'b1;
u1.r2=8'hff;
$display("%p",u1);
$display(u1);

gives different kinds of output:


'{r1:255}
255

327

SystemVerilog Reference

System Tasks and Functions

Conversion Functions
Conversion Function are provided to convert values to and from real number values.
Prototype

Input Argument
Type

Result Type

Description
Converts real value to an integer type by
truncating the real value, e.g 654.32 is
converted to 654.

$rtoi
(input_arg)

real

integer

$itor
(input_arg)

integer

real

Converts integer values to real values,


e.g. 1417 is converted to 1417.0.

$realtobits
(input_arg)

real

64-bit vector

Converts values from a real type to a


64-bit vector representation of the real
number.

$bitstoreal
(input_arg)

64-bit vector

real

Converts a bit pattern created by


$realtobits to a value of the real
type.

$shortrealtobits
shortreal
(input_arg)

32-bit vector

Converts values from a real type to a


32-bit vector representation of the real
number.

$bitstoshortreal
32-bit vector
(input_arg)

shortreal

Converts a bit pattern created by


$shortrealtobits to a value of the
shortreal type.

$signed
(input_arg)

any unsigned type

signed input type

Transforms an unsigned input expression


into a signed expression without changing
its value and size.

$unsigned
(input_arg)

any signed type

unsigned input type

Transforms a signed input expression into


an unsigned expression without changing
its value and size.

The $rtoi function differs from the cast


operator or implicit casting (i.e. direct real
to integer assignment) in that the latter
ones perform rounding rather than
truncation.

328

SystemVerilog Reference

System Tasks and Functions

Data Query Functions

$bits Function
SystemVerilog introduces expression size system function $bits. The function returns the number of bits required to
hold an expression as a bit stream. A 4-state value counts as one bit.
reg [7:0] a;
typedef struct {
byte b;
reg [1:0] c;
} T;
initial begin
$display( "%0d", $bits( a )); //Displays 8.
$display( "%0d", $bits( T )); //Displays 10.
end

The $bits function can be used as an elaboration time constant when used on fixed-size data types; hence, it can be
used in the declaration of other data types, variables, or nets. The $bits system function returns 0 when called with a
dynamically sized expression that is currently empty. It is illegal to use the $bits system function directly with a
dynamically sized data type identifier.

$typename Function
The $typename system function returns a string that represents the type of its argument. In the returned string, the
default signing is omitted, superfluous white spaces are removed and the array name is replaced with the $ sign. For
example, the $typename result in the below code is int$[-3:4].
module top;
string name;
int arr1[-3 : 4];
initial name = $typename(arr1); // result is: int$[-3:4]
endmodule

NOTE: The types supported by the $typename function are limited to the SystemVerilog built-in types and fixed-size
arrays of these types. Please contact Aldec Support to receive the latest status.

$isunbounded Function
NOTE: $isunbounded is not supported in this release. Please contact Aldec Support to receive the latest status.

329

SystemVerilog Reference

System Tasks and Functions

Array Query Functions


SystemVerilog introduces new functions returning information about arrays: $left, $right, $low, $high,
$increment, $size, $dimensions, and $unpacked_dimensions. These functions are described in Arrays and
Queues | Array Querying Functions.

330

SystemVerilog Reference

System Tasks and Functions

Severity System Tasks


SystemVerilog introduces special tasks that allow triggering specific exceptions during simulation: $fatal, $error,
$warning, and $info. The severity tasks can be used, for example, in the assertion fail statements to indicate the
severity level of particular assertion failures.
Prototype

Description

$fatal(level,
message_args)

Generates a run-time fatal error, which terminates the simulation with an error
code. The first argument, level, specifies the level of diagnostic information to
be reported by the simulator and is consistent with the corresponding argument of
the $finish task. $fatal results in an implicit call to $finish.

$error(message_args)

Generates a run-time error. The simulation is continued.

$warning(message_args)

Generates a run-time warning. The simulation is continued.

$info(message_args)

Generates a message.

The message_args argument in the syntax of these commands designates a user-defined message to be printed
when the task is called. The argument is a formatting string with an optional list of expressions to be inserted into the
% fields of the formatting string, and is identical to the argument specified to the $display system task.

Example
CheckCounter: assert property (CheckCnt)
$info("Assertion property CheckCounter passed");
else
begin
++error;
$error("Assertion property CheckCounter failed %0d times", error);
end

331

SystemVerilog Reference

System Tasks and Functions

Assertion Control System Tasks


There are three system tasks which allow controlling the evaluation of assertion statements - $asserton,
$assertoff, $assertkill.

$asserton [ ( levels [ , list_of_modules_or_assertions ] ) ] ;


$assertoff [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertkill [ ( levels [ , list_of_modules_or_assertions ] ) ] ;

The task is applied to all assertions in the design if is specified without arguments. The levels argument indicates
levels of hierarchy (see $dumpvars system tasks). The list_of_modules_or_assertions determines which
scope of the design should be controlled by the task. It can be a module name, an assertion name, can be also a
hierarchical name.
$assertoff stops (turns off) checking of all assertions mentioned in the task call (or all assertions in the design if no
arguments specified). This action does not affect the assertion evaluations, which are started before $assertoff
call. The assertions stay turned off until the next $asserton execution. The queued reports of a deferred assertion
are not flushed when $assertoff is executed. The reports may still mature until the subsequent $asserton. The same is
for pending procedural assertion instances, queued instances are not flushed, no new instances may be queued until
the $asserton.
$asserton turns on checking of all specified assertions (or all assertions in the design).
$assertkill aborts all pending evaluations of assertions and stops checking of all specified assertions (or all
assertions in the design in the case of no arguments in the task call) until a subsequent $asserton. The
$assertkill flushes all queued pending reports of deferred assertions and all pending procedural assertion
instances that have not yet matured.
Example

property p1;
@(posedge clk) a |-> ##2 !b;
endproperty
asrt1: assert property(p1);
covr1: cover sequence (@(posedge clk) a ##3 b);
asrt2: assert property(@(posedge clk) not (a ##2 b));
initial begin
#100;
$assertoff; /* turns off asrt1, asrt2, covr1 */
#60;
$asserton; /* turns on asrt1, asrt2, covr1 */
#60;
$assertoff(0,asrt1,covr1); /* turns off asrt1, covr1 */
#60;
$asserton(0,asrt1);
/* turns on only asrt1, covr1 is off */
#60;
$asserton; /* turns on covr1 */
#60;
$assertkill; /* kills asrt1, asrt2, covr1 */
#120;
$asserton; /* turns oon asrt1, asrt2, covr1 */
#100;
end

332

SystemVerilog Reference

System Tasks and Functions

Assertion Action Control System Tasks


By default, both pass and fail action blocks are executed for both vacuous and nonvacuous evaluations of assertions.
By using the assertion action control tasks, you can enable or disable pass and/or fail action blocks for assertions that
are evaluated vacuously and/or nonvacuously.
NOTE: The distinction between vacuously and nonvacuously failed evaluations of assertions is a proprietary
extension to SystemVerilog developed by Aldec. Depending upon the simulation options specified by the user, this
feature can either be enabled or disabled.
The following system tasks are provided to control the execution of assertion action blocks:
$assertpasson [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertpassoff [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertfailon [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertfailoff [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertnonvacuouson [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertvacuousoff [ ( levels [ , list_of_modules_or_assertions ] ) ] ;

As an extension to SystemVerilog specification, Aldec supports two complementing tasks:


$assertnonvacuousoff [ ( levels [ , list_of_modules_or_assertions ] ) ] ;
$assertvacuouson [ ( levels [ , list_of_modules_or_assertions ] ) ] ;

The levels argument indicates how many levels of the hierarchy below each specified module instance the task
should be applied. Specifying 1 applies the command specified instance only; specifying 2 forces the task to descend
one level below and applies the command to two hierarchy levels (the specified instance and all regions one level
below). An arbitrary number of levels can be specified. Specifying 0 applies the command to a specified module and
all module instances below that module.
The list_of_modules_or_assertions specifies which design regions the task should be applied to; the
arguments can specify a module, a program, an interface, an always or initial procedure, or a specific assertion.
Assertions that are already executing are not affected by the tasks. The tasks do not affect assertion statistics
counters.
Below are descriptions of the operation of particular assertion action control tasks:

$assertpassoff
Disables execution of the pass action for vacuous and nonvacuous success of the specified assertions.
Execution of the pass action can then be re-enabled for nonvacuous ($assertnonvacuouson), vacuous
($assertvacuouson), or both types of evaluation ($assertpasson).
$assertfailoff
Disables execution of the fail action for vacuous and nonvacuous fails of the specified assertions. Execution of
the fail action can then be re-enabled for nonvacuous ($assertnonvacuouson), vacuous
($assertvacuouson), or both types of evaluation ($assertfailon). This task also affects the default fail
action, i.e. the $error task.
$assertvacuousoff
Disables execution of pass and fail actions for vacuous evaluations of the specified assertions. Execution of
assertion actions can then be re-enabled for the pass action ($assertpasson), fail action
($assertfailon), or for both types of actions ($assertvacuouson).

333

SystemVerilog Reference

System Tasks and Functions

$assertpasson
Enables execution of the pass action for vacuous and nonvacuous success of the specified assertions.
Execution of the pass action can then be disabled for nonvacuous ($assertnonvacuousoff), vacuous
($assertvacuousoff), or both types of evaluation ($assertpassoff).
$assertfailon
Enables execution of the fail action for vacuous and nonvacuous fails of the specified assertions. Execution of
the fail action can then be disabled for nonvacuous ($assertnonvacuousoff), vacuous
($assertvacuousoff), or both types of evaluation ($assertfailoff). This task also affects the default
fail action, i.e. the $error task.
$assertnonvacuouson
Enables execution of pass and fail actions for nonvacuous evaluations of the specified assertions. Execution
of assertion actions can then be disabled for the pass action ($assertpassoff), fail action
($assertfailoff), or for both types of actions ($assertvacuousoff).
$assertnonvacuousoff
Disables execution of pass and fail actions for nonvacuous evaluations of the specified assertions. Execution
of assertion actions can then be re-enabled for the pass action ($assertpasson), fail action
($assertfailon), or for both types of actions ($assertvacuouson).
$assertvacuouson
Enables execution of pass and fail actions for vacuous evaluations of the specified assertions. Execution of
assertion actions can then be disabled for the pass action ($assertpassoff), fail action
($assertfailoff), or for both types of actions ($assertvacuousoff).

Example 1
$assertvacuousoff;
$assertnonvacuousoff;

Assumed that the commands are invoked from a top-level module, disables execution of all assertion action blocks in
the whole design for all types of assertion evaluations. The same result could be obtained by calling
$assertpassoff and $assertfailoff tasks:
$assertpassoff;
$assertfailoff;

Example 2
$assertnonvacuouson ( 3, top.uut );
$assertfailoff ( 3, top.uut );

Assumed that all action blocks were previously disabled in the whole design (as in Example 1), enables execution of
only pass actions for nonvacuous evaluations of assertions in the design region top.uut and two levels below. The
operation is executed in two steps: first, both pass and fail actions are enabled for nonvacuous evaluations
($assertnonvacuouson); then fail actions are disabled ($assertfailoff).

334

SystemVerilog Reference

System Tasks and Functions

Example 3
$assertnonvacuouson ( 0, assert_seq_1 ) ;

Enables execution of fail and pass action blocks for nonvacuous evaluations of assert_seq_1 in the design region
from which the task is called.

335

SystemVerilog Reference

System Tasks and Functions

Assertion System Functions


SystemVerilog introduces several assertion system functions. They are described in the chapter Assertions /
Assertions Building Blocks / Built-in Functions.

336

SystemVerilog Reference

System Tasks and Functions

Random Number System Functions


SystemVerilog introduces several system functions useful for generating pseudo-random numbers. For the detailed
description, see Random Constraints | System Functions and Methods.

337

SystemVerilog Reference

System Tasks and Functions

Enhancements to Verilog System Tasks


SystemVerilog extends the behavior of several system tasks from Verilog:
$sformat second argument can be an expression of string data type.
The first argument of $swrite can be a string variable.
The integer % format specifiers (h, d, o, b, c, u, and z) may be used with
any of the SystemVerilog integral data types, including enumerated types
and packed aggregate data types. It is illegal to use the specifiers with any
unpacked aggregate type.
$display, $write, $fdisplay,
$fwrite, $swrite, and their
variants

Unpacked aggregate type must be used with pattern format specifier (p).
Pattern format specifier (p) is used as default format for $display,
$write, $fdisplay, $fwrite, $swrite, and their variants, tasks
argument.
The string data type can be used as the argument corresponding to a string
% format specifier (s) . The shortreal data type can be used to the real
number % format specifiers (e, f, and g).
The above format specifiers can also be used with user-defined types that
have been defined (using typedef) to be represented using one of these
basic types.
The string data type can be used as the format arguments to these tasks.
A string variable can be used as the first argument of $sscanf.
The integer % format specifiers (b, o, d, and h) may be used to read into any
of the SystemVerilog integral data types, including enumerated types and
packed aggregate data types. They shall not be used with any unpacked
aggregate type.

$fscanf and $sscanf

The string % format specifier (s) may be used to read into variables of the
string data type.
The shortreal data type can be used as the real number % format specifiers
(e, f, and g).
The above format specifiers can also be used with user-defined types that
have been defined (using typedef) to be represented using one of these
basic types.
The $psprintf function can be used in the OVM verification library.

$psprintf

%u and %z format specifiers

Pattern format specifier (p) is used as default format for $psprintf


function argument.
NOTE: The enhancement is not supported in this release. Please contact
Aldec Support to receive the latest status.

338

SystemVerilog Reference
$fread

System Tasks and Functions


NOTE: The enhancement is not supported in this release. Please contact
Aldec Support to receive the latest status.

339

SystemVerilog Reference

System Tasks and Functions

$readmem and $writemem Tasks

$readmemb and $readmemh Tasks Enhancement


NOTE: The enhancement is not supported in this release. Please contact Aldec Support to receive the latest status.

$writememb and $writememh Tasks


SystemVerilog introduces $writememb and $writememh tasks.

Syntax
$writememb ( " file_name " , memory_name [ , start_addr [ , finish_addr ] ] );
$writememh ( " file_name " , memory_name [ , start_addr [ , finish_addr ] ] );

$writememb and $writememh tasks dump memory contents to files that are readable by $readmemb and
$readmemh, respectively. There is no append mode so if an existing file is used as an argument of $writewmem
tasks, it is overwritten. $writememb and $writememh can write out data corresponding to unpacked arrays of
2-state types, such as int or enumerated types. For enumerated types, values in the file correspond to the ordinal
values of the enumerated type.

Using Multidimensional Unpacked Arrays with $readmem and $writemem Tasks


NOTE: The enhancement is not supported in this release. Please contact Aldec Support to receive the latest status.

File Format for Multidimensional Unpacked Arrays


NOTE: The enhancement is not supported in this release. Please contact Aldec Support to receive the latest status.

340

SystemVerilog Reference

System Tasks and Functions

Miscellaneous Tasks and Functions


$system allows you to call the C function system(const char *command) that executes a command as a shell
command.

Syntax
$system ( "shell_command_line" )

If $system is called without string argument, the C function system() will be called with the NULL string. $system
can be called as either a task or a function. When called as a function, it returns the return value of the call to
system() with data type int.

Example
module top();
initial $system("cp file.sv counter.sv");
endmodule

341

Compiler Directives

`define macros
The `define macro text can include `` (a double backtick) and `" (a backtick followed by quotes). A double backtick
can be used to delimit lexical tokens without introducing white space. For example:
`define test(no) tb``no
module `test(3);
endmodule

When the above code is compiled, module tb3 will be stored in the library. (Macro `test(3) expands to tb3.)
Sequence `" changes the meaning of the quotation mark and allows the preprocessor to expand macro arguments
inside a string literal. The difference between regular quotes and quotes preceded by a backtick is shown below:
`define msg1(str) "The message is: str."
`define msg2(str) `"The message is: str.`"

The preprocessor will expand str only in the second macro (msg2).
initial begin
$display (`msg1(hello));
$display (`msg2(hello));
end

When simulation is run, the following messages will be displayed:


The message is: str.
The message is: hello.

`include
SystemVerilog introduces angle brackets <> notation for include directive.
`include <filename>

This is referred to as a system include or a library include. System includes are convenient for sharing files used in
different projects. The compiler searches for files listed in system include directives only in the directories specified
with -sysincdir <dir> and +sysincdir+<dir> options. All other directories, including the current working
directory, the directory where the source file is located, and directories specified with -incdir <dir> and
+incdir+<dir> options are ignored.

342

SystemVerilog Reference

Compiler Directives

`begin_keywords and `end_keywords


The `begin_keywords and `end_keywords directives delimit an area in source code and specify what identifiers
are to be considered reserved keywords in that area according to a specified version of IEEE Std 1364 or IEEE Std
1800. The following version specifiers are supported by the compiler running in conformance to SystemVerilog IEEE
1800-2009: "1800-2009", "1800-2005", "1364-2005", "1364-2001", "1364-2001-noconfig", and "1364-1995". When
running in conformance to SystemVerilog IEEE 1800-2005, "1800-2009" is not supported.
The directives cannot be specified inside a design element. (A design element is a SystemVerilog module, program,
interface, checker, package, primitive, or configuration). The `begin_keywords directive is effective until the
matching occurrence of the `end_keywords directive or until the end of compilation unit. The directive can be
effective across multiple source files. The `begin_keywords and `end_keyword pairs can be nested: when a code
area with a given version specifier is ended by an `end_keyword directive, the compiler returns to a version specifier
that was recently valid or, if no previous version specifier was defined, to the default set of reserved keywords:
`begin_keywords "1800-2005"
reg logic; // error: logic is a keyword
`begin_keywords "1364-2001"
module top;
reg logic; // ok: logic is not a keyword
endmodule
`end_keywords
logic n;
// ok: logic is a keyword
`end_keywords

343

DPI

Overview
DPI, or the Direct Programming Interface, is the next generation interface between SystemVerilog code and foreign
C/C++ code. The DPI specification in IEEE 1800 allows both:
Calling C/C++ foreign code from SystemVerilog.
Calling SystemVerilog tasks and functions from C/C++.
DPI is built around SystemVerilog subroutines (functions and tasks). A subroutine is treated a black box encapsulating
some functionality. That functionality can be implemented either in SystemVerilog or in a foreign language without
affecting the calling code.

Tasks and Functions


The DPI interface allows tasks and functions implemented in a foreign language (e.g. in C) to be called from
SystemVerilog code. Such tasks and functions must be made visible in SystemVerilog through foreign import
declarations. For example:
import "DPI-C" function real f1( input int i);
import "DPI-C" function integer f2( input reg[31:0] i);

Imported functions and tasks are used identically to native SystemVerilog functions. All imported functions must
complete their execution instantly and consume zero simulation time. Tasks can consume nonzero simulation time.
Calls to imported functions or tasks are indistinguishable from calls to SystemVerilog functions.
The other, complementary part of DPI allows calls in the opposite direction, that is calling SystemVerilog tasks and
functions from foreign code. Such tasks and functions must be specified in export declarations, for example:
export "DPI-C" function f1;
export "DPI-C" task t1;

SystemVerilog compiler automatically generates C code matching export declarations. The generated code can be
compiled into a foreign application (i.e. an application written in C) and utilized for calling SystemVerilog subroutines.
Data can be passed between the two domains (SystemVerilog domain and the foreign language domain) through
function arguments and results. For information on result and argument type mapping, see C/C++ and SystemVerilog
Data Types.

344

SystemVerilog Reference

DPI

Two Layers of DPI


The DPI interface consists of two layers:
SystemVerilog layer.
Foreign language layer.
IEEE 1800 does not preclude any language from being used a foreign language, however, the foreign language
layer is defined only for the C programming language.

DPI SystemVerilog Layer


The SystemVerilog side of DPI does not depend on the foreign language. The semantics of the SystemVerilog side of
the interface is independent from the foreign side of the interface. In other words, SystemVerilog code (import and
export declarations, subroutine calls) is not affected by the selection of the language used in the foreign layer.

DPI Foreign Language Layer


The foreign language layer is defined for the C programming language only. This layer specifies:
Passing actual arguments.
Accessing arguments in the foreign code.
Translation of SystemVerilog types to foreign language types and vice-versa.
Several C type definitions.

345

SystemVerilog Reference

DPI

C/C++ and SystemVerilog Data Types


The table below shows mappings between SystemVerilog types and C types.
SystemVerilog Type

C Type

void

void

byte

char

shortint

short int

int

int

longint

long long

bit

unsigned char

logic/reg

unsigned char
svLogicVecVal* or svLogicVecVal[]

logic vector
(only the latter form is allowed for structure members)
svBitVecVal* or svBitVecVal[]
bit vector
(only the latter form is allowed for structure members)
svLogicVecVal* or svLogicVecVal[]
integer
(only the latter form is allowed for structure members)
real

double

shortreal

double (inside structures) or float otherwise

time

svLogicVecVal[2]
const char* for input ports

string
const char** for output and inout ports
packed struct 4-state

svLogicVecVal*

packed struct 2-state

svBitVecVal*

packed union 4-state

svLogicVecVal*

packed union 2-state

svBitVecVal*

unpacked struct

A structure of composite types

open array

svOpenArrayHandle

unspecified type (a formal


argument with an unspecified
type or an unspecified return
type)

unsigned char

The listings below show type mapping between SystemVerilog and C arrays. The mapping is straightforward; the
number of array dimensions and their size are the same in SystemVerilog and C.

346

SystemVerilog Reference
SystemVerilog
bit a[1:0][1:0]

DPI
C

C++

svBitVecVal a[2][2];

svBitVecVal a[2][2];

An example with a mapping between a SystemVerilog structure and a C structure is shown below.
SystemVerilog

C++

typedef struct {
int a;
int b;
} inner;

typedef struct {
int a;
int b;
} inner;

struct inner {
int a;
int b;
};

typedef struct {
inner i;
int j;
} outer;

typedef struct {
inner i;
int j;
} outer;

struct outer {
inner i;
int j;
};

Arguments of type structure must be passed as pointers to C functions. Accordingly, the SystemVerilog import
declaration on the left, must be matched the following C declaration on the right.
SystemVerilog
import "DPI-C" function
void fn(outer);

C++
extern "C" void fn
(outer *o);

void fn (outer *o);

The C/C++ function could then modify the structure using the following assignments:
o->i.a = 1000;
o->i.b = 1001;
o->j = 1002;

Value changes will be visible in SystemVerilog.


Note that the o->i field is a structure (rather than a structure pointer) so its fields are accessed using the dot syntax
(o->i.a and o->i.b rather than o->i->a and o->i->b).

Open Arrays
A formal argument of an imported task or a function can be an open array. A formal argument is an open array when
at least one of its dimensions is unspecified (as indicated by empty square brackets [] in SystemVerilog). The actual
argument for an open array can be an array with an arbitrary range.
The example below shows an import declaration for task put_array.
import "DPI-C" task put_array(inout int open_arr[]);

The actual argument for such a task or function can be an array with arbitrary dimensions. For the put_array task in
the listing above, that could be arrays declared as: int a[100];, int a[0:7];, int a[15:8];, etc.
On the C/C++ side, an open array is accessible as a variable of type svOpenArrayHandle. A number of functions is
available to query the array, for example:

347

SystemVerilog Reference
int
int
int
int
int
int
int
int

DPI

left = svLeft(hnd, 1);


right = svRight(hnd, 1);
low = svLow(hnd, 1);
high = svHigh(hnd, 1);
inc = svIncrement(hnd, 1);
size = svSize(hnd, 1);
length = svLength(hnd, 1);
dim = svDimensions(hnd);

For a complete list of functions, see the svdpi.h header file. The header contains a brief description for each function.
Note that exported SystemVerilog routines cannot have formal arguments specified as open arrays.

Enumerated Types
SystemVerilog enumerated types are represented on the C++ side of the interface as enumerations of int type.
There are, however, two exceptions for longint and for time data types. 64-bit long int data type can be
represented by C++ int by assigning 64-bit initial value to at least one of enumerated values:
typedef enum { tla, tlb = 0x100001000ULL, tlc = 0x00001000ULL, tld } td_long;

time data type is both 4-state value and 64-bit length. It can be represented, however, as 4-cell vector. The following
4-value SystemVerilog enumerated type:
enum time { tla = 64'h0, tlb = 64'hFF00FF00FXX00ZFF, tlc = 64'h00FF00FFFXX0FFF0, tld = 64'h0XXX }
td_time;

can be represented by two-dimensional array of int data type (each row represents an enum value):
const int arr[4][4] = {
{0x00000000, 0x00000000,
{0xFF00FF00, 0x00000000,
{0x00FF00FF, 0x00000000,
{0x00000000, 0x00000000,

0x00000000,
0xFFF000FF,
0xFFF0FFF0,
0x00000FFF,

0x00000000},
0x0FF00F00},
0x0FF00000},
0x00000FFF}};

Two 32-bit cells are needed to encode 64-bit value. Another two cells are needed to encode additional states
available for time data type. Following encoding is used: 00=0, 10=1, 11=X, 01=Z. The First bit is taken from
columns 1-2, and the second from corresponding position in columns 3-4.

Ref Arguments
Ref mode is not a legal mode for DPI arguments

348

SystemVerilog Reference

DPI

Imported Tasks and Functions


An import declaration makes a function declared in a foreign language available in SystemVerilog code. An import
declaration consists of the following elements:
Keyword import.
"DPI-C" string. (String "DPI" is considered obsolete.)
An optional property pure or context. (The properties are mutually exclusive.) Property pure is allowed for
functions only. (It is not allowed for tasks). Property context is allowed both for functions and tasks.
An optional linkage name followed by the equals sign (=).
A prototype of the function or the task.
The prototype consists of the following elements:
Keyword function or keyword task.
The type of the return value (for functions only). Imported functions can return a result or be defined void.
Note that imported tasks, even though they do not return value in SystemVerilog, must be defined in the
foreign code as functions returning an int.
A port list.
Each port in the port list can contain:
A keyword signifying the direction (input, inout or, output). If omitted, input is assumed.
The type of the argument and, optionally, its dimensions.
The name of the argument. Formal argument names are optional unless argument binding by name is
needed.
An optional default argument value.
A sample declaration that imports function foo is shown in the example below. It is assumed that function foo returns
an integer value and accepts one integer argument.
import "DPI-C" function int foo( int i);

More examples of valid declarations are shown below:


import "DPI-C" function int f1( input r);
import "DPI-C" function int f2( input reg r);
import "DPI-C" function int f3( reg r);
import "DPI-C" function real g1( input int i);
import "DPI-C" pure function real g2( input reg[31:0] i);
import "DPI-C" c_function = function real g3( input reg[31:0] i);
import "DPI-C" context task t1( input real f);

An import declaration is equivalent to defining a task or function of that name in SystemVerilog. A function imported
through DPI (unlike PLI/VPI routines) is referenced without the preceding $ sign, for example:
initial
$display ("%d", foo(1));

The dollar sign ($) is used in the system $display task; the DPI foo routine is referenced without a dollar sign.
The evaluation order of formal arguments follows general SystemVerilog rules. Argument compatibility and coercion
rules are also the same as for native SystemVerilog functions.

349

SystemVerilog Reference

DPI

Function Result Type


The data type of the function return value must be explicitly specified or the function must be declared void.
SystemVerilog allows using the following data types for imported function results:
void
byte
shortint, int, longint
real, shortreal
string
scalar values of type bit and logic
chandle

Formal Argument Types


The following types can be used as formal arguments for the imported functions and tasks:
void
byte
shortint, int, longint
integer
real, shortreal
time
string
scalar values of type bit and logic
chandle
Packed arrays, structs, and unions composed of types bit and logic. Every packed type is eventually
represented as a packed one-dimensional array. On the foreign language side of the DPI, all packed types
are visible as packed one-dimensional arrays regardless of their declaration in the SystemVerilog code.
Enumeration types interpreted as the type associated with that enumeration.
Types constructed from the supported types with the help of the struct, union, unpacked array, and
typedef constructs.

Function Arguments
Imported functions can have input, output, and inout arguments. The following rules apply:
Functions should not modify formal input arguments. If they do, changes will not be visible outside the
function.
The initial values of output arguments are undetermined.
Imported functions can access initial values of formal inout arguments. Changes made to a formal inout
argument are visible outside the function.

Pure and Context Properties


If the function result depends solely on the values of function input arguments and the function has no side effects,
then it can be specified with the pure property. The pure property is an indication to the compiler that can facilitate

350

SystemVerilog Reference

DPI

code generation and, ultimately, improve performance.


The requirement for no side effects implies that a pure function cannot have output or inout arguments, modify
global or static variables, open files, display text on the simulator output, and so on. Because pure function results
must depend solely on input arguments, such functions are not allowed to read global or static variables, read data
from a file descriptor, or call other functions that are not pure.
Only nonvoid functions with no output or inout arguments can be specified as pure. The pure property is not
available for tasks. An imported task can never be declared pure.
For all tasks and functions, the context property is set by default. To switch it off, use the -j argument of the alog
command (the strict LRM mode).

Miscellaneous

Memory Management
The memory spaces owned and allocated by the foreign code and SystemVerilog code are disjoined. SystemVerilog
code has no access to memory space used by the foreign code and vice versa.

Reentrancy of Imported Tasks


A call to an imported task can result in the suspension of the currently executing thread. Consequently, C code for an
imported task can be simultaneously active in multiple execution threads. Therefore, care should be taken to make C
code thread safe.

C++ Exceptions
DPI imported tasks and functions can be implemented using C++. In this case exceptions must not propagate out of
any imported task or function. Undefined behavior will result if an exception crosses the language boundary from C++
into SystemVerilog.

Hierarchical Names on C++ Side


SystemVerilog Hierarchical names with the slash (/) character used as a delimiter do not work on the C++ side of the
DPI interface. When specifying a region name, use the dot (.) delimiter instead.
svScope = svGetScopeFromName("/top/UUT/m1/sub"); // triggers an error
svScope = svGetScopeFromName(".top.UUT.m1.sub"); // works properly

351

SystemVerilog Reference

DPI

Exported Tasks and Functions


DPI allows calling SystemVerilog subroutines (tasks and functions) from foreign code. Each such subroutine must be
specified in an export declaration. An export declaration consists of the following elements:
Keyword export.
"DPI-C" string.
An optional linkage name followed by the equals sign (=).
Keyword function followed by a SystemVerilog function identifier or keyword task followed by a
SystemVerilog task identifier.
Several examples of valid declarations are shown below.
export "DPI-C" function fnc;
export "DPI-C" task t;
export "DPI-C" fn = function \<funny-name> ;

Note that export declarations (unlike import declarations) include neither the function return type nor argument
types. However, the actual subroutine declarations must be present in the same scope as the export declarations.
export "DPI-C" function fnc;
export "DPI-C" task t;
export "DPI-C" fn = function \<funny-name> ;
function void fnc;
// Function body omitted.
endfunction
task t;
// Task body omitted.
endtask
function void \<funny-name> ;
// Function body omitted.
endfunction

The rules for mapping C/C++ and SystemVerilog types are the same as for imported subroutines. For details, see
C/C++ and SystemVerilog Data Types.

352

SystemVerilog Reference

DPI

Name Space of Imported and Exported Functions


Tasks and functions imported to and exported from SystemVerilog share the same name space of linkage names in
the foreign language. Therefore:
Names of imported and exported functions must be unique, even if they are imported or exported in different
SystemVerilog scopes.
Overloading is not allowed.
Linkage names of imported and exported functions must follow C naming conventions:
Names must start with a letter or an underscore and be followed by alphanumeric character.
The dollar sign $ cannot be part of the name.
If a linkage name is not explicitly given, it must be the same as the SystemVerilog task or function name.
If a linkage names clashes with a SystemVerilog keyword, then an escaped identifier can be used. Accordingly, the
linkage name begin can be coded as \begin . The simulator will strip the initial backslash (\) and the terminating
whitespace.

353

SystemVerilog Reference

DPI

Disabling DPI Tasks and Functions


NOTE: The construct is not supported in this release. Please contact Aldec Support to receive the latest status.

354

S-ar putea să vă placă și