Unable to acquire full analog pulse from XADC via AXI DMA (limited to 256 samples)

(PYNQ-Z2 (3.0.1))

Hi everyone,

I’m a student currently starting my journey in FPGA hardware acceleration. My background is a mix of physics and engineering, so I’m still relatively new to the world of digital design and PYNQ-based workflows. For context, I’m working on a small project where an AI model generates synthetic pulses mimicking the analog signal from a neutron monitor. I’m emulating the signal acquisition and its later digital processing on the FPGA.

To generate the analog signal, I use a basic DAC (MCP4725) that sends a predefined pulse array through I2C (for more info: Problem with I2C Interface with DAC MCP4725 through Arduino pins). Then, I loop that signal back into the FPGA via the XADC.
First problem: the pulse has 328 elements, each sent over I2C at 3 bytes per element, and I’m already pushing the I2C IP to 1 MHz (its max speed). At 100 kHz (as shown in the oscilloscope image), the signal is way too slow.


To minimize oversampling, I configured the XADC for its lowest sampling rate (39 kSPS) !!. I followed Adam Taylor’s example from this article and the design works, but I now hit a serious wall. I cannot acquire more than 256 samples per pulse. I confirmed TLAST is being generated every 256 samples via the AXI4-Stream Subset Converter (which seems to be the limiting factor).



I’m stuck :frowning:
What are your recommendations for acquiring full pulses from the XADC using DMA on PYNQ?Any help or guidance would be deeply appreciated. I’m running out of ideas and would love a push in the right direction.

Thanks in advance!

P.S.
Due to external constraints, I can’t share the full source code — the pulse is generated by a custom AI model. However, all the relevant configuration and behavior is clearly shown in the captures I’m uploading. Let me know if more system details are needed!

dac_xadc_CaLMa_bd_wrapper.bit (3.9 MB)
dac_xadc_CaLMa_bd_wrapper.tcl (13.7 KB)

Hi @Diego,

You could create an HLS IP that sets the TLAST when you need it. See an example here:

You may want to create a look so you set the TLAST when you need it.

Mario

Hi Mario,

First of all, thank you very much for your response!

I would like to mention that I have never worked with Vitis HLS before, but following your advice I have tried to implement it. Mainly, I have been guiding myself through this series of tutorials: PYNQ HLS Stream IP Tutorial, and by checking the example repository you kindly shared.

To summarize my situation:

  • I have created the IP block in Vitis HLS.
  • I integrated it into my hardware design, connecting it properly between the XADC and the AXI DMA.
  • Then I generated the bitstream and tried to work with it from a PYNQ Jupyter Notebook.

However, the problem arises in PYNQ:
I am unable to properly access the IP from Python. When I try to interact with it, it does not even recognize it. Additionally, I tried to manually send a random voltage value (without using the new IP) and it did not work either, which makes sense because the IP is not being correctly initialized or accessed from Python


Would you mind suggesting what might be missing in my design or flow?

Thanks a lot again for your time and support!

Best regards,
Diego

Hi @Diego,

First of all, your IP does not have an AXI4 Lite interface, so you will not be able to “see” this IP from PYNQ.

Your overlay will not work because you are not setting the TLAST, you also need to make sure TKEEP is set to all 1. Something like this,

for i in <number_samples> {
    packet tmp = S_AXIS.read();
    tmp.keep = -1,
    tmp.last = (i-1) == <number_samples>;
}

You will also have to add the directive/pragma to set II=1 and not to have control interface.

Mario