My name is Matt, an Applications Engineer at National Instruments, and I will be taking over this blog. Our pal Jeff has moved on to a new position within the company.
Have you ever needed to transfer data between loops in an FPGA VI? How would you do that? What considerations are there with doing this? This blog post will go through some of the methods you can use.
In LabVIEW FPGA we have multiple ways that we can transfer data among parallel loops. Each way is applicable for certain tasks on the FPGA. In order to determine what method is best for your application you need to ask yourself the following questions:
So let’s introduce you to the methods.
Our first transfer method is a variable. You can use local or global variables to store data in the flip-flops of the FPGA. A variable will only store the latest value written to it. Variables are capable of communicating between loops of different clock domains.
Then we also have Memory items. Memory items can be Target-Scoped or VI-Defined, meaning they can be defined in the project or within a single VI. Memory items will only store the latest value written to it. It uses the on board memory in the FPGA. Memory cannot be used to transfer data between clock domains.
We also have Registers. Registers are very similar to Memory items with some differences. One difference is that register items use logic (specifically registers) in the FPGA instead of block memory, which is the most limited FPGA resource. They also can be used to transfer data between clock domains.
Finally we have FIFOs. Jeff put together a blog on DMA FIFOs earlier. FIFOs can be Target-Scoped or VI-Defined in addition to Target to Host (FPGA to Real-Time OS) or Host to Target (Real-Time OS to FPGA). These FIFOs are lossless, and can be set up to utilize different FPGA resources based on the implementation. In FIFO Properties with a Target-Scoped FIFO you can choose between Flip-Flops, Look-up Tables, and Block Memory. Flip-flops are the fastest, but cannot handle data beyond 100 bytes. Look-up Tables are the middle option, and can handle between 100 to 300 bytes of data. The last option is Block Memory, which can handle over 300 bytes of data.
If you have any additional questions about this series, please feel free to post a reply to this blog. Thanks! Also for additional information, please click this link.
Since I am working on a waveform generator using a flexrio board, I came across this blog and thought you might be in a position to help me out with the problem that I am now facing.
I am currently working on a FlexRIO platform (NI FlexRIO7962) and the dual channel DAC board from Active Technologies (AT1212) to develop a multi-channel Arbitrary waveform generator. My application needs to generate waveforms with the following specifications
Bandwidth: 200 MHz
Centre frequency: 300 MHz.
Duration: 1.25 ms.
The sampling rate of AT1212 DAC is 1.25GHz. This high rate is achieved inside the FPGA by the simultaneous read of eight consecutive samples at a rate of 156.25 MHz thereby ensuring the final rate of 1.25 GHz.
Since, my application needs to store longer waveforms, I need to make use of the on-board DRAM. This creates a limitaion, as the maximum rate at which the data to could be read to the FPGA is 100 MHz. Also, the DRAM being 128 bits wide, I can read a maximum of 8 samples at a time which gives me the maximum rate of 800 MHz. But I need to match this to the final 1.25 GHz. This calls for the need for an interpolator/resampler.
Ideally, I need a fractional interpolation rate of 1.5625. But my concern is how do I implement such an interpolator? Let us make the interpolation factor a round value to 1.6. The maximum clock that could be generated inside the FPGA would be something less than 400 MHz. So how do I implement an interpolator that converts my 781.25 MHz (1.25GHz/1.6) to 1.25 GHz? I suspect the feasibility of implementing such a block considering the maximum FPGA clock ( which is way less than 700- 800 MHz).
It would be really great if you could suggest the feasiblilty of implementing such a scheme and get me some inputs. I would really appreciate if you could please share some ideas on this regard.
Thanks a lot,
Please take a look at this white paper:
Linear Waveform Generation with CompactRIO and LabVIEW FPGA
That may give you an idea of different ways you can implement this. If you have further questions specific questions, I believe we would better be able to assist you through a service request with our support engineers. You can create one by going to ni.com/ask or by calling our support number at 866-ASK-MYNI (866-275-6964).
I read a reply about "local variable" from NI Discussion Forums,
In this reply, it mentions that "Local will insert a flip-flop in the path".
May I ask more questions about this point ?
First, there must be one flip-flop or register corresponding to a "control (or indicator) " with
additional logic and I denote the output of this flip-flop by the letter "Q".
Suppose I use a local variable to access the control (or indicator), and I denote the access
point by the letter "A" .
Will an additional flip-flop be implemented between the path QA and the output of this additional
flip-flop will be connected to point "A" when compiling the LabVIEW FPGA code?
Dose LabVIEW FPGA use the same way when the local variable is in another clock domain?
If so, how to ensure data coherency and avoid the problem arising from metastablility?
Is there any documentation from NI which describes how the "local variable", "global variable",
and "register item" are implemented at the RTL (register tansfer level) description?
With these details, a digital system can be designed in a more robust way and the delay of
each part of the digital system can be clarified.
Thanks for your help.
I would strongly recommend reading the Data Transfer Mechanisms>Transferring Data Within the FPGA section of the LabVIEW High-Performance FPGA Developer's Guide for the lower level details and recommended implementation for this use case.
Hope this helps!