While developing test bench you might face a situation of multiple producers and a single consumer.
e.g. Single Scoreboard (consumer) receives data from the driver and monitor (multiple producers).
How to send data from multiple producers to consumer with the help of port connection?
Verification engineer often come across such situation when there are multiple producers and a single consumer.
If the port connection is used, then for all the producers there must be a different method in single consumer. But there is only one "write" method (for analysis port).
How to achieve this thing !!
UVM support such functionality with to help of that you can do this. This is possible with help of analysis port.
Let's consider following scenario: There are three producers and a single consumer. Now all three producers called write method of consumer. For that you have to follow following steps:
You have to declare macro before consumer class.
e.g.`uvm_analysis_imp_decl( _name )
Port declaration is like:
e.g.uvm_analysis_imp_name#(transaction,consumer_1) write_imp_1;
Now you can modify name of write method as write_name.
e.g.function void write_name(transaction tr_inst);
$display("Function called");
endfunction
Here is sample code for multiple producers and a single consumer to give you more clarity.
Multiple producers and a single consumer
CODE
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction);
rand int unsigned a;
rand int unsigned b;
function new(string name ="");
super.new(name);
endfunction
endclass
class producer_1 extends uvm_component;
`uvm_component_utils(producer_1);
transaction tr_inst;
uvm_analysis_port #(transaction) producer_1_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
producer_1_to_consumer_p = new("producer_1_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
tr_inst.randomize with {{b < 20};{a < 20};};
$display("Write the data");
tr_inst.a = 10; tr_inst.b = 20;
producer_1_to_consumer_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
class producer_2 extends uvm_component;
`uvm_component_utils(producer_2);
transaction tr_inst;
uvm_analysis_port #(transaction) producer_2_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
producer_2_to_consumer_p = new("producer_2_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
tr_inst.randomize with {{b < 20};{a < 20};};
$display("Write the data");
tr_inst.a = 10; tr_inst.b = 20;
producer_2_to_consumer_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
class producer_3 extends uvm_component;
`uvm_component_utils(producer_3);
transaction tr_inst;
uvm_analysis_port #(transaction) producer_3_to_consumer_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
producer_3_to_consumer_p = new("producer_3_to_consumer_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
tr_inst.randomize with {{b < 20};{a < 20};};
$display("Write the data");
tr_inst.a = 10; tr_inst.b = 20;
producer_3_to_consumer_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
`uvm_analysis_imp_decl( _pro_1 )
`uvm_analysis_imp_decl( _pro_2 )
`uvm_analysis_imp_decl( _pro_3 )
class consumer_1 extends uvm_component;
`uvm_component_utils(consumer_1);
uvm_analysis_imp_pro_1#(transaction,consumer_1) write_imp_1;
uvm_analysis_imp_pro_2#(transaction,consumer_1) write_imp_2;
uvm_analysis_imp_pro_3#(transaction,consumer_1) write_imp_3;
//transaction tr_inst;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_1 = new("write_imp_1",this);
write_imp_2 = new("write_imp_2",this);
write_imp_3 = new("write_imp_3",this);
endfunction
function void write_pro_1(transaction tr_inst);
$display("Got the data");
`uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
function void write_pro_2(transaction tr_inst);
$display("Got the data");
`uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
function void write_pro_3(transaction tr_inst);
$display("Got the data");
`uvm_info(get_full_name(),$sformatf("the value of a %0d and b is %0d",tr_inst.a,tr_inst.b),UVM_LOW);
endfunction
endclass
class env extends uvm_component;
`uvm_component_utils(env);
producer_1 p_inst_1;
producer_2 p_inst_2;
producer_3 p_inst_3;
consumer_1 c_inst_1;
function new(string name="",uvm_component parent);
super.new(name,parent);
p_inst_1 = new("p_inst_1",this);
p_inst_2 = new("p_inst_2",this);
p_inst_3 = new("p_inst_3",this);
c_inst_1 = new("c_inst_1",this);
endfunction
function void connect();
p_inst_1.producer_1_to_consumer_p.connect(c_inst_1.write_imp_1);
p_inst_2.producer_2_to_consumer_p.connect(c_inst_1.write_imp_2);
p_inst_3.producer_3_to_consumer_p.connect(c_inst_1.write_imp_3);
endfunction
endclass
module main();
env env_inst;
initial
begin
env_inst = new("env_inst",null);
run_test();
end
endmodule
Here I also provides sample code for a scoreboard (a single consumer) and driver, monitor(multiple producers).
Driver, Monitor and Scoreboard connection
CODE
class transaction extends uvm_sequence_item;
`uvm_object_utils(transaction);
rand int unsigned a;
rand int unsigned b;
rand int unsigned sum;
function new(string name ="");
super.new(name);
endfunction
endclass
class driver extends uvm_driver;
`uvm_component_utils(driver);
transaction tr_inst;
uvm_analysis_port #(transaction) driver_to_sb_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
driver_to_sb_p = new("driver_to_sb_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
`uvm_info("DRIVER","driver drive the data to scoreboard",UVM_LOW)
tr_inst.a = 10; tr_inst.b = 20;
tr_inst.sum = tr_inst.a + tr_inst.b;
driver_to_sb_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
class monitor extends uvm_monitor;
`uvm_component_utils(monitor);
transaction tr_inst;
uvm_analysis_port #(transaction) monitor_to_sb_p;
function new(string name ="",uvm_component parent);
super.new(name,parent);
monitor_to_sb_p = new("monitor_to_sb_p",this);
tr_inst = new("tr_inst");
endfunction
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
`uvm_info("MONITOR","monitor drive the data to scoreboard",UVM_LOW)
tr_inst.a = 10; tr_inst.b = 20;
tr_inst.sum = tr_inst.a + tr_inst.b;
monitor_to_sb_p.write(tr_inst);
phase.drop_objection(this);
endtask
endclass
`uvm_analysis_imp_decl( _dri )
`uvm_analysis_imp_decl( _mon )
class scoreboard extends uvm_scoreboard;
`uvm_component_utils(scoreboard);
int dri_sum,mon_sum;
uvm_analysis_imp_dri#(transaction,scoreboard) write_imp_1;
uvm_analysis_imp_mon#(transaction,scoreboard) write_imp_2;
//transaction tr_inst;
function new(string name ="",uvm_component parent);
super.new(name,parent);
write_imp_1 = new("write_imp_1",this);
write_imp_2 = new("write_imp_2",this);
endfunction
function void write_dri(transaction tr_inst);
`uvm_info("SCORE BOARD","Receive data form driver",UVM_LOW)
`uvm_info("SCORE BOARD",$sformatf("the value of a = %0d and b = %0d sum = %0d",tr_inst.a,tr_inst.b,tr_inst.sum),UVM_LOW);
dri_sum = tr_inst.sum;
endfunction
function void write_mon(transaction tr_inst);
`uvm_info("SCORE BOARD","Receive data form monitor",UVM_LOW)
`uvm_info("SCORE BOARD",$sformatf("the value of a = %0d and b = %0d sum = %0d",tr_inst.a,tr_inst.b,tr_inst.sum),UVM_LOW);
mon_sum = tr_inst.sum;
endfunction
task compare_data();
if (mon_sum == dri_sum)
begin
`uvm_info("SCORE BOARD","--------- data is matched ----------",UVM_LOW)
end
else
begin
`uvm_info("SCORE BOARD","data is not matched",UVM_LOW)
end
endtask
task run_phase(uvm_phase phase) ;
super.run_phase(phase);
phase.raise_objection(this);
compare_data();
phase.drop_objection(this);
endtask
endclass
class env extends uvm_component;
`uvm_component_utils(env);
driver dri_inst;
monitor mon_inst;
scoreboard sb_inst;
function new(string name="",uvm_component parent);
super.new(name,parent);
dri_inst = new("dri_inst",this);
mon_inst = new("mon_inst",this);
sb_inst = new("sb_inst",this);
endfunction
function void connect();
dri_inst.driver_to_sb_p.connect(sb_inst.write_imp_1);
mon_inst.monitor_to_sb_p.connect(sb_inst.write_imp_2);
endfunction
endclass
module main();
env env_inst;
initial
begin
env_inst = new("env_inst",null);
run_test();
end
endmodule