This post will provide an explanation on the SystemVerilog code itself. Please see Recipe for the class diagram.
Transactions
Jelly-Bean Transaction
The jelly_bean_transaction
class defines the jelly-bean recipe based on flavor, color, and other characteristics. It also has the property called taste
to hold the reaction of the jelly_bean_taster
(DUT) to the flavor. The relationship between the flavor and color is defined in the constraint block (line 12). For example, if the flavor is apple, the color must be red or green (not blue).
Update (April 2, 2014): In this example, we used so-called UVM field macros (lines 23 to 27) to save the effort of writing “do-hook” functions. I would recommend writing your own “do-hook” functions instead of using these macros once you become familiar with UVM. For more information, please see Field Macros and “Do” Hooks.
class jelly_bean_transaction extends uvm_sequence_item;
typedef enum bit[2:0] { NO_FLAVOR, APPLE, BLUEBERRY, BUBBLE_GUM, CHOCOLATE } flavor_e;
typedef enum bit[1:0] { RED, GREEN, BLUE } color_e;
typedef enum bit[1:0] { UNKNOWN, YUMMY, YUCKY } taste_e;
rand flavor_e flavor;
rand color_e color;
rand bit sugar_free;
rand bit sour;
taste_e taste;
constraint flavor_color_con {
flavor != NO_FLAVOR;
flavor == APPLE -> color != BLUE;
flavor == BLUEBERRY -> color == BLUE;
}
function new(string name = "");
super.new(name);
endfunction: new
`uvm_object_utils_begin(jelly_bean_transaction)
`uvm_field_enum(flavor_e, flavor, UVM_ALL_ON)
`uvm_field_enum(color_e, color, UVM_ALL_ON)
`uvm_field_int(sugar_free, UVM_ALL_ON)
`uvm_field_int(sour, UVM_ALL_ON)
`uvm_field_enum(taste_e, taste, UVM_ALL_ON)
`uvm_object_utils_end
endclass: jelly_bean_transaction
Sugar-Free Jelly Bean
The jelly_bean_transaction
class can be extended to various classes. For example, to create only sugar-free jelly beans, the child class can define the constraint as shown in line 4.
class sugar_free_jelly_bean_transaction extends jelly_bean_transaction;
`uvm_object_utils(sugar_free_jelly_bean_transaction)
constraint sugar_free_con {
sugar_free == 1;
}
function new(string name = "");
super.new(name);
endfunction: new
endclass: sugar_free_jelly_bean_transaction
Sequences
One Jelly Bean
The sequence creates the recipes of the jelly beans being generated. The first sequence is the simplest, as it is designed to create a single jelly bean. The line 10 creates a single jelly-bean transaction (a recipe), then the line 12 randomizes the recipe.
class one_jelly_bean_sequence extends uvm_sequence#(jelly_bean_transaction);
`uvm_object_utils(one_jelly_bean_sequence)
function new(string name = "");
super.new(name);
endfunction: new
task body();
jelly_bean_transaction jb_tx;
jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
start_item(jb_tx);
assert(jb_tx.randomize());
finish_item(jb_tx);
endtask: body
endclass: one_jelly_bean_sequence
Same-Flavored Jelly Beans (Sequence of Transactions)
Now let’s create the multiple jelly beans of the same flavor. The number of jelly beans being created is specified with the class property called num_jelly_beans
. The line 4 constrains the num_jelly_beans
to be between 2 and 4. The line 14 creates a single jelly bean, and the line 15 randomizes its color and flavor. With this jelly bean as the standard, the line 18 creates jelly beans of the same flavor, as many as specified by the num_jelly_beans
. In-line constraint on the line 21 guarantees the same flavor to be generated.
class same_flavored_jelly_beans_sequence extends uvm_sequence#(jelly_bean_transaction);
rand int unsigned num_jelly_beans; // knob
constraint num_jelly_beans_con { num_jelly_beans inside { [2:4] }; }
function new(string name = "");
super.new(name);
endfunction: new
task body();
jelly_bean_transaction jb_tx;
jelly_bean_transaction::flavor_e jb_flavor;
jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
assert(jb_tx.randomize());
jb_flavor = jb_tx.flavor;
repeat (num_jelly_beans) begin
jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
start_item(jb_tx);
assert(jb_tx.randomize() with { jb_tx.flavor == jb_flavor; });
finish_item(jb_tx);
end
endtask: body
`uvm_object_utils_begin(same_flavored_jelly_beans_sequence)
`uvm_field_int(num_jelly_beans, UVM_ALL_ON)
`uvm_object_utils_end
endclass: same_flavored_jelly_beans_sequence
Gift-Boxed Jelly Beans (Sequence of Sequences)
The code below demonstrates how to create multiple-flavored jelly beans. The number of flavors is specified with the class property called num_jelly_bean_flavors
(line 2). On the 4th line, the sequence randomly picks two to three flavors. The main part of the sequence is the repeat
block (from the line 12), where a sequence of same_flavored_jelly_beans_sequence
s is created.
class gift_boxed_jelly_beans_sequence extends uvm_sequence#(jelly_bean_transaction);
rand int unsigned num_jelly_bean_flavors; // knob
constraint num_jelly_bean_flavors_con { num_jelly_bean_flavors inside { [2:3] }; }
function new(string name = "");
super.new(name);
endfunction: new
task body();
same_flavored_jelly_beans_sequence jb_seq;
repeat (num_jelly_bean_flavors) begin
jb_seq = same_flavored_jelly_beans_sequence::type_id::create(.name("jb_seq"), .contxt(get_full_name()));
assert(jb_seq.randomize());
jb_seq.start(.sequencer(m_sequencer), .parent_sequence(this));
end
endtask: body
`uvm_object_utils_begin(gift_boxed_jelly_beans_sequence)
`uvm_field_int(num_jelly_bean_flavors, UVM_ALL_ON)
`uvm_object_utils_end
endclass: gift_boxed_jelly_beans_sequence
This post has an emphasis on the transactions and sequences in the jelly-bean verification environment. The next post will provide an explanation on the verification components.