Hi Sir, after 3 weeks of learning UVM through various sites. I started writing my own testbench for small design as shown below. I have worked till the monitor without any obstacles. when i started writing scoreboard. i dont know how to compare the transactions(which i got from monitor) with predicted data(i dont know where do i get this data from). please some one guide me in complete my first uvm testbench (scoreboard). how and with what(transaction items coming from sequencer or driver ??) should i compare?? I am providing my eda url link for below code : design done(1) - EDA Playground
I have half written scoreboard component below…
///////////////////////////////////////////dut///////////////////////////////////////
module dut(clk,rst,sel,in,op1,op2,op3);
input clk,rst;
input [1:0]sel;
input [3:0]in;
output reg [3:0] op1,op2,op3;
always@(posedge clk)
begin
if(rst || (sel==2'b11)) begin
op1<=4'b0;
op2<=4'b0;
op3<=4'b0;
end
else begin
case(sel)
2'b00: begin
op1<=in;
op2<=4'b0;
op3<=4'b0;
end
2'b01: begin
op1<=4'b0;
op2<=in;
op3<=4'b0;
end
2'b10: begin
op1<=4'b0;
op2<=4'b0;
op3<=in;
end
endcase
end
end
endmodule
///////////////////////////interface///////////////////////////////
interface intf(input logic clk);
logic rst;
logic [3:0]in;
logic [1:0]sel;
logic [3:0]op1,op2,op3;
clocking cb@(posedge clk);
default input #1 output #3;
input op1,op2,op3;
output in,sel;
endclocking
clocking mcb@(posedge clk);
default input #1 output #3;
input op1,op2,op3;
input in,sel;
endclocking
endinterface
/////////////////////////transaction//////////////////////////
class dut_seq_item extends uvm_sequence_item;
rand bit [1:0]sel;
rand bit [3:0]in;
bit [3:0]op1,op2,op3;
`uvm_object_utils_begin(dut_seq_item)
`uvm_field_int(sel, UVM_DEFAULT)
`uvm_field_int(in, UVM_DEFAULT)
`uvm_field_int(op1, UVM_DEFAULT)
`uvm_field_int(op2, UVM_DEFAULT)
`uvm_field_int(op3, UVM_DEFAULT)
`uvm_object_utils_end
function new(string name= "seq_item");
super.new(name);
endfunction
virtual function string convert2str();
return $sformatf("sel=%b in=0x%0d op1=0x%0d op2=0x%0d op3=0x%0d", sel, in, op1, op2, op3);
endfunction
endclass
//////////////////////////sequence//////////////////////////////////
class dut_sequence extends uvm_sequence#(dut_seq_item);
`uvm_object_utils(dut_sequence)
function new(string name= "dut_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_info ("Dut_Sequence", $sformatf ("Starting body of %s", this.get_name()), UVM_MEDIUM)
for(int i=0; i<8; i++) begin
dut_seq_item trans= dut_seq_item::type_id::create("trans");
start_item(trans);
assert(trans.randomize());
`uvm_info("Dut_sequence", $sformatf("Generating new items: %s", trans.convert2str()), UVM_MEDIUM)
finish_item(trans);
end
`uvm_info ("Dut_Sequence", $sformatf ("Sequence Items over %s", this.get_name()), UVM_MEDIUM)
endtask
endclass
//////////////////////////sequencer//////////////////////////////////
typedef uvm_sequencer#(dut_seq_item) dut_sequencer;
//////////////////////////driver////////////////////////////////////
class dut_driver extends uvm_driver#(dut_seq_item);
`uvm_component_utils(dut_driver)
virtual intf vif;
function new(string name="dut_driver", uvm_component parent=null);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual intf)::get(this, "", "vif",vif))
`uvm_error("vif","vif not found at driver")
endfunction
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
forever begin
dut_seq_item trans;
seq_item_port.get_next_item(trans);
// `uvm_info("[DRIVER]", $sformatf("Driver recieved Trans: %s", trans.convert2str()), UVM_MEDIUM)
drive(trans);
seq_item_port.item_done();
`uvm_info("[DRIVER]", $sformatf("Driver Item done: %s", trans.convert2str()), UVM_MEDIUM)
end
endtask
virtual task drive(dut_seq_item trans);
@(vif.cb);
if(trans.sel!= 2'b11) begin
vif.cb.sel <= trans.sel;
vif.cb.in <= trans.in;
trans.op1<= vif.cb.op1;
trans.op2<= vif.cb.op2;
trans.op3<= vif.cb.op3;
`uvm_info("Diver_trans_vif", $sformatf("AT DRIVER VALUES: %s", trans.convert2str()), UVM_MEDIUM)
end
if(trans.sel== 2'b11) begin
vif.cb.sel <= trans.sel;
vif.cb.in <= trans.in;
trans.op1<= vif.cb.op1;
trans.op2<= vif.cb.op2;
trans.op3<= vif.cb.op3;
`uvm_info("Diver_trans_vif", $sformatf("AT DRIVER VALUES: %s", trans.convert2str()), UVM_MEDIUM)
end
endtask
endclass
//////////////////////monitor//////////////////////////////////////
class dut_monitor extends uvm_monitor;
uvm_analysis_port#(dut_seq_item) mon_analysis_port;
virtual intf vif;
dut_seq_item trans;
`uvm_component_utils(dut_monitor)
function new(string name="dut_monitor", uvm_component parent=null);
super.new(name, parent);
trans=new();
mon_analysis_port = new ("mon_analysis_port", this);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual intf)::get(this, "", "vif", vif))
`uvm_fatal("MON", "Could not get vif")
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
@ (vif.mcb);
if(vif.mcb.sel != 2'b11)begin
trans.sel = vif.mcb.sel;
trans.in = vif.mcb.in;
trans.op1 = vif.mcb.op1;
trans.op2 = vif.mcb.op2;
trans.op3 = vif.mcb.op3;
@(vif.mcb);
end
if(vif.mcb.sel == 2'b11)begin
trans.sel = vif.mcb.sel;
trans.in = vif.mcb.in;
trans.op1 = vif.mcb.op1;
trans.op2 = vif.mcb.op2;
trans.op3 = vif.mcb.op3;
@(vif.mcb);
end
`uvm_info("Monitor",$sformatf("Monitor got VALUES: %s",trans.convert2str()), UVM_MEDIUM)
mon_analysis_port.write(trans);
end
endtask
endclass
/////////////////////////agent////////////////////////////////////
class dut_agent extends uvm_agent;
`uvm_component_utils(dut_agent)
function new(string name="dut_agent", uvm_component parent=null);
super.new(name, parent);
endfunction
dut_driver d0;
dut_sequencer s0;
dut_monitor m0;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
s0 = dut_sequencer::type_id::create("s0", this);
m0 = dut_monitor::type_id::create("m0", this);
d0 = dut_driver::type_id::create("d0", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
d0.seq_item_port.connect(s0.seq_item_export);
endfunction
endclass
////////////////////////scoreboard/////////////////////////////////
class dut_scoreboard extends uvm_scoreboard;
`uvm_component_utils(dut_scoreboard)
function new(string name="dut_scoreboard", uvm_component parent=null);
super.new(name, parent);
endfunction
dut_seq_item queue[$];
// bit [3:0]chk_op1,chk_op2,chk_op3;
uvm_analysis_imp #(dut_seq_item, dut_scoreboard) m_analysis_imp;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
m_analysis_imp = new("m_analysis_imp", this);
endfunction
virtual function void write(dut_seq_item trans);
queue.push_back(trans)
endfunction
virtual task run_phase(uvm_phase phase)
dut_seq_item pkt;
forever begin
---
---
---
---
endclass
///////////////////////environment///////////////////////////////////
class dut_env extends uvm_env;
`uvm_component_utils(dut_env)
function new(string name="dut_env", uvm_component parent=null);
super.new(name, parent);
endfunction
dut_agent a0; // Agent handle
dut_scoreboard sb0; // Scoreboard handle
function void build_phase(uvm_phase phase);
super.build_phase(phase);
a0 = dut_agent::type_id::create("a0", this);
sb0 = dut_scoreboard::type_id::create("sb0", this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
a0.m0.mon_analysis_port.connect(sb0.m_analysis_imp);
endfunction
endclass
//////////////////////////test///////////////////////////////////////
class test extends uvm_test;
`uvm_component_utils(test)
function new(string name = "test", uvm_component parent=null);
super.new(name, parent);
endfunction
dut_env env;
virtual intf vif;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = dut_env::type_id::create("env", this);
if (!uvm_config_db#(virtual intf)::get(this, "", "vif", vif))
`uvm_fatal("TEST", "Did not get vif")
uvm_config_db#(virtual intf)::set(this, "env.a0.*", "vif", vif);
endfunction
virtual task run_phase(uvm_phase phase);
dut_sequence seq = dut_sequence::type_id::create("seq");
phase.raise_objection(this);
apply_reset();
seq.start(env.a0.s0);
#50;
phase.drop_objection(this);
endtask
virtual task apply_reset();
vif.rst <= 1;
repeat(10) @ (vif.cb);
vif.rst <= 0;
repeat(10) @ (vif.cb);
endtask
endclass
///////////////////////////////top//////////////////////////////////////
module tb;
reg clk;
always #5 clk =~ clk;
intf i_intf (clk);
dut u0 ( .clk (clk),
.rst(i_intf.rst),
.sel(i_intf.sel),
.in (i_intf.in),
.op1 (i_intf.op1),
.op2 (i_intf.op2),
.op3 (i_intf.op3));
initial begin
clk = 1;
uvm_config_db#(virtual intf)::set(null, "*", "vif", i_intf);
run_test("test");
end
initial begin
$dumpvars;
$dumpfile ("dump.vcd");
end
endmodule