FPGAs are programmed using a bitstream file, which is itself produced following the implementation and placing/routing of the modules. FPGA programming toolchains are closed-source, vendor-specific and not well considered by the community. AMD (formerly Xilinx) FPGAs relies on Vivado Design Suite, which is known for its large space requirements (~200 GiB).
For the sake of simplicity, we will use a compressed image of Vivado ML Suite 2024.1 (~30 GiB only!), provided on-site on USB keys.
To mount it, copy the image to /opt/Xilinx_Vivado_ML_Suite_2024.1.sqsh
and execute the following command:
mkdir -p /opt/Xilinx
mount /opt/Xilinx_Vivado_ML_Suite_2024.1.sqsh /opt/Xilinx
Then, execute in a terminal /opt/Xilinx/Vivado/2024.1/bin/vivado
to launch the GUI interface.
FPGAs are programmed using HDL: Hardware Description Languages. The most popular are VHDL and Verilog. The Core-V CVA6 processor is a 6-stage, single-issue, in-order CPU which implements the 64-bit RISC-V instruction set. It is open-source (Apache license), written in SystemVerilog and currently maintained by Thales.
The source code for the PYNQ-Z2 board design is located in the git repo https://github.com/NicolasDerumigny/cva6.git, branch pynqz2_compas_bare
using the following command:
git clone --recurse-submodule --depth 1 -b pynqz2_compas_bare https://github.com/NicolasDerumigny/cva6.git
To generate the Vivado PYNQ CVA6 project, launch
source set-env.sh
make
This will automatically create a project in ./corev_apu/fpga/ariane.xpr
. Open it to start customizing the SoC!
When the project is opened in GUI mode, click on “Generate Bitstream” to start synthesis. Once the bitstream generation is finished, use “File -> Export -> Export Bitstream File” to export the bitstream in .bit
format.
While the bitstream (.bit
) generated by Vivado contains all the information needed to configure the FPGA, it is not in the right format to be used as-it by the board management interface, where a .bin
file is expected.
Therefore, a .bit
to .bin
converter script is needed. Save it as create_bitstream.sh
and place it in your $PATH
.
#!/usr/bin/bash
set -e
XILINX=/opt/Xilinx
XILINX_VERSION=2024.1
BOOTGEN=${XILINX}/Vivado/${XILINX_VERSION}/bin/bootgen
NAME=`basename $1`
OLDPWD=$PWD
if [ "$1" == "" ]; then
echo "Usage: $0 <bitstream.bit>"
exit
fi
cp $1 /tmp/bitstream.bit
cd /tmp
# This just parse the header to detect the part version
XILINX_VERSION_HEX=`echo -n $XILINX_VERSION |
xxd -p |
sed "s/\(..\)/\1 /g"`
PART=`xxd -p -l 300 /tmp/bitstream.bit |
tr -d "\n" |
sed "s/\(..\)/\1 /g" |
sed "s/.* ${XILINX_VERSION_HEX}00 62 00 .. //g" |
sed "s/00 .*//g" |
xxd -r -p`
echo "Detected part ${PART}"
if [ "$PART" == "xczu7ev-ffvc1156-2-e" ]; then
ARCH=zynqmp
cat > /tmp/bitstream.bif <<EOF
all: {
[destination_device=pl] bitstream.bit
}
EOF
else
ARCH=zynq
cat > /tmp/bitstream.bif <<EOF
all: {
bitstream.bit
}
EOF
fi
$BOOTGEN -arch $ARCH -image bitstream.bif -w -process_bitstream bin
rm bitstream.bit bitstream.bif
mv bitstream.bit.bin ${OLDPWD}/${NAME}.bin
To generate a bitstream, use create_bitstream.sh path/to/file.bit
which will produce path/to/file.bit.bin
. Then, copy file.bit.bin
to the board (preferably using ssh/scp), and use sudo ./flash_bin.sh file.bit.bin
from the PYNQ (the flash_bin.sh
script is already present on the board) to flash the FPGA. Congrats, the CVA6 design is in place!