I followed some examples and I already managed to make a big S2MM (stream to memory-mapped) transfer via an AXI DMA.
However, now I'm trying the reverse, i.e. to make a simple MM2S transfer to a very simple IP block that I made and the result returned from the block is wrong. Note that the MM2S code is also almost a copy from examples that I found.
I tried debugging with the ILA(integrated Logic Analyzer) tool from Vivado and the result is in attachement.
Can you help me understand why I'm writing the following values:
static void initialize_parameters(u32 SrcAddress){
u32 *BufferPtr;
union float32 thisfloat;
BufferPtr=(u32*)(SrcAddress);
thisfloat.f32=10.0;
BufferPtr[0]=thisfloat.u32;
thisfloat.f32=0.0;
BufferPtr[1]=thisfloat.u32;
thisfloat.f32=10.0;
BufferPtr[2]=thisfloat.u32;
thisfloat.f32=20.0;
BufferPtr[3]=thisfloat.u32;
}
and making a transfer like this:
// Kick off DMA transfers
Status = XAxiDma_SimpleTransfer(&axi_dma, PARAMETERS_ADDR, 4*4, XAXIDMA_DMA_TO_DEVICE);
and the signal parameters_TDATA when tvalid=1 is that thing that we can see in attachement? Also, the final result is incorrect.
What am I doing wrong?
Also, here's a print screen of my block design in Vivado.
Note: I'm working on a Zedboard
Best Answer
It seems to work, well, almost. First error I see is that you do not drive
axis_tready
. Per the AXI-Stream specification, a data-beat is valid only if bothaxis_tready
andaxis_tvalid
are '1'. The AXI DMA drivesaxis_tvalid
as expected, but do not complete the transfer of 4 dwords sinceaxis_tready
is not driven. However, the general transfer seems to work as expected.I would bet that you have a cache problem. When
initialize_parameters
is executed, it writes the data to the cache, and if you start the DMA transfer before the cache is flushed to DDR, you won't read what you wrote, but what was is still in the DDR. I don't have much experience with the Zynq and it's extensive cache system, so you have to figure out yourself how to flush the cache properly. The functions you seek are the flush functions from "xil_cache_l.h", on microblaze I would useXil_DCacheFlushRange(SrcAddress, 4*4)
. Looking at the code, it seems to flush L1 and L2 caches on Zynq, so it's probably all you need. If it doesn't work, try writing a megabyte of data, you will be sure the first 4 dwords are flushed that way.Since you have the ILA for the AXI bus, you should be able to verify if there is a write transaction at address
SrcAddress
, if there is not before the AXI dma transaction you will know this is a cache issue.On a side note, when you read using the AXI-DMA, you should do a cache invalidate before reading from the DDR. Otherwise, if you read at
SrcAddress
, start the DMA Transfer and read again atScrAddress
, you will read the old value still in cache.