Custom IP generates different results and DMA stuck at 'dma.recvchannel.wait()'

  • PYNQ version: 3.0.1
  • Board name: Xilinx RFSoC ZCU111
  • Tool Version: Vivado 2023.1

Hello,

I generated a custom IP using Simulink HDL Coder. I performed a behavioral simulation on verilog code generated for my custom IP logic in Vivado and I obtained the right results (the AXI communication was excluded during the simulation). However, I get different results from my custom IP every time I run it on hardware using PYNQ. I also noticed when I include the ‘dma.recvchannel.wait()’ command in my code, the program always hangs. I confirmed my IP generates a TLAST by passing the its value to a register on my custom IP. The value in the register always changes to 1. When I comment out that line of code (dma.recvchannel.wait()), I still obtain data in my ‘output_buffer’.

In summary, I have two problems with my design,

  • My program always hangs when there’s a ‘dma.recvchannel.wait()’ in my code.
  • My custom IP generates different results (with the same input data) every time I run it on hardware using PYNQ’ .

I have attached an image of my setup in Vivado. I tried posting my code Python code but the platform allows me to post just one image so I had to type them out.

DMA Setting below

Width of Buffer Length Register: 26
Address Width: 64

Read Channel
Memory Mapped Width: 1024
Stream Data Width: 1024
Max Burst Size: 8

Write Channel
Memory Mapped Width: 32
Stream Data Width: 32
Max Burst Size: 16

Python Code Below

import os

from pynq import PL
from pynq import allocate
import numpy as np
PL.reset()

from pynq import Overlay
from pynq.lib.dma import DMA

wrapper_name=“design_5”
overlay = Overlay(f"{os.getcwd()}/{wrapper_name}.bit")

dma = overlay.axi_dma_0

custom_IP = overlay.HDL_DUT_ip_0
custom_IP.write(0x4,1) #Enable custom IP

csv_file = “fpga_input_data.csv” # Replace with your CSV file path
with open(csv_file, “r”, encoding=“utf-8-sig”) as file:
test_data = np.loadtxt(file, delimiter=“,”, dtype=np.uint16) # Read as uint16

flattened_data = test_data.flatten() # Convert from (118, 512) to (118 * 512,)

total_elements = len(flattened_data)

input_buffer = allocate(shape=(total_elements,), dtype=“u2”)
output_buffer = allocate(shape=(total_elements,), dtype=“i2”)

input_buffer[:] = flattened_data[:]
input_buffer.flush()

dma.sendchannel.transfer(input_buffer)
dma.recvchannel.transfer(output_buffer)

dma.sendchannel.wait()
dma.recvchannel.wait()

output_buffer.invalidate()

print(“Output data:”, output_buffer[:])
del input_buffer

Hi @atb,

Welcome to the PYNQ community.

Based on your description, the IP is not setting up TLAST properly. I wrote a comprehensive tutorial to debug this on board. Debugging Common DMA Issues [Part 3]

  • My custom IP generates different results (with the same input data) every time I run it on hardware using PYNQ’ .

If the DMA is not finishing correctly, it is likely that the data you’re reading is not correct. You should fix the DMA issue first before debugging this.

Mario

Hello Mario,

Thank you for your help in debugging the cause of the issues.

I fixed the issue with TLAST. My program no longer hangs at ‘dma.recvchannel.wait()’. However, I still get different outputs every time I run the program on hardware with the same inputs.

Kindly share your thoughts on what possibly be causing this.

Hi @atb,

Kindly share your thoughts on what possibly be causing this.

Clearly, this is an issue with your HDL IP. If you have not done it yet, I suggest you simulate the IP thoroughly in HDL Coder and if you can in an RTL simulation.

Mario