AXI4 Master Interface - 2023.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
Release Date
2023.2 English

AXI4 memory-mapped (m_axi) interfaces allow kernels to read and write data in global memory (DDR, HBM, PLRAM). Memory-mapped interfaces are a convenient way of sharing data across different elements of the accelerated application, such as between the host and kernel, or between kernels on the accelerator card. Refer to Vitis-HLS-Introductory-Examples/Interface/Memory on GitHub for examples of some of these concepts.

The main advantages for m_axi interfaces are listed below:

  • The interface has a separate and independent read and write channels
  • It supports burst-based accesses with potential performance of ~17 GBps
  • It provides support for outstanding transactions
  • It can include cache to improve performance as indicated by the CACHE pragma or directive.

In the Vitis Kernel flow the m_axi interface is assigned by default to pointer and array arguments. In this flow it supports the following default features:

  • Pointer and array arguments are automatically mapped to the m_axi interface
  • The default mode of operation is offset=slave in the Vitis flow and should not be changed
  • All pointer and array arguments are mapped to a single interface bundle to conserve device resources, and ports share read and write access across the time it is active
  • The default alignment in the Vitis flow is set to 64 bytes
  • The maximum read/write burst length is set to 16 by default

While not used by default in the Vivado IP flow, when the m_axi interface is specified it has the following default features:

  • The default operation mode is offset=off but you can change it as described in Offset and Modes of Operation
  • Assigned pointer and array arguments are mapped to a single interface bundle to conserve device resources, and share the interface across the time it is active
  • The default alignment in Vivado IP flow is set to 1 byte
  • The maximum read/write burst length is set to 16 by default

In both the Vivado IP flow and Vitis kernel flow, global default values for the m_axi interface are defined by the commands as described in Interface Configuration. The INTERFACE pragma or directive can be used to modify default values as needed for specific interfaces. Some customization can help improve design performance as described in Optimizing AXI System Performance. You can also specify the CACHE pragma or directive as described in pragma HLS cache to improve performance of the m_axi interface.

You can use an AXI4 master interface on array or pointer/reference arguments, which Vitis HLS implements in one of the following modes:

  • Individual data transfers
  • Burst mode data transfers

With individual data transfers, Vitis HLS reads or writes a single element of data for each address. The following example shows a single read and single write operation. In this example, Vitis HLS generates an address on the AXI interface to read a single data value and an address to write a single data value. The interface transfers one data value per address.

void bus (int *d) {
 static int acc = 0;

 acc += *d;
 *d  = acc;

With burst mode transfers, Vitis HLS reads or writes data using a single base address followed by multiple sequential data samples, which makes this mode capable of higher data throughput. Burst mode of operation is possible when using a pipelined for loop. Refer to AXI Burst Transfers for more information.

Important: The use of memcpy is discouraged because it can not be inlined or pipelined. Its use can also be problematic because it changes the type of the argument into char, which can lead to errors if array_partition, array_reshape, or struct disaggregate is used. Instead you are recommended to write your own version of memcpy with explicit arrays and loops to provide better control.

When the prior example is synthesized, it results in the interfaces shown in the following figure.

Note: In this figure, the AXI4 interfaces are collapsed.
Figure 1. AXI4 Interface

When using a for loop to implement burst reads or writes, follow these requirements:

  • Pipeline the loop
  • Access addresses in increasing order
  • Do not place accesses inside a conditional statement
  • For nested loops, do not manually flatten loops (using LOOP_FLATTEN pragma or directive), because this inhibits the burst operation
Note: Only one read and one write is allowed in a for loop unless the ports are bundled in different AXI ports.