Hello , in this blog post we will verify up counter using UVM. Testbench architecture is shown below. link for code is given at the end of post.
Note : For readablity open this post on your PC.
UVM TB Architecture
DUT :
module up_counter(out,
clk,
rst_h,
);
input clk,rst_h;
output reg[7:0]out;
always@(posedge clk or posedge rst_h)
begin
if(rst_h==1)
out<=8'b0;
else
out<=out+1;
end
endmodule:up_counter
up_counter_sequence_item
class up_counter_sequence_item extends uvm_sequence_item;
//------------ i/p || o/p field declaration-----------------
logic rst_h ; //i/p
logic [7:0]out;
//register up_counter_sequence_item class with factory -----
`uvm_object_utils_begin(up_counter_sequence_item)
`uvm_field_int(rst_h ,UVM_ALL_ON)
`uvm_object_utils_end
//--------------------------------------------------------
//----------------- constructor --------------------
function new(string name="up_counter_sequence_item");
super.new();
endfunction
//---------------------------------------------------
endclass:up_counter_sequence_item
up_counter_sequence
class up_counter_sequence extends uvm_sequence#(up_counter_sequence_item);
`uvm_object_utils(up_counter_sequence)
// Register up_counter_sequence with factory
up_counter_sequence_item txn;
//object of up_counter_sequence_item class
//constructor -> create first base class and then derive class
function new(string name="up_counter_sequence");
super.new(name);
endfunction
virtual task body();
endtask:body
endclass:up_counter_sequence
class call_rst_h extends up_counter_sequence;
`uvm_object_utils(call_rst_h)
// Register call_rst_h with factory
function new(string name="call_rst_h");
super.new(name);
endfunction
task body();
up_counter_sequence_item txn;
txn=up_counter_sequence_item::type_id::create("txn");
start_item(txn);
txn.rst_h=1;
finish_item(txn);
endtask
endclass:call_rst_h
class call_rst_h_low extends up_counter_sequence;
`uvm_object_utils(call_rst_h_low)
// Register call_rst_h_low with factory
function new(string name="call_rst_h_low");
super.new(name);
endfunction
task body();
up_counter_sequence_item txn;
txn=up_counter_sequence_item::type_id::create("txn");
start_item(txn);
txn.rst_h=0;
finish_item(txn);
endtask
endclass:call_rst_h_low
up_counter_sequencer
class up_counter_sequencer extends uvm_sequencer#(up_counter_sequence_item);
`uvm_component_utils(up_counter_sequencer)
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
endclass:up_counter_sequencer
up_counter_driver
class up_counter_driver extends uvm_driver #(up_counter_sequence_item);
`uvm_component_utils(up_counter_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");
end
endfunction
//-----------------------------------------------------------------
//---------------------------- run task ---------------------------
task run_phase(uvm_phase phase);
up_counter_sequence_item txn;
forever begin
seq_item_port.get_next_item(txn);
@(posedge this.vif.clk);
$display($time," [Driver] ----------------------------------------");
this.vif.driver_block.cb_driver.rst_h<=txn.rst_h;
//this.vif.rst_h=txn.rst_h;
seq_item_port.item_done();
end
endtask
endclass:up_counter_driver
interface
interface intf(input logic clk);
// ------------------- port declaration--------------
logic rst_h;
logic [7:0]out;
//---------------------------------------------------
//------------------- clocking & modport declaration ------
// Clocking outputs are DUT inputs and vice versa
clocking cb_driver @(posedge clk);
default input #1step output #1step;
output rst_h;
input out;
endclocking
//---------------------------------------------------------
modport driver_block(clocking cb_driver);
//---------------------- ASSERTION -------------------------
property check_counter;
disable iff (rst_h)
@(posedge clk) out|->(out==$past(out,1)+1);
endproperty
//----------------------------------------------------------
ASSERT:assert property(check_counter) \
$display($time," [Interface]--------- ASSERTION PASS --------");
else \
$display($time," [Interface]----------- ASSERTION FAILS -----");
endinterface
up_counter_monitor
class up_counter_monitor extends uvm_monitor;
//-------------------------------------------------------------
`uvm_component_utils(up_counter_monitor)
//-------------------------------------------------------------
//------------------- constructor -----------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-------------------------------------------------------------
//---------------- sequence_item class ------------------------
up_counter_sequence_item txn;
//-------------------------------------------------------------
//------------------------ virtual interface handle------------
virtual interface intf vif;
//-------------------------------------------------------------
//------------------- 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
txn=up_counter_sequence_item::type_id::create("txn");
endfunction
//--------------------------------------------------------------
//-------------------- run phase -------------------------------
task run_phase(uvm_phase phase);
forever
begin
// write monitor code here
@(posedge vif.clk);
#1;
txn.out=vif.out;
$display($time," [Monitor] ----------- inside monitor -------");
end
endtask
//--------------------------------------------------------------
endclass:up_counter_monitor
up_counter_agent
class up_counter_agent extends uvm_agent;
//-----------------------------------------------------------------------
`uvm_component_utils(up_counter_agent)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------------
//----------------- class handles ---------------------------------------
up_counter_sequencer sequencer_h;
up_counter_driver driver_h;
up_counter_monitor monitor_h;
//-----------------------------------------------------------------------
//---------------------- build phase ------------------------------------
function void build_phase(uvm_phase phase);
driver_h = up_counter_driver::type_id::create("driver_h",this);
sequencer_h = up_counter_sequencer::type_id::create("sequencer_h",this);
monitor_h = up_counter_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:up_counter_agent
up_counter_env
class up_counter_env extends uvm_env;
//----------------------------------------------------------------------
`uvm_component_utils(up_counter_env)
//----------------------------------------------------------------------
//-----------------------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------------------
//-------------------- class handles ------------------------------------
up_counter_agent agent_h;
//-----------------------------------------------------------------------
//---------------------- build phase ------------------------------------
function void build_phase(uvm_phase phase);
super.build_phase(phase);
agent_h = up_counter_agent::type_id::create("agent_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:up_counter_env
up_counter_any_test
class up_counter_any_test extends uvm_test;
//-----------------------------------------------------------
`uvm_component_utils(up_counter_any_test)
//-----------------------------------------------------------
//-----------------------------------------------------------
function new(string name="",uvm_component parent);
super.new(name,parent);
endfunction
//-----------------------------------------------------------
up_counter_env env_h;
//-----------------------------------------------------------
function void build_phase(uvm_phase phase);
env_h = up_counter_env::type_id::create("env_h",this);
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);
call_rst_h seq1;
call_rst_h seq2;
call_rst_h_low seq3;
call_rst_h_low seq4;
phase.raise_objection(this);
$display("\t-------------- raise objection ---------");
seq1= call_rst_h::type_id::create("seq1");
seq3= call_rst_h_low::type_id::create("seq3");
seq1.start(env_h.agent_h.sequencer_h);
seq3.start(env_h.agent_h.sequencer_h);
#500;
seq2= call_rst_h::type_id::create("seq2");
seq4= call_rst_h_low::type_id::create("seq4");
seq2.start(env_h.agent_h.sequencer_h);
seq4.start(env_h.agent_h.sequencer_h);
#500;
$display("\t-------------- drop objection ---------");
phase.drop_objection(this);
endtask
//------------------------------------------------------------
endclass:up_counter_any_test
package
`ifndef TB_PKG
`define TB_PKG
`include "uvm_macros.svh"
package tb_pkg;
import uvm_pkg::*;
`include "up_counter_sequence_item.sv" // transaction class
`include "up_counter_sequence.sv" // sequence class
`include "up_counter_sequencer.sv" // sequencer class
`include "up_counter_driver.sv" // driver class
`include "up_counter_monitor.sv" // monitor class
`include "up_counter_agent.sv" // agent class
`include "up_counter_env.sv" // environment class
`include "up_counter_any_test.sv" // test1
endpackage
`endif
testbench_top
`include "interface.sv"
`include "tb_pkg.sv"
module top;
import uvm_pkg::*;
import tb_pkg::*;
logic clk ;
intf i_intf(clk);
up_counter DUT(.out (i_intf.out),
.rst_h(i_intf.rst_h),
.clk (i_intf.clk)
);
initial begin
forever #5 clk=~clk;
end
initial clk=0;
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("up_counter_any_test");
end
endmodule
waveform
Edaplayground Link : https://www.edaplayground
Thank you for reading have a nice day 😊😊.