LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Passing Data from FPGA

Solved!
Go to solution

Hey guys,

 

I'm pretty new to Labview FPGA. I am just trying to stream data from the FPGA to my RT program. The problem that I am having is that sometimes my FIFOs come across with different numbers of elements. It only happens once every few seconds. One of the FIFOs will have anywhere from 1 to 10 fewer elements than the others. I have seen examples where people use a a single FIFO to do what I am doing which I will probably try next, but I can't make sense of why this wouldn't work too. Any suggestions?

 

FPGA 

crk98_0-1583531218802.png

 

RT

crk98_1-1583531547475.png

 

Thanks

 

0 Kudos
Message 1 of 8
(4,305 Views)
Solution
Accepted by topic author crk98

Well, your code will I guess work (sort of) but as you've seen, the number of elements isn't deterministic at the RT side.

How fast is your "Analog Loop Period"? I'm guessing fairly quick...

 

The RT system probably has 1 or 2 cores, and I'm guessing what happens is something like the following:

  • Because of the error wiring, none of the <read num elements> operations can start until they're all effectively ready. However, they can start later!
  • There's no dependence between reading the number of elements, and reading the actual elements (i.e. there can be delay between those operations, or not)
  • It's possible that you (labelling your inputs as A, B, C, D) do something like this:
    • Read N_A
    • Read N_B
    • Read N_C
    • Read A(N elements)
    • Read B(N elements)
    • Read C(N elements)
    • Read N_D (different value)
    • Read D(different number of elements, because you effectively waited longer)
  • or any variation on those orderings, such that you read the number of elements at different times and get different results.

You'd be better off specifying how many elements you want to read, if you want to use this system.

If you wire a constant (choosing the value to approximately match the period you want) then you'll need to allow a timeout on the RT, but you should avoid different numbers of outputs (since they're all receiving data at the same rate, based on the visible FPGA code).


GCentral
Message 2 of 8
(4,262 Views)

cbutcher explained a lot of the reasons why I would typically recommend pushing all of the data into a single FIFO

 

If you put all 4 elements into the same FIFO then all you need to do on the host is look at the number of elements available and use the quotient & remainder function to see how many groups of 4 elements you can read. The decimate array function then makes it simple to break the single array into the 4 individual data streams.

Matt J | National Instruments | CLA
Message 3 of 8
(4,212 Views)

I regularly use multiple FIFOs in parallel to transfer data. As cbutcher said, the problem is the lack of determinism in the RT. You can rest assured that the FPGA is certainly putting one element into each FIFO; there is no circumstance where one FIFO will have had more elements put into it than another, instead the RT will have waited different amounts of time between reads.

 

To get the same number of elements, you should read batches of defined size. The size is pretty arbitrary, but you could even use the first read's Elements Remaining as the subsequent read's Number of Elements.

 

Alternatively, use a small timeout (10-100 ms) and a large number of elements (1000-10000). The read will either return the number of elements or timeout with a smaller number of elements being returned. You then use a queue to pass the data from your fast polling loop into a slower parallel processing loop.  You can decide whether you want to locally buffer (shift register) the smaller number of elements or send it on ASAP. This way you will ensure that your FIFO reads are large and you cycle your FIFO polling loop minimally, while also being responsive to sudden fluxes in data rate.

 

 

CLA - Kudos is how we show our appreciation for comments that helped us!
Message 4 of 8
(4,188 Views)

Thank you all for your help! I modified my code as follows and it's working perfectly now. No more gaps in my timestamps which is what I was seeing before.

 

FPGA:

FPGA Code.JPG

 

RT:

RT Code.JPG

0 Kudos
Message 5 of 8
(4,179 Views)

I think if it works perfectly, you're lucky in your timing.  You are sending in groups of 4, but perhaps the RT checks the number of elements and finds it isn't a multiple of 4?  That will happen if the 2nd, 3rd, or 4th elements haven't had a chance to be added to the FIFO yet.

 

You should check the number of elements on read.  Do a Mod 4.  Multiply the quotient by 4.  Then read that.  It will leave the stray elements in the FIFO for the next time around.  So if let's say 4 elements were put in one batch, and only 3 of the 4 in the next batch at the moment the # of elements check occurs, it will be 7.  Mod 4 will give a quotient of 1  (remainder of 3).  Multiply by 4.  Now read 4 elements.  The remaining 3 will stay and be waiting for when the last element of the packet gets entered.

 

If you don't always read 4 at a time, the 4 arrays will get out of sync.

Message 6 of 8
(4,155 Views)

Given your new design (4 elements enqueued in order to a single FIFO) I'd suggest (like RavensFan described in detail above) that you should dequeue a multiple of 4 elements every time.

 

If you have a fixed acquisition rate (polling loop time on FPGA) then I'd say the simplest method is something like the following:

  1. Determine the desired update rate on RT
  2. Work out how many iterations of FPGA will occur in that time
  3. Multiply by 4
  4. Read that many elements (don't check the available number, just read that number)
  5. Make the timeout value a decent chunk longer than the time value from step 1.
  6. If timeout is true, something went wrong. Handle this error appropriately, taking care that the number of elements read will be 0 if timeout is true.

 

If timeouts are absolutely not allowed, then the appropriate (and slightly more complicated) process is as RavensFan detailed:

  1. Read available elements every (N milliseconds, time as chosen in step 1 from first process)
  2. Divide by 4, take quotient, multiply by 4
  3. Read that many elements. Take care that if fewer than 4 elements are available for some reason, this might be 0.
  4. You will never timeout with this method, but you might read 0 elements if for example the FPGA toggles on/off with some other controls. So consider if you need to handle that case.

Also note if you might want a different number of channels in future (because you're turning some off, or you add new channels) making your "4" value an output of something (class, subVI, global variable, whatever) might be a worthwhile modification, then you only have to change it in one place.


Edit: as a follow-up to that last point, if you change the number of channels whilst you have elements in the queue, things will get messed up. I do this on my FPGA application and I handle this by having the RT and FIFO handshake via a boolean control on the FPGA Main front panel and flushing the FIFO. The process (at a high level) looks something like:

  • RT decides to change number of channels
  • RT sends new number of channels to FPGA, and indicates that it is waiting for the FPGA to say it is done changing. It stops reading from the FIFO
  • FPGA receives new number of channels, stops acquiring (samples might still be in the FIFO from the old number of channels) and changes the number of channels. In my case, this involves various SPI communications with digital switches etc, not just a software change.
  • FPGA indicates it is ready to resume, everything is done
  • RT flushes FIFO, indicates it is ready to resume. It can now begin waiting on the FIFO.
  • FPGA resumes acquisition, and starts enqueuing to the FIFO.

GCentral
Message 7 of 8
(4,153 Views)

Thank you guys, again, for your detailed feedback. I am learning a lot!

 

For the record, I didn't ignore the initial suggestion to add the divide by 4, multiply by 4 logic. I put that in and set a conditional breakpoint on the remainder. After a couple hours running I hadn't seen anything but zero as the remainder so I made a *bad* assumption that something must be going on in the background that was forcing the correct number of elements in and out of the FIFO. I see now that there is nothing automatically preventing the reads and writes from getting out of sync, I was just lucky. I have put that back in.

 

Thanks

0 Kudos
Message 8 of 8
(4,126 Views)