Interfaces for Vivado IP Flow - 2022.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-06-07
Version
2022.1 English
The Vivado IP flow supports a wide variety of I/O protocols and handshakes due to the requirement of supporting FPGA design for a wide variety of applications. This flow supports a traditional system design flow where multiple IP are integrated into a system. IP can be generated through Vitis HLS. In this IP flow there are two modes of control for execution of the system:
  • Software Control: The system is controlled through a software application running on an embedded Arm processor or external x86 processor, using drivers to access elements of the hardware design, and reading and writing registers in the hardware to control the execution of IP in the system.
  • Self Synchronous: In this mode the IP exposes signals which are used for starting and stopping the kernel. These signals are driven by other IP or other elements of the system design that handles the execution of the IP.

The Vivado IP flow supports memory, stream, and register interface paradigms where each paradigm supports different interface protocols to communicate with the external world, as shown in the following table. Note that while the Vitis kernel flow supports only the AXI4 interface adapters, this flow supports a number of different interface types.

Table 1. Interface Types
Paradigm Description Interface Types
Memory Data is accessed by the kernel through memory such as DDR, HBM, PLRAM/BRAM/URAMSupported Interface Protocol ap_memory, BRAM, AXI4 Memory Mapped (m_axi)
Stream Supported InterfaceData is streamed into the kernel from another streaming source, such as video processor or another kernel, and can also be streamed out of the kernel. ap_fifo, AXI4-Stream (axis)
Register Data is accessed by the kernel through register interfaces performed by register reads and writes. ap_none, ap_hs, ap_ack, ap_ovld, ap_vld, and AXI4-Lite adapter (s_axilite).

The default interfaces are defined by the C-argument type in the top-level function, and the default paradigm, as shown in the following table.

Table 2. Default Interfaces
C-Argument Type Supported Paradigms Default Paradigm Default Interface Protocol
Input Output Inout
Scalar variable (pass by value) Register Register ap_none N/A N/A
Array Memory, Stream Memory ap_memory ap_memory ap_memory
Pointer Memory, Stream, Register Register ap_none ap_vld ap_ovld
Reference Register Register ap_none ap_vld ap_vld
hls::stream Stream Stream ap_fifo ap_fifo N/A

The default execution mode for Vivado IP flow is sequential execution, which requires the HLS IP to complete one iteration before starting the next. This is specified by the ap_ctrl_hs block control protocol. The control protocol can be changed as specified in Block-Level Control Protocols.

The vadd function in the following code provides an example of interface synthesis in the Vivado IP flow.

#define VDATA_SIZE 16

typedef struct v_datatype { unsigned int data[VDATA_SIZE]; } v_dt;

extern "C" {
void vadd(const v_dt* in1, // Read-Only Vector 1
          const v_dt* in2, // Read-Only Vector 2
          v_dt* out_r, // Output Result for Addition
          const unsigned int size // Size in integer 
) {

   unsigned int vSize = ((size - 1) / VDATA_SIZE) + 1;

   // Auto-pipeline is going to apply pipeline to this loop
   vadd1:
   for (int i = 0; i < vSize; i++) {
      vadd2:
      for (int k = 0; k < VDATA_SIZE; k++) {
         out_r[i].data[k] = in1[i].data[k] + in2[i].data[k];
      }
   }
}
}

The vadd function includes:

  • Two pointer inputs: in1 and in2
  • A pointer: out_r that the results are written to
  • A scalar value size

With the default interface synthesis settings used for the Vivado IP flow, the design is synthesized into an RTL block with the ports and interfaces shown in the following figure.

Figure 1. RTL Ports After Default Interface Synthesis

In the default Vivado IP flow the tool creates three types of interface ports on the RTL design to handle the flow of both data and control.

  • Clock and Reset ports: ap_clk and ap_rst are added to the kernel.
  • Block-level control protocol: The ap_ctrl interface is implemented as an s_axilite interface.
  • Port-level interface protocols: These are created for each argument in the top-level function and the function return (if the function returns a value). As explained in the table above most of the arguments use a port protocol of ap_none, and so have no control signals. In the vadd example above these ports include: in1, in2, and size. However, the out_r_o output port uses the ap_vld protocol and so is associated with the out_r_o_ap_vld signal.

AP_Memory in the Vivado IP Flow

The ap_memory is the default interface for the memory paradigm described in the tables above. In the Vivado IP flow it is used for communicating with memory resources such as BRAM and URAM. The ap_memory protocol also follows the address and data phase. The protocol initially requests to read/write the resource and waits until it receives an acknowledgment of the resource availability. It then initiates the data transfer phase of read/write.

An important consideration for ap_memory is that it can only perform a single beat data transfer to a single address, which is different from m_axi which can do burst accesses. This makes the ap_memory a lightweight protocol, compared to the others.

  • Memory Resources: By default Vitis HLS implements a protocol to communicate with a single-port RAM resource. You can control the implementation of the protocol by specifying the storage_type as part of the INTERFACE pragma or directive. The storage_type lets you explicitly define which type of RAM is used, and which RAM ports are created (single-port or dual-port). If no storage_type is specified Vitis HLS uses:
    • A single-port RAM by default.
    • A dual-port RAM if it reduces the initiation interval or latency.

M_AXI Interfaces in the Vivado IP Flow

AXI4 memory-mapped (m_axi) interfaces allow an IP to read and write data in global memory (DDR, HBM, PLRAM), Memory-mapped interfaces are a convenient way of sharing data across multiple IP. The main advantages for m_axi interfaces are listed below:
  • The interface has independent read and write channels
  • It supports burst-based accesses
  • It provides a queue for outstanding transactions
Understanding Burst Access
AXI4 memory-mapped interfaces support high throughput bursts of up to 4K bytes with just a single address phase. 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 you use the C memcpy function or a pipelined for loop. Refer to Controlling AXI4 Burst Behavior or AXI Burst Transfers for more information.
Automatic Port Widening and Port Width Alignment
As discussed in Automatic Port Width Resizing, Vitis HLS has the ability to automatically widen a port width to facilitate data transfers and improve burst access when all the preconditions needed for bursting are present. In the Vivado IP flow the following configuration settings disable automatic port width resizing by default. To enable this feature you must change these configuration options (notice that one command is specified as bits and the other is specified as bytes):
config_interface -m_axi_max_widen_bitwidth 0
config_interface -m_axi_alignment_byte_size 0
Specifying Alignment for Vivado IP mode

The alignment for an m_axi port allows the port to read and write memory according to the specified alignment. Choosing the correct alignment is important as it will impact performance in the best case, and can impact functionality in the worst case.

Aligned memory access means that the pointer (or the start address of the data) is a multiple of a type-specific value called the alignment. The alignment is the natural address multiple where the type must be or should be stored (e.g. for performance reasons) on a Memory. For example, Intel 32-bit architecture stores words of 32 bits, each of 4 bytes in the memory. The data is aligned to one-word or 4-byte boundary.

The alignment should be consistent in the system. The alignment is determined when the IP is operating in AXI4 master mode and should be specified, like the Intel 32-bit architecture with 4-byte alignment. When the IP is operating in slave mode the alignment should match the alignment of the master.

Rules for Offset

The default for m_axi offset is offset=direct and default_slave_interface=s_axilite. However, in the Vivado IP flow you can change it as described in Offset and Modes of Operation.

Bundle Interfaces - Performance vs. Resource Utilization

By default, Vitis HLS groups function arguments with compatible options into a single m_axi interface adapter as described in M_AXI Bundles. Bundling ports into a single interface helps save device resources by eliminating AXI4 logic, which can be necessary when working in congested designs.

However, a single interface bundle can limit the performance of the IP because all the memory transfers have to go through a single interface. The m_axi interface has independent READ and WRITE channels, so a single interface can read and write simultaneously, though only at one location. Using multiple bundles lets you increase performance by creating multiple interfaces to connect to memory banks.

S_AXILITE in the Vivado IP Flow

In the Vivado IP flow, the default execution control is managed by register reads and writes through an s_axilite interface using the default ap_ctrl_hs control protocol. The IP is software controlled by reading and writing the control registers of an s_axilite interface as described in S_AXILITE Control Register Map.

The s_axilite interface provides the following features:

Control Protocols
The block control protocol as specified in Block-Level Control Protocols.
Scalar Arguments
Scalar arguments from the top-level function can be mapped to an s_axilite interface which creates a register for the value as described in S_AXILITE Control Register Map. The software can perform reads/writes to this register space.
Rules for Offset
The Vivado IP flow defines the size, or range of addresses assigned to a port based on the data type of the associated C-argument in the top-level function. However, the tool also lets you manually define the offset size as described in S_AXILITE Offset Option.
Rules for Bundle
In the Vivado IP flow you can specify multiple bundles using the s_axilite interface, and this will create a separate interface adapter for each bundle you have defined. However, there are some rules related to using multiple bundles that you should be familiar with as explained in S_AXILITE Bundle Rules.

AP_FIFO in the Vivado IP Flow

In the Vivado IP flow, the ap_fifo interface protocol is the default interface for the streaming paradigm on the interface for communication with a memory resource FIFO, and can also be used as a communication channel between different functions inside the IP. This protocol should only be used if the data is accessed sequentially, and Xilinx strongly recommends using the hls::stream<data type> which implements a FIFO.

Tip: The <data type> should not be the same as the T_data_type, which should only be used on the interface.

AXIS Interfaces in the Vivado IP Flow

The AXI4-Stream protocol (axis) is an alternative for streaming interfaces, and defines a single uni-directional channel for streaming data in a sequential manner. Unlike the m_axi protocol, the AXI4-Stream interfaces can burst an unlimited amount of data, which significantly improves performance. Unlike the AXI4 memory-mapped interface which needs an address to read/write the memory, the axis interface simply passes data to another axis interface without needing an address, and so uses fewer device resources. Combined, these features make the streaming interface a light-weight high performance interface as described in AXI4-Stream Interfaces.