In reply to uvmsd:
Using 2 analysis ports (one for input, one for output), it will be no problem. But you need to create different port using `uvm_analysis_imp_decl macro, then you will have 2 different write method to handle input/output trans.
`uvm_analysis_imp_decl(_input)
`uvm_analysis_imp_decl(_output)
class scoreboard extended uvm_socreboard;
uvm_analysis_imp_input#(spi_seq_item , scoreboard) input_export_m;
uvm_analysis_imp_output#(spi_seq_item , scoreboard) output_export_m;
...
function void write_input(spi_seq_item trans);
// Collect input trans
endfunction : write_input
function void write_output(spi_seq_item trans);
// Collect output trans
endfunction : write_output
endclass
However, if you want to handle 1 transaction including input and output data. There will have the way, all you need to do is saving the transaction until you have enough information.
For example:
class monitor extends uvm_monitor;
spi_seq_item items[$];
virtual task run_phase(uvm_phase phase);
super.run_phase(phase);
fork
forever begin
@( spi_vif.spi_cb);
if ( spi_vif.reset == 1) begin
spi_seq_item seq_item_collected = new;
seq_item_collected.mosi_in = spi_vif.mosi_in;
items.push_back(seq_item_collected);
end // if reset
end //forever
forever begin
@( spi_vif.spi_cb);
if ( spi_vif.reset == 1) begin
@( spi_vif.spi_cb);
if(items.size() > 0) begin
spi_seq_item seq_item_collected = items.pop_front();
seq_item_collected.sr = (spi_vif.spi_cb.sr);
//TLM fifo
trans_collected_port.write(seq_item_collected);
end
else begin
`uvm_error("MON", "Unexpected output without input")
end
end // if reset
end //forever
join
endtask : run_phase
Idea: Save the transaction to a queue when you collect input, restore the transaction from the queue to collect output.