Modelling delay through a mailbox

In my environment I have a transaction received in a particular clock domain which I put into a mailbox.
This transaction is popped from the mailbox on a different clock domain the transaction should then be processed before generating a response after a fixed delay.

So I have this task in one class it is forked in the run stage of this class:

      task get_lookup_request();
         forever begin
            @(negedge lkup_slave_if.slave.clk);
            if(lkup_slave_if.slave.ready === 1'b1 && lkup_slave_if.slave.valid === 1'b1) begin
               this.lkup_req_trans.key = this.lkup_slave_if.slave.key;
               $display("Time %t, Got Lookup Request %h", $realtime, lkup_req_trans.key);
               this.lkup_mbx.put(this.lkup_req_trans);
            end
         end
      endtask

The model receiving the transaction has the following task executed in a fork run stage:

    task arbitrate;
         forever begin
            fork
               wait(this.rx_lkup_mbx.num > 0 && this.cam_busy.try_get(1));
            join
            wait fork;
            // Arbitrate for access to the CAM
            if(this.rx_lkup_mbx.num > 0)
               lookup_driver();
         end
      endtask

So basically the transaction is read from the mailbox passed to some model and a response is provided.
In the model I tried to add a fixed delay on providing the response:

      task lookup_driver();
         int lkup_index;
         @(posedge cam_clk_vif.lkup_clk);
         #900ns;
         this.rx_lkup_mbx.get(lkup_trans);
         $display("Time %t, Lookup Key %h", $realtime, lkup_trans.key);
      endtask

When I include the delay I cannot see the transactions coming out of the mailbox as I expected. I guess it must be something to do with the fact that the delay is blocking?
I know there are probably better ways to do this in UVM but I’ve no experience in UVM.

In reply to eoghaino:

Your code is hard to follow and you need to explain what you mean by “cannot see the transactions coming out of the mailbox as I expected” What exactly are you expecting versus what is actually happening?

Also fork/join with one statement inside is exactly the same as having that one statement without the fork/join. Thewait fork does nothing either - there is no process to wait for at that point.

Also, why do you haveif(this.rx_lkup_mbx.num > 0)? There is no way to get to that point without it being true already.

In reply to dave_59:

Sorry the code is incomplete, the arbitrate task will eventually have multiple mailboxes so I will have some chain of if else branches. I Understand the point about the fork join.

To give more context on what’s going wrong basically say I put into this lkup_mbx 3 messages a, 8, 0. Without the fixed 900ns delay in my lookup_driver task I get the messages from the mailbox as I expected:

Time 60000, Got Lookup Request a
Time 65000, Lookup Key a
Time 80000, Got Lookup Request 8
Time 85000, Lookup Key 8
Time 100000, Got Lookup Request 0
Time 105000, Lookup Key 0

When I have this 900ns delay in my lookup driver I don’t see the second message:

Time 60000, Got Lookup Request a
Time 65000, Lookup Key a
Time 80000, Got Lookup Request 8
Time 100000, Got Lookup Request 0
Time 975000, Lookup Key 0
Time 1885000, Lookup Key 0

So it looks like I put message 8 into the mailbox ok but when I do the get I don’t see that message. I thought having the delay blocking would not be an issue since the arbitrate task will only call the lookup_driver when the cam_busy (semaphore) is released. Seems like some issue around this 900ns delay but I cant really understand what that is. I am coming more from a design background so apologies if this is a little bit muddled.

In reply to eoghaino:

Based on the different result posted by you, looks like the issue with get_lookup_request task.

mailbox store/carry/copy the handle of the object, not the entire data pointed by that handle.

Look like get_lookup_request modified the data of handle before it used by the lookup_driver.
so create new handle/object for every request.


      task get_lookup_request();
         forever begin
            @(negedge lkup_slave_if.slave.clk);
            if(lkup_slave_if.slave.ready === 1'b1 && lkup_slave_if.slave.valid === 1'b1) begin
               
               //create new object 
               lkup_req_trans = new();

               this.lkup_req_trans.key = this.lkup_slave_if.slave.key;
               $display("Time %t, Got Lookup Request %h", $realtime, lkup_req_trans.key);
               this.lkup_mbx.put(this.lkup_req_trans);
            end
         end
      endtask

In reply to Rahulkumar:

Thank you that resolved my issue.