Data Declarations

There are several forms of data in SystemVerilog: literals, parameters, constants, variables, nets, and attributes
Constants are literals, genvars parameters, localparams, and specparams.
Variables must be written by procedural statements, and nets must be written by continuous assignments or ports.
SystemVerilog extends the functionality of variables by allowing them to either be written by procedural statements or driven by a single continuous assignment, similar to a wire. Since the keyword reg no longer describes the user’s intent in many cases, the keyword logic is added as a more accurate description that is equivalent to reg.

SystemVerilog requires data to be declared before it is used, apart from implicit nets. The rules for implicit nets are the same as in Verilog-2001.

A variable can be static (storage allocated on instantiation and never de-allocated) or automatic (stack storage allocated on entry to a scope (such as a task, function or block) and de-allocated on exit). SystemVerilog follows Verilog with respect of the static default storage class, with automatic tasks and functions, but allows static to override a default of automatic for a particular variable in such tasks and functions.


Constants are named data variables that never change. There are three kinds of constants, declared with the keywords localparam, specparam, and const.

localparam byte colon1 = ":" ;
specparam int delay = 10 ; // specparams are used for specify blocks
const logic flag = 1 ;

A parameter or local parameter can only be set to an expression of literals, parameters or local parameters, genvars, enumerated names, or a constant function of these. Hierarchical names are not allowed.
A specparam can also be set to an expression containing one or more specparams.

A static constant declared with the const keyword can only be set to an expression of literals, parameters, local parameters, genvars, enumerated names, a constant function of these, or other constants. The parameters, local parameters or constant functions can have hierarchical names because constants declared with the const keyword are calculated after elaboration. An automatic constant declared with the const keyword can be set to any expression that would be legal without the const keyword.

const logic option = a.b.c ;

A constant expression contains literals and other named constants.
An instance of a class (an object handle) can also be declared with the const keyword.

const class_name object = new(5,3);

This means that the object acts like a variable that cannot be written. The arguments to the new method must be constant expressions. The members of the object can be written (except for those members that are declared const).

SystemVerilog enhancements to parameter and localparam constant declarations. SystemVerilog does not change specparam constants declarations. A const form of constant differs from a localparam constant in that the localparam must be set during elaboration, whereas a const can be set during simulation, such as in an automatic task.


A variable declaration consists of a data type followed by one or more instances.

shortint s1, s2[0:9];

A variable can be declared with an initializer, for example:

int i = 0;

In Verilog-2001, an initialization value specified as part of the declaration is executed as if the assignment were made from an initial block after the simulation has started. Therefore, the initialization can cause an event on that variable at simulation time zero.

In SystemVerilog, setting the initial value of a static variable as part of the variable declaration (including static class members) shall occur before any initial or always blocks are started, and so does not generate an event. If an event is needed, an initial block should be used to assign the initial values.

Initial values in SystemVerilog are not constrained to simple constants; they can include run-time expressions, including dynamic memory allocation. For example, a static class handle or a mailbox can be created and initialized by calling its new method, or static variables can be initialized to random values by calling the $urandom system task. This requires a special pre-initial pass at run-time.

The default values for SystemVerilog variables are:

4 state integral:   ’x
2 state integral:   ’0
real, shortreal:     0.0
Enumeration:      First value in the enumeration
string:        “” (empty string)
event:         New event
class:       Null

Scope and lifetime

Any data declared outside a module, interface, task, or function, is global in scope (can be used anywhere after its declaration) and has a static lifetime (exists for the whole elaboration and simulation time).

SystemVerilog data declared inside a module or interface but outside a task, process or function is local in scope and static lifetime (exists for the lifetime of the module or interface).

Data declared in an automatic task, function, or block has the lifetime of the call or activation and a local scope.

Data declared in a static task, function, or block defaults to a static lifetime and a local scope.

Verilog-2001 allows tasks and functions to be declared as automatic, making all storage within the task or function automatic. SystemVerilog allows specific data within a static task or function to be explicitly declared as automatic. Data declared as automatic has the lifetime of the call or block, and is initialized on each entry to the call or block. The lifetime of a forkjoin, forkjoin_any, or forkjoin_none block shall encompass the execution of all processes spawned by the block. The lifetime of a scope enclosing any forkjoin block includes the lifetime of the forkjoin block.

SystemVerilog also allows data to be explicitly declared as static. Data declared to be static in an automatic task, function or block has a static lifetime and a scope local to the block.

module msl;
int st0; // static
initial begin
int st1; //static
static int st2; //static
automatic int auto1; //Automatic
task automatic t1();
int auto2; //Automatic
static int st3; //static
automatic int auto3; //Automatic

SystemVerilog adds an optional qualifier to specify the default lifetime of all variables declared in a task, function, or block defined within a module, interface, or program. The lifetime qualifier is automatic or static. The default lifetime is static.

program automatic test ;
int i; // not within a procedural block - static
task foo( int a ); // arguments and variables in foo are automatic

Class methods and declared for loop variables are by default automatic, regardless of the lifetime attribute of the scope in which they are declared.
Note that automatic or dynamic variables cannot be written with nonblocking or continuous assignments.
Automatic variables and dynamic constructs—object handles, dynamic arrays, associative arrays, strings, and event variables—shall be limited to the procedural context.

<< Previous | Next >>

String data type

SystemVerilog includes a string data type, which is a variable size, dynamically allocated array of bytes.
SystemVerilog also includes a number of special methods to work with strings.

Verilog supports string literals, but only at the lexical level. In Verilog, string literals behave like packed arrays of a width that is a multiple of 8 bits. A string literal assigned to a packed array of an integral variable of a different size is either truncated to the size of the variable or padded with zeroes to the left as necessary.

In SystemVerilog string literals behave the same as in Verilog However, SystemVerilog also supports the string data type to which a string literal can be assigned. When using the string data type instead of an integral variable, strings can be of arbitrary length and no truncation occurs. Literal strings are implicitly converted to the string type when assigned to a string type or used in an expression involving string type operands.

Variables of type string can be indexed from 0 to N-1 (the last element of the array), and they can take on the special value “”, which is the empty string.

The syntax to declare a string is:

string variable_name [= initial_value];

where variable_name is a valid identifier and the optional initial_value can be a string literal or the value “”

for an empty string.

Example :
string myName = "John";

If an initial value is not specified in the declaration, the variable is initialized to “”, the empty string.

SystemVerilog provides a set of operators that can be used to manipulate combinations of string variables and string literals.

A string literal can be assigned to a string or an integral type. If their size differs the literal is right justified
and either truncated on the left or zero-filled on the left, as necessary.

Example :
byte c = "A"; // assign to c "A"
bit [10:0] a = "\x41"; // assigns to a ‘b000_0100_0001
bit [1:4][7:0] h = "hello" ; // assigns to h "ello"

A string, string literal, or packed array can be assigned to a string variable. The string variable shall grow or shrink to accommodate the packed array. If the size (in bits) of the packed array is not a multiple of 8, then the packed array is zero-filled on the left.

Example :
string s1 = "hello"; // sets s1 to "hello"
bit [11:0] b = 12’ha41;
string s2 = b; // sets s2 to ’h0a41

As a second example:

reg [15:0] r;
integer i = 1;
string b = "";
string a = {"Hi", b};

r = a;           // OK
b = r;           // OK (implicit cast, implementations can issue a warning)
b = "Hi";       // OK
b = {5{"Hi"}}; // OK
a = {i{"Hi"}}; // OK (non-constant replication)
r = {i{"Hi"}}; // invalid (non-constant replication)
a = {i{b}};     // OK
a = {a,b};      // OK
a = {"Hi",b};  // OK
r = {"H",""};  // yields “H\0” “” is converted to 8’b0
b = {"H",""};  // yields “H” “” is the empty string
a[0] = "h";    // OK same as a[0] = “hi” )


function int len()

  • str.len() returns the length of the string, i.e., the number of characters in the string (excluding any terminating character).
  • If str is “”, then str.len() returns 0.


task putc(int i, string s)
task putc(int i, byte c)

  •  str.putc(i, c) replaces the ith character in str with the given integral value.
  •  str.putc(i, s) replaces the ith character in str with the first character in s.
  •  s can be any expression that can be assigned to a string.
  •  putc does not change the size of str: If i < 0 or i >= str.len(), then str is unchanged.


function int getc(int i)

  •  str.getc(i) returns the ASCII code of the ith character in str.
  •  If i < 0 or i >= str.len(), then str.getc(i) returns 0.


function string toupper()

  • str.toupper() returns a string with characters in str converted to uppercase.
  • str is unchanged.


function string tolower()

  • str.tolower() returns a string with characters in str converted to lowercase.
  • str is unchanged.


function int compare(string s)

  • compares str and s and embedded null bytes are included.


function int icompare(string s)

  • str.icompare(s) compares str and s, the comparison is case insensitive and embedded null bytes are included.


function string substr(int i, int j)

  • str.substr(i, j) returns a new string that is a substring formed by characters in position i through j of str.
  • If i < 0, j < i, or j >= str.len(), substr() returns ” ” (the empty string).

<< Previous | Next >>

System Verilog data types

2-state (two-value) and 4-state (four-value) data types

Types that can have unknown and high-impedance values are called 4-state types. These are logic, reg, integer, and time. The other types do not have unknown values and are called 2-state types, for example, bit and int.
The difference between int and integer is that int is 2-state logic and integer is 4-state logic. 4-state values have additional bits that encode the X and Z states. 2-state data types can simulate faster, take less memory, and are preferred in some design styles.

Signed and unsigned data types

Integer types use integer arithmetic and can be signed or unsigned. This affects the meaning of certain operators such as ‘<’, etc.

int unsigned ui;
int signed si;

The data types byte, shortint, int, integer, and longint default to signed. The data types bit, reg and logic default to unsigned, as do arrays of these types.
Note that the signed keyword is part of Verilog-2001. The unsigned keyword is a reserved keyword in Verilog- 2001, but is not utilized.

Real and shortreal data types

The real data type is from Verilog-2001 and is the same as a C double. The shortreal data type is a SystemVerilog data type and is the same as a C float.

Void data type

The void data type represents non-existent data. This type can be specified as the return type of functions, indicating no return value. This type can also be used for members of tagged unions

Integer data types

SystemVerilog offers several integer data types, representing a hybrid of both Verilog and C data types:

shortint :   2-state SystemVerilog data type, 16 bit signed integer
int :         2-state SystemVerilog data type, 32 bit signed integer
longint :    2-state SystemVerilog data type, 64 bit signed integer
byte  :       2-state SystemVerilog data type, 8 bit signed integer or ASCII character
bit  :        2-state SystemVerilog data type, user-defined vector size
logic  :      4-state SystemVerilog data type, user-defined vector size
reg  :        4-state Verilog-2001 data type, user-defined vector size
integer  :   4-state Verilog-2001 data type, 32 bit signed integer
time  :       4-state Verilog-2001 data type, 64-bit unsigned integer

<< Previous | Next >>