Fill level of AXI-Stream Data FIFO with AXI DMA

Hi, what is the right way to check how many items currently reside in the AXI-Stream Data FIFO controlled by DMA?

I have a FIFO with 64-bit items created by following this tutorial:
https://www.youtube.com/watch?v=K4OkNH17hiA

I tried using the axis_wr_data_count and axis_rd_data_count, but on their own they do not give a fair representation, that’s because it seems that the DMA module reads the first 4 items automatically as they arrive in the FIFO, causing the counts to be 0, despite data being available.

What I mean by that is that when I send 5 elements (8 bytes each) to the FIFO, it will set the counts to 1 instead of 5.

This is especially problematic because of error prone nature of DMA with FIFO which seems to result in error whenever I attempt to send more data into fifo while waiting to receive less data. For example, I have a continuous loop that attempts to read 16 bytes (2 items) at a time.

def rec(x, ib):
    while True:
        print('dma_rec.transfer')
        with input_buffer_lock:
            x.transfer(ib, nbytes=16)
        print('dma_rec.transfer returned')
        x.wait()
        time.sleep(1)
        print('dma_rec.wait completed')
    
Thread(target=rec, args=[dma_rec, input_buffer], daemon=True).start()

When I send exactly 8 or 16 bytes through send channel, it works well. But if I send more, like 24, then I get the following error:

  File "/usr/local/share/pynq-venv/lib/python3.8/site-packages/pynq/lib/dma.py", line 210, in wait
    raise RuntimeError(
RuntimeError: DMA Internal Error (transfer length 0?)

I have pynq 2.7, Ultra96-V2 board, and Vivado 2020.1.

dma_test.ipynb (14.2 KB)
I attached the notebook file I used for testing in case if anyone would like to take a look, and here’s the design I have (I tried both, AXI-Stream Data FIFO, and FIFO generator):

My goal is to continuously receive data whenever it’s available and do it in reliable way.

Edit:
Removing “nbytes” argument from the receiving transfer call seems to prevent the error, but still it would be nice to know how to get the fill level correctly in this design. Because otherwise, is there any way to know how many items were actually received from the transfer call?

Hi @michalmonday,

Welcome to our community!

Edit:
Removing “nbytes” argument from the receiving transfer call seems to prevent the error, but still it would be nice to know how to get the fill level correctly in this design. Because otherwise, is there any way to know how many items were actually received from the transfer call?

You can check the register map of the dma and verify the length of the transaction in the s2mm channel.

Mario

1 Like