When size of a collection is unknown or the data space is sparse, an associative array is a better option. Associative arrays do not have any storage allocated until it is used, and the index expression is not restricted to integral expressions, but can be of any type.
An associative array implements a look-up table of the elements of its declared type. The data type to be used as an index serves as the lookup key and imposes an ordering.
Syntax
// Value Array_Name [ key ];
data_type array_identifier [ index_type ];
Initialization Example
module tb;
int array1 [int]; // An integer array with integer index
int array2 [string]; // An integer array with string index
string array3 [string]; // A string array with string index
initial begin
// Initialize each dynamic array with some values
array1 = '{ 1 : 22,
6 : 34 };
array2 = '{ "Ross" : 100,
"Joey" : 60 };
array3 = '{ "Apples" : "Oranges",
"Pears" : "44" };
// Print each array
$display ("array1 = %p", array1);
$display ("array2 = %p", array2);
$display ("array3 = %p", array3);
end
endmodule
Simulation Log ncsim> run array1 = '{1:22, 6:34} array2 = '{"Joey":60, "Ross":100} array3 = '{"Apples":"Oranges", "Pears":"44"} ncsim: *W,RNQUIE: Simulation is complete.
A dynamic array is an unpacked array whose size can be set or changed at run time, and hence is quite different from a static array where the size is pre-determined during declaration of the array. The default size of a dynamic array is zero until it is set by the new()
constructor.
Syntax
A dynamic array dimensions are specified by the empty square brackets [ ]
.
[data_type] [identifier_name] [];
bit [7:0] stack []; // A dynamic array of 8-bit vector
string names []; // A dynamic array that can contain strings
The new()
function is used to allocate a size for the array and initialize its elements if required.
Dynamic Array Example
module tb;
// Create a dynamic array that can hold elements of type int
int array [];
initial begin
// Create a size for the dynamic array -> size here is 5
// so that it can hold 5 values
array = new [5];
// Initialize the array with five values
array = '{31, 67, 10, 4, 99};
// Loop through the array and print their values
foreach (array[i])
$display ("array[%0d] = %0d", i, array[i]);
end
endmodule
Simulation Log ncsim> run array[0] = 31 array[1] = 67 array[2] = 10 array[3] = 4 array[4] = 99 ncsim: *W,RNQUIE: Simulation is complete.
A SystemVerilog queue is a First In First Out scheme which can have a variable size to store elements of the same data type.
It is similar to a one-dimensional unpacked array that grows and shrinks automatically. They can also be manipulated by indexing, concatenation and slicing operators. Queues can be passed to tasks/functions as ref or non-ref arguments.
Syntax and Usage
A queue is distinguished by it's specification of the size using $ operator.
[data_type] [name_of_queue] [$];
string name_list [$]; // A queue of string elements
bit [3:0] data [$]; // A queue of 4-bit elements
logic [7:0] elements [$:127]; // A bounded queue of 8-bits with maximum size of 128 slots
int q1 [$] = { 1, 2, 3, 4, 5 }; // Integer queue, initialize elements
int q2 [$]; // Integer queue, empty
int tmp; // Temporary variable to store values
tmp = q1 [0]; // Get first item of q1 (index 0) and store in tmp
tmp = q1 [$]; // Get last item of q1 (index 4) and store in tmp
q2 = q1; // Copy all elements in q1 into q2
q1 = {}; // Empty the queue (delete all items)
q2[2] = 15; // Replace element at index 2 with 15
q2.insert (2, 15); // Inserts value 15 to index# 2
q2 = { q2, 22 }; // Append 22 to q2
q2 = { 99, q2 }; // Put 99 as the first element of q2
q2 = q2 [1:$]; // Delete first item
q2 = q2 [0:$-1]; // Delete last item
q2 = q2 [1:$-1]; // Delete first and last item
SystemVerilog Queue Example
module tb;
// Create a queue that can store "string" values
string fruits[$] = { "orange", "apple", "kiwi" };
initial begin
// Iterate and access each queue element
foreach (fruits[i])
$display ("fruits[%0d] = %s", i, fruits[i]);
// Display elements in a queue
$display ("fruits = %p", fruits);
// Delete all elements in the queue
fruits = {};
$display ("After deletion, fruits = %p", fruits);
end
endmodule
Simulation Log ncsim> run fruits[0] = orange fruits[1] = apple fruits[2] = kiwi fruits = '{"orange", "apple", "kiwi"} After deletion, fruits = '{} ncsim: *W,RNQUIE: Simulation is complete.
What are queue slice expressions ?
A slice expression selects a subset of the existing variable. Queue elements can be selected using slice expressions as shown in the example below.
Some simulators provide different results, hence using queue methods is recommended.
module tb;
// Create a queue that can store "string" values
string fruits[$] = { "orange", "apple", "lemon", "kiwi" };
initial begin
// Select a subset of the queue
$display ("citrus fruits = %p", fruits[1:2]);
// Get elements from index 1 to end of queue
$display ("fruits = %p", fruits[1:$]);
// Add element to the end of queue
fruits[$+1] = "pineapple";
$display ("fruits = %p", fruits);
// Delete first element
$display ("Remove orange, fruits = %p", fruits[1:$]);
end
endmodule
Simulation Log Compiler version J-2014.12-SP1-1; Runtime version J-2014.12-SP1-1; May 15 16:21 2018 citrus fruits = '{"apple", "lemon"} fruits = '{"apple", "lemon", "kiwi"} fruits = '{"orange", "apple", "lemon", "kiwi", "pineapple"} Remove orange, fruits = '{"apple", "lemon", "kiwi", "pineapple"} V C S S i m u l a t i o n R e p o r t

A SystemVerilog case
statement checks whether an expression matches one of a number of expressions and branches appropriately. The behavior is the same as in Verilog.
Click here to learn about Verilog case statements !
unique,unique0 case
All case statements can be qualified by unique
or unique0
keywords to perform violation checks like we saw in if-else-if construct.
unique
and unique0
ensure that there is no overlapping case items and hence can be evaluated in parallel. If there are overlapping case items, then a violation is reported.
- If more than one case item is found to match the given expression, then a violation is reported and the first matching expression is executed
- If no case item is found to match the given expression, then a violation is reported only for
unqiue
unique0 does not report a violation if no items match the expression
unique : No items match for given expression
module tb;
bit [1:0] abc;
initial begin
abc = 1;
// None of the case items match the value in "abc"
// A violation is reported here
unique case (abc)
0 : $display ("Found to be 0");
2 : $display ("Found to be 2");
endcase
end
endmodule
Simulation Log
ncsim> run
ncsim: *W,NOCOND: Unique case violation: Every case item expression was false.
File: ./testbench.sv, line = 9, pos = 14
Scope: tb
Time: 0 FS + 1
ncsim: *W,RNQUIE: Simulation is complete.
unique : More than one case item matches
module tb;
bit [1:0] abc;
initial begin
abc = 0;
// Multiple case items match the value in "abc"
// A violation is reported here
unique case (abc)
0 : $display ("Found to be 0");
0 : $display ("Again found to be 0");
2 : $display ("Found to be 2");
endcase
end
endmodule
Simulation Log
ncsim> run
Found to be 0
ncsim: *W,MCONDE: Unique case violation: Multiple matching case item expressions at {line=10:pos=6 and line=11:pos=6}.
File: ./testbench.sv, line = 9, pos = 14
Scope: tb
Time: 0 FS + 1
ncsim: *W,RNQUIE: Simulation is complete.
priority case
module tb;
bit [1:0] abc;
initial begin
abc = 0;
// First match is executed
priority case (abc)
0 : $display ("Found to be 0");
0 : $display ("Again found to be 0");
2 : $display ("Found to be 2");
endcase
end
endmodule
Simulation Log
ncsim> run
Found to be 0
ncsim: *W,RNQUIE: Simulation is complete.
Till the previous stage we had defined and created everything required within the register environment. However which agent is responsible for driving these register transactions hadn't been defined.
class my_env extends uvm_env;
`uvm_component_utils (my_env)
my_agent m_agent;
reg_env m_reg_env;
function new (string name = "my_env", uvm_component parent);
super.new (name, parent);
endfunction
virtual function void build_phase (uvm_phase phase);
super.build_phase (phase);
m_agent = my_agent::type_id::create ("m_agent", this);
m_reg_env = reg_env::type_id::create ("m_reg_env", this);
endfunction
virtual function void connect_phase (uvm_phase phase);
super.connect_phase (phase);
m_agent.m_mon.mon_ap.connect (m_reg_env.m_apb2reg_predictor.bus_in);
m_reg_env.m_ral_model.default_map.set_sequencer (m_agent.m_seqr, m_reg_env.m_reg2apb);
endfunction
endclass