December 17, 2021
Editor’s Note: This content is republished from the MicroZed Chronicles, with permission from the author.
High-Level Synthesis can provide us a significant advantage when we are working in the data plane (e.g., signal / image processing and algorithmic implementations). One of the most powerful and flexible elements of HLS implementations is in its interfacing. We can control this via pragmas and compiler directives and it enables us to use the same core / algorithm across several different implementations.
When we develop Vitis HLS solutions, we can generate IP blocks for either Vitis or Vivado. If we are intending to create a Vitis Kernel, the output will be a XO file. If we are compiling for Vivado, we will be creating an IP XACT description. The flow we are using with Vitis or Vivado determines the interfaces we will be able to use for that design.
Vitis HLS blocks have two classes of interfaces. These can be defined as follows:
1. Port-Level I/O Protocols – These define how the data is passed and communicated to the HLS block, including when data is valid and can be read or written.
2. Block-Level I/O Protocols – These define the operation, status, and synchronization of the HLS block.
One of the ways that interfacing is controlled in Vitis HLS is by the type of argument used. These will define the Port-Level I/O Protocols which can be used.
Argument |
Port Level I/O Type |
Scalar |
Register |
Array |
Memory / Stream |
Pointer to Array |
Memory / Stream |
Pointer to Scalar |
Register |
Reference |
Register |
HLS Stream |
Stream |
These arguments can be implemented in a range of different interface protocols. When we are targeting a Vitis kernel development, the interfaces must be AXI based. As a result, the port-level interfaces will be either AXI Lite, AXI MM, or AXIS.
Argument |
Port Level I/O Type |
Scalar |
AXI Lite |
Array |
AXI_M |
Pointer to Array |
AXI_M |
Pointer to Scalar |
AXI Lite |
Reference |
AXI Lite |
HLS Stream |
AXI Stream |
Targeting Vivado designs provides several more interface solutions along with AXI which can be used to interface with different logical structures within RTL or IP Integrator designs. These different interfaces include the following:
Argument |
Port Level I/O Type |
Scalar |
AXI Lite / ap_none |
Array |
AXI_M / ap_memory |
Pointer to Array |
AXI_M / ap_none /ap_vld / ap_ovld |
Pointer to Scalar |
AXI Lite / ap_none /ap_vld / ap_ovld |
Reference |
AXI Lite / ap_none /ap_vld / ap_ovld |
HLS Stream |
AXI Stream / ap_fifo |
Of course, when AXI interfaces are used, software drivers will be provided for software applications which use the processing systems of SoC or MicroBlaze solutions.
While we are all familiar with AXI interfaces, we might not be so familiar with the AP_x interfaces defined above. Let’s take a quick look at them.
So far, the interfaces we have examined are those which we can use to get data into and out of the module using the Port-Level IO Protocols.
We also need to be able to control the HLS block and ensure it can be started andstopped, and that status of the block is provided. These three interfaces are called Block-Level Control protocols:ap_ctrl_chan – Pipelined execution allows processing of data as soon as the kernel is ready.
The default for Vitis Kernels is ap_ctrl_chain versus the Vivado default of ap_ctrl_hs. These interfaces can be directly synthesized as ports on the HLS IP block. They can also be included in a AXI Lite control interface which is, of course, the default for the Vitis flow.
Now that we understand a little more about HLS IP and interfacing, we can optimize and ensure that we select the most appropriate interface for our next HLS development.