Using an ILA without Physical micro USB cable [Part 4]

Using an ILA without Physical micro USB cable

In many cases it is not possible to have the micro USB cable physically connected to
the board. No need to worry, it is still possible to use ILA via the XVC and the Debug Bridge

In the forums there have been a series of questions about this topic, with satisfactory answers.

In the latest release of PYNQ (3.0.1 at the time of writing) a community contribution included support for it directly into PYNQ. You can read more in the documentation

For the purpose on of this blog, I will cover how to create the overlay and connect remotely to the ILA from the Hardware Manager.

Overlay Design

The starting point is the overlay we designed in part 1, with the System ILA already integrated.

In the IP Integrator, Add IP and search for Debug Bridge.

1_add_debug_bridge

Once added, double click on debug_bridge_0 to configure it. Select From AXI to BSCAN as Bridge Type.

Click Run Connection Automation, when the Run Connection Automation window opens, make sure the debug_bridge_0 S_AXI is selected.

Connect the reset and clock if it has not been done automatically. This is it, no more steps needed.

The Debug Bridge, it is automatically connected to the PS M_AXI_GP0 interface via the ps7_0_axi_periph AXI interconnect.

Re-generate the bitstream. Once the bitstream is generated, move the new .bit and .hwh files to the board, use the basename dma_dbridge.

PYNQ code

If you are running pynq 3.0.1, the first step is to patch the Debug Bridge driver to make the integration with your notebook smoother. Run the following code in a Jupyter notebook code cell. You can see what we are patching here.

NOTE: If you are using an older PYNQ version, I suggest you upgrade to PYNQ 3.0.1.

!wget https://raw.githubusercontent.com/Xilinx/PYNQ/master/pynq/lib/debugbridge.py -O debugbridge.py
!mv debugbridge.py /usr/local/share/pynq-venv/lib/python3.10/site-packages/pynq/lib/debugbridge.py

Restart the Jupyter kernel for the fix to take place. Notebook can be found here.

from pynq import Overlay, allocate
import numpy as np

ol = Overlay('dma_dbridge.bit')
dma = ol.axi_dma
dma_send = ol.axi_dma.sendchannel
dma_recv = ol.axi_dma.recvchannel

bridge = ol.debug_bridge_0
print(bridge)

The DebugBridge driver is automatically assigned to the ol.debug_bridge_0 IP. Learn more about PYNQ IP drivers here.

Start the XVC server, note that the default port is 2542.

bridge.start_xvc_server(bufferLen=4096, serverAddress="0.0.0.0",
                 serverPort=2542, reconnect=True, verbose=True)

Get the IP address of your board, either from the command line or from a Jupyter notebook cell. The code below, assumes that the Ethernet port is connected

!ifconfig eth0 | grep 'inet ' | awk '{print $2}'

In your Vivado instance, click Open Hardware Manger under PROGRAM AND DEBUG

1_open_hw_manager

Click on Open target, on the green bar that just appeared, then Auto Connect

2_open_target

This will automatically connect to a localhost hw_server. Since, the micro USB cable is not connected, the localhost connection does not detect any device. We need to explicitly indicate that XVC will be used, right click on localhost(0) then select Add Xilinx Virtual Cable (XVC)...

7_add_xvc

In the Add Virtual Cable window, type your board IP address in the Host Name field, make sure the Port matches what is defined in start_xvc_server.

8_xvc_settings

After a successful connection, you should see the debug_bridge_0 under localhost. In the Hardware window, select debug_bridge_0, as you can see the status is N/A. However, if you look into the Hardware Device Properties, you can see that the Probes file is empty. Click on the ... button and add the *.ltx file under the project impl_1.

Once the .ltx file is uploaded, the window should automatically refresh to show the waveform with the corresponding signals.

Add triggers the way you learned in part 2. Go back to the JupyterLab notebook, allocate the buffers and only use the sendchannel of the DMA.

data_size = 16

input_buffer = allocate(shape=(data_size,), dtype=np.uint32)
output_buffer = allocate(shape=(data_size,), dtype=np.uint32)

input_buffer[:] = np.arange(data_size, dtype=np.uint32)

dma_recv.transfer(output_buffer)
dma_send.transfer(input_buffer)
dma_send.wait()

dma_recv.wait()
print(f'Are buffers equal after DMA? {np.array_equal(output_buffer, input_buffer)}')

Do not forget to stop the XVC server once you finish.

bridge.stop_xvc_server()

In this blog, I showed how you can still use ILA to debug your overlay even if you do not have physical access to the board micro USB cable.

Please, use the comments section for questions related to the content of this blog. If you have questions about your own design or unrelated topics, please create a new topic in the forum.

2 Likes