SystemVerilog Data Types
This tutorial describes the new data types that Systemverilog
introduces. Most of these are synthesisable,
and should make RTL descriptions easier to write and understand.
Integer and Real Types
SystemVerilog introduces several new data types. Many of these
will be familiar to C programmers. The idea is that
algorithms modelled in C can more easiliy be converted to SystemVerilog
if the two languages have the same data types.
Verilog’s variable types are four-state: each bit
is 0,1,X or Z. SystemVerilog introduces new two-state
data types, where each bit is 0 or 1 only. You would use these when you
do not need X and Z values, for example
in test benches and as for-loop variables. Using two-state variables in
RTL models may enable simulators
to be more efficient. Used appropriately, they should not affect the
synthesis results.
| Type | Description | Example |
|---|---|---|
| bit | user-defined size | bit [3:0] a_nibble; |
| byte | 8 bits, signed | byte a, b; |
| shortint | 16 bits, signed | shortint c, d; |
| int | 32 bits, signed | int i,j; |
| longint | 64 bits, signed | longint lword; |
Note that, unlike in C, SystemVerilog specifies the number of bits
for the fixed-width types.
| Type | Description | Example |
|---|---|---|
| reg | user-defined size | reg [7:0] a_byte; |
| logic | identical to reg in every way | logic [7:0] a_byte; |
| integer | 32 bits, signed | integer i, j, k; |
logic is a better name than reg, so is
preferred. As we shall see,
you can use logic where in the past you have may have used reg or where
you may have used wire.
| Type | Description | Example |
|---|---|---|
| time | 64-bit unsigned | time now; |
| shortreal | like float in C | shortreal f; |
| real | like double in C | double g; |
| realtime | identical to real | realtime now; |
Arrays
In Verilog-1995, you could define
scalar and vector nets and variables. You could also define
memory arrays, which are one-dimensional arrays of a
variable type. Verilog-2001 allowed multi-dimensioned arrays of
both nets and variables, and removed some of the restrictions on
memory array usage.
SystemVerilog takes this a stage further and refines the concept
of arrays and permits more operations on arrays.
In SystemVerilog,
arrays may have either packed or unpacked
dimensions,
or both. Consider this example:
reg [3:0][7:0] register [0:9];
The packed dimensions are [3:0] and
[7:0]. The unpacked dimension is [0:9]. (You can have as many
packed and unpacked dimensions as you like.)
Packed dimensions:
- are guaranteed to be laid out contiguously in memory
- can be copied on to any other packed object
- can be sliced ("part-selects")
- are restricted to the "bit" types (bit, logic, int etc.), some of which (e.g. int) have a fixed size.
By contrast, unpacked dimensions can be arranged in memory in
any way that the simulator chooses. You can reliably copy an array
on to another array of the same type. For arrays with different
types, you must use a cast, and there are rules for how an unpacked
type is cast to a packed type. Unpacked arrays can be any type,
such as arrays of reals.
SystemVerilog permits a number of operations on complete
unpacked arrays and slices of unpacked arrays. For these, the
arrays or slices involved must have the same type and the same
shape – i.e. exactly the same number and lengths of unpacked
dimensions. The packed dimensions may be different, as long as the
array or slice elements have the same number of bits.
The permitted operations are:
- Reading and writing the whole array
- Reading and writing array slices
- Reading and writing array elements
- Equality relations on arrays, slices and elements
SystemVerilog also includes dynamic arrays (the number of
elements may change during simulation) and associative arrays
(which have a non-contiguous range).
To support all these array types, SystemVerilog includes a
number of array querying functions and methods. For example, you
could use $dimensions to find the number dimensions of an array
variable.
Typedef
SystemVerilog’s data type
system allows you to define quite complex types. To make this kind
of code clear, the typedef facility was introduced. Typedef
allows users to create their own names for type definitions that
they will use frequently in their code. Typedefs can be very
convenient when building up complicated array
definitions.
typedef reg [7:0] octet;
octet b;
is the same as
reg [7:0] b;
and
typedef octet [3:0]
quadOctet;
quadOctet qBytes [1:10];
is the same as
reg [3:0][7:0] qBytes [1:10];
Enum
SystemVerilog also introduces
enumerated types, for example
enum { circle, ellipse, freeform } c;
Enumerations allow you to define a
data type whose values have names. Such data types are appropriate
and useful for representing state values, opcodes and other such
non-numeric or symbolic data.
Typedef is commonly used together
with enum, like this:
typedef enum { circle, ellipse, freeform } ClosedCurve;
ClosedCurve c;
The named values of an enumeration type act like constants. The
default type is int. You can copy them to and from variables
of the enumeration type, compare them with one another and so on.
Enumerations are strongly typed. You can’t copy a numeric
value into a variable of enumeration type, unless you use a
type-cast:
c = 2; // ERROR
c = ClosedCurve'(2); // Casting – okay
However, when you use an enumeration
in an expression, the value you are working with is the
literal’s integer equivalent; so, for example, it’s
okay to compare an enumeration variable with an integer; and
it’s okay to use an enumeration value in an integer
expression.
Stuct and Union
Finally, SystemVerilog introduces
struct and union data types, similar to those in
C.
struct {
int x, y;
} p;
Struct members are selected using
the .name syntax:
p.x = 1;
Structure literals and expressions
may be formed using braces.
p = {1,2};
It is often useful to declare a new
structure type using typedef and then declare variables using the
new type. Note also that structs may be packed.
typedef struct packed {
int x, y;
} Point;
Point p;
Unions are useful where the same
hardware resources (like a register) can store values of different
types (e.g. integer, floating point, …)