Overview
Development with the NI LabVIEW FPGA Module is very similar in many ways to development in LabVIEW for Windows or the LabVIEW Real-Time Module. The same graphical programming constructs apply to all platforms, and the LabVIEW FPGA functions are – for the most part – a subset of the functions found in Windows. Despite the many similarities, any LabVIEW FPGA programmer will tell you to think differently from the ways of software engineering. Besides pondering processing with massive parallelism and keeping in mind hardware concepts like registers, pipelining, clock cycles, and communication between asynchronous modules, the development techniques are significantly different.
Table of Contents
Why Is FPGA Development Different from LabVIEW for PC?
There are three main reasons that make the development techniques different between field-programmable gate array (FPGA) hardware and computer software.
- Compilation time – You need a significant amount of time to compile a design to hardware code and run it in the FPGA, and it normally takes multiple compiles to work out bugs. Therefore, total time spent compiling can be expressed as a simple multiplication between the time for one compile multiplied by the number of compiles needed to get everything working. The time for one compile can come as a surprise to the LabVIEW programmer turned digital design engineer, but this issue is commonplace in the overall FPGA programming industry. The number of compiles needed is a factor of how much designers can verify their systems before compilation.
- Absence of typical LabVIEW debugging features in hardware – Once the code is running in hardware – or is hardware – there is no ability to probe, single-step, process highlight, set breakpoints, and more. In fact, if you want to probe a particular wire in LabVIEW while it is running on the FPGA, you need to add an indicator on the wire to expose that value as a register and subsequently see the value in LabVIEW. Of course, this process requires a recompilation. This concept is not specific to LabVIEW, but it is a caveat of general FPGA technology, which normally requires specialized tools just to get similar software-like debugging in reconfigurable hardware. Normally, you use simulation techniques to debug and develop code where the simulation of your FPGA logic can contain typical debugging constructs.
- FPGAs execute fast and deterministically – FPGAs are chosen for applications requiring high speed and determinism. Subsequently, designers are often concerned with exactly what is happening at every clock cycle of the FPGA, either for pure performance reasons or to characterize synchronization between parallel tasks. This puts stringent process limits on simulations that need to be accurate in both the behavioral and timing domains. And at some point, this requires that the program is tested while running in hardware to concretely verify timing and behavior. Thus, this carries all of the caveats noted in the previous problem above.
Because it could take anywhere from five minutes to multiple hours for a program to be compiled and run, it is impossible to employ a “code and fix” method of programming – even for the simplest of subVI modules. If you are spoiled by the LabVIEW background compilation when using the PC, anything longer than instantaneous is a bother. Furthermore, even when you do wait for the compile process to finish, it is difficult to probe into the functionality of the FPGA logic because there is no concept of typical software debugging on a program implemented on a chip. As you become a more proficient FPGA programmer, it is important to understand how you can increase your development efficiency. The sections below examine how to use behavioral simulation techniques as well as post-compile debugging to create a better-tested and quicker FPGA system.
FPGA Behavioral Simulation on the Development Computer
Because you are just using LabVIEW code when making FPGA logic, it is always possible to execute your VIs on the host computer. This means you can use all the debugging features of LabVIEW and you do not have to wait for it to compile every time you need to test some logic. Additionally, you can create a Testbench VI to assert the inputs that would normally be connected to the outside world with custom user-defined I/O and capture the outputs for analysis and verification. Finally, you can run the host program simultaneously with the FPGA code including simulated registers and DMA first-in-first-out (FIFO) memory buffers.
Figure 1. Conceptual Diagram of the Simulation System with a Testbench VI to Supply Custom Input and Capture Outputs with the Host Interface Running at the Same Time
To set the FPGA to run on the development computer, right-click the FPGA in the project and select “Properties…” In the debugging section, you have three possible options.

Figure 2. Properties Windows for the FPGA Showing the Three Options for Running the FPGA Code and I/O Type
- Execute VI on FPGA target – Leaving this option selected begins the compile process when you press the “Run” arrow for an FPGA VI.
- Execute VI on development computer with simulated I/O – This option sets the FPGA VI to execute on the PC when you press the run arrow. In the drop-down menu, you can select to either use random data (which was the main behavior in LabVIEW 8.5 and earlier) or use custom I/O, allowing you to write a Testbench VI to assert the inputs and capture outputs.
- Execute VI on development computer with real I/O – At this time, this feature is available for only NI R Series plug-in devices. This option runs the VI on the PC and downloads a fixed personality to the R Series device to sample the I/O when the program executes the I/O Node. This is useful for early testing and prototyping, but keep in mind that the I/O is software-timed sampling and most likely does not represent the timing you really want your VI to use.
Creating a Testbench VI to Use Custom I/O
Option 2 above is the most useful setting when developing FPGA code before compilation. With this option, you can create a Testbench VI and use all the normal LabVIEW constructs to create, assert, read, and write FPGA I/O programmatically. There is a template already built for this VI, and you can create a new VI from the template directly using the Properties window. The template created (Figure 3) gives access control to all the I/O nodes, I/O properties, and I/O Invoke nodes in the FPGA diagram when running on the development computer. Each time one of these nodes is called in FPGA simulation, the Custom I/O VI is executed instead. You use the Supplied VI in the template to find which node is calling the Custom VI and programmatically set the node to have a particular output or read and capture the input for each case. For a full tutorial on using the Testbench VI template, refer to the FPGA manual.
Figure 3. Starting Template for Custom I/O VI Used to Send Simulated Values into the FPGA Logic through I/O Nodes, Properties, and Methods
Usage of the Custom I/O VI
Now you see the importance of running your FPGA code on the development computer with simulated I/O because of compilation and debugging constraints, and you have learned how to set up the application by selecting the correct FPGA properties and creating a Custom I/O VI. Some common use cases for the Custom I/O VI include the following:
- Test vectors – For each input you have a particular set of values with which you want to exercise the code. This might come from a file, and there is a shipping example that demonstrates how to read from a file in the Custom I/O VI.
- Record and playback – Stimulate your FPGA logic with the most realistic signals by prerecording signals at the correct sampling rates directly from the real world. Store these in a file and extract them in the way as “test vectors.”
- Algorithmic stimulation – There are times when you do not need massive on-disk storage to emulate an incoming signal. If this signal can be algorithmically generated, then you can put this algorithm directly into the Custom I/O VI-specific case. An example of this would be generating a sine wave. There is a shipping example of simple sine generation as well.
- Interactive control – You might also wish, in some cases, to interactively change the I/O coming to your simulated FPGA logic. In this case, you can use shared variables inside the Custom I/O VI to send values from any source including an interactive front panel.
- Simulated “plant” – This method involves creating a model of the world your FPGA logic will talk to. Place this model within the Simulated I/O VI to create a virtual world with which the FPGA can work.
- Combination of methods – Using combinations of types of test benches, you can also exercise different logic with the best method.
Other Considerations and Techniques When Running on the Development Computer
Code generation error checking – Although running FPGA logic on the development computer is logically accurate, there are FPGA coding mistakes that a user can make that are not caught by general LabVIEW error checking (in other words, issues that would break the run arrow). Often coding mistakes are caught by the code generation step. You should check for code generation errors periodically when running on the development computer to make sure you are not programming incorrectly. The easiest way to do this is right-clicking on the VI in the project and starting the compile. After the “Generating intermediate files” step, you can easily cancel the compile and continue simulating. This step normally takes anywhere from 30 seconds up to just a few minutes.
Examples of FPGA coding mistakes found only in code generation include:
- Loops inside of single-cycle timed loops (SCTLs).
- Illegal functions inside the SCTL like integer divide, scale by power of two, or rotate array.
- Illegal arbitration in SCTL including shared resources used both in the SCTL and anywhere else in the diagram. Shared resources for which you cannot turn off arbitration include locals, globals, and non-reentrant subVIs.
Conditional compile structure – There may be times when you need a way to include certain code when running on the development computer that should not be compiled into the FPGA design in hardware. Use the conditional compile structure with the Tag “FPGA_EMULATION==TRUE” to place code somewhere in your FPGA logic only for simulation purposes. The classic example of the need for this is sleep timing for the sake of the PC processor. When running on the FPGA, sleep time is irrelevant, but when simulating G code on the development computer, it helps to avoid starving the processor. The processor is not able to run as fast as the FPGA, anyway, so throttling the loops with wait timing for simulation purposes is a good practice when you have lots of parallelism.

Figure 4. Place a structure like this in your untimed FPGA loop to throttle it down for running more efficiently on the development computer.
Synchronization of parallel loops in simulation – Although you cannot get cycle accurate simulation, you often still need loops to iterate in step. You would like to ensure that parallel loops have run the correct number of times. For instances you might have one loop that should run twice for every one of another loop. Implementing this in simulation is a challenge, and there is no easy way to do it without additional debugging code. Some users are successful with some type of Boolean handshaking method where the loops block until all loops are done. Other users are successful with running the VI in the windows context and adding synchronization concepts like semaphores or rendezvous.
Running FPGA code modules directly in the Windows context – When creating a subVI code module, it is sometimes beneficial to actually place the subVI into a Windows VI to exercise the inputs and outputs on the connector pane. This works best when the subVI has a specific task and does not contain I/O, memory, or FIFOs. Combine this with a conditional compile to make certain code executes when running in the Windows context. Keep in mind that this concept is different from the aforementioned “run on development computer” under the FPGA context. In this case, you are still running under the FPGA within the project, but the code is actually running on the computer in simulation. Running directly in Windows is a method by which you are actually calling the subVI from a VI under My Computer in the project.
Figure 5. This example of code was written for FPGA but tested within the Windows context so that you can stimulate with any testing algorithm you can create in LabVIEW.
Post-Compile Debugging Techniques
Use controls/indicators for debugging - When debugging while the program is running in the FPGA, the more controls and indicators you have the better. Since you cannot use LabVIEW probes, use an indicator to get the instantaneous value of a wire of interest. Additionally, use a control instead of a constant during this process because changing a constant value requires a recompile. Use a control, find the right value, and change to a constant when you are sure it is correct. Keep in mind that controls and indicator take a sizable amount of resources on the FPGA, because they create a communication interface with the host VI. Stripping away unnecessary controls and indicators is the first step in resource optimization. Use the additional controls and indicators while debugging, but try to pair them out as you need more room for additional code.
Latching Error Conditions - Many times there are error conditions that only happen for a short time. The worst case is that the error only happens one cycle of the clock. While debugging, these error conditions happen much too quickly to catch them through visual inspection of an indicator on the front panel or even through the communication interface. The best way to catch the error is to latch the condition when it happen and then allow a reset if needed. After you get things working correctly you might be able to take out the debugging latch and handle the error in a different manor for the deployed system. The classic example of this is debugging a periodic timeout from a FIFO.

Figure 6. This VI shows latching a Timeout condition with and without reset.
Data log a test point with DMA - Sometimes you would like to probe something in the FPGA but the instantaneous value from a control is not enough to debug. In this case, you can use a DMA channel for debugging purposes to actually capture the entire waveform of data from a test point.
Route a test point to an I/O - Whether it is an analog or digital test point, you can always route the LabVIEW wire to an I/O node. Once the signal is routed from the FPGA, you can debug the signal from any other NI test hardware like a scope, Digital card, DAQ board, or even another FPGA programmed for testing.
Test multiple candidate implementations with a case structure - In some cases you would like to test out a couple of ways to do a task in the FPGA. You could compile each of them to see which one performs better. However, in order to avoid the extra compiles, put the test implementations into cases of a case structure and select between them on the fly. You can get instant feedback on the comparison between the cases and avoid extra compilation time.

Figure 7. Place a case structure with different code you want to try out on the FPGA
Conclusion
Efficient development and debugging for LabVIEW FPGA has aspects that are similar and dissimilar from typical debugging in LabVIEW for Windows. You can use similar techniques when you set the FPGA to run on the development computer with Simulated I/O. In this case, you can use all the normal debugging feature in LabVIEW and as of version 8.6, create a testbench to exercise the logic with user-specified I/O. Once you do compile and begin running on the FPGA, it is much more difficult to debug, but there are a number of techniques to help in this process ultimately avoiding more compilation.
IP Corner addresses issues and presents technical information on LabVIEW FPGA application reusable functionality, also known as FPGA IP. This article series is designed for those interested in learning, testing, or discussing topics to make FPGA designs better and faster through the reuse of IP.
Reader Comments | Submit a comment »
Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).



