05-29-2014 11:32 AM
Hi,
I'm using FPGA 7833R to issue a sequence of digital levels in real-time into 16 digital channels.
The way I want to accomplish this, is to have a U32 variable where bits 0-15 give the level of the corresponding channel. Every time a change occurs each bit in the variable is output to corresponding DIO 0-15. (I use U32 because I'd like to scale up to 32 channels)
This solution looks elegant and supersedes other implementations I devised. It uses only a single host-to-target FIFO and a single timed loop.
The problem is that accessing the 16 bits of the U32 variable is done using a fanout. This unfortunately causes severe timing violation.
I'm attaching a screenshot of the timed loop. The problematic section is the rightmost case structure, where the U32 bits are extracted.
Does anybody have an idea how can this be overcome? Is there a better way to access individual bits?
Thanks
Itay
05-29-2014 12:00 PM - edited 05-29-2014 12:03 PM
Hi itayshom,
why not use a simple NumberToBooleanArray followed by a single IndexArray node?
It really looks like RubeGoldberg to use 16 constants with 16 boolean functions followed by 16 comparison functions…
Slightly more advanced:
Most DIO cards I used before allow settings several outputs at once by addressing them as "Connector0: DO0-7". That way you would only need to use two AND and a shift function…
Edit: Bruce got the exactly same suggestions. There seems to be a pattern… 😄
05-29-2014 12:02 PM
There are a couple of easy ways to do this.
The first is to use Integer to Bit Array, which converts the number into the individual bits. From there, use an Index Array and just pull down as many elements as you need. Wire each bit directly to the digital output.
Most digital outputs have the option to write an entire word at once. I am guessing you could split your U32 twice to get the first two U8 parts, and wire them to Connector1(0:7) and Connector2(0:7), or something like that. This really does the same thing, but is cleaner code than the bit array.
Bruce
05-29-2014 12:44 PM - edited 05-29-2014 12:44 PM
Just to show what everybody else it saying...
06-01-2014 03:11 AM
Thank you all for your help! This is exactly the kind of solution I was hoping for. However I still have a problem.
Regarding the integer-to-boolean array solution, I implemented it but there's still a timing violation. I'm attaching a picture with the new version. Is this supposed to be alright?
Regarding the multiple DIO port write: When I place an FPGA I/O node, I can choose "Connector 0", "Connenctor 1" or "Connector 2". The program works with Connectors 0 & 1, as can be seen, and I don't want to change that because of other dependencies.
However, the option DIOPORTx etc. only appear on Connector 2... is there a way to resolve this?
Thanks.
Itay
06-01-2014 03:57 AM
Your 32bit greaterorequal is costing a lot of time. Is this really neccessary?
Can you post a screenshot of the compile error?
06-01-2014 06:40 AM
Ok, sorry, I've found a way to access DIOPORT0 on both connectors. Attaching the new version.
However, there's still a timing violation. Also attached.
The greater-than-or-equal is used to decide whether it's time to output the new digital levels.
Any suggestions will be appreciated.
Itay.
06-01-2014 07:31 AM
It seems like your "Greater or equal" is costing a lot.
It seems like you're sending data from the host via DMA FIFO and are using the first 32 bits as some kind of signal when to stop. Can you not replace this with a single boolean to signal the endof the data? Even comparing to 0 is relatively expensive for a 32-bit number. Switching to a simple boolean (for example, first byte of the input data instead of the whole 32-bit number).
You can then send a "stop" signal as a simple boolean from the host to tell the loop when to stop.
The "fan out" error is an optimisation problem of the xilinx compiler and has nothing to do with the "fanout" of your 32-bit number to the digital outputs.
06-02-2014 03:51 AM
Also adding shift registers in correct strategically chosen places will help.
06-02-2014 07:35 AM
From a digital design standpoint, you are trying to accomplish a lot in a single clock:
1. Check if FIFO is non-empty (negligible)
2. Read out an element (access time of memory, depends on mem type)
3. Perform a wide subtraction followed by a wide compare option (propagation delay through multiple levels of logic)
All of those operations need to have settled within a setup time before the next 80MHz clock.
You could try inserting a feedback node between the FIFO Read and the compare; it adds (1) 80MHz period of latency, which doesn't appear likely to cause a problem, while breaking up the longest path components (memory fetch and subtract/compare) into separate operations. Could also be done with shift registers as Intaris said -- same concept and final result (one cycle of latency).
I believe your fanout issue happened because you connected your signal to 16 separate AND gates. FPGA hardware has synthesizer limits to prevent delays from excessive load capacitance; each sink (gate) has input capacitance that must be charged, and too much capacitance can slow signal rise times enough to violate setup times (especially at high clock rates). Synthesizers usually have settings that allow you to fiddle with fanout limits, but LabVIEW doesn't give you that level of access. Probably not a good idea at 80MHz, anyway, unless you really know what you're doing.