The AXI4 Master interface has a
read/write address channel that can be used to read/write specific addresses. By default the
m_axi
interface starts all read and write operations
from the address 0x00000000
. For example, given the
following code, the design reads data from addresses 0x00000000
to 0x000000C7
(50 32-bit words,
gives 200 bytes), which represents 50 address values. The design then writes data back to
the same addresses.
#include <stdio.h>
#include <string.h>
void example(int *a){
#pragma HLS INTERFACE mode=m_axi port=a depth=50
int i;
int buff[50];
//memcpy creates a burst access to memory
//multiple calls of memcpy cannot be pipelined and will be scheduled sequentially
//memcpy requires a local buffer to store the results of the memory transaction
memcpy(buff,(const int*)a,50*sizeof(int));
for(i=0; i < 50; i++){
buff[i] = buff[i] + 100;
}
memcpy((int *)a,buff,50*sizeof(int));
}
The tool provides the capability to let the base address be configured statically in the Vivado IP for instance, or dynamically by the application or another IP during runtime.
The m_axi
interface can be both a master
initiating transactions, and also a slave interface that receives the data and sends
acknowledgment. Depending on the mode specified with the offset
option of the INTERFACE pragma, an HLS IP can use multiple approaches to
set the base address.
config_interface -m_axi_offset
command provides a global setting
for the offset, that can be overridden for specific m_axi
interfaces using the INTERFACE pragma offset
option.-
Master Mode: When acting as a
master interface with different
offset
options, them_axi
interface start address can be either hard-coded or set at runtime.-
offset=off
: Sets the base address of them_axi
interface to 0x00000000 and it cannot be changed in the Vivado IP integrator. One disadvantage with this approach is that you cannot change the base address during runtime. See Customizing AXI4 Master Interfaces in IP Integrator for setting the base address.The following example is synthesized withoffset=off
, the default for the Vivado IP flow.void example(int *a){ #pragma HLS INTERFACE m_axi depth=50 port=a offset=off int i; int buff[50]; //memcpy creates a burst access to memory //multiple calls of memcpy cannot be pipelined and will be scheduled sequentially //memcpy requires a local buffer to store the results of the memory transaction memcpy(buff,(const int*)a,50*sizeof(int)); for(i=0; i < 50; i++){ buff[i] = buff[i] + 100; } memcpy((int *)a,buff,50*sizeof(int)); }
-
offset=direct
: Vitis HLS generates a port on the IP for setting the address. Note the addition of thea
port as shown in the figure below. This lets you update the address at runtime, so you can have onem_axi
interface reading and writing different locations. For example, an HLS module that reads data from an ADC into RAM, and an HLS module that processes that data. Because you can change the address on the module, while one HLS module is processing the initial dataset the other module can be reading more data into different address.void example(int *a){ #pragma HLS INTERFACE m_axi depth=50 port=a offset=direct ... }
Figure 1. offset=direct -
-
Slave Mode: The slave mode for an
interface is set with
offset=slave
. In this mode the IP will be controlled by the host application, or the micro-controller through thes_axilite
interface. This is the default for the Vitis kernel flow, and can also be used in the Vivado IP flow. Here is the flow of operation:- initially, the Host/CPU will start the IP or kernel using the
block-level control protocol which is mapped to the
s_axilite
adapter. - The host will send the scalars and address offsets for the
m_axi
interfaces through thes_axilite
adapter. - The
m_axi
adapter will read the start address from thes_axilite
adapter and store it in a queue. - The HLS design starts to read the data from the global memory.
- initially, the Host/CPU will start the IP or kernel using the
block-level control protocol which is mapped to the
As shown in the figure below, the HLS design will have both the s_axilite
adapter for the base address, and the m_axi
to perform read and write transfer to the global
memory.
Offset Rules
The following are rules associated with the offset
option:
- Fully Specified Offset: When the user explicitly sets the offset value
the tool uses the specified settings. The user can also set different offset values for
different
m_axi
interfaces in the design, and the tool will use the specified offsets.#pragma HLS INTERFACE s_axilite port=return #pragma HLS INTERFACE mode=m_axi bundle=BUS_A port=out offset=direct #pragma HLS INTERFACE mode=m_axi bundle=BUS_B port=in1 offset=slave #pragma HLS INTERFACE mode=m_axi bundle=BUS_C port=in2 offset=off
- No Offset Specified: If there are no offsets specified in the INTERFACE
pragma, the tool will defer to the setting specified by
config_interface -m_axi_offset
.Note: If the globalm_axi_offset
setting is specified, and the design has ans_axilite
interface, the global setting is ignored andoffset=slave
is assumed.void top(int *a) { #pragma HLS interface mode=m_axi port=a #pragma HLS interface mode=s_axilite port=a }