SystemVerilog Fixed Arrays

Let's talk about most used data type - Arrays. An array is a collection of data elements having the same type. Individual elements are accessed by index using a consecutive range of integers. However there are some type of arrays allows to access individual elements using non consecutive values of any data types. SystemVerilog Arrays offers several flavors of arrays beyond the single-dimension, fixed-size Verilog-1995 arrays. Many enhancement have been made to these classic arrays. Arrays can be classified as
  • Fixed Arrays or Fixed-Sized Arrays (sometimes known as static arrays) whose size cannot be changed once declared. 
  • Dynamic arrays which can be resized run time.

Declaring and initializing fixed-size array
Verilog requires that the low and high array limits must be given in the declaration. Almost all arrays use a low index of 0, so SystemVerilog lets you use the shortcut of just giving the array size, similar to C:

Example 1 : Declaring and using SystemVerilog fixed-sized arrays

int data[0:15];  // 16 ints [0]..[15]
int address[16]; // 16 ints [0]..[15]
address[15] = 1; // Set last array element


You can create multidimensional fixed-size arrays by specifying the dimensions after the variable name. This makes an unpacked array; we will take a look for packed arrays later. The following example creates several two-dimensional arrays of integers, 8 entries by 4, and sets the last entry to 1.

Example 2 : Declaring and using multidimensional fixed-sized array

int array2 [0:7][0:3]; // Verbose declaration
int array3 [8][4];     // Compact declaration
array2[7][3] = 1;      // Set last array element

SystemVerilog stores each element on a longword (32-bit) boundary. So a byte, shortint, and int are all stored in a single longword, while a longint is stored in two longwords. (Simulators frequently store four-state types such as logic and integer in two or more longwords.)

Example 3 : SystemVerilog Unpacked Array Declaration

bit [7:0] unpacked_array[3]; // Unpacked array

Unpacked array declared above is stored as shown below


You can initialize an array using an array literal that is an apostrophe and curly braces. Using this array literal you can set some or all elements at once. Also its easy to replicate values by putting a count before the curly braces. Below we have shown example to initialize the systemverilog fixed arrays

Example 4 : Initialize SystemVerilog Array

int ascend[4] = {0,1,2,3}; // Initialize 4 elements
int decend[5];
int array[2][3] = {{0,1,2}, {3,4,5}};
descend = {4,3,2,1,0}; // Set 5 elements
descend[0:2] = {5,6,7}; // Set first 3 elements
ascend = {4{8}}; // Four values of 8

Basic Array Operations
The most common way to manipulate an array is with a for or foreach loop. In below example the variable "i" is declared local to the for loop. To get the size of array we can use system function $size that returns the size of array. For foreach loop statement, you specify the array name and an index in square brackets and Systemverilog automatically steps through all the elements of the array. The index variable is local to the loop.

Example 5 : Access the arrays using for and foreach loops

// SystemVerilog For and Foreach loop to access arrays
module array_loops;
  initial begin
    bit [31:0] src[5], dst[5];
    for (int i=0; i<$size(src); i++) begin
      src[i] = i;
      $display("src[%0d] = %0d", i, src[i]); 
    end
    foreach (dst[j]) begin
      dst[j] = src[j] * 2; // dst doubles src values
      $display("dst[%0d] = %0d", j, dst[j]); 
    end
  end
endmodule

Simulation Results:
src[0] = 0
src[1] = 1
src[2] = 2
src[3] = 3
src[4] = 4
dst[0] = 0
dst[1] = 2
dst[2] = 4
dst[3] = 6
dst[4] = 8

Now in below example note that for SystemVerilog multidimensional arrays the syntax is not as you might expected. Instead of listing each subscript in separate square brackets – [i][j] – they are combined with a comma – [i,j].

Example 6: SystemVerilog Accessing Multidimensional Arrays using Foreach loop


// SystemVerilog For and Foreach loop to access arrays
module array_loops;
  int md[2][3];
  initial begin
    $display("Initial value:");
    foreach (md[i,j]) // Yes, this is the right syntax
      $display("md[%0d][%0d] = %0d", i, j, md[i][j]);
    $display("New value:");
    md = '{{9, 8, 7}, {default:5}}; // Replicate last 3 values
    foreach (md[i,j]) // Yes, this is the right syntax
      $display("md[%0d][%0d] = %0d", i, j, md[i][j]);
    end
endmodule

Simulation Results:
Initial value:
md[0][0] = 0
md[0][1] = 0
md[0][2] = 0
md[1][0] = 0
md[1][1] = 0
md[1][2] = 0
New value:
md[0][0] = 9
md[0][1] = 8
md[0][2] = 7
md[1][0] = 5
md[1][1] = 5
md[1][2] = 5

Packed arrays :


Before knowing what exactly packed and unpacked arrays are, lets also see how you can know which array is what, just by their declaration. 

Packed arrays have an object name comes before size declaration. 
For example: bit [3][7] a;

As specified previously unpacked array have an object name comes after size declaration. 
For example: bit a[3];

For some data types, you may want both to access the entire value and also divide it into smaller elements. For example, you may have a 32-bit register that sometimes you want to treat as four 8-bit values and at other times as a single, unsigned value. A SystemVerilog packed array is treated as both an array and a single value. Packed arrays can be made of only the single bit data types (bit, logic, reg) and recursively other packed arrays and packed structures. It is stored as a contiguous set of bits with no unused space, unlike an unpacked array.

Packed Array Example 
The packed bit and word dimensions are specified as part of the type, before the variable name. These dimensions must be specified in the [lo:hi] format. The variable bytes is a packed array of four bytes, which are stored in a single longword.


1
bit [3:0] [7:0] bytes; // 4 bytes packed into 32-bits

Packed Array Layout



You can mix packed and unpacked dimensions. You may want to make an array that represents a memory that can be accessed as bits, bytes, or long words. In Example 2-14, barray is an unpacked array of three packed elements.


Declaration of mixed packed and unpacked arrays


1
bit [3:0] [7:0] barray [3]; // Packed: 3x32-bit

The variable bytes is a packed array of four bytes, which are stored in a single longword. barray is an array of three of these elements.


With a single subscript, you get a longword of data, barray[2]. With two subscripts, you get a byte of data, barray[0][3]. With three subscripts, you can access a single bit, barray[0][1][6]. Note that because one dimension is specified after the name, barray[3], that dimension is unpacked, so you always need to use at least one subscript.

Choosing Between Packed and Unpacked Array

Which should you choose — packed or unpacked array?
A packed array is handy if you need to convert to and from scalars. For example, you might need to reference a memory as a byte or as a longword. The above array barray can handle this requirement. Only fixed-size arrays can be packed, not dynamic arrays, associative arrays, or queues.

If you need to wait for a change in an array, you have to use a packed array. Perhaps your testbench might need to wake up when a memory changes value, so you want to use the @ operator. But this is only legal with scalar values and packed arrays. Using the earlier examples, you can block on the variable lw, and barray[0], but not the entire array barray unless you expand it: @(barray[0] or barray[1] or barray[2]).

Previous : Net Type
Next : Dynamic Arrays

No comments:

Post a Comment

Please provide valuable comments and suggestions for our motivation...

Popular Posts