We are in the process of upgrading our project from Quartus 13.1 to 18.1. Everything is working again, except the SGDMA component, which seems to have undergone some changes between these versions. We’re working with an Arria V FPGA and the SGDMA is connected via an PCIe bus to a Linux system.
The first problem I encountered was the address offset of the registers. I’ve looked at different versions of the documentation from Quartus 9 to 20 and the documentation always stated that the register offsets are given in 32bit word offsets. So the control register is at 4 words or 16 bytes offset from the base address. Contrary to this the Linux kernel module we use to control the SGDMA always accessed the register with an offset of only 4 bytes. But with the upgrade to 18.1 the SGDMA didn’t work at all until I changed the offset to 16 bytes as stated in the documentation. I also tried the 13.1 version with a 16 bytes offset which didn’t work. Can you confirm that the register offsets did change or explain this difference I’m seeing?
While the SGDMA is now kind of working again with 18.1 there still seems to be a problem with the reporting/detection of end of packet in streams. We’re using the stream to memory configuration and use the EOP signal to flush the data buffers. With the 18.1 SGDMA I’m just never seeing the EOP_ENCOUNTERED status. The transfer always completes the whole descriptor chain and finishes with the DESCRIPTOR_COMPLETED and CHAIN_COMPLETED status. I have no clue how to fix this problem. Was there any change affecting the detection of EOP?
I've just had another idea and compared the generated HDL files generated by the Platform Designer. I've found some interesting changes regarding the EOP behavor. The file generated with the SGDMA component version 13.1 has the following line:
assign t_eop = sink_stream_endofpacket && sink_stream_really_valid;
With version 18.1 this line was changed to:
assign t_eop = (sink_stream_endofpacket && sink_stream_really_valid) && (bytes_to_transfer == 0);
So there is now an additional check for bytes_to_transfer. It looks like this is the field comming from the DMA descriptor. For a test I changed the byte_to_transfer field to 0 instead of the buffer size reserved for DMA. And sure enough the EOP is now processed and everything works as expected. However, I'm extremely unhappy with this change, because it could allow the DMA to write outside the allocated buffer when no EOP is generated in time. Why was this behaviour changed in the first place? Why is it not documented anywhere?
Nevermind. The issue was not with Quartus but actually the design contained a modified version of the SGDMA component. Thus upgrading the IP version would switch to the unmodified original version. The custom modifications performed by a third-party explain the byte/word addressing issue and EOP behavior.