First of all, I’m sorry for the late reply. I’ve been really busy lately and haven’t had a chance to look at this.
I have a few notes on your design in terms of PYNQ and our own QPSK design, and some follow up questions for you to help clarify what it is you’re trying to do.
In the block design tcl file you supplied you are using a PL DDR4 MIG IP. Is there a particular reason you want to use this as opposed to the PS DRAM? I haven’t used the DDR4 MIG IP before so am unsure about what the setup would look like for this. PS DRAM is the method we use to communicate via AXI-Stream in our own QPSK demo using the DMA IP. What example on this site did you base your design on?
On the subject of DMAs: Scatter Gather is not currently supported by PYNQ so you would need to disable this in order to use the DMA with PYNQ.
The xrfclk driver only supports certain PLL reference clock frequencies. There is a function in the xrfclk driver that will output the reference clock frequencies available to you. I don’t think the one you have picked (400 MHz) is supported. This frequency shouldn’t have any impact on your design therefore, if you pick a supported one should have the same effect. There is also a method to send your own register values to the clocks to set custom frequencies (this is only in the PYNQ 2.4.1 image), but this is not a particularly user-friendly option.
The Data Converter IP settings in your design show that you are using the DAC-C2C-Multi-2x2* preset. What are your reasons for using this? In your design you have no connections made to the 3 AXI-Stream inputs on the Data Converter IP, so no data would be able to get to the DACs. The AXI-Lite interface is used for configuration.
Generally, you would use PYNQ to write to memory using a DMA, and this DMA IP would be connected to a DAC using the respective IP AXI-Stream interfaces. If this was the approach you wanted to take, you could use 3 DMAs to send data to each of the 3 DAC inputs you have instantiated. Due to PS restrictions, PYNQ can only write to one DMA at a time though, meaning there would be idle time between each DMA transaction. Also, there’s not neceassrily a guarantee from Linux that data could be continuously sent to the DMAs. In our QPSK design we generated our random symbols on the PL so we avoided this obstacle.
If you did want to write continuous, looped data to the DACs, one option would be to use BRAMs on the PL filled with the data you generated in Python, then cycle through the BRAM address space using a counter. There is a ‘Single/Dual Port Ram’ IP in System Generator that would make this fairly easy to set up (although you would have to design the AXI-Stream Master signals yourself). You could then use PYNQ to write the data to this System Generator IP, with an AXI-Lite interface to control the counter and RAM blocks.
You can go to our GitHub repo for the QPSK design and look at how we put that together (we provide all our design files in there including System Generator and Vivado project files).
I will be able to look at this again in a week or two if you can provide a bit more information (and if you still need help of course).