DATA TYPES
• System Verilog offers many improved data types as compared to
Verilog.
• These datatypes are useful for design as well as verification.
• The following slides discusses data structures that are useful mainly
for verification.
• The new datatypes that are introduced in system Verilog have the
following advantages.
Built In Data Types
• Verilog-1995 has two datatypes: Variables and Nets.
• Both of them hold four state values:0,1,X & Z.
• Variables in RTL code are used to store combinational and sequential
values.
• The most common type of variable used in Verilog is the ‘reg’.
• Variables can be of the following types:
• Unsigned single bit or multi bit Ex. reg [7:0] m
• Signed 32 bit (integer)
• Unsigned 64 bit (time)
• Floating point numbers (real).
• A net is used to connect parts of the design like gate primitives and module
instances. Ex. Wire
• System Verilog uses many new data types to help both hardware engineers as
well as verification engineers.
The Logic Type
SystemVerilog introduces a new 4-state data type called logic that can be driven in both procedural blocks and
continuous assign statements.
Thus the classic reg datatype can be driven by continuous assignments, gates and modules in addition to being a variable.
One more example…
The State data types
Fixed Size Arrays
• An array is a collection of variables.
• An array is a variable to store different values in contiguous locations.
• Single Dimension Arrays:
• Declaring and initializing fixed size variables:
int array1 [6]; //Compact declaration
int array2 [5:0]; // Verbose declaration
int array1 [10]
Multidimensional array
Multidimensional arrays are also known as an array of arrays.
Two-dimensional array
int arr[2][3];
This array has total 2*3 = 6 elements.
TWO-DIMENSIONAL ARRAY DECLARATION
int array3 [2:0][3:0];
The data in a two-dimensional array is stored in a tabular form as shown in the below diagram.
• Array assignment
Queues
• A queue is a variable-size, ordered collection of homogeneous
elements.
• like a dynamic array, queues can grow and shrink
• queue supports adding and removing elements anywhere
• Queues are declared using the same syntax as unpacked arrays, but
specifying $ as the array size. In queue 0 represents the first, and $
representing the last entries.
• A queue can be bounded or unbounded.
• bounded queue – queue with the number of entries limited or queue
size specified
• unbounded queue – queue with unlimited entries or queue size not
specified
• Queue Declaration
• data_type queue_name[$];
• where:
data_type – data type of the queue elements.
queue_name – name of the queue.
Queue Declaration Example
Associative arrays
• When the size of the collection is unknown or the data space is sparse, an
associative array is a better option.
• Dynamic arrays are good if you want to occasionally create a big array, but what
if you want something really large?
• Perhaps you are modeling a processor that has a multi-gigabyte address range.
During a typical test, the processor may only touch a few hundred or thousand
memory locations containing executable code and data, so allocating and
initializing gigabytes of storage is wasteful.
• SystemVerilog offers associative arrays that store entries in a sparse matrix. This
means that while you can address a very large address space, SystemVerilog
only allocates memory for an element when you write to it.
• In the following picture, the associative array holds the values 0:3, 42, 1,000,
4,521, and 200,000. The memory used to store these is far less than would be
needed to store a fixed or dynamic array with 200,000 entries.
Array Declaration
Associative Array Examples
2.6 Linked Lists
2.7 Array Methods
• There are many array methods that you can use on any unpacked
array types:
• fixed, dynamic, queue, and associative. These routines can be as
simple as giving the cur rent array size or as complex as sorting the
elements. The parentheses are optional if there are no arguments.
• 2.7.1 Array Reduction Methods
• A basic array reduction method takes an array and reduces it to a
single value, as shown in Sample 2.23.
• The most common reduction method is sum, which adds together all
the values in an array.
• Array reduction methods SUM and PRODUCT
• On calling sum() method sum of array_1 elements (1,2,3,4) will be
returned to variable t_sum.
On calling product() method product of array_1 elements (1,2,3,4) will
be returned to variable t_product.
• Array reduction method AND
• On calling and() method, bit-wise and (&) will be performed on all the
array elements and returned.
• 1. Array with 2 elements.
Consider A=2 and B=3.
Y = A & B;
• 2. Array with 3 elements.
Consider A=10, B=9, and C=8.
• AND operation of 3 elements performed in 2 steps, In first step A & B,
will be performed. In the second step result of the first step & C will
be done. Considering X as the first step result.
Array reduction method OR
• On calling or() method, bit-wise or (|) will be performed on all the array elements and returned.
• Other array reduction methods are product, and, or, and xor.
• 2.7.2 Array Locator Methods
• What is the largest value in an array? Does an array contain a certain
value?
• The array locator methods find data in an unpacked array. These methods
always return a queue.
• Sample 2.25 uses a fixed-size array, f [6] , a dynam ic array, d [ ] , and a
queue, q [$] .
• The min and max functions find the smallest and largest elements in an
array.
• Note that they return a queue, not a scalar as you might expect.
• These methods also work for associative arrays. The unique method
returns a queue of the unique values from the array - duplicate values are
not included.
You could search through an array using a foreach-Ioop, but System Verilog can do this in one
operation with a locator method. The with expression tells System Verilog how to perform the
search, as shown in Sample 2.26,
• In a with clause, the name item is called the iterator argument and
represents a single element of the array. You can specify your own
name by putting it in the argument list of the array method as shown
in Sample 2.27.
2.7.3 Array Sorting and Ordering
• SystemVerilog has several methods for changing the order of
elements in an array. You can sort the elements, reverse their order.
or shuffle the order as shown in Sam ple 2.29. Notice that these
change the original array. unlike the array locator methods in Section
2.7.2. which create a queue to hold the results.
2.7.4 Building a Scoreboard with
Array Locator Methods
• The array locator methods can be used to build a scoreboard.
• Sample 2.31 defines the Packet structure.
• then creates a scoreboard made from a queue of these structures.
Section 2.9 describes how to create structures with typedef.
• The check_addr () function in Sample 2.31 looks up an address in the
scoreboard.
• The find_index () method returns an int queue.
• If the queue is empty (size==O). no match was found.
• If the queue has one member (size== I), a single match was found.
which the check_addr () function deletes.
• If the queue has multiple members (size> I), there are multiple packets
in the scoreboard whose address matches the requested one.
2.8 Choosing a Storage Type
2.9 Creating New Types with
typede£
• In complex testbenches some variable declarations might
have a longer data-type specification or require to be used
in multiple places in the testbench.
In such cases we can use a typedef to give a user-defined name to an existing data type. The
new data-type can then be used throughout the code and hence avoids the need to edit in
multiple places if required.
typedef data_type type_name
[range];
• Sample 2.35 User-defined array type
typedef
• int fixed_arrayS[S];
• fixed_arrayS fS;
• initial begin
• foreach (fS[i) fS[i) = i;
• end
2.10 Creating User-Defined Structures
• One of the biggest limitations of Verilog is the lack of data structures.
• In System verilog you can create a structure using the struct
statement similar to what is available in C..
• A struct just groups data fields together.
• If you want to model a complex data type. such as a pixel, in your
design code, put it in a struct.
2.10.1 Creating a struct and a New Type
• You can combine several variables into a structure.
• Sample 2.36 creates a structure called pixel that has three unsigned bytes for red,
green, and blue.
• Sample 2.36 Creating a single pixel type struct {bit [7:0] r, g, b;} pixel;
• The problem with the preceding declaration is that it creates a single pixel of this
type.
• To be able to share pixels using ports and routines, you should create a new type
instead. as shown in Sample 2.37.
• Sample 2.37 The pixel struct
• typedef struct {bit [7:0) r, g, b;} pixel_s;
• pixel_s my_pixel;
• Use the suffix "_s" when declaring a struct.
• This makes it easier to spot user defined types. simplifying the process of sharing
and reusing code.
2.10.2 Initializing a Structure
• You can assign multiple values to a struct just like an array, either in the
declaration or in a procedural assignment.
• Just surround the values with an apostrophe and braces. as shown in Sample
2.38. Sample 2.38
• Initializing a struct
initial begin
typedef struct {int a;
byte b;
shortint c;
int d;} my_struct_s;
my_struct _s st = '{32'haaaa_aaaad, 8'hbb, 16'hcccc, 32'hdddd_dddd};
$display ("%x %x %x %x ", st.a, st.b, st.c, st.d);
end
2.10.3 Making a Union of Several Types
• In hardware the interpretation of a set of bits in a register may depend on the value
of other bits.
• For example. a processor instruction may have many layouts based on the
opcode.
• Immediate-mode operands might store a literal value in the operand field.
• This value may be decoded differently for integer instructions than for floating
point instructions.
• Sample 2.39 stores both the integer i and the real f in the same location.
• Sample 2.39 Using typedef to create a union
typedef union { int i; real f; } num_u;
num_u un;
un.f = 0.0; //set value in floating point format
Use the suffix "_u"' when declaring a union.
• Unions are useful when you frequently need to read and write a register in several
different formats.
2.11 Type Conversion
• Casting is a process of converting from one data type into another data
type for compatibility.
• Importance of Casting
• In SystemVerilog, a data type is essential to mention while declaring a
variable and it can hold values of the same data type.
• For example, the int data type can not hold real data type values. If we
try doing so, it will lead to a compilation error. Casting helps to resolve
this problem.
• Types of Casting in SystemVerilog
• There are two types of casting in SystemVerilog
• Static Casting
• Dynamic Casting
Static Casting in SystemVerilog
• As the name suggests, static casting is only applicable to fixed data
types. It does not apply to the Object-Oriented programming concept.
• Syntax:
• <data_type>'(value or variable or expression)
• It converts values or variables from one data type to another data
type.
• Static casting is checked during compile time. So, there will not be any
run time error
Dynamic Casting in SystemVerilog
• Dynamic casting is used to cast the assigned values to the variables
that might not be ordinarily valid. The $cast is the system method.
• The $cast can be either function or task
• Syntax:
• function int $cast(destination, source);
• task $cast(destination, source);
• In both $cast as a function or task, $cast will try to assign source value
or expression to the destination variable. If dynamic casting fails due
to incompatible assignments, the destination variable will remain
unchanged. The only difference between $cast as a function and as a
task is mentioned below.
• $cast as a task: If $cast fails, it will cause a runtime error.
• $cast as a function: As $cast as a function returns 1 for legal casting,
otherwise it returns 0. But run time error will not occur for failed
casting and the destination variable will be unchanged.
2.11.3 Streaming Operators
• The » operator streams data from left to right while
• « streams from right to left, as shown in.
2.12 Enumerated Types
• An enumeration is a data type that allows you to define a set of
named values. Each value in the set is assigned an integer value,
starting from zero and increasing by one for each subsequent value.
For example, here's how you could define an enumeration for the four
cardinal directions:
In this example, North is assigned a value of 0, East is assigned a value of 1,
and so on.
2.13 Constants
• Systemverilog also supports the const modifier that allows you to
make a variable that can be initialized in the declaration but not
written by procedural code.
2.14 Strings
• The System Verilog string type holds variable-length strings. An
individual character is of type byte. The elements of a string of length
N are num bered 0 to N-l.
• Memory for strings is dynamically allocated, so you do not have to
worry about running out of space to store the string.
2.15 Expression Width
• A prime source for unexpected behavior in Verilog has been the width
of expressions.
• Sample 2.54 adds I + I using four different styles.
• Addition A uses two I-bit variables, and so with this precision I + I =0.
• Addition B uses 8-bit precision because there is an 8-bit variable on
the left side of the assignment.
• In this case, 1 + 1 =2.
• Addition C uses a dummy constant to force System Verilog to use 2-bit
precision.
• Lastly, in addition D. the first value is cast to be a 2-bit value with the
cast operator, and so 1 + I =2.