LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Multiple FPGA loops to solve 8 channel AI / 4 Channel AO with PID compilation problem

I've got a challenging FPGA project that I'm working on and I was hoping the community could help me out.  I have a 9014 with a 8-port backplane and I'm using a 9205 (configured for +-1V measurement) for AI and a 9263 for AO.

I have a custom circuit that modulates (using the AO line) the voltage applied to the thin-film device (i.e. to heat it up).  In order to calculate the highly dynamic resistance of the device we measure the voltage across two fixed resistors.  Using some network algebra, I can obtain on-the-fly resistance.  I can do this with one device (read, calculate, go through PID, and write), but the trouble is that I want to do this with four or more devices.  The hardware is there (many AI's and four AO's), but I can never get my FPGA code to compile with more than one loop.

I have to do this on the FPGA (the math part) because I also have incorporated a PID loop to hold the device at a certain resistance (so, for example, airflow through or across the device will not affect the heating).

The thermal response of the thin-film devices have time constants of <100 ms (Apply 10V, the device heats to steady-state in 40-50 ms).  I'd like to sample at least twice per millisecond at a minimum, but of course the more the better.

Attached is the "single device" FPGA code (FPGA One Shot) that works (ugly original version that compiles successfully also included FPGA Orig).  I've pipelined the code as much as I can - maybe there's more I can do?  Adding more independent loops (identical, just changing the AO/AI channels) kills the compile.  I've also tried to put all the code in a single loop with no success either.

I've considered using two fifo's, one to send the measured data back to the RT host to do the calculations, then one to send data back to FPGA for PID and AO.

Also, is there a way to use a slower clock than the 40MHz one on the RIO?  My compile attempts always seem to fail at like 39.8 MHz or really close to 40 MHz.  Seems like 8us (1/8us = 40 Mhz) is overkill.

As always, thanks for the input!

Tommy R.


Message Edited by trouinky on 06-03-2008 03:20 PM
><><><><><><
Tommy R.
><><><><><><
Download All
0 Kudos
Message 1 of 16
(3,932 Views)

Hi Tommy,

It seems like you are following most of the techniques for optimizng FPGA code.  There are a few you may still be able to apply:

1. Use the Select function instead of a Case Structure with R 1 hiLow. 

2. Eliminate coercion dots by using Conversion functions.

3. Use the smallest data types possible.

4. Where possible, change front panel controls and indicators to constants.

It is possible to derive a clock from the onboard clock, but the slowest top-level clock supported on the 9104 is 40 MHz, or 25 ns per clock cycle.     

Jennifer R.
National Instruments
Applications Engineer
0 Kudos
Message 2 of 16
(3,890 Views)
Memory wise, I have plenty of slices left (I think I'm at like 18 percent) but I mostly get timing violations at the end of a compile.  Does this basically mean that my loop can't complete in a single clock cycle (equivalent to less than 25 ns)?  This is starting to make sense.  The trouble with this solution is that the deterministic value I'm sending to the PID is the result of two voltage measurements (some math in there based on a network of resistor values).  Using a single measurement with some math would no doubt run a lot faster.  I did this before when I was measuring current directly, but I needed better resolution so I switched to measuing the voltage drop across a fixed resistor . . . . this required me to measure two voltages in order to calculate the resistance - similar to a full bridge technique.

Thanks!

Tommy R.
><><><><><><
Tommy R.
><><><><><><
0 Kudos
Message 3 of 16
(3,876 Views)

I notice you are not using a single cycle timed loop, but I don't think you can use those with analog signals.  If you can, you probably need to generate a slower clock.  I didn't think you would have timing exceptions when not using the single cycle timed loop, but what do I know?

My big question:  Why did you use delayed shift registers?  By using multiple terminals for each shift register, the delay between reading an input signal and generating an output related to that input is about 10 loops.  It really doesn't make any sense to me unless the delayed signals are part of your calculations, but I doubt that.

I would think that you could easily clean up the code and put four copies of the loop on the diagram without much problem.  It is kind of challenging to debug FPGA programs, though.  Things that look like they should work great have some small error that is unexpected.

Posting the actual code wouldn't hurt, either.  We would have to sit through the compile process to test it, but we might be able to post improved code for you.

Bruce

Bruce Ammons
Ammons Engineering
0 Kudos
Message 4 of 16
(3,857 Views)
The delayed shift registers were an attempt to pipline the whole loop since my PID variable is based on two voltage measurements.  The idea was to stack up the readings and preliminary calculations based on previous analog reads so that once everything was available the pid subroutine could run based on data from previous loops and the analog reads would be used in later loops and the write would be performed in the next loop.  My current code uses a subroutine that dispenses with the pipelining, but my compile still fails when I add four independent loops for each device.  Actually, it occasionally fails with only one loop.  I can't figure out what's the offending code.  It doesn't seem to be asking too much of the hardware.

I'll attached the newest FPGA master VI and the subroutine that it calls in each loop shortly if anyone wants to take a shot.

Thanks!

TR
><><><><><><
Tommy R.
><><><><><><
0 Kudos
Message 5 of 16
(3,842 Views)
Yes, can you please attach your code so I can take a look at it?
Eli S.
National Instruments
Applications Engineer
0 Kudos
Message 6 of 16
(3,821 Views)
Here's the latest version doing DAQ and PID for all four devices in one big loop (four independent loops fail to compile, as does this VI - a timing error, not a memory thing).

There's no pipelining in this version since I use a subvi without a loop to do the actual AI/PID/AO step.

I can get a three device program to compile with either a single loop or independent loops.

All this is not considering I still need to get the data off the FPGA via the FIFO.  That code has been removed, but it's in another loop inside the main vi (using local variables) and doesn't seem to affect the timing error.

I guess if this technique doesn't work, my only alternative to this is to read the AI, send the data to RT via FIFO, do PID there, then send back to FPGA via FIFO for AO.

Thanks,

Tommy R.
><><><><><><
Tommy R.
><><><><><><
0 Kudos
Message 7 of 16
(3,813 Views)
The PID Express VI is what's causing your problems.  If you look at the implementation of the PID VI, you will see that it uses a couple of single cycle timed loops to minimize the amount of logic it consumes in the FPGA.  To see the implementation, right click on the VI and select Open Front Panel.  This will convert the Express VI to a regular sub VI that you can view.  However, it appears these single cycle timed loops are creating some combinatorial paths where it is difficult to meet timing at 40 MHz loop rates as the utilization of the FPGA increases.  To work around this, I created a 30 MHz derived clock in the project, converted the Express VI to a sub VI, changed the source of both single cycle timed loops to the 30 MHz derived clock, and resaved the sub VI.  Once I did this, I was able to compile the top level VI successfully.  I've attached the modified project for reference.  If you have difficulty reproducing what I did, post back any questions and we can go into more detail on the specifics of creating a derived clock, etc.  Also, be sure to post back if you're unhappy with the final loop rate or utilization of the FPGA for the overall program.  I think there are some additional opportunities for optimization, but I won't complicate the implementation of your program if you're happy with the current performance.  The one thing I will mention (since it won't affect your code at all) is that the convert period on the property page for the 9205 is set to 25 microseconds.  This can be set as low as 4 microseconds.  However, a lower setting may affect the accuracy of your measurements so you'll have to make that trade off yourself.
0 Kudos
Message 8 of 16
(3,794 Views)
I knew there was a way to create a derived clock that runs at a slower rate, but since I couldn't use the pid in a SCTL, I didn't push the point.  Know I know how to do it, and I owe you a premium six pack.

I never considered the PID VI to be the offending item - looking in the dependencies and seeing the three sub-vi's that make up the express VI, I should have investigated further.

I played around with the timing on the 9205 convert period mainly in an attempt to make the main VI compile successfully.  I seemed to have better success when the settling time was higher (25-100 ns) compared to when I compiled with lower settings.

I'm recompiling with your new PID SubVI and am confident it will succeed.  When I left work last night, I had a successful compile with my original code (nothing was changed from what's posted above other than a few really minor tweaks) so I'm perplexed.  Unfortunately, there was an error in the program where measurements for one of the AI channels was being used twice.  I fixed the error and once again, the compile was a no go.  Argh!

As I may or may not have mentioned previously, I need to get the data onto the RT controller, mostly to closely monitor the current through each device.  Since the resistance changes when voltage is applied (the devices heat up - resistance changes about 10-20%), I have a VI (on the host that calculates the thermal time constant which can change over time (this has to do with how we're using the devices in our system).  The thermal time constant is on the order of 40-60 ms, hence the need for a high frequency measurement (at least two samples every ms should be sufficient).  I've sent the data with a FIFO back to the host, but of course when adding this function to the MainVI on the FPGA target, it kills the compile.  Any suggestions for this addition, as well as any other optimizations are greatly appreciated.
><><><><><><
Tommy R.
><><><><><><
0 Kudos
Message 9 of 16
(3,775 Views)
Hi,

What compilation error are you getting? Are you using almost all of the FPGA resources without this function? Is possible that you ran out of space.

Eli S.
National Instruments
Applications Engineer
0 Kudos
Message 10 of 16
(3,733 Views)