Forum Discussion
SGDMA debug
Hello,
I am trying to learn how to use SGDMA to transfer data to memory. First of all, I am trying to connect SGDMA TX directly to SGDMA RX and check results. You can find the source code ->here<- (http://www.codeupload.com/4051) (I've edited the code found on forum, so thanks the guy who provided it). In order to check what is written to the memory, I've connected the SGDMA modules to ONCHIP memory (size: 32768 bytes) and enabled memory content reader on the on-chip memory options. You can see my connections ->here<- (http://i51.tinypic.com/1zz6fj5.png). The problem is that this dma design doesn't work. The data I get is corrupted. I've tried to disconnect cpu.instruction_master and cpu.data_master from onchip memory, then the memory start address goes to 0x00, but results are the same. If I connect the DMA to the DDR memory, then the data passes correctly, Screenshot is ->here<- (http://i53.tinypic.com/2heak61.png). Now why I get this situation: either I try to read or write from/to onchip memory or DDR memory, the core always tries to read/write from/to address 0x800xxxxx. Obviously when it is connected to DDR ram it works, but when to onchip ram it doesn't. Why is this happening? Nios memory bus bugs? How can I check what is written to the memory? If I use only onchip memory for the whole system and DMA it also works fine, but I want a clear vision without Nios stuff in the memory. Thanks.55 Replies
- Altera_Forum
Honored Contributor
BadOmen,
Thank you very much. I will try it as your guide. Reference to the examples, I wrote my code. Care must pay attetion to the two diferrences: 1) descriptors are stored in on-chip memory, and just use a small piece of the memory in this test code. So how to solve the other ? 2) the buffers for ADC data is defined as an array, not allocate with Malloc() function. So I beg you to check my code again, please. Another question: how about the SGDMA data rate? In this test, the ADC is 200Msps. - Altera_Forum
Honored Contributor
* edit misinterpreted what you said.
200MS/s would require a memory of equal width or wider operating over 200MHz (SGDMA would need to be just as fast). Normally you take the ADC data, feed it through a data format adapter to make it wider and make the SGDMA and memory path wide to accomidate the data rate. That said I think Nios II will have a hard time keeping up with interrupts coming in that fast unless you allocate huge buffers to hold the data. The SGDMA is limited to under 64kB buffer transfers due to the descriptor limitations. Perhaps your buffer length is 64kB or larger? That would be a problem for that SGDMA to handle. - Altera_Forum
Honored Contributor
The ADC is 200Msps 8-bit, and the DDR2 clock frequency is 150MHz, 16-bit data bus.
Bufffers are defined as follows:# define number_of_data (1024*1024) # define number_of_buffer 10# define length_of_buffer 12 - Altera_Forum
Honored Contributor
So do you have 1MB of data split into 10 individual buffers (so ~100KB each)? If so then you'll need to use smaller buffers since the SGDMA can't transfer any more than 65535 bytes because the transfer field of the descriptor is only 16 bits wide. I might be misinterpreting what number_of_buffer and length_of_buffer represent.
Do you have to continuosly sample? I ask because it sounds like you have enough SGDMA and memory bandwidth to handle 200MS/s but you might need some long descriptor chains in order for Nios II to be able to keep up with the maintence (asumming you use ping-pong buffering). Also if you continously sample and need to ship the data offchip over Ethernet Nios II will not be able to keep up with that over TCP (it'll struggle to do that with UDP). - Altera_Forum
Honored Contributor
Thanks for your reply.
The number_of_data defines the memory for ADC data. In my test design, only part of the memory are used. The number_of_buffer and length_of_buffer represent the number of descriptors in the descriptor list and number of bytes transmitted for one descriptor respectively. So the defination is OK. I don't need to continuously smple, just sample several MB bytes and then stream out . Now, SGDMA is the bottleneck of my design. I'm really confused. - Altera_Forum
Honored Contributor
I created a Avalon stream component for ADC, consisting of a LVDS_RX module and other conduits. Maybe there is some flaw in my ADC component. Is there any examples ?
- Altera_Forum
Honored Contributor
Hi nwyfauq,
I was wondering how you "set the last descriptor in the chain to point to the first one"?. I'm using the mSGDMA and wondering if the same functionality is possible. - Altera_Forum
Honored Contributor
nwyfauq would have pointed the next descriptor field to the start of the descriptor chain. The SGDMA uses linked-list descriptors where one descriptor points to the next so to have the DMA wrap back around the end of the chain just needs to point to the start. When the SGDMA consumes descriptors it sets the owned by hardware bit to 0 so if you wrap the end of the descriptor list to the start and want the SGDMA to immediately start consuming those descriptor again you have to set the park control bit as well. This park bit prevents the SGDMA from setting the owned by hardware bit to 0 after it's consumed (i.e. the descriptor remains owned by the SGDMA after the SGDMA is done processing it).
The mSGDMA doesn't use linked-list so there is no direct way to have it recycle descriptors. It has park bits in the descriptor field but the behavior is different. The mSGDMA re-uses the same descriptor if the park bit is enabled and there are no other descriptors buffered. For example if you want to transfer 1MB and keep transfering 1MB from the same location(s) in memory as soon as the 1MB has been transferred the mSGDMA will reuse the same descriptor to transfer the data again. To stop it from re-using the same descriptor you simply write a new descriptor and it will switch over (after the current transfer completes). - Altera_Forum
Honored Contributor
Thanks for your reply. I had worried something like this might be the case. In the last couple of days my plan has been to hack the "fifo_with_byteenables" block in the dispatcher to restart the chain.
My understanding is that the descriptors are held in a ram ("the_dp_ram"), so I'm trying to reset the read address to 0 at the end of my descriptor chain. So when "pop" is asserted and read address is at the end of my chain, reset the read address for the descriptor ram to 0 and set the "internal_used" back to its value at the beginning of the chain (I have 8 descriptors for 8 different memory locations). So far it seems to be working well, but I havent finished testing it yet. - Altera_Forum
Honored Contributor
That should work as long as you plan on that to be the behavior all the time. I haven't thought this through much but the way I would implement it is use a falling edge detector on the fifo_empty signal and use that to reset the tail (read) address of the FIFO while leaving the head (write) address alone. Having a host keep track of where you are at might be a pain unless you have the last descriptor firing off an interrupt but I'm not sure if that matters to you.
The way I planned to tackle this was to have a prefetch block sit in front of the dispatcher and have it responsible for fetching descriptors out of memory and shoveling them into the dispatcher. I became sidetracked with a new and improved DMA that I'm perodically working on that should kill two birds with one stone so I never got back to making that prefetch block.