Jump to content

Controlling a sequence through an Agent's Slave ...

Recommended Posts

I am curious about the UVM recommended approach to controlling a sequence based on transactions received on an Agent's Slave monitor.

Let's say I have an Agent that can be either a Master or Slave (in this case a slave). In Slave mode; I have monitor that is watching a bus for a Master request. After detecting a request; the Slave monitor builds a response transaction and sends it out it's analysis port to a scoreboard or coverage collector. The problem is that I would like the transaction to go to a waiting sequence that would create the response transaction and send it to the Agent's driver.

I see several possible solutions:

1.) Create a sequence (like the interrupt sequence) that would be created inside the sequencer and would get triggered by an event.

2.) Modify the Agent's driver so that it could be configured as either a Master or Slave. When in slave mode; it could be instructed by the sequence to monitor the bus for a Master request and send this to the sequencer. The problem with this is that you want the monitor to be autonomous.

Any ideas would be greatly appreciated.

Link to comment
Share on other sites

3) Agent's driver can be configured as a Master or Slave, and in both cases operates autonomously with the interface pins without taking any direction from the monitor. Monitor remains independent and aloof.

Yes, that means you might have some duplicate code in monitor and {slave, or master} driver. Shared code in configuration objects referred to by both may help. But important that both remain autonomous.

Think of 'Slave Driver' as just another protocol, same as 'Master Driver'. Monitor should be common to both though.

A driver of the Slave end of a protocol could use configuration either at build time or dynamically by a sequence connection, to specify any knobs you have on the Slave end of your protocol (e.g. response delay or kind)

Link to comment
Share on other sites

Hi Don,

Your slave device should have it's own sequencer/driver pair. As Gordon mentioned, the slave generates its own protocol based on the data it sees on the interface bus. The slave sequencer should have a blocking peek port which connects to the monitor and your sequences can look at the transaction and generate an appropriate response. You can find an example in the UVM Reference flow in the contributions area of uvmworld - or you can look at the ubus example provided in the UVM release. THe example below is from the Reference Flow (the APB UVC).

for example:

Your monitor will independently collect transactions on the bus - it will have a separate port so the sequencer can look at the transaction when the address is valid:

class apb_monitor extends uvm_monitor;
 uvm_blocking_peek_imp#(apb_transfer, apb_monitor) addr_trans_export;
  task apb_monitor::run_phase(uvm_phase phase);
     forever begin
        // start collecting a transaction - when the address phase is complete
        -> trans_addr_grabbed;
  endtask : run_phase

  task apb_monitor::peek(output apb_transfer trans);
        trans = trans_collected;

// Now  your sequencer has a port so the sequences can access the data from the monitor
class apb_slave_sequencer extends uvm_sequencer #(apb_transfer);

 uvm_blocking_peek_port#(apb_transfer) addr_trans_port;

class simple_response_seq extends uvm_sequence #(apb_transfer);
 function new(...);
 `uvm_declare_p_sequencer(apb_slave_sequencer)    // allows your sequence to look at his parent sequencer
  apb_transfer util_transfer;
  virtual task body();
     forever begin
        p_sequencer.addr_trans_port.peek(util_transfer);  // waits until it sees a valid address on the bus
        if (utl_transfer.direction == APB_READ && p_sequencer.cfg.check_address_range(util_transfer.addr))
           `uvm_do_with(req, {req.direction == APB_READ;})

// connection between a bus monitor and the sequencer is done in the connect phase of the env:
function void apb_env::connect_phase(uvm_phase phase);
   if (slaves[i].is_active == UVM_ACTIVE)


Link to comment
Share on other sites

To serve your purpose, and more generally in order to get a sequence to react interactively with the pins wiggling, and feed back data onto the bus, the following approach can also be used :

1) the sequence keeps a handle on the sequence_item it issues to the driver => sequence and driver can exchange information through this object

2) the driver triggers some flag inside the sequence_item, by instance an event

3) in the meantime the sequence waits for this event to be triggered

4) when the sequence detects the event, it updates the relevant fields of the sequence_item

5) the driver can access the seq_item fields updated by the sequence, since both share the handle on the same seq_item

Hope this helps.


Link to comment
Share on other sites

Thanks all for the quick reply - It saved me a bunch of time.

I have many flavors of my driver and it can be both master or slave. I created a separate class for each the driver and slave and then pull from the factory the correct one. This is all done in the test case. I then created a blocking_peek_port in both the monitor and sequencer and connected the two. The sequence can now peek the monitor port. I ended up using the same sequencer for both the driver and monitor.

Thanks again, this was easy to code up.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...