One of the key components in UVM is the sequence item (uvm_sequence_item), which represents transactions in a testbench. UVM provides several built-in methods for sequence items to facilitate debugging, comparison, and data manipulation.
In this article, we will explore the most commonly used UVM sequence item methods with examples:
- create()
- print()
- copy() and clone()
- compare()
- pack() and unpack()
1. create() Method
The create() method is used to instantiate an object dynamically using the UVM factory. It ensures that objects are created correctly and allows for factory overrides.
Example:
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction) // Register with the factory
rand bit [7:0] addr;
rand bit [31:0] data;
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
// Using the create() method
my_transaction tr;
tr = my_transaction::type_id::create("tr");
Why use create()?
- Supports factory overrides
- Allows for flexible object instantiation
- Essential for reusable and configurable testbenches
2. print() Method
The print() method displays the contents of a sequence item, making it useful for debugging.
Example:
class my_transaction extends uvm_object;
rand bit [7:0] addr; // Randomizable field
rand bit [31:0] data; // Randomizable field
//utility and field macros
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(addr,UVM_ALL_ON)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_object_utils_end
// Constructor
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
module testbench;
initial begin
my_transaction txn;
txn = my_transaction::type_id::create("txn"); // Factory-based creation
txn.randomize(); // Randomize the transaction fields
txn.print(); // Print the object details
end
endmodule
Output:
----------------------------------------
Name Type Size Value
----------------------------------------
txn my_transaction - @336
addr integral 8 'hb9
data integral 32 'ha1098c6c
----------------------------------------
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
3. copy() and clone() Methods
copy()
The copy() method copies the values from one sequence item to another.
clone()
The clone() method creates a deep copy of the sequence item.
clone() = create() + copy()
Example:
class my_transaction extends uvm_object;
rand bit [7:0] addr; // Randomizable field
rand bit [31:0] data; // Randomizable field
//utility and field macros
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(addr,UVM_ALL_ON)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_object_utils_end
// Constructor
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
module testbench;
initial begin
my_transaction txn_0;
my_transaction txn_1;
my_transaction txn_2;
txn_0 = my_transaction::type_id::create("txn_0"); // Factory-based creation
txn_1 = my_transaction::type_id::create("txn_1"); // Factory-based creation
txn_0.randomize(); // Randomize the transaction fields
txn_0.print(); // Print the object details
txn_1.copy(txn_0); //copy txn_0 to txn_1
txn_1.print(); //printing the txn_1
`uvm_info("","clone process",UVM_LOW)
$cast(txn_2,txn_0.clone()); //creating txn_2 object and copy txn_0 to txn_1
txn_2.print(); //printing the txn_2
end
endmodule
Output:
----------------------------------------
Name Type Size Value
----------------------------------------
txn_0 my_transaction - @336
addr integral 8 'hb9
data integral 32 'ha1098c6c
----------------------------------------
----------------------------------------
Name Type Size Value
----------------------------------------
txn_1 my_transaction - @337
addr integral 8 'hb9
data integral 32 'ha1098c6c
----------------------------------------
UVM_INFO testbench.sv(36) @ 0: reporter [] clone process
----------------------------------------
Name Type Size Value
----------------------------------------
txn_0 my_transaction - @340
addr integral 8 'hb9
data integral 32 'ha1098c6c
----------------------------------------
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
Name of txn_2 item will be printed as txn_0 because in cloning process, while creating the object, there is no option of passing argument.
4. compare() Method
The compare() method compares two sequence items and returns a boolean indicating whether they match.
Example:
class my_transaction extends uvm_object;
rand bit [7:0] addr; // Randomizable field
rand bit [31:0] data; // Randomizable field
//utility and field macros
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(addr,UVM_ALL_ON)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_object_utils_end
// Constructor
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
module testbench;
initial begin
my_transaction txn_0;
my_transaction txn_1;
txn_0 = my_transaction::type_id::create("txn_0"); // Factory-based creation
txn_1 = my_transaction::type_id::create("txn_1"); // Factory-based creation
txn_0.addr = 8'hAA;
txn_0.data = 32'h55555555;
txn_1.addr = 8'hAA;
txn_1.data = 32'h55555555;
if (txn_0.compare(txn_1))
`uvm_info("COMPARE", "Transactions match!", UVM_MEDIUM)
else
`uvm_info("COMPARE", "Transactions do not match!", UVM_MEDIUM)
end
endmodule
Output:
UVM_INFO testbench.sv(37) @ 0: reporter [COMPARE] Transactions match!
5. pack() and unpack() Methods
pack()
The pack() method converts a sequence item into a bit-stream (array of bits).
unpack()
The unpack() method extracts values from a bit-stream into a sequence item.
Example:
class my_transaction extends uvm_object;
rand bit [7:0] addr; // Randomizable field
rand bit [31:0] data; // Randomizable field
//utility and field macros
`uvm_object_utils_begin(my_transaction)
`uvm_field_int(addr,UVM_ALL_ON)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_object_utils_end
// Constructor
function new(string name = "my_transaction");
super.new(name);
endfunction
endclass
module testbench;
initial begin
my_transaction txn_0;
my_transaction txn_1;
bit bitstream[];
txn_0 = my_transaction::type_id::create("txn_0"); // Factory-based creation
txn_1 = my_transaction::type_id::create("txn_1"); // Factory-based creation
txn_0.addr = 8'hAA;
txn_0.data = 32'h55555555;
// Pack transaction into a bitstream
txn_0.pack(bitstream);
foreach(bitstream[i])
`uvm_info("PACK",$sformatf("bit_packed_data[%0d] = %b",i,bitstream[i]), UVM_LOW)
// Unpack bitstream into another transaction
txn_1.unpack(bitstream);
// Check if both transactions are identical
if (txn_0.compare(txn_1))
`uvm_info("PACK_UNPACK", "Packing and unpacking successful", UVM_MEDIUM)
else
`uvm_info("PACK_UNPACK", "Mismatch after unpacking", UVM_MEDIUM)
end
endmodule
Output:
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[0] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[1] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[2] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[3] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[4] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[5] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[6] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[7] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[8] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[9] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[10] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[11] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[12] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[13] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[14] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[15] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[16] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[17] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[18] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[19] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[20] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[21] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[22] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[23] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[24] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[25] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[26] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[27] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[28] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[29] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[30] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[31] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[32] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[33] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[34] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[35] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[36] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[37] = 1
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[38] = 0
UVM_INFO testbench.sv(37) @ 0: reporter [PACK] bit_packed_data[39] = 1
UVM_INFO testbench.sv(44) @ 0: reporter [PACK_UNPACK] Packing and unpacking successful
V C S S i m u l a t i o n R e p o r t
Conclusion
UVM sequence item methods make it easier to create, manipulate, and compare transactions in a testbench. Here’s a quick summary of their use:
| Method | Purpose |
|---|---|
create() | Instantiates objects using the UVM factory |
print() | Displays sequence item data |
copy() | Copies values from one object to another |
clone() | Creates a deep copy of an object |
compare() | Compares two transactions |
pack() | Converts a transaction into a bit-stream |
unpack() | Restores a transaction from a bit-stream |
By leveraging these methods effectively, you can build a robust and efficient verification environment.