Software defined radio (SDR) has been a fairly prominent topic in the FPGA development space for some time now. However, getting started with a development platform for an SDR isn't always the most straightforward, especially for those new to the topic.
Analog Devices (ADI) offers a line of FMC breakout boards for their RF transceiver chips that you can mix and match with various AMD-Xilinx and Intel FPGA development boards. The drivers for the FPGA to communicate with the ADI transceivers are available in both no-OS (bare-metal) and embedded Linux. For this tutorial, I'm using the AMD-Xilinx Zynq UltraScale+ based ZCU102 with the ADI ADRV9371-W/PCBZ and deploying the ADI drivers in embedded Linux.
Overall there are two main steps to accomplish here:
- Build the corresponding hardware design in Vivado for the ZCU102 with the ADRV9371-W/PCBZ connected to one of its FMC connectors.
- Build the embedded Linux image using PetaLinux for the ZCU102 with the ADI drivers to communicate with the AD9371 transceiver chip.
Analog Devices Inc (ADI) maintains a Github repository that contains the necessary sources with makefiles to generate the base HDL project for any of their supported FPGA development board with ADI development board combinations.
Create a new project directory and clone the ADI hdl repository into it:
~$ mkdir -p xilinx_sdr
~$ cd ./xilinx_sdr/
~/xilinx_sdr$ git clone https://github.com/analogdevicesinc/hdl.git
Check out the latest stable version (which at the time of writing, is v2021.1):
~/xilinx_sdr$ cd ./hdl/
~/xilinx_sdr/hdl$ git checkout hdl_2021_r1
Change directories into the project for the FPGA development board and ADI development board combination desired (ZCU102 with ADRV9371PCB/W in this case), source the Vivado tools to the environment, then run the makefile to generate the Vivado project.
~/xilinx_sdr/hdl$ cd ./projects/adrv9371x/zcu102/
~/xilinx_sdr/hdl/projects/adrv9371x/zcu102$ source /tools/Xilinx/Vivado/2021.1/settings64.sh
~/xilinx_sdr/hdl/projects/adrv9371x/zcu102$ make
Be sure the license for the target AMD-Xilinx development board is already in place prior to sourcing the Vivado toolset and running the makefile. A one-year license is included in the box with the AMD-Xilinx development board, or you can request a 30-day trail license if you don't already have one.
ADI PetaLinux ProjectChanging directories back into the top level project directory, create a PetaLinux project for the target AMD-Xilinx development board. You can either use the BSP from Xilinx or create a new project from scratch, I'm using the ZCU102 BSP.
~$ cd ./xilinx_sdr/
~/xilinx_sdr$ source /tools/Xilinx/PetaLinux/2021.1/settings.sh
~/xilinx_sdr$ petalinux-create -t project -s ./xilinx-zcu102-v2021.1-final.bsp --name adi_os
Change directories into the project-spec folder of the PetaLinux project and clone the ADI Yocto layers into it (be sure to checkout the same version as you did the HDL repository).
~/xilinx_sdr$ cd ./adi_os/project-spec/
~/xilinx_sdr/adi_os/project-spec$ git clone https://github.com/analogdevicesinc/meta-adi.git
~/xilinx_sdr/adi_os/project-spec$ cd ./meta-adi/
~/xilinx_sdr/adi_os/project-spec/meta-adi$ git checkout 2021_R1
~/xilinx_sdr/adi_os/project-spec/meta-adi$ cd ../../
Import the hardware generated by the Vivado project built from the HDL repository:
~/xilinx_sdr/adi_os$ petalinux-config --get-hw-description ../hdl/projects/adrv9371x/zcu102/adrv9371x_zcu102.sdk/
The system configuration editor will appear once the hardware file has been imported.
Since I'm using PetaLinux v2021.1, it's important to first fix the known issue with the default network SSTATE feeds URL link generated by the tool not working. This is just a simple matter of changing rel-v${PETALINUX_VER%%.*}
to rel-v2021.1
in the network SSTATE feeds URL. Navigate to Yocto Settings > Network sstate feed URL and change:
http://petalinux.xilinx.com/sswreleases/rel-v${PETALINUX_VER%%.*}/aarch64/sstate-cache
to:
http://petalinux.xilinx.com/sswreleases/rel-v2021.1/aarch64/sstate-cache
Then navigate to Yocto Settings > User Layers and add both the meta-adi-core
and meta-adi-xilinx
layers. Be sure the meta-adi-core
is layer 0 and meta-adi-xilinx
is layer 1, as meta-adi-xilinx
has dependencies on meta-adi-core
.
Exit the system configuration editor, electing to save all changes.
The next step is to call out the target device tree that matches the project being built (the ZCU102 with ADRV9371PCB/W) in the /<PetaLinux project path>/project-spec/meta-user/conf/petalinuxbsp.conf
file. You can find the full list of device tree file names here (again, be sure you're in the branch that matches the version of Vivado/PetaLinux you're using). Overall, the /<PetaLinux project path>/project-spec/meta-user/conf/petalinuxbsp.conf
file should look like the following:
#User Configuration
KERNEL_DTB="zynqmp-zcu102-rev10-adrv9371-jesd204-fsm"
#OE_TERMINAL = "tmux"
IMAGE_BOOT_FILES_zynqmp = "BOOT.BIN boot.scr Image ramdisk.cpio.gz.u-boot rootfs.cpio.gz.u-boot"
Launch the kernel configuration editor to add any extra desired kernel modules:
~/xilinx_sdr/adi_os$ petalinux-config -c kernel
Launch the root filesystem configuration editor to add any extra desired libraries/packages:
~/xilinx_sdr/adi_os$ petalinux-config -c rootfs
Finally, build the PetaLinux project:
~/xilinx_sdr/adi_os$ petalinux-build
After the project has successfully built, package the boot binary (boot.bin) for the platform with the Zynq MPSoC FSBL (--fsbl
flag), FPGA bitstream (--fpga
flag), and U-Boot (--u-boot
flag):
~/xilinx_sdr/adi_os$ petalinux-package --boot --fsbl --fpga --u-boot
If you just use the flags for each, PetaLinux will pull the source files from the /<PetaLinux project path>/images/linux
directory. If you want to use a custom FSBL, bitstream, or U-Boot, then simply pass the directory location of each after their respective flag like so:
~/xilinx_sdr/adi_os$ petalinux-package --boot --fsbl <path to fsbl.elf> --fpga <path to bitstream.bit> --u-boot <path to u-boot.elf>
Finally, package a WIC image to flash the SD card with including boot.bin, image.ub, and boot.scr in the boot partition:
~/xilinx_sdr/adi_os$ petalinux-package --wic --bootfiles "BOOT.BIN image.ub boot.scr"
Then use a program like balenaEtcher to flash the image onto an SD card.
Setup the ZCU102 by connecting the 12V power supply wall adapter, connect a USB cable from the host PC to the microUSB labeled "USB UART" port on the ZCU102, and connect the ADRV9371PCB/W to the FMC connector labeled HPC0.
Connect the Ethernet from the ZCU102 to your router or to a separate NIC card on the host PC (pro tip: USB to Ethernet adapters are a quick/cheap way to add an auxiliary NIC to your host PC and create a local network for peripherals like FPGAs).
Set the ZCU102 for SD boot mode by setting SW6 to on-off-off-off:
Open your preferred serial terminal application such as Putty or TeraTerm. Four serial ports will appear on the host PC. The main UART output will be on port 1 of 4. Since it's Zynq MPSoC, the baud rate will be 115200.
Once everything is properly connected and the terminal application is ready, power on the ZCU102 with the toggle switch located next to the 12V plug.
Verify that Linux can in fact see that the ADRV9371PCB/W is connected by looking at the IIO devices available in the /dev directory.
root@xilinx-zcu102-2021_1:~# ls /dev/iio*
There should be 7 (iio:device0
- iio:device6
) IIO devices preset:
So at this point, you have a clean slate for starting your SDR development. I will be posting subsequent parts to this design with more basic setup and testing.
Comments