Editor’s Note: This content is contributed by Ted Booth, Technical Lead FPGA Design & Support Engineer at DesignLinx Solutions, Inc.
Xilinx has standardized on the AXI4 bus for the vast majority of its IP. To easily connect and operate in that environment, your custom IP should also use the AXI4 bus interfaces. These interfaces often add to the time required to implement and test your custom logic. Xilinx provides an IP Wizard that can be used to generate AXI4 interfaces so that they can be incorporated into your code, but the generated code usually requires some amount of modification and, therefore, still requires testing to verify the operation of the interface.
Here at DesignLinx, we have found that we can accelerate our AXI4-based IP development by using Vivado® HLS to implement our custom logic. One of the major advantages we have found is that Vivado HLS can automatically generate the necessary AXI4 interfaces for an IP. Because it is generated code that does not require any modification, we can be confident that the AXI4 interfaces will operate according to the AXI4 specification. This alleviates the need to do extensive testing of the AXI4 interface.
Vivado HLS can generate any of the three AXI4 interface types:
Let’s examine each of the interface types and see what Vivado HLS has to offer.
The most basic AXI4 interface is AXI4-Stream. It is an efficient way to move data from one IP to another. In Vivado HLS, the basic AXI4-Stream implementation consists of three signals:
Implementing a basic AXI4-Stream interface is as easy as adding an INTERFACE directive to your code.
In addition to the three basic signals, the AXI4-Stream interface also has several optional signals that are referred to as “side-channels.” Vivado HLS provides two structures that allow the user to declare AXI4-Streams with side-channels. These structures are “ap_axis” for signed data and “ap_axiu” for unsigned data. These structures provide the following signals:
The user has full access to all of the signals except for the TVALID and TREADY signals, which are already handled by the AXI4-Stream interface logic.
Implementing an AXI4-Stream interface with side-channels is the same as before. Just add an INTERFACE directive to your code.
An AXI4-Lite interface can be very useful if you want to control your IP with a CPU such as a Zynq® programmable device or MicroBlaze™ processor. Vivado HLS make implementing an AXI4-Lite interface simple and easy. In addition to generating the AXI-Lite interface for you, Vivado HLS also generates C driver files that can be called from your C/C++ code. Implementing the AXI4-Lite interface is once again nothing more than adding a few INTERFACE directives to your code.
In the function declaration above, we define two inputs “a” and “b” as well as an output “sum.” All three have INTERFACE directives that include them in the AXI4-Lite interface for the IP. Additionally, there is an INTERFACE directive for the “return” port, which tells Vivado HLS to include the control of the IP in the AXI4-Lite interface.
The “bundle” option is used to group all the ports into the same AXI4-Lite interface. Also, note that the bundle name is used to create the name of the AXI4-Lite port on the IP.
By default, Vivado HLS automatically creates the address map for all of the ports in an AXI4-Lite interface. The user can explicitly specify an address for a port by using the “offset” option in the INTERFACE directive.
Inputs “a” and “b” both have “Set” and “Get” functions defined for them. The “sum” output has only a “Get” function. Additionally, the “sum” output has a “vld” register that specifies when the “sum” register contains valid data. The “Get_sum_V_vld” function will return a ‘1’ when “sum” contains valid data. It will return a ‘0’ otherwise.
AXI4 Master Interfaces
If your IP needs to be able to access memory buffers directly, then an AXI4 Master interface is the preferred option in Vivado HLS. Two modes of data access are supported:
Single data transfers
Burst mode data transfers
Single data transfers are the simplest to implement but are very inefficient and are typically not recommended. Burst mode data transfers read in a number of data samples that are contiguous in memory. Burst transfers are much more efficient for transferring data and are the recommended method for using an AXI4 Master interface.
The figure below shows the AXI Master being declared as part of the INTERFACE directive for the “a” port as well as an INTERFACE directive for the return port.
The INTERFACE directive for the “a” port declares the AXI4 Master port. It includes a couple of options as well. The “depth=128” is used to tell Vivado HLS the maximum size of a data burst for that port. The “bundle=a” option specifies the grouping for the AXI4 Master port. This is most useful when multiple ports are grouped into a single AXI4 Master interface. The “offset=slave” option tells Vivado HLS to add a register called “a” to the AXI4-Lite interface. This register is used to specify the offset address in memory of the buffer that “a” is to access. As with the previous AXI4-Lite interface, Vivado HLS has to generate C driver code for us to use in our C/C++ software.
Vivado HLS makes it very easy to implement any of the AXI4 interfaces in your custom IP. Of course, this post is only an overview of what Vivado HLS can produce. For more details, go to the “Vivado Design Suite User Guide – High-Level Synthesis” (UG902).
If you are just getting started using Vivado HLS and are looking for design support, DesignLinx would be more than happy to discuss your needs. As a Xilinx Premier Partner, DesignLinx offers in-depth experience with Vivado Design Suite, Vivado HLS, and Vitis™ unified software platform.