0% found this document useful (0 votes)
34 views

Hackster - io-Hardware-as-Code Part II Hello FPGA

The document discusses setting up software to develop hardware designs using an FPGA board. It explains how to install PlatformIO, the Upduino HLS toolchain, and Radiant Programmer. An example project is created that implements a simple calculation function in hardware on the FPGA by compiling C/C++ code. The output is tested in simulation and by programming the FPGA board.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

Hackster - io-Hardware-as-Code Part II Hello FPGA

The document discusses setting up software to develop hardware designs using an FPGA board. It explains how to install PlatformIO, the Upduino HLS toolchain, and Radiant Programmer. An example project is created that implements a simple calculation function in hardware on the FPGA by compiling C/C++ code. The output is tested in simulation and by programming the FPGA board.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

Hardware-as-Code Part II: Hello FPGA

hackster.io/sthibault/hardware-as-code-part-ii-hello-fpga-1f898a

Scott Thibault

Things used in this project

Hardware components

× 1
UPduino

Software apps and online services

PlatformIO IDE

Story

1/7
Welcome back! In this installment, we’re going to get our development environment set
up and generate our first custom hardware design. If you found yourself here without
seeing Part I, head on over to Hardware-as-Code Part I and read the introduction to what
series is all about. If you haven't gotten the hardware yet, see the link in the Things
section.

Software installation
First, let’s install the required software. We need to install three packages:

PlatformIO – this is a common embedded-systems development platform that can


be used to develop for Arduino and many other boards.
Upduino HLS – this is a toolchain built for PlatformIO that compiles C/C++ down
to hardware.
Radiant Programmer – this is a tool from the FPGA vendor that is used to download
a compiled design into the chip on the board,

PlatformIO can be used from the command line or within the Visual Studio Code
environment. The following are instructions for both options.

Option 1: Visual Studio Code extension


Click on the Extensions icon to open the extensions folder
Enter platformio ide in the search box
Select and install the PlatformIO IDE extension

To install the Upduino HLS toolchain, we need to use the PlatformIO CLI. To open a CLI
window, click the PlatformIO icon (ant) on the left and then select PlatformIO Core CLI
under the Miscellaneous heading as shown below.

This will open a new terminal windows where you can enter pio commands. Install the
HLS toolchain by entering the following two commands:

Install the Windows C/C++ tools:

> pio platform install windows_x86

Install the Upduino HLS tools (this takes around 10 minutes):

> pio platform install upduino_hls

Option 2: Command-line installation


Requires python 3.6+

Download the install script from:


https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-
platformio.py

Enter the following commands from a Command Prompt:

2/7
Install PlatformIO:

> python get-platformio.py

Add PlatformIO to the PATH:

> set PATH=%USERPROFILE%\.platformio\penv\Scripts;%PATH%

Install the Windows C/C++ tools:

> pio platform install windows_x86

Install the Upduino HLS tools (this takes around 10 minutes):

> pio platform install upduino_hls

Radiant install
If you purchased the target hardware mentioned in part I
(https://tinyvision.ai/products/upduino-v3-0?variant=39608867618919), then you will
need to install the Radiant Programmer to download hardware designs into the board. If
you do not have the board, then you do not need this package and can skip ahead to the
project creation section.

The Radiant download page is: https://www.latticesemi.com/LatticeRadiant#windows

You do not need to download the complete Radiant package which is quite large. We just
need the programmer, so look for this download option towards the bottom of the
download page:

Project creation
With these tools in hand, let’s create a first project. If you want to save time, simply clone
the Hardware-as-Code Examples git repository (https://github.com/sathibault/hac-
examples.git) and open the hello-fpga folder.

If you don’t have git installed, or don’t want to clone the project, these are the detailed
steps to create your own project:

Create a new folder for the project


Create a platformio.ini file in the project folder with the following contents:

[env:fpga]
platform = upduino_hls

Create a src sub-folder in the project folder


Copy the source code from https://raw.githubusercontent.com/sathibault/hac-
examples/main/hello-fpga/src/hello.cc into a C++ source file in the src sub-
folder.
If you are using Visual Studio Code then go ahead and open the project using the
File -> Open folder… menu option.

3/7
NOTE: If you did not install the Radiant programmer because you don’t have the board,
you will need to edit the project’s platform.ini file to add the line: upload_command
= none . This will prevent the tool chain from complaining about not finding the
programmer software.

Hello FPGA
Let’s walk through the source code of this first example:

Line 3: Include the Core Fusion FPGA programming framework header. Often
times, programming a co-processor like an FPGA or GPU requires a lot of boilerplate
code. We've designed the Core Fusion framework to minimize the effort necessary to get
started, but still provide lower-level APIs for more advanced design.

Line 6-8: The example function that we want to implement as custom


hardware on the FPGA.

Line 12: Create an instance of the C++ type that represents the FPGA board.
This not only tells the compiler what board to compile for, but provides an interface to
communicate with the board.

Line 15: Turn the calc function into a custom FPGA function. The call to
fpga_func is what indicates to the compiler that we want to implement the calc
function in hardware. It also synthesizes and returns a wrapper function that will
communicate with the FPGA to call the hardware version whenever we invoke the
wrapper. The first two arguments tell it how to communicate with the FPGA, i.e. via the
board's serial input/output.

Line 18: Initialize the board. This must appear after the creation of any hardware
functionality; for now that means after the call to fpga_func .

Line 23: Call the FPGA function! When we call fun , the wrapper function returned
by fpga_func , it sends the input argument i to the FPGA function over the board's
serial input and then waits for the FPGA function to return the result over the board's
serial output.

Line 27: Do necessary cleanup. This terminates any connections to the board and
performs some other necessary internal housekeeping when we are done with the board.

Build and run the example (simulation)


You may now build this program by clicking the check mark icon (next to house icon) at
the bottom of the IDE, or if you are using the command line, enter the command: pio
run

So, what exactly did that do anyway? If you look at the output, it appears to have built an
executable named program.exe . That looks like software, not hardware! That’s because
the default build rule will build only the software version of your program. All the

4/7
“hardware-as-code” we write is also valid software and can be run on our computer. In
fact, that’s one of the major advantages of this approach, that we can easily verify the
functional behavior of our code without building any hardware at all!

Okay, let's run it. From the command prompt enter (if you’re using Visual Studio Code,
open a command prompt by clicking the PlatformIO icon (ant) on the left and then
selecting Platform Core CLI under Miscellaneous):

> .\program

This should output a bunch of numbers like:

calc(0) = -15
calc(1) = -8
calc(2) = -1
calc(3) = 6
calc(4) = 13

When run without any options, instead of using the FPGA, the software will simply call
the original calc function compiled for the CPU. In this way, we can quickly develop
and test our function before generating the hardware implementation.

Build and run the example (on FPGA)

Inspecting the output, you can see that the calc function seems to be doing what we'd
expect, so we can go ahead and implement this in hardware.

First, plug the board into a USB port on your computer. Generate the hardware
implementation and upload it to the FPGA by clicking the right-arrow icon (next to build
icon) at the bottom of the IDE, or if you are using the command line, enter the command:
pio run --target upload

NOTE: if you don't have the board, you can go through the build process without
uploading to a board with the command: pio run --target bitstream

This process will take a couple minutes and you will see a lot of output fly by, but when it
completes, you will have a hardware implementation of the calc function on the FPGA.

The board needs to be reset after programming, so unplug it from the USB port and
plug it back in to reset the USB interface.

After re-plugging the board into the USB port, you will need to open the device manager
to see what serial port it is using. See the example below:

Under Ports (COM & LPT), you will see a "USB Serial Port" with the name of the COM
port it is using next to it. This is the UPduino board (TIP: The COM port number will not
change if you always plug the board into the same USB port).

You may now run the program again, this time using the FPGA by providing the
appropriate COM port name as an argument (COM5 in my case):

5/7
> .\program --dev COM5
calc(0) = -15
calc(1) = -8
calc(2) = -1
calc(3) = 6
calc(4) = 13

You should get the same output as before, but this time it's from the FPGA!

What have we done?

We've just created our first special-purpose hardware implementation from a C function.
Since it's a standard C function, it is quick and easy to test/debug on the computer using
any standard software development tools. It's also super small and ultra efficient! This
post is already long, so we won't look into the details just yet, but the generated hardware
is basically want you'd expect: 1 multiplier connected to 1 adder.

Next steps
Although every function we implement in hardware is standard a C function, not any C
function can be translated to hardware. In the next few installments, we'll work through
the features that are available to us and how to use them effectively. We'll also get into
some details of performance: What are the strengths and weaknesses of the generated
hardware? How does it compare with the software/CPU approach?

Continue to Part III: Space vs Time

Connect
Please follow me to stay up-to-date as I release new installments. There is also a Discord
server (public chat platform) for any comments, questions, or discussion you might have
at https://discord.gg/3sA7FHayGH

Code

Hardware-as-Code Examples

sathibault / hac-examples

00
Hardware-as-Code Examples — Read More

Latest commit to the master branch on 3-5-2022

Download as zip

Credits

6/7
Scott Thibault
3 projects • 5 followers
Doctorate in programming languages + experience in FPGA, design automation,
embedded systems, and machine learning.
Contact

7/7

You might also like