# 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](https://www.amd.com/en/corporate/university-program/aup-boards/pynq-z2.html) | pynq-z2 | | AMD | [Zynq™ UltraScale+™ MPSoC ZCU104](https://www.amd.com/en/products/adaptive-socs-and-fpgas/evaluation-boards/zcu104.html) | zcu104 | | AMD | [Zynq™ UltraScale+™ MPSoC ZCU102](https://www.amd.com/en/products/adaptive-socs-and-fpgas/evaluation-boards/ek-u1-zcu102-g.html) | zcu102 | | Digilent | [Nexys-A7-100t](https://digilent.com/reference/programmable-logic/nexys-a7/start) | nexys-a7-100t | | Digilent | [Genesys2](https://digilent.com/reference/programmable-logic/genesys-2/start) | genesys2 | | RealDigital | [AUP-ZU3 (8GB)](https://www.amd.com/en/corporate/university-program/aup-boards/realdigital-aup-zu3.html) | 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](https://pynq.readthedocs.io/en/v2.5/overlay_design_methodology/board_settings.html) to download and install them. 2. Make sure you set up the Vivado environments by running ``` source /settings64.sh ``` > We recommend adding this command to your `.bashrc` 3. Install the Xilinx cable drivers. * Follow the [instructions for Linux](https://docs.amd.com/api/khub/documents/6EIhov6ruoilhq8zq7bXBA/content?Ft-Calling-App=ft%2Fturnkey-portal&Ft-Calling-App-Version=4.3.26#G4.262534) * Restart your PC ## 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= ``` where `` can be chosen among the supported boards from the above table. From now on we will refer to it as ``. 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_.bit` in the `build/openhwgroup.org_systems_core-v-mini-mcu_/-vivado`. Or simply type: ```sh make vivado-fpga-pgm FPGA_BOARD= ``` ### 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: ```sh 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, ```sh scp ./build/_/-vivado/.runs/impl_1/_wrapper.bit board@remote-host:/path/to/bitstream/ scp ./build/_/-vivado/.gen/sources_1/bd//hw_handoff/xilinx_ps_wizzard.hwh board@remote-host:/path/to/bitstream/_wrapper.hwh ``` Or simply type: ```sh make vivado-fpga-remote-pgm FPGA_BOARD= 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](https://github.com/x-heep/xheep-Xilinx-SoCs-interface). ## Running firmware on the FPGA To run SW, follow the [Debug](./../How_to/Debug.md) guide to load the binaries with the HS2 cable over JTAG, or follow the [ExecuteFromFlash](./../How_to/ExecuteFromFlash.md) 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](./../How_to/ExecuteFromFlash.md) 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](https://github.com/esl-epfl/x-heep-programmer-pmod). To interface with the jtag one can use [openocd](http://openocd.org/), to interface with the UART one can use [picocom](https://linux.die.net/man/8/picocom), and to interface with the SPI flash one can use iceprog (from the [icestorm](http://www.clifford.at/icestorm/) project) already shipped and built in X-HEEP main repo. Check the [Debug](./../How_to/Debug.md) and [ExecuteFromFlash](./../How_to/ExecuteFromFlash.md) 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](../Configuration/CPUConfiguration.md) to see how to enable those features using the `make mcu-gen` command. ```