Lecture 6
Systemverilog 2
Data Types
Memory Read
Fundamental difference between working of Test Bench and RTL
No always blocks in Test bench
No fork-join in RTL
Few examples of fork-join, fork-join_any, fork-join_none, wait and
disable.
Creating interesting stimulus using fork-join and repeat blocks
Data Types Topics
•The logic type
• 2-state logic
• Fixed size arrays
•for/foreach loops
•packed/unpacked arrays
•Dynamic arrays
•Queues
•Associative arrays
• Array Methods
• Choosing a storage type
• Structures
• User defined types
Chapter 2 Copyright 2011 G. Tumbush, C. Spear, v1.2 3
Basic Data Types
bit b; // 2-state, single-bit
bit [31:0] b32; // 2-state, 32-bit unsigned integer
int unsigned ui; // 2-state, 32-bit unsigned integer
int i; // 2-state, 32-bit signed integer
byte b8; // 2-state, 8-bit signed integer Explicit 2-state variables allow compiler
optimizations to improve performance
shortint s; // 2-state, 16-bit signed integer
longint l; // 2-state, 64-bit signed integer
Logic Data Type
• The logic type was added to SystemVerilog to reduce confusion when using the “reg” data
type.
– reg is defined as a general-purpose variable in Verilog 2001 that can represent either
sequential logic or combinational logic
– In hardware – reg (register) refers to sequential design elements.
• logic has equivalent functionality to reg and can be used anywhere that a reg is traditionally
used.
module counter (output [3:0] dout, input clk, rst, cnt);
logic [3:0] dout;
always_ff @(posedge clk or posedge rst)
if (rst)
dout <= ’0;
else if (cnt)
dout <= dout + 1;
endmodule
Signed/Unsigned
byte, shortint, int, integer and longint defaults to signed
Use unsigned to represent unsigned integer value
Example: int unsigned ui;
bit, reg and logic defaults to unsigned
To create vectors, use the following syntax:
logic [1:0] L; // Creates 2 bit logic vector
Constants
Systemverilog Data Structures
• Static Arrays :
• Size is known at the compile time
• Dynamic Arrays :
• Size is not known at the compile time. Defined and expanded
as needed during run time
• Associative Arrays
• Where the constant is stored with certain key.
• Queues
• Where the data can be pushed into the queue and popped out
of the queue
Fixed-Size Arrays
Since almost all arrays use a low index of 0,
int lo_hi[0:15]; // 16 ints [0]..[15] SystemVerilog lets you use the shortcut
of just giving the array size, which is similar
int c_style[16]; // 16 ints [0]..[15]
to C’s style.
int array2 [0:7][0:3]; // Verbose declaration
int array3 [8][4]; // Compact declaration
array2[7][3] = 1; // Set last array element
int ascend[4] = ‘{0,1,2,3}; // Initialize 4 elements
int descend[5];
descend = ‘{4,3,2,1,0}; // Set 5 elements
descend[0:2] = ‘{5,6,7}; // Set first 3 elements
ascend = ‘{4{8}}; // Four values of 8
descend = ‘{9, 8, default:-1}; // {9, 8, -1, -1, -1}
Packed Arrays
• Static Arrays are further classified into packed and unpacked arrays
• You may have a 32-bit register that sometimes you want to treat as four 8-bit
values and at other times as a single, unsigned value.
• SystemVerilog packed array is treated as both an array and a single value.
• The packed bit and array dimensions are specified as part of the type, before
the variable name. These dimensions must be specified in the [msb:lsb] format,
not [size].
Example: bit [3:0] [7:0] bytes; // 4 bytes packed into 32-bits
Packed/Unpacked Arrays
• In packed arrays [range is on the left side of the identifier] all elements
are glued together
• Ex: logic [3:0] m;
m = 4’b1100;
• In unpacked arrays [range is on the right side of the identifier] each
individual element is considered by itself without any relation to other
elements.
• Ex: logic m [5:0];
// each element is only 1-bit deep
• Arrays can have packed and unpacked dimensions.
• Ex: logic [3:0] m [5:0]
Packed Array Example
bit [1:0] [2:0] [3:0] barray;
barray = '{'{4’h6, 4’h5, 4’h4}, '{4’h3, 4’h2, 4’h1}};
$displayh(barray,, barray[1],, barray[1][2],, barray[1][2][3]);
barray 4'b0110 4'b0101 4'b0100 4'b0011 4'b0010 4'b0001
# 654321 654 6 0
Chapter 2 Copyright 2011 G. Tumbush, C. Spear, v1.2 12
Indexing Mixed Arrays
•Unpacked dimensions are referenced first from the left-most to the
right-most dimension
•Packed dimensions are referenced second from the left-most
dimension to the right-most dimension
packed dimensions unpacked dimensions
logic [3:0][7:0] mixed_array [0:7] [0:7] [0:7];
mixed_array [0] [1] [2] [3] [4] = 1’b1;
unpacked indexes packed indexes
Chapter 2 Copyright 2011 G. Tumbush, C. Spear, v1.2 13
Array Literals and Default
To help in assigning literal values to arrays SV introduces the default keyword:
int k [1:1000] = '{default: 5}; // All elements “5”
For more control, consider the dimensions of the array and use { } to match those
dimensions exactly.
int k [1:3][1:4] = '{'{1,2,3,4},'{5,6,7,8},'{9,10,11,12}}; // 3 groups of 4
int m [1:2][1:3] = '{'{0,1,2},'{3{4}}}; // 2 groups of 3
mixed packed/unpacked array
bit [3:0] [7:0] barray [3]; // Packed: 3x32-bit
Basic Array Operations – for and foreach
initial begin The variable i is declared local to the for-loop.
bit [31:0] src[5], dst[5]; The SystemVerilog function $size returns the
size of the array.
for (int i=0; i<$size(src); i++)
src[i] = i;
In the foreach-loop, you specify the array name
foreach (dst[j]) and an index in square brackets, and SV
dst[j] = src[j] * 2; // dst doubles src values automatically steps through all the elements of
the array.
end
The index variable is automatically declared for
you and is local to the loop.
Printing a multidimensional array
initial begin
byte twoD[4][6];
foreach(twoD[i,j])
0: 0 1 2 3 4 5
twoD[i][j] = i*10+j;
1: 10 11 12 13 14 15
2: 20 21 22 23 24 25
foreach (twoD[i]) begin // Step through first dim.
3: 30 31 32 33 34 35
$write("%2d:", i);
foreach(twoD[,j]) // Step through second
$write("%3d", twoD[i][j]);
$display;
end
end
Dynamic Arrays
Dynamic declaration of one index of an unpacked array
Syntax:
data_type array_name[] ;
Declares a dynamic array array_name of type data_type
data_type array_name[] = new[ array_size ] [(array)] ;
Allocates a new array array_name of type data_type and size array_size
Optionally assigns values of array to array_name
If no value is assigned then element has default value of data_type
Examples:
bit [3:0] nibble[ ]; // Dynamic array of 4-bit vectors
integer mem[ ]; // Dynamic array of integers
int data[ ]; // Declare a dynamic array
data = new[256]; // Create a 256-element array
int addr = new[100]; // Create a 100-element array
addr = new[200](addr); // Create a 200-element array
// preserving previous values in lower 100 addresses
Dynamic Arrays – Methods
function int size()
Returns the current size of the array
int addr[ ] = new[256];
int j = addr.size(); // j = 256
function void delete()
Empties array contents and zero-sizes it
Cannot delete selected elements
int addr[ ] = new[256];
addr.delete();
Dynamic Array Example
module dyn_arry ();
bit data1 [];
initial
begin
// create a 128 element array
data1 = new [128];
$display("Size of array = %d",
data1.size());
data2 = new[256](data1);
$display("Size of array = %d",
data2.size());
data1.delete();
$display("Size of array = %d",
data1.size());
end
endmodule
20
Queues and Lists
SV has a built-in list mechanism which is ideal for queues, stacks, etc.
A list is basically a variable size array of any SV data type.
int q1[$]; // $ represents the ‘upper’ array boundary
int n, item;
q1 = ‘{ n, q1 }; // uses concatenate syntax to write n to the left end of q1
q1 = ‘{ q1, n }; // uses concatenate syntax to write n to the right end of q1
item = q1[0]; // read leftmost ( first ) item from list
item = q1[$]; // read rightmost ( last ) item from list
n = q1.size; // determine number of items on q1
q1 = q1[1:$]; // delete leftmost ( first ) item of q1
q1 = q1[0:$-1]; // delete rightmost ( last ) item of q1
for (int i=0; i < q1.size; i++) // step through a list using integers (NO POINTERS)
begin … end
q1 = { }; // clear the q1 list
Queue Methods (insert, delete, pop, push)
size() Returns the number of items in the queue. Prototype:
If the queue is empty, it returns 0. function int size();
insert() Inserts the given item at the specified index position. Prototype:
function void insert (int index, queue_type item);
Q.insert (i, e) => Q = ‘{Q[0:i-1], e, Q[i,$]}
delete() Deletes the item at the specified index position. Prototype:
function void delete (int index);
Q.delete (i) => Q = ‘{Q[0:i-1], Q[i+1,$]}
pop_front() Removes and returns the first element of the queue. Prototype:
function queue_type pop_front();
e = Q.pop_front () => e = Q[0]; Q = Q[1,$]
pop_back() Removes and returns the last element of the queue. Prototype:
function queue_type pop_back();
e = Q.pop_back () => e = Q[$]; Q = Q[0,$-1]
push_front() Inserts the given element at the front of the queue. Prototype:
function void push_front (queue_type item);
Q.push_front (e) => Q = ‘{e, Q}
push_back() Inserts the given element at the end of the queue. Prototype:
function void push_back (queue_type item);
Q.push_back (e) => Q = ‘{Q, e}
Queue Example
module queues ();
int q [$]; // declare the q
initial
begin: store_disp
// Push elements into the queue
q.push_back(1);
q.push_back(0);
// Display its contents
$display("Size of queue = %0d", q.size());
// Delete the element of queue at index 1
q.delete(1);
// Push to front of the queue
q.push_front (0);
// Display all the contents in the queue
for (int i = 0; i < q.size(); i++)
$display("q[%0d] = %0d", i, q[i]);
end: store_disp
endmodule: queues 23
Associative Arrays
• Associative arrays are used when the size of the array is not known
or the data is sparse.
• Syntax:
data_type array_name [index_type];
In other words
value_type array_name [key_type];
• It implements a lookup table of the elements of its declared type.
• Data type used as an index serves as lookup key and imposes an
order.
• Associative array do not have their storage allocated until it is used.
Associative Arrays
• Suppose a processor you are modeling has a 4GB memory space.
• A fixed/packed/dynamic array will take up too much memory
• Use an associative array to model sparse memories
byte assoc[byte], idx = 1;
initial begin
do begin
assoc[idx] = idx;
idx = idx << 1;
end while (idx != 0);
foreach (assoc[i])
$display("assoc[%h] =Tumbush,
Chapter 2 Copyright 2011 G. %h", i,v1.2assoc[i]);
C. Spear, 25
Index Types
• String Index Types
• Ex: int a [string];
a[“joe”] = 21;
• Integer Index Types
• Ex: bit [1:0] a [int];
a[5] = 2’b11;
Associative Array Methods
Function Use
num() Returns number of entries
delete(<index>) Index for delete optional. When
specified used to delete given index
else whole array.
exists (<index>) Returns 1 if element exists at index
else 0
first (<index>), last (<index>) assigns to the given index variable the
value of the first/last (smallest/largest)
index in the associative array.
It returns 0 if the array is empty, and 1
otherwise.
next (<index>), prev (<index>) finds the entry whose index is
greater/smaller than the given index.
Associative array methods - Example
module asoc_arry ();
int db [string]; // Define an associative array
initial
begin: test
string s;
db ["joe"] = 21; // store values at indexes of associative array
db ["jill"] = 19;
// Display the size of the associative array
$display("Size of hash = %0d", db.num());
if (db.exists("jill")) // check if index exists and change value
begin
db["jill"] = 25;
end
// print the contents of associative array
if (db.first(s))
do
begin
$display("Name = %s -- Age = %0d", s, db[s]);
end
while (db.next(s));
end: test
endmodule: asoc_arry 28
Array Methods
int f[6] = ‘{1,6,2,6,8,6};
int d[] = ‘{2,4,6,8,10};
int q[$] = {1,3,5,7}, tq[$];
tq = q.min(); // {1}
tq = d.max(); // {10}
tq = f.unique(); // {1,6,2,8}
Array Methods
int d[] = ‘{9,1,8,3,4,4}, tq[$];
// Find all elements greater than 3
tq = d.find with (item > 3); // {9,8,4,4}
// Equivalent code
tq.delete();
foreach (d[i])
if (d[i] > 3)
tq.push_back(d[i]);
tq = d.find_index with (item > 3); // {0,2,4,5}
tq = d.find_first with (item > 99); // {} none found
tq = d.find_first_index with (item==8); // {2} d[2]=8
tq = d.find_last with (item==4); // {4}
tq = d.find_last_index with (item==4); // {5} d[5]=4
Summary: Where to use what?
SystemVerilog provides many new data types and structures so that you can
create high-level testbenches without having to worry about the bit-level
representation.
Queues work well for creating scoreboards for which you constantly need to add
and remove data.
Dynamic arrays allow you to choose the array size at run-time for maximum
testbench flexibility.
Associative arrays are used for sparse memories and some scoreboards with a
single index.
Enumerated types make your code easier to read and write by creating groups of
named constants.
Systemverilog summary so far…
– C/C++ type language constructs for efficient programming
– Interfaces to encapsulate communication between design blocks
– Assertions and coverage for new verification techniques
– System-level testbench features
– Lightweight interface to C/C++ programs
It is a concise, unified language for design and testbenches.