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. Strings help you handle text data for debugging and file operations. Let's learn how to use both effectively.

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: