Queues & Strings in SystemVerilog

Queues are one of the most useful data structures in verification. They're like dynamic arrays but with convenient methods for adding and removing elements.

Queue Methods at a Glance

Method Action Example
push_back(val) Adds to end q.push_back(10);
pop_front() Removes from front v = q.pop_front();
size() Returns count n = q.size();
delete(idx) Removes element q.delete(2);
insert(idx, val) Inserts at index q.insert(1, 5);

What is a Queue?

A queue is a variable-size, ordered collection of elements. Unlike arrays, you can easily add or remove elements from either end without having to resize manually.

Think of a queue like a line at a bank. People can join at the back (push_back), leave from the front (pop_front), or even cut in line at any position (insert). You can also count how many people are waiting (size) or check if the line is empty.
Queue Declaration
// Unbounded queue (can grow indefinitely)
int q [$];
// Bounded queue (max 10 elements)
int bounded_q [$:9];
// Initialize with values
int q2 [$] = '{1, 2, 3, 4, 5};

Key Difference from Dynamic Arrays

Dynamic arrays require new[] to resize. Queues resize automatically when you add or remove elements.

Queue Operations

Adding Elements

Adding to Queue
int q [$];
// Add at the end
q.push_back(10);        // q = {10}
q.push_back(20);        // q = {10, 20}
q.push_back(30);        // q = {10, 20, 30}
// Add at the front
q.push_front(5);        // q = {5, 10, 20, 30}
// Insert at specific position
q.insert(2, 15);        // q = {5, 10, 15, 20, 30}
                        // Inserted 15 at index 2

Removing Elements

Removing from Queue
int q [$] = '{1, 2, 3, 4, 5};
int val;
// Remove from front
val = q.pop_front();    // val=1, q={2,3,4,5}
// Remove from back
val = q.pop_back();     // val=5, q={2,3,4}
// Delete at specific index
q.delete(1);            // q={2,4} (removed index 1)
// Delete all elements
q.delete();             // q={}

Accessing Elements

Accessing Queue Elements
int q [$] = '{10, 20, 30, 40, 50};
// Access by index
int first = q[0];       // 10
int last = q[$];        // 50 ($ = last index)
int second_last = q[$-1]; // 40
// Get size
int size = q.size();    // 5
// Check if empty
if (q.size() == 0) $display("Empty!");
// or
if (q == '()) $display("Empty!");

Queue Use Case: Transaction Buffer

Queues are perfect for storing transactions in verification. The driver pushes transactions, and the monitor pops them for comparison.

Transaction Queue Example
class Transaction;
    rand bit [31:0] addr;
    rand bit [31:0] data;
endclass
class Scoreboard;
    Transaction expected_q [$];  // Queue of expected transactions
    // Add expected transaction
    function void add_expected(Transaction t);
        expected_q.push_back(t);
        $display("Added transaction. Queue size: %0d", expected_q.size());
    endfunction
    // Compare with actual and remove
    function void compare(Transaction actual);
        Transaction expected;
        if (expected_q.size() == 0) begin
            $error("No expected transaction!");
            return;
        end
        expected = expected_q.pop_front();
        if (expected.data !== actual.data)
            $error("Mismatch! Expected: %h, Got: %h", 
                   expected.data, actual.data);
        else
            $display("Match!");
    endfunction
endclass

Strings in SystemVerilog

Strings are used for text handling - debug messages, filenames, formatted output, etc. SystemVerilog provides a string type with many useful methods.

String Basics
// Declaration
string name = "VLSI Verification";
string empty_str;         // Empty string
// Length
int len = name.len();     // 17
// Concatenation
string full = {"Hello, ", name, "!"};
// full = "Hello, VLSI Verification!"
// Comparison
if (name == "VLSI Verification")
    $display("Match!");
// Case conversion
string upper = name.toupper();  // "VLSI VERIFICATION"
string lower = name.tolower();  // "vlsi verification"

Common String Methods

String Methods
string s = "Hello World";
// Substring
string sub = s.substr(0, 4);      // "Hello"
// Find character/substring
int pos = s.first("o");            // 4 (first 'o')
int last_pos = s.last("o");        // 7 (last 'o')
// Get character at position
byte c = s.getc(0);                // 72 (ASCII for 'H')
// Format string
string fmt;
fmt = $sformatf("Addr: 0x%08h, Data: 0x%08h", 
                32'h1000, 32'hDEADBEEF);
// fmt = "Addr: 0x00001000, Data: 0xDEADBEEF"

The Power of $sformatf

$sformatf is incredibly useful for creating formatted strings for debug messages. It works just like $display but returns a string instead of printing.

Quick Summary

Queues

  • Declared with [$]
  • Variable size - grows and shrinks automatically
  • push_back(), push_front() to add
  • pop_back(), pop_front() to remove
  • size() to get count

Strings

  • Use string type for text data
  • len() for length
  • toupper(), tolower() for case conversion
  • $sformatf() for formatted strings

What's Next?

Now that you understand data structures, move on to: