Driver, Monitor, Agent
Driver: Sends stimulus. Monitor: Observes responses. Agent: Wraps both.
// Driver: generate transactions on interface
class axil_driver extends uvm_driver #(axil_transaction);
virtual axil_if vif;
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
// Drive signals: vif.awaddr = req.addr, etc.
@(posedge vif.clk);
seq_item_port.item_done();
end
endtask
endclass
// Monitor: observe interface, create transactions
class axil_monitor extends uvm_monitor;
virtual axil_if vif;
uvm_analysis_port #(axil_transaction) ap;
virtual task run_phase(uvm_phase phase);
forever begin
@(posedge vif.awvalid && vif.awready);
// Capture: tr.addr = vif.awaddr, etc.
ap.write(tr); // Send to subscribers (scoreboard)
end
endtask
endclass
// Agent: wrap driver + monitor + sequencer
class axil_agent extends uvm_agent;
axil_driver drv;
axil_monitor mon;
uvm_sequencer #(axil_transaction) seqr;
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
drv = axil_driver::type_id::create("drv", this);
mon = axil_monitor::type_id::create("mon", this);
seqr = uvm_sequencer #(axil_transaction)::type_id::create("seqr", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
drv.seq_item_port.connect(seqr.seq_item_export);
endfunction
endclassSequences & Testbenches
Sequences generate transaction streams:
class axil_write_sequence extends uvm_sequence #(axil_transaction);
task body();
repeat(10) begin
`uvm_create_on(req, m_sequencer)
req.randomize(); // Random transaction
`uvm_send(req)
end
endtask
endclassKey Takeaways
- ✅ Driver = stimulus generator
- ✅ Monitor = response observer
- ✅ Agent = reusable bundle
- ✅ Sequencer = sequence executor
Day 23: Sequences and testbenches.