UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Adam Taylor’s MicroZed Chronicles Part 145: Cracking Open HLS part 2

by Xilinx Employee on ‎08-29-2016 11:20 AM (12,532 Views)

 

By Adam Taylor

 

 

Having introduced the flow we use for Vivado HLS in my previous blog post, I now want to spend a little time looking at some of the more basic functions that we skipped over last week.

 

When we used SDSoC in the previous blog post about synthesis, we did not discuss the rules we must follow when writing the module to be synthesized by Vivado HLS. These rules are not surprising really because SDSoC uses the Vivado HLS engine. The rules are:

 

  • The function must be self-contained; that is it must contain the entire design to be implemented.
  • You cannot use system calls or dynamic memory allocations.
  • You must use fixed or bounded constructs
  • The function must be unambiguous in its use of the bounds.

 

With the ground rules set for creating the function, I now want to look at how we define the interface to our function in the final RTL module. Generally speaking, there are two interface types to consider:

 

 

  • Block-Level Interface – This is the default for a generic interface that provides clock and reset inputs along with start, ready, idle, and done handshaking signals.

 

  • Port-Level Interface – This interface implements a more complete I/O protocol on the data ports such as AXI, AXI streaming, or AXI Lite.

 

 

We can use the simple Block-Level interface if we want, without the need for a Port-Level interface. If this is the case, we will need to ensure that the data on the block’s inputs is stable for the I/O operation.

 

Looking at the example from last week, the synthesised results produced a very simple entity that implemented a Block-Level Interface. 

 

 

Image1.jpg

 

 

Block-Level Interface from the example in the MicroZed Chronicles, Part 144

 

 

There are three options we can apply when we use the Block-Level Interface. The first, AP_NONE, will generate no interfaces beyond the ones defined within the module. You can use this option for very simple modules. However, should you choose this option, you will not be able to use Co-Simulation to verify your design.

 

 

 

Image2.jpg

 

 

HLS results with AP_NONE set

 

 

The default option for the Block-Level interface is AP_CNTRL_HS, which provides the required clock, reset, and handshaking ports needed to create a handshake for the block, as discussed above. The final option, AP_CNTRL_CHAIN, is very similar in that it provides the same handshaking signals as AP_CNTRL_HS but adds the ability to chain HLS blocks together by adding a continue signal, which can be used to stall an upstream block if necessary.

 

Depending on the structure we create with our HLS module, there are a number of other options we can apply to the Block-Level interface such as “MEMORY” or “FIFO,” for example.

 

We can control these options using pragmas to define the block’s I/O architecture or we can use the directives window, which opens a dialog allowing us to select the I/O architecture that we want to use.

 

By highlighting the top-level function in the directives window, we can select the Block-Level interface or the AXI interface. We can also do this for the inputs by selecting the required standards.

 

 

Image3.jpg

 

 

Directives Window – Set to use AXI Lite

 

 

Image4.jpg

 

Directives Insertion Window for Input A

 

 

If we decide to use a pragma-based approach to define out interfaces, we can do so as shown below which creates AXI Streaming and AXI Lite interfaces.

 

 

 

Image7.jpg

 

Defining an Interface using pragmas

 

 

Setting our simple example from last week to provide an AXI Lite interface using the directives window, you can see the resultant interface below:

 

 

Image5.jpg

 

AXI Slave Interface for example from the MicroZed Chronicles, Part 144

 

 

Depending upon the type of AXI interface (indeed any interface) we wish to implement, we need to consider if we are passing the arguments to the function by either value or reference. Here’s a figure that summarizes the argument-passing options for different argument types:

 

 

Image6.jpg

 

Interface type and Function passing style for different interfaces

 

 

 

Having covered how we can control our resultant module interface, next time we will look at the libraries available to help us accelerate our HLS developments.

 

 

Code is available on Github as always.

 

If you want E book or hardback versions of previous MicroZed chronicle blogs, you can get them below.

 

 

 

  • First Year E Book here
  • First Year Hardback here.

 

 

 

MicroZed Chronicles hardcopy.jpg 

 

 

  • Second Year E Book here
  • Second Year Hardback here

 

 

 

MicroZed Chronicles Second Year.jpg 

 

 

 

All of Adam Taylor’s MicroZed Chronicles are cataloged here.

 

 

 

Labels
About the Author
  • Be sure to join the Xilinx LinkedIn group to get an update for every new Xcell Daily post! ******************** Steve Leibson is the Director of Strategic Marketing and Business Planning at Xilinx. He started as a system design engineer at HP in the early days of desktop computing, then switched to EDA at Cadnetix, and subsequently became a technical editor for EDN Magazine. He's served as Editor in Chief of EDN Magazine, Embedded Developers Journal, and Microprocessor Report. He has extensive experience in computing, microprocessors, microcontrollers, embedded systems design, design IP, EDA, and programmable logic.