Hello again, so in this blog we will verify 4x1 multiplexer using UVM , and also learn how to create .log file for dumping reporting messages like `uvm_info(). In the verification we will also use coverage to measure verification progress.
Link : https://www.edaplayground
Updated TB with Scoreboard (self checking TB) : https://www.edaplayground.com
So the architecture of testbench is shown below.
design.sv
module mux4x1(in,sel,out);
input [3:0]in;
input [1:0]sel;
output out;
assign out=in[sel];
endmodule
mux_sequence_item
class mux_sequence_item extends uvm_sequence_item; //------------ i/p || o/p field declaration-------------
rand logic [3:0]in ; //i/p
rand logic [1:0]sel ;
logic out; //o/p
//register mux_sequence_item class with factory ---------
`uvm_object_utils_begin(mux_sequence_item)
`uvm_field_int(in ,UVM_ALL_ON)
`uvm_field_int(sel ,UVM_ALL_ON)
`uvm_object_utils_end
//--------------------------------------------------------
//----------------- constructor --------------------
function new(string name="mux_sequence_item");
super.new(name);
endfunction
//---------------------------------------------------
endclass:mux_sequence_item
mux_sequence
class mux_sequence extends uvm_sequence#(mux_sequence_item);
//----------------------------------------------------
`uvm_object_utils(mux_sequence)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="mux_sequence");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
virtual task body();
endtask:body
//----------------------------------------------------
endclass:mux_sequence
class random_data extends mux_sequence;
//----------------------------------------------------
`uvm_object_utils(random_data)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
task body();
repeat(20)
begin
txn=mux_sequence_item::type_id::create("txn");
start_item(txn);
txn.randomize();
#4;
finish_item(txn);
end
endtask:body
//----------------------------------------------------
endclass:random_data
class mux_sel_00 extends mux_sequence;
//----------------------------------------------------
`uvm_object_utils(mux_sel_00)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
task body();
repeat(10)
begin
txn=mux_sequence_item::type_id::create("txn");
start_item(txn);
txn.randomize()with{txn.sel==0;};
#4;
finish_item(txn);
end
endtask:body
//----------------------------------------------------
endclass:mux_sel_00
class mux_sel_01 extends mux_sequence;
//----------------------------------------------------
`uvm_object_utils(mux_sel_01)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
task body();
repeat(10)
begin
txn=mux_sequence_item::type_id::create("txn");
start_item(txn);
txn.randomize()with{txn.sel==1;};
#4;
finish_item(txn);
end
endtask:body
//----------------------------------------------------
endclass:mux_sel_01
class mux_sel_10 extends mux_sequence;
//----------------------------------------------------
`uvm_object_utils(mux_sel_10)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
task body();
repeat(10)
begin
txn=mux_sequence_item::type_id::create("txn");
start_item(txn);
txn.randomize()with{txn.sel==2;};
#4;
finish_item(txn);
end
endtask:body
//----------------------------------------------------
endclass:mux_sel_10
class mux_sel_11 extends mux_sequence;
//----------------------------------------------------
`uvm_object_utils(mux_sel_11)
//----------------------------------------------------
mux_sequence_item txn;
//----------------------------------------------------
function new(string name="");
super.new(name);
endfunction
//----------------------------------------------------
//----------------------------------------------------
task body();
repeat(10)
begin
txn=mux_sequence_item::type_id::create("txn");
start_item(txn);
txn.randomize()with{txn.sel==3;};
#4;
finish_item(txn);
end
endtask:body
//----------------------------------------------------
endclass:mux_sel_11
mux_sequencer
class mux_sequencer extends uvm_sequencer#(mux_sequence_item);
//----------------------------------------------------
`uvm_component_utils(mux_sequencer)
//----------------------------------------------------
//----------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//----------------------------------------------------
endclass:mux_sequencer
mux_driver
class mux_driver extends uvm_driver #(mux_sequence_item);
//-----------------------------------------------------------------
`uvm_component_utils(mux_driver)
//-----------------------------------------------------------------
//-----------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------
//-------------------------- virtual interface handel ------------
virtual interface intf vif;
//-----------------------------------------------------------------
//------------------------- get interface handel from top --------
function void build_phase(uvm_phase phase);
if(!(uvm_config_db#(virtual intf)::get(this,"","vif",vif))) begin
`uvm_fatal("driver","unable to get interface",UVM_MEDIUM);
end
endfunction
//-----------------------------------------------------------------
//---------------------------- run task ---------------------------
task run_phase(uvm_phase phase);
mux_sequence_item txn;
forever begin
seq_item_port.get_next_item(txn);
vif.sel =txn.sel;
vif.in =txn.in;
`uvm_info(get_type_name(),$sformatf("sel=%2b in=%4b",txn.sel,txn.in)\
,UVM_MEDIUM)
seq_item_port.item_done();
end
endtask
//------------------------------------------------------------------
endclass:mux_driver
interface
interface intf();
// ------------------- port declaration--------------
logic [3:0]in ;
logic [1:0]sel;
logic out;
//---------------------------------------------------
//------------- clocking & modport declaration ------
/* clocking clocking_block_name @(posedge signal_name);
default input #1step output #1step;
output //input of DUT
input //output of DUT
endclocking
*/
//modport modport_name(clocking name_of_block);
//---------------------------------------------------
endinterface
mux_monitor
class mux_monitor extends uvm_monitor;
//-------------------------------------------------------------
`uvm_component_utils(mux_monitor)
//-------------------------------------------------------------
//------------------- constructor -----------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-------------------------------------------------------------
//---------------- sequence_item class ------------------------
mux_sequence_item txn;
//-------------------------------------------------------------
//------------------------ virtual interface handle------------
virtual interface intf vif;
//-------------------------------------------------------------
//------------------------ analysis port ----------------------
uvm_analysis_port#(mux_sequence_item) ap_mon;
//-------------------------------------------------------------
//------------------- build phase -----------------------------
function void build_phase(uvm_phase phase);
if(!(uvm_config_db#(virtual intf)::get(this,"","vif",vif)))
begin
`uvm_fatal("monitor","unable to get interface")
end
ap_mon=new("ap_mon",this);
txn=mux_sequence_item::type_id::create("txn",this);
endfunction
//--------------------------------------------------------------
//-------------------- run phase -------------------------------
task run_phase(uvm_phase phase);
forever
begin
// write monitor code here
@(vif.in or vif.sel or vif.out);
txn.in = vif.in;
txn.sel = vif.sel;
txn.out = vif.out;
ap_mon.write(txn);
#1;
`uvm_info(get_type_name(),$sformatf("sel=%2b in=%4b out=%0b"\
,txn.sel,txn.in,txn.out),UVM_MEDIUM)
end
endtask
//--------------------------------------------------------------
endclass:mux_monitor
mux_agent
class mux_agent extends uvm_agent;
//-----------------------------------------------------------------------
`uvm_component_utils(mux_agent)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------------
//----------------- class handles ---------------------------------------
mux_sequencer sequencer_h;
mux_driver driver_h;
mux_monitor monitor_h;
//-----------------------------------------------------------------------
//---------------------- build phase ------------------------------------
function void build_phase(uvm_phase phase);
driver_h = mux_driver::type_id::create("driver_h",this);
sequencer_h = mux_sequencer::type_id::create("sequencer_h",this);
monitor_h = mux_monitor::type_id::create("monitor_h",this);
endfunction
//------------------------------------------------------------------------
//----------------------- connect phase ----------------------------------
function void connect_phase(uvm_phase phase);
driver_h.seq_item_port.connect(sequencer_h.seq_item_export);
endfunction
//------------------------------------------------------------------------
endclass:mux_agent
mux_coverage
class mux_coverage extends uvm_subscriber #(mux_sequence_item);
//-----------------------------------------------------------------------
`uvm_component_utils(mux_coverage)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
cg=new();
endfunction
//-----------------------------------------------------------------------
function void build_phase(uvm_phase phase);
endfunction
//-----------------------------------------------------------------------
mux_sequence_item txn;
real cov;
//------------------------------------------------------------------------
//------------------------------------------------------------------------
covergroup cg;
IN:coverpoint txn.in {
bins in1_1={[0:3]};
bins in2_1={[4:7]};
bins in3_1={[8:11]};
bins in4_1={[12:15]};
}
SEL:coverpoint txn.sel{
bins sel1_2={0};
bins sel2_2={1};
bins sel3_2={2};
bins sel4_2={3};
}
endgroup:cg
//------------------------------------------------------------------------
//--------------------- write method -----------------------------------
function void write(mux_sequence_item t);
txn=t;
//inside suscriber
cg.sample();
endfunction
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function void extract_phase(uvm_phase phase);
cov=cg.get_coverage();
endfunction
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function void report_phase(uvm_phase phase);
`uvm_info(get_type_name(),$sformatf("Coverage is %f",cov),\
UVM_MEDIUM)
endfunction
//-----------------------------------------------------------------------
endclass:mux_coverage
mux_env
class mux_env extends uvm_env; //----------------------------------------------------------------------
`uvm_component_utils(mux_env)
//----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------------
//-------------------- class handles ------------------------------------
mux_agent agent_h;
mux_coverage coverage_h;
//-----------------------------------------------------------------------
//---------------------- build phase ------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent_h = mux_agent::type_id::create("agent_h",this);
coverage_h = mux_coverage::type_id::create("coverage_h",this);
endfunction
//-----------------------------------------------------------------------
//-------------------------- connect phase ------------------------------
function void connect_phase(uvm_phase phase);
agent_h.monitor_h.ap_mon.connect(coverage_h.analysis_export);
endfunction
//------------------------------------------------------------------------
endclass:mux_env
mux_test
class mux_any_test extends uvm_test;
//-----------------------------------------------------------------------
`uvm_component_utils(mux_any_test)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------------
int file_h; //use for file operation (file handel)
mux_env env_h;
random_data seq;
mux_sel_00 seq00;
mux_sel_01 seq01;
mux_sel_10 seq10;
mux_sel_11 seq11;
//-----------------------------------------------------------------------
function void build_phase(uvm_phase phase);
env_h = mux_env::type_id::create("env_h",this);
seq= random_data::type_id::create("seq");
seq00= mux_sel_00::type_id::create("seq00");
seq01= mux_sel_01::type_id::create("seq01");
seq10= mux_sel_10::type_id::create("seq10");
seq11= mux_sel_11::type_id::create("seq11");
endfunction
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function void start_of_simulation_phase(uvm_phase phase);
file_h=$fopen("mux_report.log","w");
env_h.set_report_default_file_hier(file_h);
env_h.set_report_severity_action_hier(UVM_INFO,UVM_DISPLAY\
+UVM_LOG);
env_h.set_report_verbosity_level_hier(UVM_MEDIUM);
endfunction
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function void end_of_elobartion_phase(uvm_phase phase);
//factory.print();
$display("End of eleboration phase in agent");
endfunction
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
task run_phase(uvm_phase phase);
phase.raise_objection(this);
seq00.start(env_h.agent_h.sequencer_h);
seq01.start(env_h.agent_h.sequencer_h);
seq10.start(env_h.agent_h.sequencer_h);
seq11.start(env_h.agent_h.sequencer_h);
seq.start(env_h.agent_h.sequencer_h);
#5;
phase.drop_objection(this);
endtask
//-----------------------------------------------------------------------
endclass:mux_any_test
tb_pkg.sv
`ifndef TB_PKG
`define TB_PKG
`include "uvm_macros.svh"
package tb_pkg;
import uvm_pkg::*;
`include "mux_sequence_item.sv" // transaction class
`include "mux_sequence.sv" // sequence class
`include "mux_sequencer.sv" // sequencer class
`include "mux_driver.sv" // driver class
`include "mux_monitor.sv"
`include "mux_agent.sv" // agent class
`include "mux_coverage.sv" // coverage class
`include "mux_env.sv" // environment class
`include "mux_test.sv" // test1
endpackage
`endif
testbench_top.sv
`include "interface.sv"
`include "tb_pkg.sv"
module top;
import uvm_pkg::*;
import tb_pkg::*;
intf i_intf();
mux4x1 DUT(.sel(i_intf.sel),
.in(i_intf.in),
.out(i_intf.out)
);
initial begin
$dumpfile("dump1.vcd");
$dumpvars(0,top);
end
initial begin
uvm_config_db#(virtual intf)::set(uvm_root::get(),"","vif",\
i_intf);
end
initial begin
run_test("mux_any_test");
end
endmodule
output messages
log file
As you run this code you will see that functional coveragge is 100% , so we verified our simple design in UVM. In next blog we will verify 64KB RAM.
Thank you for reading have a nice day 😊😊👍.
Shortcut for emojie in PC is " Windows + .(dot)"
You Might Also Like