UVM APB Agent
AMBA APB is a widely used bus protocol by the company ARM Holdings, typically used to access control registers in a design.
The APB is part of the AMBA 3 protocol family. It provides a low-cost interface that is optimized for minimal power consumption and reduced interface complexity. The APB interfaces to any peripherals that are low-bandwidth and do not require the high performance of a pipelined bus interface. The APB has unpipelined protocol.
All signal transitions are only related to the rising edge of the clock to enable the integration of APB peripherals easily into any design flow. Every transfer takes at least two cycles.
|PCLK||Clock. The rising edge of PCLK times all transfers on the APB.|
|PRESETn||Reset. The APB reset signal is active LOW. This signal is normally connected directly to the system bus reset signal.|
|PADDR||Address. This is the APB address bus. It can be up to 32 bits wide and is driven by the peripheral bus bridge unit.|
|PSELx||Select. The APB bridge unit generates this signal to each peripheral bus slave. It indicates that the slave device is selected and that a data transfer is required. There is a PSELx signal for each slave.|
|PENABLE||Enable. This signal indicates the second and subsequent cycles of an APB transfer.|
|PWRITE||Direction. This signal indicates an APB write access when HIGH and an APB read access when LOW.|
|PWDATA||Write data. This bus is driven by the peripheral bus bridge unit during write cycles when PWRITE is HIGH. This bus can be up to 32 bits wide|
|PREADY||Ready. The slave uses this signal to extend an APB transfer|
|PRDATA||Read Data. The selected slave drives this bus during read cycles when PWRITE is LOW. This bus can be up to 32-bits wide.|
|PSLVERR||This signal indicates a transfer failure. APB peripherals are not required to support the PSLVERR pin. This is true for both existing and new APB peripheral designs. Where a peripheral does not include this pin then the appropriate input to the APB bridge is tied LOW.|
The first phase is called setup phase where an APB master drives paddr, pwrite, penable, psel and pwdata regardless of whether slave is ready which is indicated by pready. Note that penable should always be driven low in the setup phase.
The second cycle is called access phase and is the time when write data is either captured by the slave or read data is provided by the slave. The slave can extend either phase by pulling pready low thereby indicating to the master that it is not ready to accept any transfer at the moment, and is called a wait state. The master should drive penable high in the access phase.
The complete APB specification can be downloaded here.
The interface is used to connect between design blocks that use APB protocol or connect with a testbench. Hence the interface should have all signals supported within APB protocol specification. The clocking block is primarily used by testbench to sample and drive signals relative to a clocking event, which in this case is the positive edge of pclk.
interface apb_if (input pclk); logic presetn; logic [31:0] paddr; logic psel; logic penable; logic pwrite; logic [31:0] pwdata; logic pready; logic [31:0] prdata; logic pslverr; clocking cb @ (posedge pclk); default input #1step output #1ns; input pready, prdata, pslverr; output paddr, psel, penable, pwrite, pwdata; endclocking endinterface
APB Sequence Item
APB signals can be grouped into either control or data signals. pwdata and prdata are data signals while rest of it decide how an APB master should initiate a transfer. Based on this protocol, there are only 4 signals that really need to be driven with random value which are paddr, pwrite and the two data signals. All other signals has to be driven with a fixed value based on protocol definition and hence do not need to be randomized as a transaction object.
This seqeunce item will be started on an APB sequencer, which ultimately gets driven onto the bus by an APB driver.
class apb_pkt extends uvm_sequence_item; function new(string name = "apb_pkt"); super.new(name); endfunction rand bit [15:0] m_addr; rand bit [31:0] m_wdata; bit [31:0] m_rdata; rand bit m_write; `uvm_object_utils_begin(apb_pkt) `uvm_field_int (m_addr, UVM_DEFAULT) `uvm_field_int (m_wdata, UVM_DEFAULT) `uvm_field_int (m_rdata, UVM_DEFAULT) `uvm_field_int (m_write, UVM_DEFAULT) `uvm_object_utils_end virtual function string convert2string(); return $sformatf("addr=0x%0h write=0x%0h wdata=0x%0h rdata=0x%0h", m_addr, m_write, m_wdata, m_rdata); endfunction endclass