Reactive Agents (Slave Mode)

Not all agents drive requests. Some must wait, listen, and respond.

Architecture: Initiators vs. Responders

While most UVM Agents are Initiators (driving requests into the DUT), many systems require Reactive (Slave) Agents. These components wait for the DUT to initiate a transaction (like a memory read) and provide the appropriate response.

Feature Master (Initiator) Slave (Reactive)
Flow Control Agent starts transaction cycle. DUT starts transaction cycle.
Driver Logic Asks sequencer, then drives pins. Watches pins, then asks sequencer.
Sequence body() Finite loop (e.g., 10 packets). Forever loop (waiting for requests).

The Reactive Driver Pattern

In a Reactive Driver, the standard seq_item_port.get_next_item(req) call is delayed until the hardware interface indicates a request is pending.

Implementation: Slave Driver Flow

task run_phase(uvm_phase phase);
    forever begin
        // 1. Wait for physical request (e.g., Slave Select or Valid)
        @(posedge vif.req_valid);
        // 2. NOW ask the Sequencer: "The DUT is asking, what do I reply?"
        seq_item_port.get_next_item(req);
        // 3. Drive the response data from the sequence item
        vif.resp_data <= req.data;
        vif.resp_ready <= 1;
        @(posedge vif.clk);
        vif.resp_ready <= 0;
        // 4. Return control to sequence
        seq_item_port.item_done();
    end
endtask
                            

The Perpetual Sequence

A Reactive Sequence acts like a background service. It stays active for the duration of the test, yielding only when the Driver signals a hardware event.

Architecture: The Response Loop

task body();
    forever begin
        req = my_item::type_id::create("req");
        // This blocks until the Driver reaches the get_next_item() call
        start_item(req);
        // Randomize the response (e.g., success coding or error)
        if (!req.randomize() with { status == RESP_OK; }) 
            `uvm_error("SEQ", "Randomization failed")
        finish_item(req);
    end
endtask
                            

Design Tip: Response Information

For complex slaves (like an AXI Slave), the sequence needs to know which address the DUT requested. You can achieve this by having the Driver copy the request address into the req object before calling item_done(), or by using a separate rsp object with put_response().