1. Create The Project
After opening LabVIEW, choose to create an Empty Project. Add the FPGA device by right-clicking on My Computer, and choosing New>>Targets and Devices. Find the FPGA Target you wish to program, and add it to the project.
Your project should look similar to this:
To add a blank VI for the FPGA, right-click the FPGA in the Project Explorer and choose New>>VI. Open Up the block diagram of this blank VI.
2. Create a FIFO
For our FPGA VI, we would like to acquire data from an analog input channel, and write this data into an FPGA FIFO to implement the DMA transfer.
To create the FIFO, right-click the FPGA Target again and choose New>>FIFO.
The FPGA FIFO properties window will appear. Here we can name the FPGA FIFO, and configure it for DMA. For this example program, we will name the FPGA FIFO “FIFO”. To use DMA, click the pull-down menu in the Transfer box, and select a DMA option. There are two DMA options, Host to Target and Target to Host. This selects the direction of the DMA FIFO either to or from your FPGA. This is different than Local since the data within the RAM used by a DMA FIFO is transferred to or from the host machine. For this example we will use Target to Host for high speed acquisition.
When using LabVIEW 8.5 and earlier, the FPGA DMA FIFO only supports U32 (unsigned 32-bit integer) datatypes. For LabVIEW 8.6 and later, all datatypes are supported. For the training purposes of this tutorial, we will use the U32 datatype. However, if you are using LabVIEW 8.6 or later, set the FIFO to the datatype of your data. Note that at the hardware level, all DMA FIFO transfers are 32 bit width. Therefore configuring a DMA FIFO for boolean datatype is very inefficient. Data packing techniques on the FPGA level can avoid this inefficiency.
To save resources, choose the smallest DMA size that is reasonable for your application. This is done by comparing the rate at which data points are put into the FPGA FIFO to the rate at which the Host application will be able to read points out. The slower the Host VI is compared to the FPGA VI, the larger a FIFO you will need to allocate. For the purposes of this application, let’s use a depth of 4095.
3. The FPGA VI
The attached VI, fpgaAcquire.vi, runs on the FPGA target.
Following the block diagram above, four channels of analog input are sampled simultaneously. The resulting 16-bit numbers are combined into an array. The array is passed into a For Loop. The For Loop indexes through each element of the array and passes the data into a DMA FIFO sequentially with a timeout of 5 ticks. This means that if the DMA operation takes longer than 5 ticks, the data value will not be written. This would appear as data switching between channels. In this case, increase the timeout or add a while loop which tries to write as long as the value returned from Timed Out? is true. If Timed Out? is frequently true, then increasing the size of the DMA FIFO buffer may help if it is too small. Otherwise, the DMA FIFO is being filled faster than it is being emptied and the timing of the loops on the FPGA and the Host should be examined.
The overall loop rate is set by the Count (uSec) control which sets the period.
4. Implement DMA on the Host Side
DMA uses a programming flow similar to many communication/acquisition techniques used in LabVIEW. This is done using an Invoke Method Node found on the FPGA Interface Palette. To use FIFO methods, note that the FIFO name “FIFO” appears at the top of the list of methods when left-clicking the node.
Note: You must first configure the Open FPGA VI Reference function and wire the output of this function to the FPGA VI Reference input of the Invoke Method Node to see the available DMA FIFOs and methods. The Invoke Method will allow you to Read or Write, depending on the direction of your FIFO. Target to Host allows the host to Read, while Host to Target allows the host to Write.
To the right of the FIFO names are the available methods, in order of proper programming flow. We begin by configuring the DMA FIFO depth on the host side memory and starting the DMA. Then in a loop we can read from the FIFO until the stop button is pressed. Outside the loop, we execute the Stop method to make sure all allocated resources are freed. Below is an example:
The DMA methods configure, start, and stop are optional methods. The DMA read method is the only required method to read data from a DMA FIFO. If only the Read Method is used, the host side FIFO memory is configured to a default size. This varies by LabVIEW FPGA version and is documented in the help. Also the read method will automatically start the DMA transfers on the first read. DMA transfers are stopped when the Close FPGA VI Reference function is called.
Note the parameters of the Read method:
Number of Elements indicates how many elements are to be read. The function will complete when this many elements are acquired, or the Timeout is exceeded, whichever comes first. The same amount of overhead is associated with reading a few elements as with reading many. For applications in which the host loop is much slower than the FPGA loop, it is better to read more elements at a time. By monitoring the Elements Remaining output, one can determine if the host loop should be run at a faster rate or if more samples should be read per loop iteration.
Note: The Elements Remaining output returns the number of elements remaining in memory on the host machine. This does not return the number of elements remaining in the FPGA device RAM.
The rest of the host application de-interlaces the 32-bit array to get four arrays that represent the four channels and are converted to signed 16-bit integers, double, and then recalibrated to reflect the full +/-10V range of the FPGA target. Note that with the LabVIEW 8.6 FPGA Module and later, de-interlacing and converting to I16s can be avoided by configuring the DMA FIFO to be of I16 type.
Using DMA, it is easy to create a fast and intuitive data acquisition application for R Series or ComapctRIO FPGA hardware. This makes it even easier to create customized hardware for control or monitoring at high speed with deterministic behavior.