S_AXILITE Example - 2022.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-06-07
Version
2022.1 English

The following example shows how Vitis HLS implements multiple arguments, including the function return, as an s_axilite interface. Because each pragma uses the same name for the bundle option, each of the ports is grouped into a single interface.

void example(char *a, char *b, char *c)
{
#pragma HLS INTERFACE mode=s_axilite port=return bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=a bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=b bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=c bundle=BUS_A
#pragma HLS INTERFACE mode=ap_vld port=b 

  *c += *a + *b;
}
Tip: If you do not specify the bundle option, Vitis HLS groups all arguments into a single s_axilite bundle and automatically names the port.
The synthesized example will be part of a system that has three important elements as shown in the figure below:
  1. Host application running on an x86 or embedded processor interacting with the IP or kernel
  2. SAXI Lite Adapter: The INTERFACE pragma implements an s_axilite adapter. The adapter has two primary functions: implementing the interface protocol to communicate with the host, and providing a Control Register Map to the IP or kernel.
  3. The HLS engine or function that implements the design logic
Figure 1. S_AXILITE Adapter

By default, Vitis HLS automatically assigns the address for each port that is grouped into an s_axilite interface. The size, or range of addresses assigned to a port is dependent on the argument data type and the port protocol used, as described below. You can also explicitly define the address using the offset option as discussed in S_AXILITE Offset Option.

  • Port a: By default, is implemented as ap_none. 1-word for the data signal is assigned and only 3 bits are used as the argument data type is char. Remaining bits are unused.
  • Port b: is implemented as ap_vld defined by the INTERFACE pragma in the example. The corresponding control register is of size 2 bytes (16-bits) and is divided into two sections as follows:
    • (0x1c) Control signal : 1-word for the control signal is assigned.
    • (0x18) Data signal: 1-word for the data signal is assigned and only 3 bits are used as the argument data type is char. Remaining bits are unused.
  • Port c: By default, is implemented as ap_ovld as an output. The corresponding control register is of size 4 bytes (32 bits) and is divided into three sections:
    • (0x20) Data signal of c_i: 1-word for the input data signal is assigned, and only 3 bits are used as the argument data type is char, the rest are not used.
    • (0x24) Reserved Space
    • (0x28) Data signal of c_o: 1-word for the output data signal is assigned.
    • (0x2c) Control signal of c_o : 1-word for control signal ap_ovld is assigned and only 3 bits are used as the argument data type is char. Remaining bits are unused.

In operation the host application will initially start the kernel by writing into the Control address space (0x00). The host/CPU completes the initial setup by writing into the other address spaces which are associated with the various function arguments as defined in the example.

The control signal for port b is asserted and only then can the kernel read ports a and b (port a is ap_none and does not have a control signal). Until that time the design is stalled and waiting for the valid register to be set for port b. Each time port b is read by the HLS engine the input valid register is cleared and the register resets to logic 0.

After the HLS engine finishes its computation, the output value on port C is stored in the control register and the corresponding valid bit is set for the host to read. After the host reads the data, the HLS engine will write the ap_done bit in the Control register (0x00) to mark the end of the IP computation.

Vitis HLS reports the assigned addresses in the S_AXILITE Control Register Map, and also provides them in C Driver Files to aid in your software development. Using the s_axilite interface, you can exploit the C driver files for use with code running on an embedded or x86 processor using provided C application program interface (API) functions, to let you control the hardware from your software.