Error: UVM scoreboard with multiple uvm_analysis_export

Hello All, this if my first post, please excuse any mistakes I might make as I try to explain what I am trying to do.

I am trying have multiple broadcasters (uvm_analysis_export) and receivers (uvm_analysis_imp) in one scoreboard. However it seems to generate compile error as seen below.

What I would like is to to compare my generated PKT_IN_DATA with the output of the black box GMII_OUT_DATA.
In addition compare my generated GMII_IN_DATA with the output of the black box PKT_OUT_DATA.
Therefore the data types(class definitions) of the pkt_in_transaction sequencer is of a different format than that of my gmii_rx_n_transaction sequencer. It is intended to be like that because they are both different data formats.

…±------------------------------+…
…PKT_OUT_DATA…|…|…GMII_IN_DATA
<------------------------------+…<------------------+
…|…BLACK BOX…|…
…PKT_IN_DATA…|…|…GMII_OUT_DATA
±----------------------------->…±----------------->
…±------------------------------+…

Here is a snip of how I define my scoreboard ports:

// --> Declaring ports
   // --> Broadcasts a value to all subscribers implementing a uvm_analysis_imp.
   uvm_analysis_export #(pkt_out_transaction) obj_pkt_out;
   uvm_analysis_export #(gmii_tx_n_transaction) gmii_obj_pkt_out;

   // --> Receives all transactions broadcasted by a uvm_analysis_port.
   uvm_analysis_imp #(pkt_in_transaction ,eth_mac_n_gmii_scoreboard)  obj_pkt_in;
   uvm_analysis_imp #(gmii_rx_n_transaction ,eth_mac_n_gmii_scoreboard)  gmii_obj_pkt_in;

   // --> analysis fifo is a uvm_tlm_fifo with an unbounded size and a write interface
   uvm_tlm_analysis_fifo #(pkt_in_transaction)  before_fifo;  
   uvm_tlm_analysis_fifo #(gmii_rx_n_transaction)  gmii_before_fifo;  
   uvm_tlm_analysis_fifo #(pkt_out_transaction) after_fifo;  
   uvm_tlm_analysis_fifo #(gmii_tx_n_transaction) gmii_after_fifo;  
   
   // -> The table printer prints output in a tabular format.
   uvm_table_printer tprinter;

   pkt_in_transaction     transaction_before;
   gmii_rx_n_transaction  gmii_transaction_before;
   pkt_out_transaction    transaction_after;
   gmii_tx_n_transaction  gmii_transaction_after;

Here is my error:

** Error: (vsim-7065) Illegal assignment to class work.tb_top_sv_unit::pkt_in_transaction from class work.tb_top_sv_unit::gmii_rx_n_transaction

Time: 0 ns Iteration: 0 Region: /uvm_pkg::uvm_analysis_imp #(tb_top_sv_unit::gmii_rx_n_transaction, tb_top_sv_unit::eth_mac_n_gmii_scoreboard) File: X:/CAD/tools/UVM/uvm-1.2/src/tlm1/uvm_analysis_port.svh Line: 114

** Error: (vsim-8754) Actual input arg. of type ‘class work.tb_top_sv_unit::gmii_rx_n_transaction’ for formal ‘pkt_in’ of ‘write’ is not compatible with the formal’s type ‘class work.tb_top_sv_unit::pkt_in_transaction’.

Time: 0 ns Iteration: 0 Region: /uvm_pkg::uvm_analysis_imp #(tb_top_sv_unit::gmii_rx_n_transaction, tb_top_sv_unit::eth_mac_n_gmii_scoreboard) File: X:/CAD/tools/UVM/uvm-1.2/src/tlm1/uvm_analysis_port.svh Line: 114

You are passing wrong type of packet to your write method as it clearly mentions formal and actual type of arguments doesn’t match. For ‘pkt_in_transaction’ you are passing ‘gmii_rx_n_transaction’. You need to check your monitor/collector class or driver class for before transaction. Ideally you should a dynamic type check ($cast) in your scoreboard when handling packets from different base types. Also why are you using analysis imp’s you could have used analysis export as the other two and used imp ports of the FIFO’s.

In reply to ShreemantVats :

Hello

I am fairly new at UVM and system verilog. Can you please elaborate with your recommendations by posting what my snip should be change to, when you say

“Ideally you should a dynamic type check ($cast) in your scoreboard when handling packets from different base types. Also why are you using analysis imp’s you could have used analysis export as the other two and used imp ports of the FIFO’s”

Thanks

The transaction class coming into the predictor is rarely the same type as the one being sent to the scoreboard. From your code it looks like the incoming transaction is type ‘pkt_in_transaction’ and what you are sending out is of type ‘gmii_rx_n_transaction’
You cannot assign a transaction of type A with a transaction to type B

Here is an example of a predictor write method which receives ALU_in_transactions and sends out ALU_out_transactions.

=====================================
// FUNCTION: write_ALU_in_agent_ae
// Transactions received through ALU_in_agent_ae initiate the execution of this function.
// This function performs prediction of DUT output values based on DUT input, configuration and state
virtual function void write_ALU_in_agent_ae(ALU_in_transaction #() t);

`uvm_info("PRED", "Transaction Received through ALU_in_agent_ae", UVM_MEDIUM)
`uvm_info("PRED", {"            Data: ",t.convert2string()}, UVM_FULL)

// Construct one of each output transaction type.
ALU_sb_ap_output_transaction = ALU_sb_ap_output_transaction_t::type_id::create("ALU_sb_ap_output_transaction");
  
  case (t.op)
    add_op: begin
               ALU_sb_ap_output_transaction.result = t.a + t.b;
               `uvm_info("PREDICT",{"ALU_OUT: ",ALU_sb_ap_output_transaction.convert2string()},UVM_MEDIUM);
               // Code for sending output transaction out through alu_sb_ap
               ALU_sb_ap.write(ALU_sb_ap_output_transaction);
            end
    and_op: begin
               ALU_sb_ap_output_transaction.result = t.a & t.b;
               `uvm_info("PREDICT",{"ALU_OUT: ",ALU_sb_ap_output_transaction.convert2string()},UVM_MEDIUM);
               // Code for sending output transaction out through alu_sb_ap
               ALU_sb_ap.write(ALU_sb_ap_output_transaction);
            end
    xor_op: begin
               ALU_sb_ap_output_transaction.result = t.a ^ t.b;
               `uvm_info("PREDICT",{"ALU_OUT: ",ALU_sb_ap_output_transaction.convert2string()},UVM_MEDIUM);
               // Code for sending output transaction out through alu_sb_ap
               ALU_sb_ap.write(ALU_sb_ap_output_transaction);
            end
    mul_op: begin
               ALU_sb_ap_output_transaction.result = t.a * t.b;
               `uvm_info("PREDICT",{"ALU_OUT: ",ALU_sb_ap_output_transaction.convert2string()},UVM_MEDIUM);
               // Code for sending output transaction out through alu_sb_ap
               ALU_sb_ap.write(ALU_sb_ap_output_transaction);
            end
  endcase // case (op_set)

endfunction

You can take a look at Predictors | Verification Academy for some other ideas.