User defined Types in SystemVerilog
Verilog does not support user defined types that could be useful while modeling at higher levels of abstraction. SystemVerilog extends Verilog and offers users flexibility to create new variable and net types. User defined types allow new types to be created from existing types using the typedef command.
typedef int unsigned uint;
uint i; // unsigned integer
A user defined type can be used before it is created provided it is first defined using empty typedef.
typedef flag_t;
flag_t = '0;
typedef logic [3:0] flag_t ;
type definitions can be declared either externally or in packages or locally.
SV Enumerated Types provide a way to declare abstract variables that can have listed set of values. Syntax is
enum (enum_base_type) { enum_name_declarations } enum_name
-
enum {ADD, SUB, DIVI, MUL} opcode; // ADD is assigned value 1, SUB 2, DIVI 3 and MUL 4
-
enum {ADD=4, SUB, DIVI=10, MUL} opcode; // ADD is 4, SUB is 5, DIVI is 10, MUL is 11
Verilog does not support enumerated types but supports parameter and 'define macros to make the code easier to read - for example, FSM states can be defined as parameters while `define would be used to define a error condition. The disadvantage is that the state and nextstate variables can be declared using only predefined datatypes and the list of values they can take cannot be limited.
-
enum logic [3:0] {IDLE = 4'b001,
-
XMT_ADDR = 4'b0010,
-
XMT_DATA = 4'b0100,
-
WAIT_FOR_ACK = 4'b1000} State, NextState;
SV enum types limit the state variables to the enum values maintaining consistency for synthesis and simulation.
Enumerated types can also be declared as user defined type using typedef.
typedef enum {TRUE, FALSE} boolean;
boolean flag, result;
Enumerated types are strongly typed and cannot be assigned a value outside it's legal list. As a result, arithmetical operations such as state++ are illegal as it can go out of bounds. Static and Dynamic casting to an enumerated type is allowed.
-
typedef enum {IDLE, XMT, WAIT, DONE} states_t;
-
states_t state, next_state;
-
-
next_state = states_t'(state++); // Legal, casting can cause out-of-bounds !!
-
$cast(next_state, state + 1); // Legal, will report error if out of bounds
SV includes a set of specialized methods to enable iterations over values of the enumerated types.
| Enumerated Type Methods | Description |
|
<enum_var>.first
|
returns first enum value in the list of enumerated types |
|
<enum_var>.last
|
returns last enum value in the list |
|
<enum_var>.next(N) |
return next value in the list. If a number is added to next, it returns the Nth next value from the current value in the list. If the Nth next value is not legal, it returns the first value in the list. |
|
<enum_var>.prev(N) |
return previous value in the list. Similar to next, except if Nth previous value is not legal, returns last value in the list. |
|
<enum_var>.name |
returns string representation of the label given to enum value. If label is absent, returns empty string. Can be used to display current value of enum_variable using $display. |
Type casting in SystemVerilog
SystemVerilog adds a cast operator ( ' , forward tick) that supports the ability to cast a value to a different type. The expression to be cast should be enclosed in parentheses or within concatenation or replication braces and is self-determined. The syntax is
<casting_type> '(<expression>)
shortint'(2 * 4) // cast result of 2 *4 to shortint
In addition to this, SV also offers support to cast a unsigned value to signed (or vice versa) and to cast a vector to a different size.
<size>'(<expression>)
logic [7:0] x;
x = 8'(5) // cast literal value 5 to 8-bits wide
<sign>'(<expression>)
y = signed'(x)
Static casting does not include run-time checking i.e. if the cast results in a illegal value during run time, SV does not report any error. For more robust checking, SV offers a dynamic cast function $cast that performs dynamic run time checking. The syntax of $cast is
$cast (dest_var, source_exp) where
dest_var is the variable to which assignment is made and
source_exp is expression that is assigned
-
int x, y;
-
always @(posedge clk)
-
$cast(y, 2.5 * x);
$cast can also be defined as a task and reports a error if the cast value is illegal during runtime. An example would be assigning a cast value to an enumerated type that is not in the set. When called as a function, $cast returns a '1' if the cast was successful or a '0' if it fails. When called as a function, $cast does not report any runtime error and leaves the destination variable unchanged.
-
typedef enum { ADD, MUL, DIVI, SUB, MOD } Opcode;
-
Opcode operat_e;
-
$cast( operat_e, 2 + 1 ); // Dynamic cast : assigns 3 => DIVI to operat_e
-
operat_e = Opcode'(2+1) // Static cast
Type casting can also applied to unpacked arrays and structs known as bit-stream casting. We will visit this when we cover arrays and structs.
Sphere: Related Content
Data Types in SystemVerilog
Verilog supports variable and net types that are identical to each other and drive four-state values.
- reg, integer, time variables can have '0', '1', 'Z' and 'X' values
- wand , wor , wire net types can have '0', '1', 'Z' and 'X' values with 7 strengths giving 120 values
SystemVerilog (SV) extends Verilog variable types that can be either 2-state ('0' or '1') or 4-state ('0', '1', 'X', 'Z') data types while net types can be only 4-state data types. Data declarations in SystemVerilog have a type (that indicates if the signal is a net or a variable) and a data type (that indicates if it is 2-state or 4-state values).
SV Four state logic type
To replace the confusing reg type in Verilog, SystemVerilog defines a 4-state logic data type that can be associated with variables or nets. For example,
var logic [31:0] data; // a 32-bit variable supporting 4-state values
wire logic [31:0] data; // a 32-bit net capable of driving 4-state values.
Note that Verilog reg type cannot be associated with net types while SV logic type can be. Also note that the variable is implied if var keyword is absent in a declaration i.e.
logic [31:0] data // is same as var logic [31:0] data
Similarly, if the var is explicitly defined but the datatype is absent, it is assumed to be logic data type by default.
var [31:0] data // is same as var logic [31:0] data
wire [31:0] data; // a 32-bit net type, 4-state logic datatype.
SV Two state types
SV adds new 2-state types that can aid faster simulations and also consume less memory while modeling hardware at higher levels. These include
- bit - a single bit 2-state integer, user-defined vector size
var bit flag; // -bit wide 2-state variable
var bit [31:0] count; // a 32-bit 2-state variable
- byte - a single byte 2-state integer
- shortint - a 16-bit 2-state integer
- int - a 32-bit 2-state integer, similar to C
- longint - a 64-bit 2-state integer
The byte, int, longint, shortint types are signed by default, SV includes unsigned keyword to override this default.
int unsigned data; // Unsigned 32-bit variable
The 4-state variables if uninitialized take a value of 'X' until the first assignment - it is the recommended choice for synthesizable RTL. 2-state variables if uninitialized default to '0'. When a 4-state variable is assigned to a 2-state variable, the 'X' and 'Z' are translated to '0'. 2-state variables are synthesized similar to the 4-state variables by tools that ignore the default value of zero.
Abstract Data Types (not synthesizable) such as real (similar to Cdouble), shortreal (C float), void (used to define functions that do not return any value or in tagged unions) are also supported in SV.