Dynamic arrays

A dynamic array is one dimension of an unpacked array whose size can be set or changed at runtime. The space for a dynamic array doesn’t exist until the array is explicitly created at runtime.
The syntax to declare a dynamic array is:

data_type array_name [];

where data_type is the data type of the array elements. Dynamic arrays support the same types as fixed-size arrays.
For example:

bit [3:0] nibble[]; // Dynamic array of 4-bit vectors
integer mem[]; // Dynamic array of integers

The new[] operator is used to set or change the size of the array.
The size() built-in method returns the current size of the array.
The delete() built-in method clears all the elements yielding an empty array (zero size).

new[]

The built-in function new allocates the storage and initializes the newly allocated array elements either to their default initial value or to the values provided by the optional argument.

size()

The prototype for the size() method is:
function int size();

The size() method returns the current size of a dynamic array, or zero if the array has not been created.

int j = addr.size;

addr = new[ addr.size() * 4 ] (addr); // quadruple addr array

Note: The size method is equivalent to $length( addr, 1 ).

delete()

The prototype for the delete() method is:
function void delete();

The delete() method empties the array, resulting in a zero-sized array.

int ab [] = new[ N ]; // create a temporary array of size N

ab.delete; // delete the array contents

$display( "%d", ab.size ); // prints 0

Array assignment

Assigning to a fixed-size unpacked array requires that the source and the target both be arrays with the same number of unpacked dimensions and the length of each dimension be the same. The assignment is done by assigning each element of the source array to the corresponding element of the target array, which requires that the source and target arrays be of compatible types. Compatible types are types that are assignment-compatible.

Assigning fixed-size unpacked arrays of unequal size to one another shall result in a type check error.

int A[10:1]; // fixed-size array of 10 elements

int B[0:9]; // fixed-size array of 10 elements

int C[24:1]; // fixed-size array of 24 elements

A = B; // ok. Compatible type and same size

A = C; // type check error: different sizes

An array of wires can be assigned to an array of variables having the same number of unpacked dimensions and the same length for each of those dimensions, and vice-versa.

wire [31:0] W [9:0];
assign W = A;
initial #10 B = W;

A dynamic array can be assigned to a one-dimensional fixed-size array of a compatible type if the size of the dynamic array is the same as the length of the fixed-size array dimension. Unlike assigning with a fixed-size array, this operation requires a run-time check that can result in an error.

int A[100:1]; // fixed-size array of 100 elements
int B[] = new[100]; // dynamic array of 100 elements
int C[] = new[8]; // dynamic array of 8 elements
A = B; // OK. Compatible type and same size
A = C; // type check error: different sizes

A dynamic array or a one-dimensional fixed-size array can be assigned to a dynamic array of a compatible type. In this case, the assignment creates a new dynamic array with a size equal to the length of the fixed-size array. For example:

int A[100:1]; // fixed-size array of 100 elements
int B[]; // empty dynamic array
int C[] = new[8]; // dynamic array of size 8
B = A; // ok. B has 100 elements
B = C; // ok. B has 8 elements

The last statement above is equivalent to:

B = new[ C.size ] (C);

Similarly, the source of an assignment can be a complex expression involving array slices or concatenations.
For example:

string d[1:5] = { "a", "b", "c", "d", "e" };
string p[];
p = { d[1:3], "hello", d[4:5] };

The preceding example creates the dynamic array p with contents: “a”, “b”, “c”, “hello”, “d”, “e”.

Arrays as arguments

Arrays can be passed as arguments to tasks or functions. The rules that govern array argument passing by value are the same as for array assignment. When an array argument is passed by value, a copy of the array is passed to the called task or function. This is true for all array types: fixed-size, dynamic, or associative.

Note that unsized dimensions can occur in dynamic arrays and in formal arguments of import DPI functions. If one dimension of a formal is unsized, then any size of the corresponding dimension of an actual is accepted.

For example, the declaration:

task fun(int a[3:1][3:1]);

declares task fun that takes one argument, a two-dimensional array with each dimension of size three. A call to fun must pass a two-dimensional array and with the same dimension size 3 for all the dimensions. For example,

given the above description for fun, consider the following actuals:

int b[3:1][3:1]; // OK: same type, dimension, and size

int b[1:3][0:2]; // OK: same type, dimension, & size (different ranges)

reg b[3:1][3:1]; // OK: assignment compatible type

event b[3:1][3:1]; // error: incompatible type

int b[3:1]; // error: incompatible number of dimensions

int b[3:1][4:1]; // error: incompatible size

A subroutine that accepts a dynamic array can be passed a dynamic array of a compatible type or a one-dimensional fixed-size array of a compatible type

For example, the declaration:

task ABC( string arr[] );

declares a task that accepts one argument, a dynamic array of strings. This task can accept any one-dimensional array of strings or any dynamic array of strings.

An import DPI function that accepts a one-dimensional array can be passed a dynamic array of a compatible type and of any size if formal is unsized, and of the same size if formal is sized. However, a dynamic array cannot be passed as an argument if formal is an unsized output.

<< Previous | Next >>

Arrays

Introduction

An array is a collection of variables, all of the same type, and accessed using the same name plus one or more indices.

In Verilog-2001, arrays are indexed from left-bound to right-bound. If they are vectors, they can be assigned as a single unit, but not if they are arrays. Verilog-2001 allows multiple dimensions.

In Verilog-2001, all data types can be declared as arrays. The reg, wire and all other net types can also have a vector width declared. A dimension declared before the object name is referred to as the “vector width” dimension.

The dimensions declared after the object name are referred to as the “array” dimensions.

reg [7:0] r1 [1:256]; // [7:0] is the vector width, [1:256] is the array size

SystemVerilog uses the term “packed array” to refer to the dimensions declared before the object name (what Verilog-2001 refers to as the vector width). The term “unpacked array” is used to refer to the dimensions declared after the object name.

bit [7:0] c1; // packed array

real u [7:0]; // unpacked array

SystemVerilog enhances packed arrays by allowing multiple dimensions. SystemVerilog adds the ability to procedurally change the size of one of the dimensions of an unpacked array. Fixed-size unpacked arrays can be multi-dimensional and have fixed storage allocated for all the elements of the array. Each dimension of an unpacked array can be declared as having a fixed or un-fixed size.

A dynamic array allocates storage for elements at runtime along with the option of changing the size of one of its dimensions.

An associative array allocates storage for elements individually as they are written. Associative arrays can be indexed using arbitrary data types.

A queue type of array grows or shrinks to accommodate the number of elements written to the array at runtime.

Packed and unpacked arrays

A packed array is a mechanism for subdividing a vector into subfields which can be conveniently accessed as array elements. Consequently, a packed array is guaranteed to be represented as a contiguous set of bits.

An unpacked array may or may not be so represented. A packed array differs from an unpacked array in that when a packed array appears as a primary, it is treated as a single vector.

If a packed array is declared as signed, then the array viewed as a single vector shall be signed. The individual elements of the array are unsigned unless they are of a named type declared as signed. A part-select of a packed array shall be unsigned.

Packed arrays allow arbitrary length integer types, so a 48 bits integer can be made up of 48 bits. These integers can then be used for 48 bits arithmetic. The maximum size of a packed array can be limited but shall be at least 65536 (216) bits.

Packed arrays can only be made of the single bit types (bit, logic, reg, wire, and the other net types) and recursively other packed arrays and packed structures.

Integer types with predefined widths cannot have packed array dimensions declared. These types are byte, shortint, int, longint, and integer. An integer type with a predefined width can be treated as a single-dimension packed array. The packed dimensions of these integer types shall be numbered down to 0, such that the right-most index is 0.

byte c2; // same as bit [7:0] c2;

integer i1; // same as logic signed [31:0] i1;

Unpacked arrays can be made of any type. System Verilog enhances fixed-size unpacked arrays in that in addition to all other variable types, unpacked arrays can also be made of object handles and events.

System Verilog accepts a single number, as an alternative to a range, to specify the size of an unpacked array, like C. That is, [size] becomes the same as [0:size-1]. For example:

int Array[8][32]; is the same as: int Array[0:7][0:31];

The following operations can be performed on all arrays, packed or unpacked. The examples provided with these rules assume that A and B are arrays of the same shape and type.

  • Reading and writing the array, e.g., A = B
  • Reading and writing a slice of the array, e.g., A[i:j] = B[i:j]
  • Reading and writing a variable slice of the array, e.g., A[x+:c] = B[y+:c]
  • Reading and writing an element of the array, e.g., A[i] = B[i]
  • Equality operations on the array or slice of the array, e.g. A==B, A[i:j] != B[i:j]

The following operations can be performed on packed arrays, but not on unpacked arrays. The examples provided with these rules assume that A is an array.

  • Assignment from an integer, e.g., A = 8’b11111111;
  • Treatment as an integer in an expression, e.g., (A + 3)

If an unpacked array is declared as signed, then this applies to the individual elements of the array, since the whole array cannot be viewed as a single vector.

When assigning to an unpacked array, the source and target must be arrays with the same number of unpacked dimensions, and the length of each dimension must be the same. Assignment to an unpacked array is done by assigning each element of the source unpacked array to the corresponding element of the target unpacked array. Note that an element of an unpacked array can be a packed array.

For the purposes of assignment, a packed array is treated as a vector. Any vector expression can be assigned to any packed array. The packed array bounds of the target packed array do not affect the assignment. A packed array cannot be directly assigned to an unpacked array without an explicit cast.

Multiple dimensions

Like Verilog memories, the dimensions following the type set the packed size. The dimensions following the instance set the unpacked size.

bit [3:0] [7:0] john [1:10]; // 10 entries of 4 bytes (packed into 32 bits)

can be used as follows:

john[9] = john[8] + 1; // 4 byte add
john[7][3:2] = john[6][1:0]; // 2 byte copy

<< Previous | Next >>