Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Currently we have used HLS on its own. In this practical we will actually implement the HLS component as part of an FPGA design. First we will learn how to do this, and then we will create some hardware to solve some problems.

First create a new HLS project with the toplevel.cpp and toplevel.h files from Practical 43a.

  • Synthesise it.

  • Every time we have changed our hardware, we need to tell HLS to export it to a hardware description language and to generate all the various metadata that Vivado wants.

    • Select Solution → Export RTL → Select "Vivado IP for System Generator" → Click OK

  • Now we need to tell Vivado where our new IP is

    • Back in Vivado, open your Block Design. Click Window -> IP Catalog to open the IP Catalog. Click Settings in the Flow Navigator on the left. Select IP, and then Repository. Press the Plus icon. From the file browser select your HLS project directory and click Select. Vivado will scan your HLS project and should pop up a box showing that an IP was added to your project. Click OK, and OK.

  • Back in your Block Design, click the Add IP button on the left of the diagram. The IP core will be called the Display Name you entered, or Toplevel if you forgot to enter one. Double click the IP to add it. 

  • To allow your IP core to access DDR memory you need to enable an AXI slave interface on the Zynq processing system. Double click the Zynq IP block, select "PS-PL Configuration", expand "HP Slave AXI Interface", and check S AXI HP0 interface. Click OK and you should see a new port appear on the Zynq block. 

  • You can now use Connection Automation to complete the connection. Run Connection Automation and check S_AXI_HP0. It should be suggesting to connect to the m_axi port on your IP core. 

  • Also in Connection Automation check s_axi_AXILiteS and s_axi_control. It should be suggesting to connect to M_AXI_GP0 on the processing system. Click OK.

...

Info

Connection Automation issues

If you have issues with the AXI buses generated using connection automation (i.e. if they differ from the structure above), try deleting all AXI Interconnect blocks and running it again. If in doubt, ask a demonstrator.

The general principle is that your Zynq block's M_AXI should be traceable to all S_AXIs on your IP cores, and the IP core's M_AXI should be traceable to the S_AXI_HP0 on the Zynq block.

Using the IP in Vitis

When HLS exported our IP it helpfully autogenerated us a software driver. However we need to tell Vitis where to find this driver.

...

As you can see, your component can be started with XToplevel_Start and XToplevel_IsDone tells you when it is complete. XToplevel_Set_ram tells the HLS component where our shared memory is located in main memory. This allows HLS to read and write as if RAM starts at 0, but it will actually be pointing at our shared memory. Don't forget to set the RAM offset or your HLS component will be writing over random bits of memory!

Info

AXI bus problems

If your software hangs when trying to write to registers in your HLS component, double-check that the AXI buses are connected correctly, take your Vitis back to basics. Reexport a new hardware platform, create a new Hello World on it, making sure you can see the output. Check the System has the driver for your IP core, then copy in your code to access the core.

Functions like XToplevel_Get_arg1 and XToplevel_Set_arg1 get and set the parameters of the toplevel function. Sometimes these getters and setters may have slightly different names based on how your core uses the arguments. For example, if you only read an input then HLS will generate functions like:

...

Info

The Collatz Conjecture

Take any positive integer n (where n is not 0).
If n is even, divide it by 2 to get n / 2. If n is odd, multiply it by 3 and add 1 to obtain 3n + 1.
Repeat the process indefinitely.
The conjecture is that no matter what number you start with, you will always eventually reach 1.

You will create an HLS component to test the first 1000 integers to verify that if you perform the above steps they all eventually converge to 1. You will output the number of steps that each number takes to get to 1 in a shared array.

...