Design details:
2 input ports with dst_addr, data as sequence item fields.
2 output ports that receive input packets.
any input port can send txn to any output port.
Following are the two approaches I am contemplating. Please let me know if both the methods are accurate.
example sequence item is as below:
Assuming there are 2 master agents one for each input port driving traffic and monitoring the interfaces.
Also assuming there are 2 slave agents one for each output port just monitoring interface.
class txn_item extends uvm_sequence_item
rand bit [1:0] addr;
rand bit [15:0] data;
endclass
Method1:
scoreboard uses uvm_tlm_analysis_fifo
class router_scoreboard extends uvm_scoreboard
`uvm_component_utils(router_scoreaboard)
`uvm_tlm_analysis_fifo in1_fifo;
`uvm_tlm_analysis_fifo in2_fifo;
`uvm_tlm_analysis_fifo out1_fifo;
`uvm_tlm_analysis_fifo out2_fifo;
`uvm_analsyis_export #(txn_item) in1_export;
`uvm_analsyis_export #(txn_item) in2_export;
`uvm_analsyis_export #(txn_item) out1_export;
`uvm_analsyis_export #(txn_item) out2_export;
// not showing build_phase, new or connect_phase
txn_item out1_q[$];
txn_item out2_q[$];
task run_phase();
forever begin
fork
begin
in1_fifo.get(txn);
process_req(txn);
end
begin
in2_fifo.get(txn);
process_req(txn)
end
begin
out1_fifo.get(txn);
compare_results(txn);
end
begin
out2_fifo.get(txn);
compare_results(txn);
end
join
end
endtask
task process_req(txn_item txn)
if(txn.addr inside out1 range)
out1_q.push_back(txn)
else
out2_q.push_back(txn)
endtask
task compare_results(txn_item txn)
if(txn.addr inside out1 range)
compare(txn, out1_q.pop_front())
else
compare(txn, out1_q.pop_front())
endtask
endclass
Method2:
scoreboard use uvm_analysis_imp and implements write functions.
class router_scoreboard extends uvm_scoreboard
`uvm_component_utils(router_scoreboard)
`uvm_analysis_imp_decl(_in1)
`uvm_analysis_imp_decl(_in2)
`uvm_analysis_imp_decl(_out1)
`uvm_analysis_imp_decl(_out2)
uvm_analysis_imp#(router_scoreboard, ten_item) in1_export;
uvm_analysis_imp#(router_scoreboard, ten_item) in2_export;
uvm_analysis_imp#(router_scoreboard, ten_item) out1_export;
uvm_analysis_imp#(router_scoreboard, ten_item) out2_export;
txn_item exp_item_1[$];
txn_item exp_item_2[$];
// not showing new function or build phase
function write_in1(txn_item txn);
if(txn.addr inside range of out1) begin
exp_item_1.push_back(txn);
end
else begin
exp_item_2.push_back(txn);
end
endfunction
function write_in2(txn_item txn);
if(txn.addr inside range of out1) begin
exp_item_1.push_back(txn);
end
else begin
exp_item_2.push_back(txn);
end
endfunction
function write_out1(txn_item txn);
txn_item exp_txn;
exp_txn = ex_item_1.pop_front();
if(exp_txn.addr == txn.addr)
//address match
else
// address mismatch
if(exp_txn.data == txn.data)
// data match
else
// data mismatch
endfunction
function write_out2(txn_item txn);
txn_item exp_txn;
exp_txn = ex_item_2.pop_front();
if(exp_txn.addr == txn.addr)
//address match
else
// address mismatch
if(exp_txn.data == txn.data)
// data match
else
// data mismatch
endfunction
endclass
This scoreboard is assuming the order of output is same as order of input txn.