LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

FPGA: interleaved dma fifo "shuffles" inputs

Solved!
Go to solution

I'm using a DMA FIFO to transfer acquired data from a FPGA (NI 5783 in a NI 7931R) to the RT host. I acquire 3 inputs and would like to stream the data. I have read in whitepapers that the best practice to do so is using a interleaving scheme.

However, when reading out the data on the RT host, I notice that data got shuffled on the way, e.g. data from DA input 3 is now input 1. The RT host reads out three elements of data per time, as suggested in the white paper, therefore I can exclude having made a mistake on the readout side. I suppose I made a mistake on the FPGA side, yet I cannot find it.

 

I attached the FPGA vi in question, perhaps you can have a look and notice anything stupid. Also, please find below screenshots of said vi. there you can see two loops.

 

The first loop acquires data and does sort of a "continuos average" in a FPGA gentle manner using bitshifts. Since this is a single cycle timed loop, I cannot feed multiple elements into an DMA FIFO. Therefore, I only feed an acquisition buffer.

The second loop then reads out the acquisition buffer and writes the data into the DMA. If the DMA is full, it is flushed before writing the next element (this is desired).

 

Acquisition and averagingAcquisition and averagingFilling the DMAFilling the DMA

 

0 Kudos
Message 1 of 12
(3,534 Views)
Solution
Accepted by topic author TomD3

I doubt that the data is not shuffled.

 

What happens is that the moment you get a time out or flush the stream, you have no idea where you start again. So the stream is 1,2,3,1,2,3, and that seems to stay that way. But the moment you get a timeout or flush, there is no telling where you continue. So you might get 3,1,2,3,1,2, 3.

 

If you're careful, you should be able to get in sync again. First stop the pushing of data, then flush on RT, then start waiting for data, and then start.

 

Alternatively, and much safer AFAIC (but less scalable) you could build an U64 instead of an array. Then put the U64 on the buffer. This will guarantee the data integrity. EDIT: It will also obsolete the 2nd loop, I think.

0 Kudos
Message 2 of 12
(3,515 Views)

@wiebe@CARYA: thanks for your reply. I understand: flushing the DMA might take some time. During that time, the first Buffer-FIFO might overflow. Three elements at once will be written into the Buffer-FIFO, while another three elements will pop out into the nirvana. Therefore, they should not shuffle.

Also, readout is always three elements at once.

 

I now tried another approach: i got rid of the Buffer-FIFO and the second loop. In the single-cycle-timed loop, I filled the FIFO using shift registers, one element per tick... Let's see where that goes.

0 Kudos
Message 3 of 12
(3,504 Views)

@TomD3 wrote:

@wiebe@CARYA: thanks for your reply. I understand: flushing the DMA might take some time. During that time, the first Buffer-FIFO might overflow. Three elements at once will be written into the Buffer-FIFO, while another three elements will pop out into the nirvana. Therefore, they should not shuffle.

Also, readout is always three elements at once.


I think it's a bit different. It's not about the flush taking time. When you flush, there's no telling where the steam is cut off. Same for a time out, unless the number of elements is a multiple of 3, the point where the stream is broken is not an exact number of elements. The read and write are out of sync.

 


@TomD3 wrote:

I now tried another approach: i got rid of the Buffer-FIFO and the second loop. In the single-cycle-timed loop, I filled the FIFO using shift registers, one element per tick... Let's see where that goes.


That will probably do some good, as you eliminate a layer. It won't solve time out problems, unless you stop the pushing, flush on both sides, then start reading and then start pushing.

 

I'd still go for integer packing over multiple elements, but suit yourself. I've been burned by this kind of problem a few times... Simpler is better.

0 Kudos
Message 4 of 12
(3,501 Views)

I can see the ease and simplicity of going to U64. Just afraid that at some point I would like to cram more data into that DMA - as you say, it is not perfectly scalable....

0 Kudos
Message 5 of 12
(3,496 Views)

@TomD3 wrote:

I can see the ease and simplicity of going to U64. Just afraid that at some point I would like to cram more data into that DMA - as you say, it is not perfectly scalable....


On modern FPGAs, there are a few DMA channels. If you can make 3, that would make things a lot easier as well.

0 Kudos
Message 6 of 12
(3,492 Views)

In fact I could. However, this will further increase compilation time (at least in my experience) and my development turnaround.

 

After the shift-register approach also brought up those "shuffling" errors every now and then, I do not understand how that's possible, I am now trying the U64-approach...

edit: I guess you just add 65536 to the second input and 131072 to the third and then add everything up. On the RT system you would then subtract again to get the raw inputs. Is that correct or is there a more genuine way to go?

 

Im surprised: This seems in fact pretty much like a routine thing to do, yet it is quite tricky to implement.

0 Kudos
Message 7 of 12
(3,485 Views)

I believe the DMA FIFO channels are 32 bits wide, unless this has changed on more recent targets.

If you have 2 16 bit values, in terms of performance, its best to bit pack them into a single 32 bit number.

 

In this case, combining 3 16 bit values into a 64 bit number would make the FPGA actually split the number into (2x32bit) and trigger 2 writes (transparent to the user), so you wont gain much if anything.

 

On these modern FPGAs you will have 16 DMA channels anyway, you should need to interleave less.

 

0xDEAD

 

 

0 Kudos
Message 8 of 12
(3,479 Views)

@deceased wrote:

I believe the DMA FIFO channels are 32 bits wide, unless this has changed on more recent targets.


Maybe internally. I've used 64 bit DMA FIFOs a long time ago.

 


@deceased wrote:

If you have 2 16 bit values, in terms of performance, its best to bit pack them into a single 32 bit number.


Yes, check out Join Numbers function. Join A and B, and C and 0, Join the results, to get one U64. Use Split Numbers to get them back...

 


@deceased wrote:

In this case, combining 3 16 bit values into a 64 bit number would make the FPGA actually split the number into (2x32bit) and trigger 2 writes (transparent to the user), so you wont gain much if anything.


The FIFO will simply pass 64 bit integers. It would make life a hole lot easier.

 


@deceased wrote:

On these modern FPGAs you will have 16 DMA channels anyway, you should need to interleave less.


That might be best. I'm not sure if compile times should be a concern. I'm not sure how much a DMA FIFO adds in terms of slices\gates. It might not be too bad...After all, the total amount of buffered data will be the same.

Message 9 of 12
(3,470 Views)

I too have joined number into 64bit for sending along the DMA, but the bus is (or was) physically only 32 bits wide, so it automagically splits the number up for you and does the 2 DMA writes behind the scenes.

 

0xDEAD

 

0 Kudos
Message 10 of 12
(3,463 Views)