Arrays in SystemVerilog
An array is a collection of similar variables, accessible via indices and the array name. Verilog-2001 supports multi-dimensional arrays and net and variable type array declarations are valid. Verilog restricts access to only one element or a slice of an array at a time.
-
reg r [0:63]; // 1 dimensional unpacked array
-
wire [0:7] count [0:144]; // a 1-dimensional unpacked array 145 8-bit nets
-
int i [0:7] [0:15]; // a 2-dimensional unpacked array
-
-
// Packed Arrays
-
wire [3:0] count; // packed array of 4-bits
-
-
wire [3:0] [1:0] addr; // 2-dimensional packed array
-
wire [7:0] addr_out = addr; // entire packed array
-
-
// Initializing Packed array
-
wire [7:0] [1:0] data = 16'h0;
-
// Initializing Unpacked array
-
wire data [0:1] [0:3] = '{ '{11, 12, 13, 14}, '{2, 3, 4, 5} }
-
int addr [0:1] [0:15] = '{ default: 2'h3 } // initialize all elements to 2'b11
SV extends the unpacked arrays to new types like int, shortint, logic, bit, byte, real and shortreal. SV also allows accessing all elements of an array at a time unlike Verilog. For packed arrays, multi-dimensional arrays are supported by SV. The entire packed array is stored as contiguous order of bits and arithmetic/logical operations are supported.
Packed arrays can be assigned to another packed array even if their sizes do not match. However, unpacked arrays can be assigned to another unpacked array only if the vector and dimension size are equal. To assign an unpacked array to a packed array or vice versa, bit stream casting needs to be done. A bit-stream cast converts an unpacked array into a stream of bits using the SV static cast operator '. Both packed and unpacked arrays are synthesizable.
SV also supports dynamic arrays for higher levels of modeling (not synthesizable) - A dynamic array is one dimension of an unpacked array, the size of which is set or changed during runtime.
-
bit [3:0] crc [];// Dynamic array of 4-bit vectors
SV supports new[], size() and delete() methods similar to C for dynamic arrays.
Associative arrays are also supported by SV - the array index is not restricted to integral values (like int, shortint) and can be any data type.
-
integer assoc[*]; // * is wildcard indicates unspecified but integral value index
-
bit [7:0] assoc [string]; // indexed by string
SV supports in-built methods for associative arrays as tabulated below.
Associative Methods |
Description |
|
<array>.num( )
|
Returns number of entries in the associative array. |
|
<array>.delete(N)
|
if index N is not specified, deletes all elements of the |
|
<array>.exists(N) |
checks if element exists at that particular index of the array. returns 1 if true. index is mandatory |
|
<array>.first(N) |
assigns to the index variable N the value of the smallest |
|
<array>.last(N) |
assigns to the index variable N the value of the largest index in the array, returns 1 if array is not empty, 0 otherwise |
| <array>.next(N) | finds the entry whose index is greater than current index N and assigns the index variable to that next entry. Retruns 1 if true |
| <array>.prev(N) | finds the entry whose index is smaller than current index N and assigns the index variable to that previous entry. Retruns 1 if true |
Structures and Unions in SystemVerilog
SystemVerilog supports C-like structures without the optional tag before braces using struct keyword to group several related signals together.
Both variable and net types can be defined as structures. However, net types cannot be used for members of structures. By default, all structures are variable types. Structures that are defined without typedef are known as anonymous structures.
-
// Anonymous Structure
-
struct {
-
pkt_type_t type;
-
bit [15:0] addr;
-
bit [ 31:0] data;
-
byte crc;
-
} Packet_s;
-
// To assign a value to a struct member
-
Packet_s.type = ETHER_II;
-
-
// User defined struct
-
typedef struct {
-
pkt_type_t type;
-
bit [15:0] addr;
-
bit [ 31:0] data;
-
byte crc;
-
} Packet_s;
-
-
Packet_s pkt;
-
// To assign a value to a struct member
-
pkt.type = ETHER_II;
-
-
// Structures can be initialized using '{ and } operators
-
Packet_s pkt = '{ETHER_II, 16'h40, 32'hffff, 8'b30};
-
-
// Alternate way - explicit
-
Packet_s pkt = '{crc: 8'b30, addr:16'h40, data:32'hffff, type:ETHER_II};
-
-
// Default to zero using default keyword
-
Packet_s pkt = '{default:0};
structures are unpacked by default but packed structures are also possible using packed keyword after the struct - the members are stored as a bit vector with the first member being the MSB. Packed structures can compass only integral values (byte, int, shortint, logic or bit) - real types, enum types are not allowed. This allows mathematical/logical operations on packed structures. packed structures can be either signed or unsigned.
-
typedef struct packed signed {
-
logic [7:0] addr;
-
logic [31:0] data;
-
byte crc;
-
} Packet_s;
-
-
Packet_s pkt_a, pkt_b;
-
-
always @(posedge clock)
-
if (pkt_a < pkt_b) // Arithmetic signed operation
-
..
Structures can be passed through modules and also passed as arguments to tasks and functions if they are not anonymous. structs are also synthesizable.
Unions are supported in SV using union keyword and stores only a single value unlike structures. Unpacked unions can consist of any variable type like real, unpacked structs for abstract modeling and are not synthesizable.
-
typedef union {
-
logic [3:0] data;
-
logic data_valid;
-
} data_u;
-
-
data_u data_ctrl_u;
-
-
//tagged union
-
typedef union tagged {
-
logic [3:0] data;
-
logic data_valid;
-
} data_u;
-
-
data_u data_ctrl_u;
-
-
data_ctrl_u = tagged data_valid 1; // set data_valid in union data_ctrl_u to 1
-
-
data_valid_out = data_ctrl_u.data_valid;
unions can be tagged to include a member with implicit tag - this tag represents the name of the union member last written to. Values are stored in tagged unions using a tagged expression.
unions can also be packed - the members must have same number of bits making them synthesizable.
Sphere: Related ContentUser 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. |