I would like to understand how the data from the DMA gets stored in the DDR RAM in in pynq. I was trying to save ADC data in bursts (using RFSoC) where, unlike the base overlay example where the trigger comes from the user space, I trigger the ADC to dump 256x8 samples every second. On the Pynq side, from the jupyter notebook, I allocate a buffer (corresponding to the above sample number), initiate a receive channel transfer, then wait. Code snippet below:
transfersize = 256 for i in range(10): cfg.write(0x00,int(1)) // enables the transfer to automatically generate 256x8 samples from the RFSoC. buffer_re = allocate(shape=(transfersize*8,), dtype=np.int16) axi_dma0.recvchannel.transfer(buffer_re) axi_dma0.recvchannel.wait() cfg.write(0x00,int(0)) print(buffer_re) time.sleep(1) buffer_re.freebuffer()
This works as expected.
The IP that is generating the AXI signals is also capable of generating trigger once per second after I enable it too, so when I try this:
transfersize = 256 buffer_re = allocate(shape=(transfersize*8,), dtype=np.int16) for i in range(10): if i == 0: axi_dma0.recvchannel.transfer(buffer_re) cfg.write(0x00,int(1)) axi_dma0.recvchannel.wait() print(buffer_re) time.sleep(1) else: axi_dma0.recvchannel.transfer(buffer_re) axi_dma0.recvchannel.wait() print(buffer_re) time.sleep(1) cfg.write(0x00,int(0))
This just print the same values 10 times. The same IP, when I replace the DMA with BRAM, works fine in both the modes. So I had a few doubts:
- After the first sample 256 samples are written, are the next 256 written to the next subsequent memory location? If this is the case should we define a 8 MB buffer directly (as 8 MB is the max buffer length for DMA), and read data to user space after 8 MB is written by having a fifo to mediate the process?
- If I want to have a location in the RAM fixed for data from a particular operation, I can add a BRAM and read as AXI stream from that to the DMA controller. But is there a cleaner way for this?