I have written an UVM environment for Round robin arbiter. But when I am displaying a output, which is coming in the monitor from the DUT, it always shows as zero. I am giving my code below:
`include "uvm_macros.svh"
package my_pkg;
import uvm_pkg::*;
////////////Transaction Class///////////////////////////////
class my_transaction extends uvm_sequence_item;
`uvm_object_utils(my_transaction)
rand bit[3:0] requ; //Request Signal
logic [3:0] grant; //Grant Signal
constraint c_requ { requ > 0; requ < 10; }
//constraint c_data { data >= 0; data < 256; }
function new (string name = "");
super.new(name);
endfunction
function string convert2string;
return $sformatf("requ=%b",requ);
endfunction
function string output2string;
$sformatf("grant=%b", grant);
endfunction
endclass: my_transaction
///////////////////////Sequencer//////////////////////////////////
typedef uvm_sequencer #(my_transaction) my_sequencer;
////////////////////////Sequence/////////////////////////////////////
class my_sequence extends uvm_sequence #(my_transaction);
`uvm_object_utils(my_sequence)
function new (string name = "");
super.new(name);
endfunction
task body;
if (starting_phase != null)
starting_phase.raise_objection(this);
repeat(8)
begin
req = my_transaction::type_id::create("req");
start_item(req);
if( !req.randomize() )
`uvm_error("", "Randomize failed")
finish_item(req);
end
if (starting_phase != null)
starting_phase.drop_objection(this);
endtask: body
endclass: my_sequence
///////////////////////Driver//////////////////////////////////////
class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils(my_driver)
virtual dut_if dut_vi; //Interface Handle
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
// Get interface reference from config database
`uvm_info("Driver Build",$sformatf("Driver Build Phase Started"),UVM_MEDIUM);
if( !uvm_config_db #(virtual dut_if)::get(this, "", "dut_if", dut_vi))
`uvm_error("", "uvm_config_db::get failed")
`uvm_info("Driver Build",$sformatf("Driver Build Phase Ended"),UVM_MEDIUM);
endfunction
task run_phase(uvm_phase phase);
my_transaction tr;
forever
begin
@(posedge dut_vi.clk);
seq_item_port.get_next_item(tr);
// Wiggle pins of DUT
dut_vi.requ <= tr.requ;//Assigning transaction to the DUT Port
`uvm_info("Driver to DUT",$sformatf("requ=%b",dut_vi.requ),UVM_LOW)
seq_item_port.item_done();
end
endtask
endclass: my_driver
//////////////////////Monitor/////////////////////////////////////
class my_monitor extends uvm_monitor;
`uvm_component_utils(my_monitor)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual dut_if tb_vif; // virtual interface
uvm_analysis_port #(my_transaction) dut_inputs_port; // analysis port for DUT inputs
uvm_analysis_port #(my_transaction) dut_outputs_port; // analysis port for DUT outputs
function void build_phase(uvm_phase phase);
dut_inputs_port = new("dut_inputs_port", this); // construct the analysis port
dut_outputs_port = new("dut_outputs_port", this); // construct the analysis port
if (!uvm_config_db #(virtual dut_if)::get(this, "", "dut_if", tb_vif))
`uvm_error("", "uvm_config_db::get failed")
endfunction: build_phase
task run_phase(uvm_phase phase);
my_transaction tx_in;
my_transaction tx_out;
my_transaction tx_copy;
fork
// monitor DUT inputs synchronous to the interface clock
forever @(tb_vif.clk)
begin
// create a new tx_write object for this cycle
tx_in = my_transaction::type_id::create("tx_in");
tx_in.requ = tb_vif.requ;
`uvm_info("Inputs to DUT",$sformatf("request=%b",tx_in.requ),UVM_LOW)
dut_inputs_port.write(tx_in);
end
// create a tx_tmp object to reuse each pass of the loop
tx_out = my_transaction::type_id::create("tx_out"); // tx_out is reused each loop pass
forever @(tb_vif.clk)
begin
tx_out.grant = tb_vif.grant;
`uvm_info("Output from DUT",$sformatf("Output=%b",tx_out.grant),UVM_LOW)
// create a copy of tx_out to send to the scoreboard
$cast(tx_copy, tx_out.clone());
dut_outputs_port.write(tx_copy);
end
join
endtask: run_phase
endclass: my_monitor
/////////////////////////////Agent///////////////////////////////////
class my_agent extends uvm_agent;
`uvm_component_utils(my_agent)
uvm_analysis_port #(my_transaction) dut_inputs_port;
uvm_analysis_port #(my_transaction) dut_outputs_port;
my_driver drv;
my_sequencer seqr;
my_monitor mon;
function new(string name, uvm_component parent);
super.new(name, parent);
dut_inputs_port=new("dut_inputs_port",this);
dut_outputs_port=new("dut_outputs_port",this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("Agent Build",$sformatf("Agent Build Phase Started"),UVM_LOW);
if(get_is_active() == UVM_ACTIVE) begin
drv = my_driver::type_id::create("drv", this);
seqr = my_sequencer::type_id::create("seqr", this);
end
mon = my_monitor::type_id::create("mon", this);
`uvm_info("Agent Build",$sformatf("Agent Build Phase Ended"),UVM_LOW);
endfunction : build_phase
// connect_phase
function void connect_phase(uvm_phase phase);
// set agent's analysis ports to point to the monitor's ports
dut_inputs_port = mon.dut_inputs_port;
dut_outputs_port = mon.dut_outputs_port;
if (is_active == UVM_ACTIVE) begin
drv.seq_item_port.connect(seqr.seq_item_export); // connect driver to sequencer
end
endfunction: connect_phase
endclass
////////////////////////////Scoreboard/////////////////////////////
`uvm_analysis_imp_decl(_verify_outputs)
`uvm_analysis_imp_decl(_inputs)
class my_scoreboard extends uvm_scoreboard;
`uvm_component_utils(my_scoreboard)
function new(string name, uvm_component parent );
super.new(name, parent);
endfunction: new
uvm_analysis_imp_verify_outputs #(my_transaction, my_scoreboard) dut_out_imp_export;
uvm_analysis_imp_inputs #(my_transaction, my_scoreboard) dut_in_imp_export;
mailbox #(my_transaction) expected_fifo=new(); // SystemVerilog mailbox for my_tx handles
int num_passed, num_failed; // score cards
function void build_phase(uvm_phase phase);
dut_out_imp_export = new("dut_out_imp_export", this);
dut_in_imp_export = new("dut_in_imp_export", this);
endfunction
function void write_inputs(my_transaction t);
my_transaction expected_tx;
$cast(expected_tx, t.clone()); // create new my_tx object and preserve input vals
// calculate expected results and store in FIFO
if(t.requ[0])
expected_tx.grant=4'b0001;
else if(t.requ[1])
expected_tx.grant=4'b0010;
expected_fifo.try_put(expected_tx); // save transaction handle
endfunction: write_inputs
function void write_verify_outputs(my_transaction t);
my_transaction expected_tx=new();
expected_fifo.try_get(expected_tx); // blocks if FIFO is empty
if (t.grant !== expected_tx.grant)
begin: mismatch
`uvm_error("SCBD_ERR:", "DUT outputs did not match expected results")
`uvm_info("DUT OUT:",$sformatf("Grant=%b",t.grant), UVM_LOW)
`uvm_info("EXPECTED:", $sformatf("Grant=%b",expected_tx.grant), UVM_LOW)
num_failed++;
end: mismatch
else
begin:match
`uvm_info("DUT OUT:",$sformatf("Grant=%b",t.grant), UVM_LOW)
`uvm_info("EXPECTED:",$sformatf ("Grant=%b",expected_tx.grant), UVM_LOW)
num_passed++;
end:match
endfunction: write_verify_outputs
function void report_phase(uvm_phase phase);
`uvm_info("Scoreboard:", $sformatf("\n passed=%0d failed=%0d\n",num_passed, num_failed),UVM_NONE)
endfunction: report_phase
endclass
////////////////////////////Environment/////////////////////////////
class my_env extends uvm_env;
`uvm_component_utils(my_env)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
my_agent agent;
my_scoreboard scoreboard;
function void build_phase(uvm_phase phase);
agent = my_agent::type_id::create("agent", this);
scoreboard = my_scoreboard::type_id::create("scoreboard", this);
endfunction: build_phase
function void connect_phase(uvm_phase phase);
agent.dut_inputs_port.connect(scoreboard.dut_in_imp_export);
agent.dut_outputs_port.connect(scoreboard.dut_out_imp_export);
endfunction: connect_phase
endclass: my_env
//////////////////////////////Test/////////////////////////////////////
class my_test extends uvm_test;
`uvm_component_utils(my_test)
my_env env;
function new(string name = "my_test",uvm_component parent=null);
super.new(name,parent);
endfunction : new
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = my_env::type_id::create("env", this);
endfunction : build_phase
task run_phase(uvm_phase phase);
my_sequence seq;
phase.raise_objection(.obj(this));
seq = my_sequence::type_id::create("seq");
assert(seq.randomize());
seq.start(env.agent.seqr);
phase.drop_objection(.obj(this));
endtask: run_phase
endclass
endpackage
///////////////////////////Top module////////////////////////////
module top;
import uvm_pkg::*;
import my_pkg::*;
dut_if dut_if1 ();
dut dut1 (dut_if1.clk,dut_if1.rst_an,dut_if1.requ,dut_if1.grant);
// Clock generator
initial
begin
dut_if1.clk = 0;
forever #5 dut_if1.clk = ~dut_if1.clk;
end
initial
begin
dut_if1.rst_an = 1'b0;
#10;
dut_if1.rst_an = 1'b1;
end
initial
begin
uvm_config_db #(virtual dut_if)::set(null, "*", "dut_if", dut_if1);
uvm_top.finish_on_completion = 1;
run_test("my_test");
end
endmodule: top
///////////////////////////////END///////////////////////////////////
///////////////////////////Interface//////////////////////////////////////////////////////////////
interface dut_if;
logic clk,rst_an;
logic [3:0] requ;
//logic [7:0] data;
logic [3:0]grant;
endinterface