How to compare the data between two uvm_tlm_analysis_fifo in scoreboard?

In reply to Subhra Bera:

Hi Subhra,

  virtual function void write();
       //if((!sb_wr_txn.csn_0)||(!sb_wr_txn.csn_1)) begin
	   fork
		   if(sb_wr_txn.wen_0)
			   ram_model[sb_wr_txn.addr_0]=sb_wr_txn.datain_0;
		   if(sb_wr_txn.wen_1)
			   ram_model[sb_wr_txn.addr_1]=sb_wr_txn.datain_1;
		join
		//end
	endfunction

I believe you want a join_any, not join. Your fork started 2 processes, and they both must complete before the fork will exit. The only transactions that will complete this fork MUST have wen_0 and wen_1 both logic high.

task run_phase(uvm_phase phase);
  forever begin
    wr_fifo.get(sb_wr_txn);
    write();
    rd_fifo.get(sb_rd_txn);
    compare();
  end			 
endtask

This component you described is a “dual port RAM model, with a scoreboard”. However, your run_phase looks like code for a dual-port fifo scoreboard. The writing of the RAM should be independent of the reading/comparing. i.e. They should not be in the same thread.

This might be a lot to digest if you are just beginning, but I recommend also using a single transaction type. address, data, either an enum {RAM_WRITE, RAM_READ) or a logic rd_nwr signal. I’d removed the “dual port” information out of the transaction, and use the 2 “imp” ports to represent the two ports of your RAM This will greatly shrink the size of your code, which is too complicated currently. I can help more if you are interested.

result will look something like:

  // Macros to create the uvm_analysis_imp ports (just an export + write function)
  `uvm_analysis_imp_decl(_port0) 
  `uvm_analysis_imp_decl(_port1)

   // The macros above created these ports
   uvm_analysis_imp_exp #(ram_txn,scoreboard) port0_imp;
   uvm_analysis_imp_act #(ram_txn,scoreboard) port1_imp;

  virtual function void write_port0(ram_txn t, 0);
    if (t.rd_nwr) check_ram(t);             // READ & VERIFY       
    else          ram_model[t.addr]=t.data; // WRITE
  endfunction

  virtual function void write_port1(ram_txn t, 1);
    if (t.rd_nwr) check_ram(t);             // READ & VERIFY       
    else          ram_model[t.addr]=t.data; // WRITE
  endfunction

  function void check_ram(ram_txn t, int port_num);
    if(ram_model[t.addr]==t.data) begin
      `uvm_info("compare", {"Test: OK!"}, UVM_HIGH);
    end else begin 
      `uvm_error(get_type_name(), $sformatf("miscompare on port %0d, addr=", port_num, t.addr))
      `uvm_info(get_type_name(), $sformatf("ACT data=0x%0h",t.data), UVM_MEDIUM)
      `uvm_info(get_type_name(), $sformatf("EXP data=0x%0h",ram_model[t.addr]), UVM_MEDIUM)
    end
  endfunction

That leaves your run_phase empty, so just delete it for now.

You can build on to this model, if your RAM has write access semaphores etc.

I’m assuming you don’t need an associative array for your RAM either… I’d just use a typically array if you know the size.
bit [31:0] RAM[512]; // e.g.