Dma becomes unresponsive in Jupyer notebook

i am trying to time my hardware implementation of a fir filter using Xilinx’s Pynq platform, but every time I try to run that block of code in the jupyter notebook, my entire session becomes unresponsive. I am not sure what I am doing wrong because I just learned this a few hours ago.

If someone knows possible causes, please let me know.
Is there a way to check the design was correctly implemented or for errors along the way?

i attached the python file used in the notebook and commented the line where i begin to have problems. (2.7 KB)

1 Like


I have not tried the copyto function before. The pynq buffers are compatible with numpy, but they have more attributes. Instead of using copyto can you try?

in_buffer[:] = samples


That didn’t work

Is it possible that something’s wrong with the design ?

If you are not sending and “reading” the correct amounts of data, the DMA status will be waiting. You may want to check when the FIR block asserts TLAST. If you try to read X bytes from the DMA, TLAST needs to be asserted after X bytes, or earlier, the DMA will be waiting for data.
Can you report back the values of .register_map for the DMA?

Video example of register_map:

What is the RTL block doing? This may be for future reference but if you are just slicing 16 bits from the larger 40 bit signal then you can use a slice block in IP integrator.


Thanks for giving me some direction, Cathal!
the RTL block just takes 16 bits from the 40 bit output.
the FIR asserts tlast according to the below configuration.

dma.register map:
RegisterMap {
MM2S_DMACR = Register(RS=1, Reset=0, Keyhole=0, Cyclic_BD_Enable=0, IOC_IrqEn=0, Dly_IrqEn=0, Err_IrqEn=0, IRQThreshold=1, IRQDelay=0),
MM2S_DMASR = Register(Halted=0, Idle=0, SGIncld=0, DMAIntErr=0, DMASlvErr=0, DMADecErr=0, SGIntErr=0, SGSlvErr=0, SGDecErr=0, IOC_Irq=0, Dly_Irq=0, Err_Irq=0, IRQThresholdSts=0, IRQDelaySts=0),
MM2S_CURDESC = Register(Current_Descriptor_Pointer=0),
MM2S_CURDESC_MSB = Register(Current_Descriptor_Pointer=0),
MM2S_TAILDESC = Register(Tail_Descriptor_Pointer=0),
MM2S_TAILDESC_MSB = Register(Tail_Descriptor_Pointer=0),
MM2S_SA = Register(Source_Address=0),
MM2S_SA_MSB = Register(Source_Address=0),
MM2S_LENGTH = Register(Length=0),
SG_CTL = Register(SG_CACHE=0, SG_USER=0),
S2MM_DMACR = Register(RS=1, Reset=0, Keyhole=0, Cyclic_BD_Enable=0, IOC_IrqEn=0, Dly_IrqEn=0, Err_IrqEn=0, IRQThreshold=1, IRQDelay=0),
S2MM_DMASR = Register(Halted=0, Idle=0, SGIncld=0, DMAIntErr=0, DMASlvErr=0, DMADecErr=0, SGIntErr=0, SGSlvErr=0, SGDecErr=0, IOC_Irq=0, Dly_Irq=0, Err_Irq=0, IRQThresholdSts=0, IRQDelaySts=0),
S2MM_CURDESC = Register(Current_Descriptor_Pointer=0),
S2MM_CURDESC_MSB = Register(Current_Descriptor_Pointer=0),
S2MM_TAILDESC = Register(Tail_Descriptor_Pointer=0),
S2MM_TAILDESC_MSB = Register(Tail_Descriptor_Pointer=0),
S2MM_DA = Register(Destination_Address=0),
S2MM_DA_MSB = Register(Destination_Address=0),
S2MM_LENGTH = Register(Length=0)

OK so you don’t get to the point where you start your DMA?
I just noticed your comment in the Python file about where you think the problem is. You think your systems hangs as you are copying data to the buffer?
I checked your code and I don’t see anything wrong to that point or with the DMA transfers. I swapped your code from reading the samples and coefficients from file to the code which generates them and it all seems fine.
Can you try transfer the uninitialized buffer through the DMA? i.e. skip the line where you copy data to the buffer.


Hi Cathal, I tried transferring the uninitialized buffer through the DMA but that caused an error. Would you mind taking a look at my zipped design? I would really appreciate it, I’ve spent the last week debugging it and I still do not know what is wrong.
That’s the compressed version, so you should be able to run it by just opening it :slight_smile:

In Vivado, what does the address editor look like for the M_AXI ports on the DMA?


Hi Cathal! It looks like this. Is this what you were looking for?

Yes, can you try assign addresses for those interfaces?
I think you can right click on the interface and select assign address.


hmmm I am not able to

Try “unassign all”, then assign again?
If they do not get an address assigned, go back through your design and check everything is connected correctly on those paths.
If you still have this problem if you can post a screenshot of your block design showing these paths it might help.


tried that, everything is assigned but the 2 incomplete paths are still there. In the link I posted, you can find the pdf of the diagram, and the complete project if you want to interact with it deeper.

I did try rebuild your block diagram but it is timeconsuming looking through someone else’s design.
Your project wouldn’t open, so I tried rebuild with the Tcl. I had to make a few modifications to the script; modify path for coe file, add truncate.v to the design.

I see an error with this becuase out is a reserved keyword.
create_bd_pin -dir O -from 0 -to 15 out

ERROR: [BD 41-85] Exec TCL - Illegal Name: The name ‘out’ cannot be used because it is a keyword in a Hardware Description Language.

I’m not sure why you don’t see this.

When I build it, the HP port on the Zynq wasn’t enabled, so there was no connection or path for the DMA. The ports show unconnected in the address view, as expected.
I don’t see this in the block design image you posted.

I manually enabled the ports on the PS and connected with automation and addresses were assigned.

I’m asking you do check this as you seem to have something different to what I see.
I also tested your .bit on the board and I see a DMA decerr - (decode error - invalid address) which is consistent with the unassigned addresses. When you ran your Python code you said you couldn’t get to this part so I’m not sure what is going on.


hi Cathal! wow thank you so much! I did have that error (that in is a keyword), but I changed it. I apologize for that. I changed (in, out) to (in0, out0) respectively. those ports came from the truncate.v module .
What would you like me to do on my end?

  1. Should I manually enable the ports on the PS and connect them with automation and addresses were assigned?

  2. should I try this command on my end?
    create_bd_pin -dir O -from 0 -to 15 out0

  3. did you test the .bit via Jupiter? When I test it via jupyter, ie call dma.sendchannel.transfer(in_buffer) , I get a runtime error, that the dma is inactive.

I apologize for so many beginner questions, I have been on this project for 3 weeks and had no previous PS PL experience. I really appreciate your help!

You can do 1, but it looked like you already did this in the image you posted above. If you are creating the project again, check if you did this.
2. yes, you can change the port name, but again it looked like you had made this change. I think there were also 2 other places I needed to change it. If you are going to change the project, I would suggest you remove truncate. You should check that you really do want to truncate the data.
3. The error is a little misleading. It says DMA not started which is true (I expect halted =1), but if you check the register_map I think you will also see decerr is set. We can look into improving the error message.

No problem. It sounds like you made great progress in 3 weeks :wink:


Thanks, Cathal! the thing is, we do need truncate. And I haven’t changed the project, so what would be the next steps?

Can you go back and check everything, and make sure the HP ports are enabled and the DMA is connected to them as it is in your original image?