Run on FPGA

This project offers X-HEEP implementations on Xilinx FPGAs.

Set-up

In this version, the X-HEEP architecture is implemented on the programmable logic (PL) side of the FPGA, and its input/output are connected to the available headers on the FPGA board.

The following FPGA boards are supported:

Vendor

Board

BOARD_NAME

TUL

Pynq-Z2

pynq-z2

AMD

Zynq™ UltraScale+™ MPSoC ZCU104

zcu104

AMD

Zynq™ UltraScale+™ MPSoC ZCU102

zcu102

Digilent

Nexys-A7-100t

nexys-a7-100t

Digilent

Genesys2

genesys2

RealDigital

AUP-ZU3 (8GB)

aup-zu3

  1. Make sure you have the FPGA board files installed in your Vivado.

For example, for the Pynq-Z2 board, use the documentation provided at the following link to download and install them.

  1. Make sure you set up the Vivado environments by running

    source <vivado-installation-path>/settings64.sh
    

    We recommend adding this command to your .bashrc

  2. Install the Xilinx cable drivers.

Building and programming the FPGA

To build and program the bitstream for your FPGA with vivado, make sure you have run mcu-gen and then run:

make vivado-fpga FPGA_BOARD=<BOARD_NAME>

where <BOARD_NAME> can be chosen among the supported boards from the above table. From now on we will refer to it as <BOARD_NAME>.

Adding the fusesoc flag use_bscane_xilinx enables the native Xilinx scanchain for the JTAG interface in the on chip debug module (Currently only supported for the pynq-z2 board):

make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_FLAGS=--flag=use_bscane_xilinx

To program the bitstream, open Vivado,

open --> Hardware Manager --> Open Target --> Autoconnect --> Program Device

and choose the file openhwgroup.org_systems_core-v-mini-mcu_<version>.bit in the build/openhwgroup.org_systems_core-v-mini-mcu_<version>/<BOARD_NAME>-vivado.

Or simply type:

make vivado-fpga-pgm FPGA_BOARD=<BOARD_NAME>

Build and program the FPGA using the Processing System

The Processing System (PS) enables remote access to the SoC over SSH. With the PYNQ utilities, you can connect to the board and program the FPGA by loading the bitstream from Python.

Setting the PS_ENABLE argument instantiates the PS in the design for the supported boards:

make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_PARAM="--PS_ENABLE"

Upload the bitstream to the remote board

To program the bitstream upload both the .bit and the .hwh file to the board,

scp ./build/<project_name>_<version>/<board_target>-vivado/<project_name>.runs/impl_1/<project_name>_wrapper.bit board@remote-host:/path/to/bitstream/
scp ./build/<project_name>_<version>/<board_target>-vivado/<project_name>.gen/sources_1/bd/<project_name>/hw_handoff/xilinx_ps_wizzard.hwh board@remote-host:/path/to/bitstream/<project_name>_wrapper.hwh

Or simply type:

make vivado-fpga-remote-pgm FPGA_BOARD=<BOARD_NAME> REMOTE=board@remote-host REMOTE_DIR=/path/to/bitstream

Warning

Important: The *.bit and *.hwh files must:

  1. Have the same base name (ex.bit & ex.hwh).

  2. Be in the same directory. This ensure the bitstream to be loaded correctly through the PYNQ drivers.

Program the FPGA on the remote board

SSH into the board, activate the PYNQ environment, and load the overlay:

$ ssh board@remote-host

$ sudo -i
# source /etc/profile.d/pynq-venv.sh

# python
>>> from pynq import Overlay
>>> ol = Overlay("/path/to/bitstream.bit")

Additionally, you can find utilities to program the bitstream on the FPGA and run programs from the Processing System in the following repository: xheep-Xilinx-SoCs-interface.

Running firmware on the FPGA

To run SW, follow the Debug guide to load the binaries with the HS2 cable over JTAG, or follow the ExecuteFromFlash guide if you have a FLASH attached to the FPGA.

Do not forget that the pynq-z2 board requires you to have the ethernet cable attached to the board while running.

For example, if you want to run your application using flash_exec, do as follow: compile your application, e.g. make app PROJECT=example_matfadd TARGET=pynq-z2 ARCH=rv32imfc LINKER=flash_exec and then follow the ExecuteFromFlash to program the flash and set the boot buttons on the FPGA correctly. To look at the output of your printf, run in another terminal: picocom -b 9600 -r -l --imap lfcrlf /dev/ttyUSB2 Please be sure to use the right ttyUSB number (you can discover it with dmesg --time-format iso | grep FTDI for example).

To get X-HEEP running on the FPGA, you need to program the FPGA with the bitstream generated by the make vivado-fpga command. After that, you can run the software application on it.

On Xilinx FPGAs, the JTAG, UART, and SPI interfaces of X-HEEP are exposed on PMODs. Once that you have identified the pinout of the PMODS you can connect to them your preferred JTAG connector, UART to USB converter, and SPI flash programmer.

To run the software application on the FPGA, you can use the HS2 cable to load the binaries over JTAG, or you can use the SPI flash programmer to program the flash and set the boot switches on the FPGA correctly.

Both the JTAG, UART and SPI interfaces are mapped to be compliant with the ESL iceprog compatible programmer.

To interface with the jtag one can use openocd, to interface with the UART one can use picocom, and to interface with the SPI flash one can use iceprog (from the icestorm project) already shipped and built in X-HEEP main repo.

Check the Debug and ExecuteFromFlash guides for more details.

FPGA Utilizations

X-HEEP is a continuously evolving design, therefore these numbers need to be updated from time to time.

As of today (29.01.2025), on a pynq-z2 FPGA, X-HEEP utilizes:

Small configuration

It contains few peripherals, 64kB of SRAM, the small bus, and the CV32E2 CPU with RV32IMC ISA extensions.

Generated as:

make mcu-gen MCU_CFG_PERIPHERALS=mcu_cfg_minimal.hjson
make vivado-fpga FPGA_BOARD=pynq-z2

Resource

Quantity

Utilization (%)

Slice LUTs

12.1K

22.7

Slice Registers

12.1K

11.3

RAM

16

11.4

DSP

1

0.5

Bigger configuration

It contains more peripherals, 64kB of SRAM, the wider bus, and the CV32E40P CPU with RV32IMFCXpulp ISA extensions.

Generated as:

make mcu-gen CPU=cv32e40p BUS=NtoM
make vivado-fpga FPGA_BOARD=pynq-z2 FUSESOC_PARAM="--COREV_PULP=1 --FPU=1"

Resource

Quantity

Utilization (%)

Slice LUTs

33.5K

62.9

Slice Registers

28.8K

27.1

RAM

16

11.4

DSP

9

4.1

Note

The FUSESOC_PARAM="--COREV_PULP=1 --FPU=1" is an old way to enable the CV32E40P CPU with FPU and PULP extensions. Now you can check the CPU Configuration docs to see how to enable those features using the make mcu-gen command.