* Bare skeleton implementation of everything * Testbench builds with Verilator * Test runs
120 lines
4.5 KiB
Systemverilog
120 lines
4.5 KiB
Systemverilog
// ----------------------------------------------------------------------
|
|
// Driver for AXI transactions
|
|
// ----------------------------------------------------------------------
|
|
class axi_driver extends uvm_driver; // #(axi_transaction);
|
|
virtual `AXI_INTF.MANAGER m_if;
|
|
virtual `AXI_INTF.SUBORDINATE s_if;
|
|
agent_type_t agent_type;
|
|
|
|
`uvm_component_utils(axi_driver)
|
|
|
|
// --------------------------------------------------
|
|
// Constructor
|
|
function new(string name = "axi_driver", uvm_component parent = null);
|
|
super.new(name, parent);
|
|
endfunction
|
|
|
|
// --------------------------------------------------
|
|
// Set agent type
|
|
function void set_agent_type(agent_type_t atype);
|
|
agent_type = atype;
|
|
`uvm_info("set_agent_type", $sformatf("Agent type set to %s", agent_type.name()), UVM_LOW)
|
|
endfunction
|
|
|
|
// --------------------------------------------------
|
|
// Set virtual interfaces
|
|
function void set_virtual_intefaces(virtual `AXI_INTF.MANAGER m_if_p,
|
|
virtual `AXI_INTF.SUBORDINATE s_if_p);
|
|
`uvm_info("set_virtual_intefaces", $sformatf("Setting virtual interfaces"), UVM_LOW)
|
|
|
|
m_if = m_if_p;
|
|
s_if = s_if_p;
|
|
|
|
// if (m_if == null && s_if == null) begin
|
|
// `uvm_fatal("AXI_DRIVER", "Both MANAGER and SUBORDINATE interfaces are null")
|
|
// end else if ((agent_type == MANAGER) && (m_if == null)) begin
|
|
// `uvm_error("AXI_DRIVER", $sformatf("MANAGER interface is null"))
|
|
// end else if ((agent_type == SUBORDINATE) && (s_if == null)) begin
|
|
// `uvm_error("AXI_DRIVER", $sformatf("SUBORDINATE interface is null"))
|
|
// end
|
|
endfunction
|
|
|
|
// --------------------------------------------------
|
|
// Run phase
|
|
virtual task run_phase(uvm_phase phase);
|
|
`uvm_info("axi_driver", $sformatf("Running AXI driver: %s as %s",
|
|
get_full_name(), agent_type.name()), UVM_LOW)
|
|
|
|
if (agent_type == MANAGER) begin
|
|
`uvm_info("axi_driver", $sformatf("Manager agent detected, driving transactions"), UVM_LOW)
|
|
drive_transactions();
|
|
end else if (agent_type == SUBORDINATE) begin
|
|
`uvm_info("axi_driver", $sformatf("Subordinate agent detected, responding to transactions"), UVM_LOW)
|
|
respond_to_transactions();
|
|
end else begin
|
|
`uvm_fatal("AXI_DRIVER", "Unknown agent type")
|
|
end
|
|
endtask
|
|
|
|
// ------------------------------------------------------------
|
|
task drive_transactions();
|
|
if (m_if == null) begin
|
|
`uvm_error("AXI_DRIVER", "MANAGER interface is null, cannot drive transactions")
|
|
end
|
|
forever begin
|
|
`uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
|
|
get_full_name(), m_if.ARESETn), UVM_LOW)
|
|
|
|
if (m_if.ARESETn == 0) begin
|
|
`uvm_info("axi_driver", $sformatf("Waiting for reset to be released (rst_n = %0b)",
|
|
m_if.ARESETn), UVM_LOW)
|
|
@(posedge m_if.ARESETn);
|
|
end
|
|
|
|
`uvm_info("axi_driver", $sformatf("Starting to drive transactions for %s (rst_n = %0b)",
|
|
get_full_name(), m_if.ARESETn), UVM_LOW)
|
|
|
|
while (m_if.ARESETn != 0) begin
|
|
uvm_sequence_item txn;
|
|
|
|
`uvm_info("axi_driver", $sformatf("Waiting for next transaction"), UVM_LOW)
|
|
|
|
seq_item_port.get_next_item(txn);
|
|
drive_item(txn);
|
|
seq_item_port.item_done();
|
|
end
|
|
end
|
|
endtask
|
|
|
|
// ------------------------------------------------------------
|
|
task drive_item(uvm_sequence_item txn);
|
|
axi_transaction req;
|
|
|
|
if (!$cast(req, txn)) begin
|
|
`uvm_fatal("AXI_DRIVER", "Invalid transaction type")
|
|
end
|
|
|
|
`uvm_info("drive_item", $sformatf("Driving AXI transaction:\n%s", req.sprint()), UVM_LOW)
|
|
@(posedge m_if.ACLK);
|
|
m_if.AWVALID = 1;
|
|
m_if.AWADDR = req.addr;
|
|
@(posedge m_if.ACLK);
|
|
m_if.WDATA = req.data;
|
|
m_if.WSTRB = req.strb;
|
|
`uvm_info("drive_item", $sformatf("Driving AXI transaction done."), UVM_LOW)
|
|
endtask
|
|
|
|
// ------------------------------------------------------------
|
|
task respond_to_transactions();
|
|
forever begin
|
|
@(posedge s_if.ARESETn);
|
|
|
|
while (s_if.ARESETn != 0) begin
|
|
@(posedge s_if.ACLK);
|
|
|
|
@(negedge s_if.ACLK);
|
|
end
|
|
end
|
|
endtask
|
|
endclass : axi_driver
|