Overview

In SystemVerilog, an array is a fundamental data structure used to store multiple elements of the same data type/ or different data types under a single variable name. It provides a convenient and efficient way to organize and manipulate data, making it essential for digital hardware design and verification. Unlike Verilog, in SystemVerilog, there are differnt types of arrays which make it possible to store homogenous or non homogenous elements in the array. All the types of arrays avialable in SystemVerilog are mentioned below.

Dynamic Array

Usage example:

bit [7:0] ARRAY []
reg ARRAY [][]
int ARRAY []

ARRAY = new[10] ( memory allocation, in this case 10 elements size is allocated )

Array Function/ System Task Usage Example Description
size ARRAY.size() returns the number of elements that the array is capable of storing
delete ARRAY.delete() unallocated the memoery which was provided to the array upon "new[]" call
Associative Array

Usage example:

bit [7:0] ARRAY [int]
reg ARRAY [string] ( string is used as index )
int ARRAY [*] ( any datatype can be used as an index )

Array Function/ System Task Usage Example Description
num ARRAY.num() returns the number of elements that the array is capable of storing
size ARRAY.size() returns the number of elements that the array is capable of storing
delete ARRAY.delete( INDEX ) delete the element at the INDEX position in the array. if index is not mentioned, the entire array is deleted
exists ARRAY.exists( INDEX ) returns 1 if an element exists at the INDEX, else returns 0
first ARRAY.first( REF_INDEX ) the index of the first element in tha array is stored in REF_INDEX variable
last ARRAY.last( REF_INDEX ) the index of the last element in tha array is stored in REF_INDEX variable
next ARRAY.next( REF_INDEX ) the index of the next element in tha array after the ref_index is stored in ref_index variable
prev ARRAY.prev( REF_INDEX ) the index of the previous element in tha array before the ref_index is stored in ref_index variable
Queues

Usage example:

bit [7:0] ARRAY [$]
reg ARRAY [$:100] ( bounded queue with a limit of 100 elements )
int ARRAY [$]

Array Function/ System Task Usage Example Description
size ARRAY.size() returns the number of elements that the array is capable of storing
insert ARRAY.insert( INDEX, ELEMENT ) insert an element ELEMENT at the index position INDEX
delete ARRAY.delete( INDEX_OPTIONAL ) delete the array elements entirely or only the element mentioned with the INDEX_OPTIONAL value
pop_front ARRAY.pop_front() remove the 0th element from the array and return it
push_front ARRAY.push_front( ELEMENT ) insert an element ELEMENT in the 0th position of the array
pop_back ARRAY.pop_back() remove the last element from the array and return it
push_back ARRAY.push_back( ELEMENT ) insert an element ELEMENT after the ARRAY.size-1 index element of the array
Array Manipulator Methods
Array Function/ System Task Usage Example Description
reverse ARRAY.reverse() array elements are reversed in the index order
sort ARRAY.sort() array elements are sorted by default in ascending order
rsort ARRAY.rsort() array elements are sorted by default in descending order
shuffle ARRAY.shuffle() randomly shuffles the elements order in the array
sum ARRAY.sum() returns the sum of the all array elements
product ARRAY.product() returns the product of the all array elements
and ARRAY.and() returns the bitwise AND of the all array elements
or ARRAY.or() returns the bitwise OR of the all array elements
xor ARRAY.xor() returns the bitwise XOR of the all array elements
Array Locator Methods & Array Index Querying
Array Function/ System Task Usage Example Description
find ARRAY.find( ELEMENT_VAR ) with ( CONDITION ) returns an array with all the elements which satisfy the with condition
find_index ARRAY.find_index( INDEX_VAR ) with ( CONDITION ) returns an array with all the element indices which satisfy the with condition
find_first ARRAY.find_first( ELEMENT_VAR ) with ( CONDITION ) returns first element which satisfy the with condition
find_first_index ARRAY.find_first_index( INDEX_VAR ) with ( CONDITION ) returns first element index which satisfy the with condition
find_last ARRAY.find_last( ELEMENT_VAR ) with ( CONDITION ) returns last element which satisfy the with condition
find_last_index ARRAY.find_last_index( INDEX_VAR ) with ( CONDITION ) returns last element index which satisfy the with condition

Index Querying Method Usage Example Description
find ARRAY.find() with ( item == item.index ) returns an array of all the indices whose elements satisfy the with condition

Theory Questions
    shuffle function can be used to randomize the elements order
    Yes, but the return value is the default value of the datatype which the queue is defined with ( plus a warning is thrown by the simulator )
    1-bit value where, 0 means no key exists in the array and 1 means a key exists in the array
    Dynamic arrays can be used in cases where the size of the array required is known to an extent, but it can increase in certain cases ( a good example is the use of dynamic array while modelling an elastic buffer )
    In scenarios where a buffer is required with varying number of elements coming and going. Otherwise to simply model a queue of FIFO is also a good use case.
    Scenarios which involve modelling a memory ( address-data pair )
    .size() function can give the number of elements in an associative array
    Yes, by passing the position to the .delete( {position} ) call
    /*
        Yes
    */
    int ARR[*][];
    
    /*
        Yes
    */
    int ARR[8];
    
    /* Use case */
    
    wait( ARR[3] )
    @( ARR[1] )
    
    A queue whose upper limit is defined when its declared. ( eg: int ARR[$:1000] ( the array can have a maximum of 1000 elements ) )
    Yes, but for that to happen the struct needs to be declared as a typedef, ie user defined datatype
    module top;
        int ARR1[];
        int ARR2[];
    
        initial
        begin
            ARR1 = new[10];
            ARR2 = new[20](ARR1); // The 10 elements from ARR1 are copied into the lower indices of ARR2
        end
    endmodule
    
Coding Questions
    `timescale 1ns / 1ps
    
    module test;
    
        // Declare a two-dimensional unpacked dynamic array
        int array[][];
    
        initial begin
            // Allocate the first dimension with 3 rows
            array = new[3];
    
            // Allocate each row with different sizes
            array[0] = new[4]({10, 20, 30, 40});    // Row 0 with 4 columns
            array[1] = new[2]({50, 60});            // Row 1 with 2 columns
            array[2] = new[3]({70, 80, 90});        // Row 2 with 3 columns
    
            // Print the array
            $display("Two-Dimensional Dynamic Array:");
            for (int i = 0; i < array.size(); i++) begin
                $write("Row %0d: ", i);
                for (int j = 0; j < array[i].size(); j++) begin
                    $write("%0d ", array[i][j]);
                end
                $write("\n");
            end
    
            // Modify the array
            array[0][1] = 25; // Change element at Row 0, Column 1
            array[2][1] = 99; // Change element at Row 2, Column 1
    
            // Print the modified array
            $display("\nModified Array:");
            for (int i = 0; i < array.size(); i++) begin
                $write("Row %0d: ", i);
                for (int j = 0; j < array[i].size(); j++) begin
                    $write("%0d ", array[i][j]);
                end
                $write("\n");
            end
    
            // Finish the simulation
            $finish;
        end
    endmodule
    
    int ARR_2D [$][$];
    
    /*
    Multiple Methods
    */
    
    // First
    for(int i=0 ; i<10 ; i++)
    begin
        ARR_2D[i].push_back({$random}%10);
    end
    
    // Second
    for(int i=0 ; i<10 ; i++)
    begin
        for (int j=0 ; j<10 ; j++)
        begin
            ARR_2D[i][j]={$random};
        end
    end
    
    // To Print The Contents
    foreach( ARR_2D[i][j] )
        $display( "ARR_2D[%0d][%0d] : %0d", i,j,ARR_2D[i][j] );
    
    int ARR_3D [10][$][*];
    
    Locked Solution
    // Note : There are many ways to do this. One easy way is given below.
    
    module abc;
        int dyn[]; // Global Variable
        int return_values;
    
        function int dyn_to_q (bit [1:0]operation,int value=0);
            if ($size(dyn) == 0)
            begin
                dyn=new[1];
                dyn[$size(dyn)-1]=value;
            end
            else
            begin
                if (operation == 1 ) //push_back
                begin
                    dyn=new[$size(dyn)+1](dyn);
                    dyn[$size(dyn)-1]=value;
                end
                else if (operation == 2 ) // push_front
                begin
                    dyn.reverse();
                    dyn=new[$size(dyn)+1](dyn);
                    dyn[$size(dyn)-1]=value;
                    dyn.reverse();
                end
                else if(operation == 3 ) //pop_back
                begin
                    dyn_to_q=dyn[$size(dyn)-1];
                    dyn=new[$size(dyn)-1](dyn);
                    return dyn_to_q;
                end
                else
                begin // pop_front
                    dyn_to_q=dyn[0];
                    dyn.reverse();
                    dyn=new[$size(dyn)-1](dyn);
                    dyn.reverse();
                    return dyn_to_q;
                end
            end
        endfunction
    
        initial
        begin
            for(int i=0 ; i<10;i++)
            begin
                dyn_to_q(1,i); // pushing back
            end
            for(int i=0 ; i<10;i++)
            begin
                $display("dyn[%0d]=%0d",i,dyn[i]);
            end
            for(int i=0 ; i<10;i++)
            begin
                $display(dyn_to_q(0)); // popping front
            end
        end
    endmodule
    
    reg [15:0] ARR [*];
    
    module abc;
        reg [15:0] ARR [*];
        
        task  automatic display_as (ref reg [15:0] ARR [*]);
            int index;
            for(int i=0;i<$size(ARR);i++)
            begin
                if (i<1)
                begin
                    if(ARR.first(index))
                    begin
                        $display("ARR[%0d]=%0d",index,ARR[index] );
                    end
                    else
                    begin
                        $display("Array is empty");
                        return;
                    end
                end
                if(ARR.next(index))
                    $display("ARR[%0d]=%0d",index,ARR[index] );
                else
                begin
                    $display("Array all Index covered");
                    return;
                end
            end
        endtask
    
        initial
        begin
            int count;
            count=0;
            while (count !=10 )
            begin
                int index;
                index={$random}%30;
                if (ARR.exists(index) )
                    continue;
                else
                begin
                    ARR[index]={$random}%30;
                    count=count+1;
                end
            end
            display_as(ARR );
        end
    endmodule
    
    /*
        Populate the array with random number of your choice and random keys
    */
    int ARR[byte];
    
    module abc;
        int ARR[byte];
    
        function  automatic int return_index_of_value (ref int ARR [byte],int value);
            int index;
            if (!(ARR.first(index) ))
                return -1;
            
            repeat($size(ARR) )
            begin
                if (ARR[index] == value)
                begin
                    return_index_of_value=index;
                    break;
                    return return_index_of_value;
                end
                else
                begin
                    void'(ARR.next(index));
                end
            end
            if(return_index_of_value == 0 )
                return -1;
        endfunction
    
        initial
        begin
            int count,index,value;
            count=0;
            while (count !=10 )
            begin
                int index;
                index={$random}%30;
                if (ARR.exists(index) )
                    continue;
                else
                begin
                    ARR[index]={$random}%30;
                    $display("ARR[%0d]=%0d",index,ARR[index] );
                    count=count+1;
                end
            end
            value={$random}%30;
            index=return_index_of_value(ARR,value);
            if(index<0)
            begin
                $display("Value %0d is not present inside array",value);
            end
            else
            begin
                $display("Value %0d is present on %0d index of array",value,index);
            end
        end
    endmodule
    
    /*
                  -----
    addr      -> |     |
    wr_rd     -> |     |
    valid     -> |     |
    data_in   -> |     |
    data_out  <- |     |
                  -----
    a. txn is valid only when valid bit is high
    b. Ignore the data_out when write is happening and ignore the data_in when read is happening
    */
    
    Locked Solution
    module abc;
        typedef struct {int data ;bit [7:0] length;} data_pkts;
        data_pkts sender_reciever;
        semaphore sm;
        event sended_data;
    
        initial
        begin
            sm=new(1);
            fork
            begin
                forever
                begin
                    $display ("sender started waiting");
                    sm.get(1);
                    $display ("wait ended for sender");
                    sender_reciever.data ={$random}%10;
                    sender_reciever.length = {$random}%10;
                    $display(" Time =%0t data sended data =%0d  length =%0d",$time,sender_reciever.data,sender_reciever.length );
                    ->>sended_data;
                end
            end
            begin
                forever
                begin
                    @(sended_data);
                    #($random%20);
                    $display("TIME=%0t data recieved data =%0d  length =%0d",$time,sender_reciever.data,sender_reciever.length );
                    sm.put(1);
                end
            end
            join_none
            #100;
            disable fork;
        end
    endmodule
    
    module top;
        bit queue[$];
        int got;
    
        task automatic put_sem (ref bit queue[$],input int keys);
            repeat(keys)
            queue.push_back(1);
            return;
        endtask
    
        task automatic get_sem ( ref bit queue[$],input int keys);
            if(queue.size < keys)
            begin
                wait(queue.size >= keys );
            end
            else
            begin
                repeat(keys)
                void'(queue.pop_front);
            end
        endtask
    
        initial
        begin
            queue='{1,1,1,1,1};             // assuming 3 keys
            #5 get_sem(queue,3);
            #6 get_sem(queue,1);
            got=got+1;
            $display($time,got);
            #2 get_sem(queue,1);
            got=got+1;
            $display($time,got);
        end
    
        initial
        begin
            #8 get_sem(queue,2);
            #7 put_sem(queue,2);
        end
    endmodule
    
    module top#(parameter asic_desic=1);
        int queue [$];
        
        initial
        begin
            fill_unique_queue(queue,30,50);
            sort_queue(queue);              // parameter asic_desic = 0:ascending 1:decending
            display_queue(queue);
        end
    
        function automatic int  find_min_max (ref int queue [$]);
            bit check;
            int index,value;
            bit loop=1;
            while(loop)
            begin
                value=queue[index];
                check=1'b1;
                for(int i=0;i<queue.size();i++)
                begin
                    if(index != i)
                    begin
                        case(asic_desic)
                            0:begin
                                if( !(value < queue[i] ))
                                check=0;
                            end
                            1:begin
                                if( !(value > queue[i] ))
                                check=0;
                            end
                        endcase
                    end
                end
                if(!check )
                begin
                    index++;
                end
                else
                begin
                    loop=0;
                    return value;
                end
            end
        endfunction
    
        function automatic void sort_queue (ref int queue [$]);
            int local_queue[$];
            int first_min_max_value;
            while(queue.size != 0 )
            begin
                first_min_max_value = find_min_max(queue);
                local_queue.push_back(first_min_max_value);
                foreach(queue[i] )
                begin
                    if(queue[i] == first_min_max_value)
                        queue.delete(i);
                end
            end
            queue=local_queue;
        endfunction
    
        function automatic void fill_unique_queue (ref int queue [$],input int first,input int last);
            int size;
            int temp_value,index;
            size=$urandom_range(first,last);
            while(index != size)
            begin
                temp_value={$random} % 50;
                if(index == 0 )
                begin
                    queue.push_back(temp_value);
                    index=index+1;
                end
                else
                begin
                    for(int i=0; i<$size(queue);i++ )
                    begin
                        if(temp_value == queue[i] )
                        begin
                            break;
                        end
                        if(i == ($size(queue)-1) )
                        begin
                            queue.push_back(temp_value);
                            index=index+1;
                        end
                    end
                end
            end
        endfunction
    
        function automatic void display_queue (ref int queue [$]);
            foreach(queue[i] )
                $display("queue[%0d]=%0d",i,queue[i]);
        endfunction
    endmodule
    
    module top#(parameter asic_desic=0);
        int queue [$];
        
        initial
        begin
            fill_unique_queue(queue,30,50);
            sort_queue(queue);              // parameter asic_desic = 0:ascending 1:decending
            display_queue(queue);
        end
    
        function automatic int  find_min_max (ref int queue [$]);
            bit check;
            int index,value;
            bit loop=1;
    
            while(loop)
            begin
                value=queue[index];
                check=1'b1;
                for(int i=0;i<queue.size();i++)
                begin
                    if(index != i)
                    begin
                        case(asic_desic)
                            0:begin
                                if( !(value < queue[i] ))
                                check=0;
                            end
                            1:begin
                                if( !(value > queue[i] ))
                                check=0;
                            end
                        endcase
                    end
                end
                if(!check )
                begin
                    index++;
                end
                else
                begin
                    loop=0;
                    return value;
                end
            end
        endfunction
    
        function automatic void sort_queue (ref int queue [$]);
            int local_queue[$];
            int first_min_max_value;
    
            while(queue.size != 0 )
            begin
                first_min_max_value = find_min_max(queue);
                local_queue.push_back(first_min_max_value);
                foreach(queue[i] )
                begin
                    if(queue[i] == first_min_max_value)
                        queue.delete(i);
                end
            end
            queue=local_queue;
        endfunction
    
    
        function automatic void fill_unique_queue (ref int queue [$],input int first,input int last);
            int size;
            int temp_value,index;
    
            size=$urandom_range(first,last);
    
    
            while(index != size)
            begin
                temp_value={$random} % 50;
                if(index == 0 )
                begin
                    queue.push_back(temp_value);
                    index=index+1;
                end
                else
                begin
                    for(int i=0; i<$size(queue);i++ )
                    begin
                        if(temp_value == queue[i] )
                        begin
                            break;
                        end
                        if(i == ($size(queue)-1) )
                        begin
                            queue.push_back(temp_value);
                            index=index+1;
                        end
                    end
                end
            end
        endfunction
    
        function automatic void display_queue (ref int queue [$]);
            foreach(queue[i] )
                $display("queue[%0d]=%0d",i,queue[i]);
        endfunction
    
    endmodule