The Xilinx Virtual Cable (XVC) is a TCP/IP-based protocol that acts like a JTAG cable and provides a means to access and debug your FPGA or SoC design without using a physical cable. This enables a user to access a Xilinx device through another medium (In this case we use Ethernet) instead of needing a dedicated JTAG cable. This can be advantageous for in-field debugging or during stress test scenarios where JTAG is not an option.
The Xilinx Virtual Cable started as an application note, XAPP1251, a number of years ago. Since that time, the solution has evolved to be cleaner and simpler using IP available in Vivado and source code from a GitHub repository. This wiki page is designed to be an update to the application note without duplicating information that has not changed.
One of the major differences in the implementation between XAPP1251 and this article, is location of the target FPGA. In XAPP1251 the target FPGA was another device and it was being accessed via JTAG pins from GPIO of the master FPGA. In this wiki article, the Target FPGA is the Programmable Logic within the Zynq/ZynqMP SoC device. This primary difference was enabled with the introduction of the Debug Bridge IP within the IP Catalog.
This wiki page is intended to illustrate details of the Xilinx Virtual Cable but is not intended to be a tutorial for any of the tools that are used such as Vivado and PetaLinux. Users are expected to have background knowledge of Linux, embedded systems, and networking.
This wiki page will not describe XVC over PCIe. XVC over PCIe is more common in a data center application where there is a PCIe accelerator card. The concept is similar to what is described in this wiki page, but rather than Ethernet, PCIe is used.
The 2020.1 version of Xilinx tools including Vivado and PetaLinux were used for the prototype build of the hardware and software.
The solution is made up of a hardware design running on a board with a Xilinx SoC or FPGA together with a Linux device driver and a Linux application running on a CPU of the SoC or FPGA. The solution should be portable such that it will run on any Xilinx CPU, but testing has only been done on the ARM CPUs which run Linux.
A embedded system is built in Vivado which requires a CPU capable of running Linux (Cortex A9, Cortex A53, MicroBlaze) together with the peripherals for a networked device (Ethernet). A Xilinx board was used for the prototype tests the wiki is based on.
Vivado IPI Block Diagram
The following block diagrams illustrate prototype systems which includes the Xilinx Debug Bridge IP core together with a minimal binary counter connected to a System ILA to verify operation of the system.
Debug Bridge Configuration
The Debug Bridge must be configured for the AXI to BSCAN mode since the CPU will be driving the Debug Bridge IP based on packets received from the network; which ultimately need access to the device’s Boundary Scan. If the SoC were to drive another FPGA via JTAG pins, then the AXI to JTAG mode would be used. In our demonstration, the configuration of the Debug Bridge should be as shown in the following illustration.
The Xilinx Virtual Cable GitHub project XilinxVirtualCable provides the source code for a Linux kernel driver and Linux application. This wiki page gives details using PetaLinux but it could be accomplished in other manners as PetaLinux is only the build mechanism.
Linux Device Driver Details
The Linux device driver is located in the src/driver directory of the repository. The driver supports device tree and non-device tree initialization with device tree being the default. Non-device tree is somewhat legacy or advanced use cases not supported by device tree. The device driver source code requires two small changes to build in the newer 5.4 rebase kernel for the 2020.1 release of PetaLinux.
The Linux application source code is located in the src/user directory of the repository. The application supports the use of the Linux device driver using IOCTL calls or a UIO mmap method as described in the readme.md in the src/user directory of the repository. The Linux device driver with IOCTLs is the recommended method as the UIO mmap method is a legacy mode of operation prior to the existence of the Linux device driver.
It is assumed that a user is starting with a solid baseline of a Linux system running with a working network. BSPs are available for many Xilinx boards which are a great baseline and can be updated with Vivado hardware changes. The following steps will build a kernel module xvc-driver.ko and a user application xvcServer which will be put into the rootfs of the Linux system.
A Vivado hardware build creates an XSA output file(bitstream packaged in XSA) which is then imported into PetaLinux project. After exporting the hardware from Vivado import the new Vivado system into PetaLinux as illustrated below.
The name of the driver must not include the "_" character such that the name of the driver was changed from xvc_driver to xvc-driver for PetaLinux.
The xvc-driver module recipe you created can be found in the <plnx-proj-root>/project-spec/meta-user/recipes-modules/xvc-driver directory. Copy some of the source code files from the XilinxVirtualCable repository, including the xvc_driver*.c, xvc_driver.h, xvc_user_config.h, and xvc_ioctl.h, into the recipe to build the kernel module in the PetaLinux project (<plnx-proj-root>/project-spec/meta-user/recipes-modules/xvc-driver/files).
Not all the source files are required.
The xvc_user_config_example.h supports the legacy method of configuring the driver without the use of device tree
The xvc_fragment.dts is a device tree fragment illustrating the changes required to the device tree.
The PetaLinux generated Makefile is used rather than the repository provided Makefile.
Alter the SRC_URI BitBake vairable in the project at <plnx-proj-root>/project-spec/meta-user/recipes-modules/xvc-driver/xvs-driver.bb recipe file to include the required source files into the build area as illustrated below.
The xvcServer apps recipe you created can be found in the <plnx-proj-root>/project-spec/meta-user/recipes-apps/xvcServer directory, Copy xvcServer.c from the src/user directory of the XilinxVirtualCable repository and xvc_ioctl.h from the src/driver directory of the XilinxVirtualCable repository into the recipe directory of the PetaLinux project at <plnx-proj-root>/project-spec/meta-user/recipe-apps/xvcServer/files.
Edit the xvcServer.c source file adding the following line after the #include of the header files to cause the device driver with IOCTL support to be used rather than UIO with mmap as illustrated below.
Alter the BitBake recipe of the application at <plnx-proj-root>/project-spec/meta-user/recipes-apps/xvcServer/xvcServer.bb to copy the source files into the build area as illustrated below.
The device tree node for the Xilinx Debug Bridge IP in the PetaLinux generated device tree (pl.dtsi) does not match the compatibility string for the device driver. Alter the system-user.dtsi device tree of the PetaLinux project in <plnx-proj-root>/project-spec/meta-user/recipes-bsp/device-tree/files to alter the compatible string to match that driver as illustrated below.
compatible = "xlnx,xvc";
The previous lines should be added to the end of the system-user.dtsi file.
PetaLinux Image Build
Build the PetaLinux System Images as illustrated below, When the build finishes, the generated images are stored in the <plnx-proj-root>/images/linux or /tftpboot directories.
Package the BOOT.BIN image with all the boot components including the FPGA bitstream. From the <plnx-proj-root>/images/linux directory the boot image is built as illustrated below.
The following steps assume Linux has booted on the embedded target and the network is functional with respect to a valid IP address and the host computer running Vivado is on the same network (subnet). From the running target the device driver should be started as illustrated below.
root@xilinx-zcu102-2020_1:~# modprobe xvc-driver
The following console output illustrates the expected output when the driver is working.
From the running target the server application should be started as illustrated below.
root@xilinx-zcu102-2020_1:~# xvcServer &
The following console output illustrates the expected output when the server is working and ready to use.
root@xilinx-zcu102-2020_1:~# xvcServer &
INFO: XVC driver character file: /dev/xilinx_xvc_driver
INFO: debug_bridge base address: 0xA0000000
INFO: debug_bridge size: 0x10000
INFO: debug_bridge device tree compatibility string: xlnx,xvc
INFO: To connect to this xvcServer instance, use url: TCP:xilinx-zcu102-2020_1:2542
Note the base address of the Debug Bridge in the output above could be at a different address depending on the connections in the IPI design of Vivado.
Hardware Manager In Vivado
In Vivado open the hardware manager and open the target by opening a new hardware target. As the wizard guides you through the process you will see the following set of dialog boxes.
As illustrated below, the user now has the option using the Add Xilinx Virtual Cable (XVC) button.
Enter the network information for the Xilinx Virtual Cable server running on the embedded target.
And the IP address address of the server is shown in the hardware targets as illustrated below.
And after completing the new target the ILA is shown in the hardware manager and can be triggered as shown below.
Linux Power Management
In the past there have been issues where the clock(s) to the PL could be shut off so that the ILA does not function. This can be prevented by adding a kernel parameter to the Linux boot arguments in the device tree. Edit the <plnx-proj-root>/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi file in the PetaLinux project and alter the boot arguments to add “cpuidle.off=1” as illustrated below. For more details refer AR# 69143
The boot arguments (bootargs) above may not exactly match your system and are only intended to show the addition of the “cpuidle.stop=1”. There is no way to add an argument without specifying all of the existing boot arguments. The bootargs for the PetaLinux system can be found in the system-conf.dtsi file of the build in the <plnx-proj-root>/components/plnx_workspace/device-tree/device-tree directory or from a running target using the command: cat /proc/cmdline.
Device Tree Issues
If the output of the device driver does not include all the lines (as illustrated below) then the device tree for the Debug Bridge may not be up to date as specified in the steps. The driver can be inserted into the kernel but not find any compatible driver so that it is not functioning even though it is in the kernel.