0% found this document useful (0 votes)
368 views16 pages

Uvm TB Code 1672202269

The document describes the UVM testbench architecture for verifying a mod-13 loadable up counter design. It includes transaction classes to model the counter protocol, agent classes for the input and output interfaces, a scoreboard for comparison, and a top-level testbench configuration class. Key components are the driver, sequencer and monitor classes for each interface agent, and a reference model in the scoreboard for comparison against monitored transactions.

Uploaded by

Sumanish Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
368 views16 pages

Uvm TB Code 1672202269

The document describes the UVM testbench architecture for verifying a mod-13 loadable up counter design. It includes transaction classes to model the counter protocol, agent classes for the input and output interfaces, a scoreboard for comparison, and a top-level testbench configuration class. Key components are the driver, sequencer and monitor classes for each interface agent, and a reference model in the scoreboard for comparison against monitored transactions.

Uploaded by

Sumanish Sharma
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

UVM

TESTBENCH
ARCHITECTURE
UVM TB ARCHITECTURE
Testbench Architecture

Verification Component includes:

Sequence_item - Data item based on the DUT protocol


Sequencer -Route sequence_items from a sequence to the driver
Driver - It converts sequence_item into the pin level for DUT
Monitor - It converts pin-level data to the transactions for use in the scoreboard,
coverage model, etc.,
Agent – Encapsulated with Sequencer, Driver, and Monitor
Agent Configuration ACTIVE — Sequencer, Driver
Agent Configuration PASSIVE—Monitor
Test - configuring the testbench. Initiate the testbench components construction
process by building the next level down in the hierarchy example:
environment(env). Initiate the stimulus by starting the sequence.
Environment - It is a container component for grouping higher-level
components like agents and scoreboards.
Scoreboard: - Receive data items from the monitor and compare them with the
expected value.
Configuration object -A container object, used to pass information to the agent
which affects what it does and how it is built and connected
Sequencers and Drivers are connected using TLM ports
Sequence: It defines the sequence in which the data items need to be generated
and sent/received to/from the driver.
Sequencer: It is responsible for routing the data packets(sequence_item)
generated in sequence to the driver or vice versa.
Interface: Contains design signals that can be driven or monitored.
Verification of Mod-13 Loadable UP Counter

Design Diagram

Testbench Architecture
============
//Interface
============
interface counter_inf (input bit clock);

logic [3:0] data_in ;


logic [3:0] data_out ;
logic load ;
logic rst;

//Driver Clocking Block


clocking driver_cb@(posedge clock);
default input #1 output #1;
output rst ;
output data_in;
output load;
endclocking

// output monitor clocking block


clocking output_mon_cb @(posedge clock);
default input #1 output #1 ;
input data_out ;
endclocking

//input monitor clocking block


clocking input mon cb@(posedge clock);
default input #1 output #1 ;
input load ;
input rst;
input data_in;
endclocking

//driver modport
modport DRIVER (clocking driver_cb);

//input Monitor modport


modport INPUT_MON (clocking input_mon_cb);

//Output monitor modport


modport OUTPUT_MON (clocking output_mon_cb );
endinterface
===================================
//Transaction Class (Sequence Ieam)
===================================
class counter_trans extends uvm_sequence_item ;
`uvm_object_utils (counter_trans)

rand logic rst ;


rand logic load;
randc logic [3:0] data_in;
logic [3 : 0] data_out ;
static int no_of_xtn ;

constraint VALID_RST {rst dist{ 1:=1,0:=15};}


constraint VALID_LOAD {load dist{ 1:= 1, 0:=15};}
constraint VALID_DATA {data_in inside {[0:15]};}

function new (string name = " counter_trans");


super.new(name);
endfunction:new

function bit do_compare (uvm_object rhs ,uvm_comparer comparer );


counter_trans rhs_;
if (!$cast (rhs_,rhs))
begin
`uvm_fatal (" do_compare","cast of the rhs object failed")
return 0;
end
return super.do_compare (rhs,comparer) &&
data_out== rhs_.data_out;
endfunction:do_compare

function void do_print (uvm_printer printer);


super.do_print (printer);
printer.print_field ("rst", this.rst, '1 , UVM DEC);
printer.print_field ("load ", this.load , '1 , UVM DEC);
printer.print_field (" data_in", this.data_in , 4, UVM_DEC);
printer.print_field ("data_out", this.data_out , 4 , UVM_DEC );
endfunction:do_print

function void post_randomize ();


no of xtn++;
`uvm_info("randomized data", $sformatf ("randomized transaction [%d] is \n%s"
no_of_xtn , this.sprint ()), UVM_MEDIUM)
endfunction :post_randomize
endclass

=====================
//Configuration Class
=====================
class counter_env_config extends uvm_object;
`uvm_object_utils(counter_env_config)
bit has_input_agent ;
bit has_output_agent ;
bit has_scoreboard ;
uvm_active_passive_enum input_agent_is_active ;
uvm_active_passive_enum output_agent_is_active;
virtual counter_inf vif ;

function new (string name = "counter_env_config");


super.new(name);
endfunction
endclass

=====================
//Input Driver
=====================
class counter_input_driver extends uvm_driver #(counter_trans);
`uvm_component_utils (counter_input_driver)
virtual counter_inf.DRIVER drv_inf;
counter_trans data2duv_pkt ;
counter_env_config m_cfg;

function new (string name="counter_input_driver", uvm_component parent);


super.new(name ,parent);
endfunction

function void build_phase (uvm_phase phase);


super.build_phase(phase);
if(!uvm_config_db
#(counter_env_config)::get(this,"","counter_env_config",m_cfg))
`uvm_fatal("CONFIG","cannot get() m_cfg from uvm_config_db. Have you set()
it?")
endfunction

function void connect_phase(uvm_phase phase );


drv_inf = m_cfg.vif ;
endfunction

task run_phase(uvm_phase phase);


forever
begin
seq_item_port.get_next_item =(req);
send_to_dut(req);
seq_item_port.item_done();
end
endtask

virtual task send_to_dut(counter_trans data2duv_pkt);


@(drv_inf.driver_cb);
drv_inf.driver_cb.data_in<=data2duv_pkt.data_in;
drv_inf.driver_cb.rst<=data2duv_pkt.rst;
drv_inf.driver_cb.load<=data2duv_pkt.load ;
endtask
endclass
=====================
//Input Sequencer
=====================
class counter_input_sequencer extends uvm_sequencer #(counter_trans);
`uvm_component_utils(counter_input_sequencer)

function new(string name="counter_input_sequencer", uvm_component parent);


super.new(name ,parent );
endfunction
endclass

=====================
//Input Monitor
=====================
class counter_input_monitor extends uvm_monitor ;
`uvm_component_utils (counter_input_monitor)

virtual counter_inf.INPUT_MON mon_if;


counter_trans drv2mon_pkt;
counter_env_config m_cfg ;
uvm_analysis_port#(counter_trans) monitor_port;

function new(string name="counter_input_monitor", uvm_component parent);


super.new(name ,parent);
endfunction

function void build_phase(uvm_phase phase);


super.build_phase (phase);
if (!uvm_config_db #(counter_env_config)::get
(this,"","counter_env_config",m_cfg ))
`uvm_fatal(get_type_name,"cannot get() m_cfg")
monitor_port = new("monitor_port", this);
endfunction

function void connect_phase(uvm_phase phase);


mon_if =m_cfg.vif ;
endfunction

task run_phase (uvm_phase phase);


@(mon_if.input_mon_cb);
forever
monitor();
endtask

task monitor();
begin
@(mon_if.input_mon_cb);
drv2mon_pkt = counter_trans::type_id::create("drv2mon_pkt") ;
drv2mon_pkt.load = mon_if.input_mon_cb.load ;
drv2mon_pkt.rst =mon_if.input_mon_cb.rst;
drv2mon_pkt.data_in= mon_if.input_mon_cb.data_in;
`uvm_info(get_type_name, $sformatf("input monitor has captured below
transaction \n%s", drv2mon_pkt.sprint ()), UVM_MEDIUM)
monitor_port.write(drv2mon_pkt);
end
endtask
endclass
=====================
//Input Agent
=====================
class counter_input_agent extends uvm_agent;
`uvm_component_utils(counter_input_agent)

counter_env_config m_cfg ;

counter_input_monitor monh;
counter_input_sequencer seqrh;
counter_input_driver drvh;

function new(string name = "counter_input_agent", uvm_component parent =


null);
super.new(name, parent);
endfunction

function void build_phase (uvm_phase phase);

super.build_phase(phase);

if(!uvm_config_db #(counter_env_config)::get
(this,"","counter_env_config",m_cfg))
`uvm_fatal("CONFIG","cANNOT GET() m_cfg from uvm_config_db. Have YOU set ()
it")
monh=counter_input_monitor::type_id::create("monh",this);

if(m_cfg input_agent_is_active==UVM_ACTIVE)
begin
drvh=counter_input_driver::type_id::create(" drvh",this);
seqrh=counter_input_sequencer ::type_id ::create("seqrh",this) ;
end
endfunction

function void connect_phase (uvm_phase phase);


if(m_cfg.input_agent_is_active==UVM_ACTIVE)
begin
drvh.seq_item_port.connect(seqrh.seq_item_export);
end
endfunction
endclass : counter_input_agent

=====================
//Output Monitor
=====================
class counter_output_monitor extends uvm_monitor ;
'uvm_component_utils(counter_output_monitor)

virtual counter_inf.OUTPUT MON rdmon_inf;


counter_trans output_mon_pkt ;
counter_env_config m cfg;
uvm_analysis_port#(counter_trans) monitor_port;

function new(strinq name"counter_input_monitor", uvm_component parent );


super.new(name ,parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db #(counter_env_config)::get(this,"",
"counter_env_config",m_cfg))
'uvm_fatal (get_type_name ,"cannot qet() m_cfg ")
monitor_port=new("monitor_port", this);
endfunction

function void connect_phase(uvm_phase phase);


rdmon_inf = m_cfg.vif ;
endfunction

task run_phase (uvm_phase phase);


repeat(2)
@(rdmon_inf.output_mon_cb);
forever
monitor();
endtask

task monitor ();


output_mon_pkt "' counter_trans ::type_id::create ("-.utput mon p :t");
@(rdmon inf .output mon cb);
output_mon_pkt.data_out = rdmon_inf.output_mon_cb .data_out ;
'uvm_info(get_type_name, $sformatf ("output monitor has captured below
transaction \n%s", output_mon_pkt .sprint() ) , UVM_MEDIUM)
monitor_port.write(output_mon_pkt );
endtask
endclass

=====================
//Output Agent
=====================
class counter_output_agent extends uvm_agent;
`uvm_cornponent_utils(counter_output_agent)

counter_env_config m_cfg ;
counter_output_monitor monh ;
function new (string name = "counter_output_agent",uvm_component parent
=null);
super.new (name , parent);
endfunction

function void build_phase (uvm_phase phase);


super.build_phase (phase);
if(!uvm_config_db #(counter_env_config)::get
(this,"","counter_env_config",m_cfg))
'uvm_fatal ("C0NIG"," cannot get() m_cfg from uvm_config_db.Have you set()
?")
if{m_cfg.output_agent_is_active==UVM_PASSIVE)
monh=counter_output_monitor ::type_id ::create ("monh", this);
endfunction
endclass : counter_output_agent
=======================================
//Scoreboard with Reference Model Logic
=======================================

class counter_scoreboard extends uvm_scoreboard;


`uvm_component_utils(counter_scoreboard)

uvm_tlm_analysis_fifo #(counter_trans) input_mon_fifo;


uvm=tlm_analysis=fifo #(counter_trans) output_mon_fifo ;

counter_trans input_mon_pkt;
counter_trans output_mon_pkt:
counter_trans expected_output_pkt ;
counter_trans cov_data_pkt;

int data_verified =0;


int input_mon_pkt_count =0;
int output_mon_pkt_count =0;

covergroup counter_coverage;
option.per_instance= 1;
LOAD_DATA : coverpoint cov_data_pkt.data_in {
bins ZERO ={0};
bins LOWl ={[1:2]};
bins LOW2 ={[3:4]};
bins MID_LOW ={[5:6]};
bins MID ={[7:8]};
bins MID HIGH ={[9:10]};
bins HIGHl ={[11:12]};
bins HIGH2 ={[13:14]};
bins MAX ={[15]};
}

RESET_CMD : coverpoint cov_data_pkt.rst{


bins cmd_rst ={1}I;
}
LOAD_CMD : coverpoint cov_data_pkt.load {
bins load_dut = {1};
}
READxWRITE : cross LOAD_CMD, LOAD_DATA;

function new(string name,uvm_component parent);


super.new(name.parent);
input_mon_fifo= new("input_mon_fifo",this) ;
output_mon_fifo= new(" output_mon_fifo", this) ;
expected_output_pkt=counter_trans::type_id::create (" expected_output_pkt");
;
counter_coverage=new:
endfunction

task run_phase (uvm_phase phase):


forever
begin
input_mon_fito.get(input_mon_pkt);
input_mon_pkt_count++:
'uvm_into(get_type_name, $sformatf ("sb has got below packet from input
monitor \n%s", input_mon_pkt .sprint ()), UVM_MEDIUM)
output_mon_fifo.get(output_mon_pkt );
output_mon_pkt_count++;
'uvm_into(get_type_name, $sformatf ("sb has got below packet from output
monitor \n%s", output_mon_pkt .sprint ()), UVM_MEDIUM)

ref_model_logic();
validate_output();
end
endtask

task ref_model_logic();
begin
if (input_mon_pkt.rst || (input_mon_pkt.load&input_mon_pkt.data_in >=13))
expected_output_pkt.data_out = 4'b0; ;
else if(input_mon_pkt.load)
expected_output_pkt.data_out = input_mon_pkt.data_in ;
else if (expected_output_pkt.data_out >=13)
expected_output_pkt.data_out = 4'b0;
else
expected_output_pkt.data_out=expected_output_pkt.data_out + 1'b1;
end
endtask

virtual task validate_output ();


if (!expected_output_pkt.compare(output_mon_pkt))
begin:failed compare
'uvm_info(get_type_name , $sformatf (" expected packet is below \n%s
",expected_output_pkt.sprint ()), UVM_MEDIUM)
'uvm_info(get_type_name , $sformatf (" dut's output packet is below \n%s
",expected_mon_pkt.sprint ()), UVM_MEDIUM)

//Sfinish ;
end:failed_compare

else
begin
'uvm info (get type name (), $sformatf ("Data Match successful ") ,
UVM_MEDIUM)
data_vrified++ ;
end
cov_data_pkt=input_mon_pkt;
counter_coverage.sample();
endtask

function void report_phase (uvm_phase phase);


$display (" \n----------- Scoreboard ---------- \n ");
$display (" input mon pkt count = %0d , output mon pkt count = %0d, no of
successful comparisions = %0d\n", input_mon_pkt_count,output_mon_pk t_count
,data_verified);
$display (" -------------------------------------- \n ");
endfunction
endclass
=====================
//Environment
=====================
class counter_env extends uvm_env ;

`uvm_component_utils(counter_env)
counter_input_agent input_agent_h ;
counter_output_agent output_agent_h;
counter_scoreboard scoreboard_h ;

counter_env_config m_cfg ;

function new (string name = "counter_input_agent" uvm_component parent =


null);
super.new(name , parent);
endfunction

function void build_phase (uvm_phase phase);


if(!uvm_config_db #(counter_env_config)::get (this,"","counter env config",m
cfg))
'uvm_fatal(get_type_name,"cannot get from contig db. Have you set() it?")
if (m_cfg.has_input_agent )
input_agent_h = counter_input_agent::type_id::create ("input_agent_h",this);
if(m_cfg.has_output_agent)
output_agent_h = counter_output_agent::type_id ::create ("output_agent_h"
this);
if(m_cfg .has_scoreboard)
scoreroard_h = counter_scoreboard ::type_id::create (" scoreboard_h" ,this);
super build_phase(phase);
endfunction

function void connect_phase(uvm_phase phase);


uvm_top.print_topology();
if(m_cfg.has_input_agent && m_cfg.has_scoreboard)
input_agent_h.monh.monitor_port.connect(scoreboard_h.input_mon_fifo.analysis_
export);
if(m_cfg.has_output_agent && m_cfg.has_scoreboard)
output_agent_h.monh.monitor_port.connect(scoreboard_h.output_mon_fifo.analysi
s_export);
endfunction
endclass
=====================
//Sequence
=====================
class counter_seq extends uvm_sequence # (counter_trans );
`object_utils(counter_seq)
int xtn_num =1;
function new (string name = "counter_seq");
super.new(name);
endfunction

task body ();


repeat(number_of_transactions)
begin
req=counter_trans::type_id::create("req");
start_item(req);
if (xtn_num ==1)
begin
assert(req.randomize() with {rst==1;});
xtn num++;
end
else
assert (req.randomize ());
finish_item(req);
end
endtask endclass

=====================
//Base testcase
=====================
import counter_pkg ::*;

class counter_base_test extends uvm_test;


`uvm_component_utils(counter_base_test)
counter_env_config m_cfg;
counter_env counter_env_h;

function new(string name = "counter_base_test",uvm_component parent=null);


super.new(name , parent);
endfunction

function void build_phase (uvm_phase phase);


m_cfg = counter_env_config ::type_id::create (" m_cfg");
if(!uvm_config_db #(virtual counter_inf )::get(this,"", "vif",m_cfg.vif))
`uvm_fatal(get_type_name," cannot get() interface vif from uvm_config_db");
m_cfg.has_input_agent =1;
m_cfg.has_outp1t_agent =1;
m_cfg.has_scoreboard =1;
m_cfg.output_agent_is_active = UVM_PASSIVE ;
m_cfg.input_agent_is_active = UVM_ACTIVE ;

uvm_config_db #(counter_env_config)::set(this,"*","counter_env_config",m
cfg);
counter_env_h = counter_env::type_id::create (" counter_env_h", this);
endfunction
endclass
=====================
//Derived testcase
=====================

class counte_test_1 extends counter base test;


`uvm_component_utils(counter_test_l)

counter_seq cnunter_seq_h ;

function new (string name = "counte_test_1" uvm_component parent = null);


super.new(name , parent);
endfunction

function void build_phase (uvm_phase phase);


super.build_phase(phase);
endfunction

task run_phase (uvm_phase phase );


phase.raise_objection (this);
counter_seq_h=counter_seq ::type_id ::create ("counter_seq_h");
counter_seq h.start (counter_env_h.input_agent_h.seqrh);
#30;
phase.drop_objection (this);
endtask
endclass

=====================
//Package
=====================
package counter_pkg;

int number_of_transactions=100 ;
import uvm_pkg ::*;

`include "uvm_macros.svh"

`include "counter_trans.sv"
`include "counter_env_config.sv"
`include "counter_input_driver.sv"
`include "counter_input_monitor.sv"
`include "counter_input_sequencer.sv "
`include "counter_input_agent.sv"
`include "counter_output_monitor.sv"
`include "counter_output_agent.sv"
`include "counter_scoreboard.sv"
`include "counter_env.sv "
`include "counter_sequence.sv"
`include "counter-test.sv"

endpackage
=====================
//Top Module
=====================
module counter_top ();

import counter_pkg ::*;


import uvm_pkg: :*;
parameter cycle =10;
reg clk ;
counter_inf DUT_INF (clk);

counter_load DUv(.clk(clk),
.rst (DUT_INF .rst),
.load (DUT_INF .loadl ,
.data out (DUT INF .data out),
.data=in (DUT_INF .data_ln));

initial
begin
uvm_config_db #(virtual counter_inf)::set (null,"*","vif",DUT_INF);
run_test ();
end

//Generate the clock


initial
begin
clk=1'b0;
forever
# (cycle/2) clk=clk;
end

endmodule

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy