Different Array Types and Queues in System Verilog

In short: SystemVerilog gives you four main array types beyond the fixed size array: the dynamic array (size set at run time with new[]), the associative array (sparse, indexed by any key such as a string), the queue (an ordered list that grows and shrinks with push and pop), and each has its own methods. Pick the dynamic array when the size is known only at run time, the associative array when the index range is huge but mostly empty, and the queue when you push and pop from the ends.

A fixed size array is fine when you know the count up front. But testbenches often do not know the count until the simulation runs, or need to look up data by an odd key, or need a list that changes length while it runs. SystemVerilog covers those needs with three flexible array types. This guide shows each one, its methods, and when to reach for it.

A simple way to picture it

Think of three ways to store books. A dynamic array is like a shelf where you decide the width when you install it, then keep everything in a neat row. An associative array is like a library card catalog: you look up a book by its title, not by shelf position, and most possible titles do not exist. A queue is like a line of people at a counter: new people join at either end and leave from either end, and the line length changes all the time.

Quick comparison of the array types

TypeSize set whenIndex typeBest for
Fixed sizeCompile timeInteger, contiguousCounts known up front
Dynamic arrayRun time via new[]Integer, contiguousSize known only at run time
Associative arrayGrows as keys are addedAny type: int, string, classSparse or huge index space
QueueGrows and shrinks freelyInteger, contiguousPush and pop from the ends

Dynamic arrays

A dynamic array has a size you set at run time with the new[] operator. It stores its elements in a contiguous row and is indexed by an integer. You can resize it and even copy the old contents into the larger one in the same call.

module dyn_demo;
  int data[];        // unsized at first
  initial begin
    data = new[4];               // allocate 4 elements
    foreach (data[i]) data[i] = i * 10;
    $display("size = %0d", data.size());   // 4

    data = new[6](data);         // resize to 6, keep old values
    $display("after resize size = %0d, data[1] = %0d", data.size(), data[1]);

    data.delete();               // empty it
    $display("after delete size = %0d", data.size());  // 0
  end
endmodule

The key methods are size() to read the current length and delete() to empty the array and set its size to zero. Passing the old array name inside new[6](data) copies the existing values into the resized array.

Associative arrays

An associative array is the right choice when the index space is very large but only a few entries are used. Memory is only used for entries you actually write. The index can be an integer, a string, or another scalar type, so it works well as a lookup table.

module assoc_demo;
  bit [7:0] age [string];   // indexed by a string key
  initial begin
    age["tom"] = 21;
    age["joe"] = 32;

    $display("entries = %0d", age.num());        // 2
    if (age.exists("tom"))
      $display("tom is %0d", age["tom"]);         // 21

    // Walk entries in key order
    string k;
    if (age.first(k))
      do $display("%s -> %0d", k, age[k]);
      while (age.next(k));

    age.delete("joe");
    $display("after delete entries = %0d", age.num());  // 1
  end
endmodule

Associative array methods

MethodWhat it returns or does
num() or size()Number of entries currently stored
exists(key)1 if an entry exists at that key, else 0
delete(key)Removes one entry, or all if no key is given
first(ref k) / last(ref k)Gets the smallest or largest key
next(ref k) / prev(ref k)Steps to the next or previous key in order

Queues

A queue is an ordered list of the same element type that can grow and shrink while the simulation runs. Unlike a dynamic array, it does not need new[]. You add and remove items with push and pop, and you can insert or delete at any position.

module queue_demo;
  string q[$] = {"first", "second", "third"};
  string item;
  initial begin
    q.push_back("fourth");     // add at the end
    q.push_front("zero");      // add at the front
    $display("size = %0d", q.size());   // 5

    item = q.pop_front();      // remove from the front
    $display("popped front = %s", item);      // zero
    item = q.pop_back();       // remove from the end
    $display("popped back  = %s", item);      // fourth

    q.insert(1, "inserted");   // insert at index 1
    q.delete(0);               // delete index 0

    foreach (q[i]) $display("q[%0d] = %s", i, q[i]);
  end
endmodule

Note the difference from the original example many people copy: always index the same queue variable you declared. A common typo is popping from q but printing from a differently named variable, which will not compile.

Queue methods at a glance

MethodWhat it does
push_back(x) / push_front(x)Add x at the end or the front
pop_back() / pop_front()Remove and return the end or front element
insert(i, x)Insert x at index i
delete(i)Delete the element at index i
size()Current number of elements

Expected output, in plain words

The dynamic array example allocates four elements, then resizes to six while keeping the first four, so the size prints 4 then 6, and delete brings it back to 0. The associative array example stores two named ages, confirms tom exists, walks the keys in order, then drops one entry. The queue example ends with five items, pops the two ends you added, then inserts and deletes to leave a short ordered list.

Note: these outputs describe what the code is written to produce based on a read of the IEEE 1800 LRM. Compile and run on your own simulator or EDA Playground for a true sign off.

When to use which array

  • Fixed size array: the count is known at compile time and never changes.
  • Dynamic array: the count is known only at run time, for example after reading a config or a file, and the data sits in a contiguous block.
  • Associative array: the index range is huge or sparse, such as a memory model keyed by a wide address, or a lookup keyed by a string.
  • Queue: you push and pop from the ends, such as a scoreboard holding expected transactions waiting to be matched.

Common mistakes to avoid

  • Forgetting new[] on a dynamic array: using it before allocation leaves it size zero and indexing fails.
  • Using an associative array where a queue fits: if you only add and remove at the ends, a queue is simpler and faster.
  • Reading a missing associative key: check with exists() first, or you may read a default zero and think the entry was real.
  • Mismatched variable names in queue loops: pop from and print the same queue variable, or the code will not compile.
  • Assuming order in an associative array: walk it with first and next if you need a defined order.

Dynamic array vs queue

Both grow at run time, so which do you pick? Use a dynamic array when you set the size once and then index it like a block of memory. Use a queue when the length changes often through push and pop, such as a buffer of pending items. The queue also gives you insert and delete at any index without a manual copy.

For more on the operator that packs these collections into a stream, see our guide on the streaming operator. To pass a queue of items between two threads, read about the SystemVerilog mailbox. More tutorials are in our SystemVerilog section and interview questions.

Frequently asked questions

Arrays and queues store values of a base type, so it helps to be solid on the logic data type that most of these arrays hold.

What are the array types in SystemVerilog?

Beyond the fixed size array there are three flexible types: the dynamic array sized at run time with new[], the associative array indexed by any key for sparse data, and the queue which grows and shrinks with push and pop.

What is the difference between a dynamic array and a queue?

A dynamic array is sized with new[] and used like a contiguous block of memory. A queue does not need new[]; it grows and shrinks through push and pop, and supports insert and delete at any index.

When should I use an associative array?

Use it when the index space is very large or sparse, such as a memory model keyed by a wide address, or a lookup keyed by a string. Memory is used only for entries you actually write.

How do I resize a dynamic array and keep the data?

Call new with the old array inside the parentheses, for example data = new[6](data). This resizes to six elements and copies the existing values into the new array.

How do I safely read an associative array?

Check the key first with exists(key). If you read a missing key you get a default value such as zero, which can look like a real entry. Use first and next to walk keys in order.

What are the main queue methods?

push_back and push_front add items, pop_back and pop_front remove and return items, insert adds at an index, delete removes at an index, and size returns the current count.

Similar Posts