Walkthrough4: High Level Synthesis Example

[edit this page]

This page already assumes that you are familiar with building and uploading firmware to an FPGA. Instructions for creating your own repository for EMP payloads and modifying it is also advisable:

High Level Synthesis

High Level Synthesis (HLS) is a method of generating firmware (RTL - register transfer level) starting from a higher level (c, c++).

Here we will describe creating a simple algorithm (“plus 7”) in c++ using vivado_hls and then including that IP-core within your emp-payload.

Prerequisistes

Make sure you have installed the pre-requisites (Prerequisites) and are familiar with the first two walkthroughs linked above. In addition you should have the vivado_hls component installed (this is an extension of standard vivado, initiated with vivado_hls from the command-line) and be familiar with the vivado GUI. IPBB (more info) will be used to create the project and lastly the address table, however, vivado and vivado_hls will be used interactively to compile the HLS core, instantiate it, and then synthesize and generate the bitfile.

Create the HLS IP Core

Step 1: Open the Project

  1. open vivado HLS:

    vivado_hls
    
  2. create new project in the file menu (or quick start icon) and choose a suitable name (e.g. walkthrough_plus7)

  3. add files X.cc and X.h files to the project if they already exist, otherwise click new file for both .cc and .h with suitable names (e.g. func.cc and func.h). NB: The .cc file extension is important for c++ even though the dialogue states “C-based source files”

  4. click next through the add/remove C-based testbench files (design test) options

  5. In the Create Vivado HLS solution for selected technology choose a name (e.g. solution1) and then add the correct part for the FGPA - in the case of the KU15P this should be the kintexuplus family and then xcku15p-ffva1760-2-e (slightly different abbreviated names than in standard vivado). After choosing the right FPGA part click Finish.

Step 2: Create the HLS algorithm code:

  1. Open the Source tab in the explorer (left panel) and double-click on your empty func.cc (or appropriate name chosen in 3 above).

  2. Create the content of your func.cc (note that .cc is important to pick up c++ compiler and not the default c one):

    /* HLS code: */
    
    #include "func.h"
    
    ap_int<64> myfunc(const ap_int<64> a) {
    
    ap_int<64> sum = 0;
    
    sum = a+7;
    
    return sum;
    
    }
    

    Here we are creating a simple arithmetic operation of adding 7.

  3. Save the file - either choose save in the menu or ctrl-s.

  4. Similarly create content in your header file by double-clicking on the func.h (must be the same name as in the c++ include statement above):

    /* HLS .h */
    
    #ifndef my_func_h
    
    #define my_func_h
    
    #include <ap_int.h>
    
    #define NDATA 12
    
    
    ap_int<64> myfunc(const ap_int<64> a) ;
    
    
    #endif
    
  5. Again save the file - either save in the menu or ctrl-s.

  6. Set your function as the top one in the project:

    Project
    └── project settings
        └── synthesis
            └── browse for top function
                └── myfunc(func.cc)
    

    myfunc(func.cc) should be picked up as a target or whatever you chose as the function and file name.

  7. run c-synthesis: either green right arrow icon or:

    menu
    └── solution
        └── run c-synthesis
            └── active solution
    
  8. export RTL as IP: either press two buttons to the right of the green arrow icon or:

    menu
    └── solution
        └── export RTL
    
  9. you now should have a zip file with the IP located in solution1/impl/ip. This can then be imported in your EMP vivado project in the following steps.

Step 2: Create the HLS algorithm framework:

Now create your own algo repo as in Walkthrough1: creating your own repository from scratch (and the Prerequisites).

If you look in the payload src directory you should find the emp_payload:

cd src/my-algo-repo/an-algo/firmware/hdl/
ls -la

The emp_payload.vhd is a special filename where you should create your algorithm to be included in the EMP project. Currently our emp_payload is a null algorithm which copies the input buffers to the outputs. Here we would like to modify the VHDL so that we can include our HLS as a component such that the buffers are passed through the previously created IP-core. First you should copy your emp_payload.vhd to a back-up filename (easier for debugging):

cp emp_payload.vhd emp_payload_nullalgo.vhd

Then you should edit emp_payload.vhd so that you have the myfunc component and the buffers are passed through it. This can be an exercise or if you want to directly jump to the solution it can be downloaded - solution along with the equivalent null algorithm.

Copying emp_payload_hls.vhd to emp_payload.vhd will instantiate the HLS component.

Create the full vivado project with ipbb:

cd proj/my_hls_algo
ipbb vivado generate-project

Here my_hls_algo is your choice of algo name which you then create above. Pay attention to any warning message which IPBB outputs and correct accordingly.

Step 3: Open the EMP Project in Vivado GUI and include the HLS IP-core:

  1. Open your project in vivado:

    vivado sm1_hls_algo/sm1_hls_algo.xpr
    
  2. Add your HLS IP directory/repoistory to the vivado project:

    tools
    └── settings
        └── IP (click expand tab/arrow)
            └── Repository
                └── "plus" sign and then choose the directory that contains the zip file you created with vivado_hls (above).
    
  3. Open IP Catalog: double click icon on left panel of GUI

  4. You should now see your User IP catalog (expand tab/arrow) and with your myfunc IP core (expand tab/arrow). Double click it to load it into your to the project:

    User Repository
    └── VIVADO HLS IP
         └── Myfunc (double click here)
    
  5. Synthesize the IP core within your project (i.e. click OK then Generate)

  6. Now (finally) create the bitfile which contains your HLS algo

Create the address Table:

  1. Create address table:

    ipbb vivado addrtab -d my_hls_addrtab
    
  2. Download hls_connections.xml and edit it correctly according to create address table

Now you can probe the buffers and verify if your algorithm does indeed add 7 to the input buffers on the baseboard (as described in Walkthrough2: First payload modifications and buffer manipulation - “Plus5”):

empbutler -c my_connections.xml do x1 reset

Now we inject empty data to the buffers using empbutler and capture the output:

empbutler -c my_connections.xml do x1 buffers rx PlayOnce --inject generate://empty
empbutler -c my_connections.xml do x1 buffers tx Capture
empbutler -c my_connections.xml do x1 capture

Now you can check if you have indeed been successful in your algorithm implementation, firmware build, buffer injection and capture:

geany data/rx_summary.txt

Note that tx corresponds to the outputs (post algo) and rx to the inputs since the reference is to the FPGA.