How time advances in uvm scoreboard

Hi,
My apologies for possibly a very silly question for most people. In a uvm scoreboard in the run phase, if we have below code,


task run_phase (uvm_phase phase);
 forever begin
  after_fifo.get (after_txn);  // this is an uvm tlm analysis fifo which is getting the output txn from dut via monitor)
  if (before_queue.size())     // before_queue is populated by a uvm_tlm_analysis_imp port's write methode when it receives packet from input monitor
    compare_data();
 end
endtask

My understanding is that in this case, if the before_queue is empty when after_fifo gets a txn, no comparison can happen until after_fifo gets another transaction and checks the size of before_queue. This would be a wrong implementation since last txn wll not get compared if after_fifo gets the last txn before before_queue correct? forever begin in run phase wouldn’t change this right?

In reply to svq:

Yes, in last transaction after_txn come first and before_queue has not entry compare_data won’t execute and forever loop again block at after_fifo.get().

Btw, you can add wait after fifo like below.


task run_phase (uvm_phase phase);
 forever begin
  after_fifo.get (after_txn);  // this is an uvm tlm analysis fifo which is getting the output txn from dut via monitor)
  
  // We are make sure before_queue transaction is available before compare.
  wait (before_queue.size > 0);

  // before_queue is populated by a uvm_tlm_analysis_imp port's write methode when it receives packet from input monitor
  //if (before_queue.size())
  compare_data();
 end
endtask

And 1 more thing, if before_queue is used for expected data and after_fifo used for actual data.
Then, I think you need to check your TB because expected data must arrive before actual data.
If it not the case, you can simply wait for before_queue has entry ( like above code ).

Thanks!

In reply to svq:

Hi,
My apologies for possibly a very silly question for most people. In a uvm scoreboard in the run phase, if we have below code,


task run_phase (uvm_phase phase);
forever begin
after_fifo.get (after_txn);  // this is an uvm tlm analysis fifo which is getting the output txn from dut via monitor)
if (before_queue.size())     // before_queue is populated by a uvm_tlm_analysis_imp port's write methode when it receives packet from input monitor
compare_data();
end
endtask

My understanding is that in this case, if the before_queue is empty when after_fifo gets a txn, no comparison can happen until after_fifo gets another transaction and checks the size of before_queue. This would be a wrong implementation since last txn wll not get compared if after_fifo gets the last txn before before_queue correct? forever begin in run phase wouldn’t change this right?

I do not understand why you are mixing tlm_analysis_fifo and a queue.
You should use for both data streams tlm_analysis_fifo.
Then you can execute on both fifos a get. The get is a blocking statment and you do not have to check any fifo size.
After getting both transactions in the scoreboard you can compare the values and the scoreboard is progressing to the next pair of transactions.

In reply to harsh pandya:

Thank you for explaining this concept. I am trying to write a scoreboard for a design which gets transactions of 2 types in out of order (but not interleaved - different types of packets cannot mix. Example: A3A0A2A1 B0B2B1B3) on the input side, while transactions goes out in order on the output side (AOA1A2A3 B0B1B2B3). so design does reordering of transactions and sends all transactions of type A followed by all transactions of type B. Below is my approach to solve this,

//On input side (write method from input monitor):

  1. Push all transactions of type A into a temp queue, until type B starts showing up. (Planning to use cast for this check)
  2. Sort this queue inorder based on id (or however design does it) and push content of entire queue to another queue (before_queue) or uvm_tlm_fifo.
  3. Start storing type B packet into temp queue

On output side:

  1. Transactions are stored in uvm_tlm_analysis_fifo (after_fifo)
  2. Compare after_fifo and before_fifo/before_queue with a wait like you mentioned in the run phase of scoreboard with forever begin end

Does this approach have any issues or is there a better way to approach this problem?

Thanks

In reply to chr_sue:

Thank you chr_sue for the comment. I understand it better now. I got confused since there is a chance that my expected data structure may get transactions earlier than output side. Also do you know of any resource or paper which discusses scoreboard implementation other than uvm oook book? I have gone through the example in cookbook.

In reply to svq:

On the Transaction Level there is no timing. Important is the order of your transactions. It does not matter which transaction comes first, because you are compairing after the last get was successful.

In reply to svq:

The current method will work.
But, I think if you change your approach little it will more efficient and won’t require wait logic.

  1. your input is out of order and via temp_store and shorting you making as like DUT order and store into before queue.

But, i think as you already shorted in like output order you need to store in “analysis fifo” instead of queue as Christopher mentioned.


  //Somewhere else as per your TB.
  1) Out of order A0,A3,A2,A1 // original
  2) Short transaction and store inside fifo. // befor_fifo = A0,A1,A2,A3
  3) Dut is already providing in order.       // after_fifo = A0,A1,A2,A3
  task run_phase (uvm_phase phase);
    forever begin
      if( after_fifo.used() && before_fifo.used() ) begin
       before_fifo.get (before_txn); // before data packet
       after_fifo.get (after_txn);   // after data packet
       if ( ! after_txn.compare(before_txn) ) `uvm_error ("SCB_CHECK","TX_MISMATCH");

       // If compare data used for comparison between before and after txn. Then it won't require in this case
      // compare_data();
      end
      #1ns; // to advance time in case of fifo empty
    end
endtask
  // In run phase
  

Thanks!

In reply to harsh pandya:

Thanks Harsh for looking into the approach. Yes, I will use a fifo instead of queue to store expected packets. And it can be a uvm_tlm_fifo correct? Do we need analysis_fifo? Last question, Can you please explain why we need #1ns in the end in little more detail? I see your comment to advance time, but I dont understand it. If fifo is empty, then code will be blocked on the .get() right?

In reply to svq:

yes, uvm_tlm_fifo or uvm_tlm_analysis_fifo.
but, uvm_tlm_analysis_fifo should be more accurate as it has built in analysis_export. Will help to connect directly with monitor.
And I put #1 because, I wanted to perform .get (retrieve transection) only we have entery in fifo.
But,you are right as get is blocking method.
We won’t require if guard and #1 logic. ( Sorry for confusion )

Thanks!