HDL Coder™ and LabVIEW FPGA: Importing HDL Coder Exports in LabVIEW FPGA

Updated Oct 30, 2020

Environment

Software

  • LabVIEW FPGA Module

LabVIEW FPGA offers several methods for importing or using external IP such as the HDL code generated by MATLAB®, Simulink®, and HDL Coder™. This tutorial walks through importing the VHDL designs created in either HDL Coder and LabVIEW FPGA: Modifying and Exporting a Simulink Model for LabVIEW FPGA or HDL Coder and LabVIEW FPGA: Modifying and Exporting a MATLAB Function for LabVIEW FPGA and completing a LabVIEW FPGA VI based around the imported code.
 

Prerequisites

This tutorial assumes completion of either HDL Coder and LabVIEW FPGA: Modifying and Exporting a Simulink Model for LabVIEW FPGA or HDL Coder and LabVIEW FPGA: Modifying and Exporting a MATLAB Function for LabVIEW FPGA.
 

Make sure the following software versions are installed.
 

Understanding Fixed-Point Representations

Before importing the design, you must clearly understand the data types used by the HDL code. In most representations – such as Boolean or unsigned integers – the import is simple. In the case of fixed-point numbers, this process is a bit more difficult due to the different methods of describing such numerical representations. Fixed-point numeric representations are particularly common and is recommended for FPGA use as they consume less resources and are more efficient than floating-point representations while allowing for the representation of fractional numbers.
 

MATLAB – and by extension Simulink – and LabVIEW both support fixed-point numerical representations. However, these are configured in slightly different ways between the two development environments. MATLAB typically specifies the word length and fractional word length while LabVIEW specifies the word length and integer word length. To convert between MATLAB and LabVIEW in the context of this tutorial, complete the following steps:
 

  1. Open the top-level VHDL file generated by HDL Coder in a text editor.

  2. Make note of the data types used for each top-level input and output in the port declaration. Each input or output should have a comment next to it that represents the data type that HDL Coder selected as the fixed-point data type.


  3. Convert the given HDL Coder representation to the correct LabVIEW representation using the following definitions.

    • If the comment starts with an s, the number is signed. If it starts with a u, the number is unsigned.

    • Since all the values in question are fixed-point, they should contain fix.

    • The number directly following fix is the word length of the number.

    • If the number has a non-zero fractional word length, this value will be represented by the number following En.

    • To calculate the integer word length for LabVIEW, subtract the fractional word length from the word length.

    • For example, the Fixed-Point Configuration for x_in in LabVIEW would look as follows:


    • To convert back to a MATLAB representation, subtract the integer word length from the word length to get the fractional word length.
       

Creating a LabVIEW FPGA Project and VI

Now that the generated VHDL files are available, complete the following steps to create a LabVIEW FPGA Project with an FPGA target to which the VHDL will be imported:
 

  1. Launch LabVIEW.

  2. In LabVIEW, select File >> New…

  3. Select Empty Project and click OK.


  4. In the project, add an FPGA Target. For this tutorial, a disconnected device can be added as follows:

 

  1. Right-click My Computer in the LabVIEW project, then select New >> Targets and Devices…

 

  1. Select New target or device. This will allow the addition of a device that may not be present on the system for simulation and compilation purposes.

  2. Choose the FPGA target to use. For this tutorial, select an R Series PCIe-7856.

 

  1. Click OK.

 

  1. In the project, right-click on the FPGA Target and select New >> VI to create a new VI in the FPGA context.


 
  1. Hit Ctrl + Shift + S to save both the project and the new VI. NI Recommends creating a new directory as the top-level folder for the files.


  1. Create a subdirectory next to the project for the VHDL source files to be imported.

  1. Copy the VHDL exports from HDL Coder to this location. Note that the exact files needed will differ between different designs.

     


Importing the HDL Coder Exports

With the LabVIEW project created, complete the following steps to create a top-level FPGA VI which imports and uses the external files:
 

  1. Open the FPGA VI created in the previous section and witch to the block diagram by pressing Ctrl + E or selecting Window >> Show Block diagram.

  2. On the Block diagram, right-click anywhere to view the Function Palette. Select Structures >> Timed Structures >> Timed Loop.


  3. Click and drag on the block diagram to create a Single-Cycle Timed Loop. This is a LabVIEW FPGA structure that represents a clock domain. Code inside this loop will execute in one tick of the top-level clock for the loop (by default, the 40 MHz reference clock).


  4. Right-click to open the Function Palette again and select Programming>>IP Integration.


  5. Click inside the Timed Loop to create an IP Integration Node.


  6. Double-click the IP Integration Node to launch the IP Integration Node Properties window.

  7. On the Name and Source page, provide a name for the node in the IP Name field.

  8. Click Add Synthesis File… to add the VHDL source files. Select the HDL source files from the subdirectory created for the LabVIEW project, then click OK.


  9. Ensure that the correct top-level VHDL file is set as the Top Level file. If not, select the file in the IP Source list and click the Set as Top Level button. Click Next.


  10. Next is the Entity, Architecture, and Targets page. This page can be used to limit the FPGA targets the IP Integration Node can be reused on, such as when FPGA Family-specific IP is being used, and to choose the Entity and Architecture in source files with multiple implementations. For this instance, use the default configurations and click Next.


  11. On the Generics and Support File Generation page, specify the values for VHDL generics. This example has no generics.

  12. Click Generate to generate the support files required by LabVIEW FPGA. This allows LabVIEW to properly integrate and simulate the imported IP.


  13. Once generation is complete, click Next.

  14. On the Clock and Enable Signals page, select clk_enable in IP Enable Signal(s).

  15. Click Next.

  16. On the Reset Signals and Behavior page, the reset configuration should match what was specified in the HDL Coder Workflow Advisor. The default for the Workflow Advisor is an asynchronous active high reset.

    • Deselect reset in the Synchronous reset signal(s).

    • Select reset in the Asynchronous reset signal dropdown.

    • Ensure that the Active logic level is High.

  17. Click Next.

  18. On the IP Terminals page, define the data type, order, and visibility of each of the inputs and outputs. NI recommends referring to the Understanding Fixed-Point Representations section of this document for information on how to configure the fixed-point inputs and outputs. The final configuration should look like the following:


  19. Click Finish to complete the configuration of the IP Integration Node


  20. Save the VI.
     

Interfacing with the Integrated IP

Now that the IP is imported, complete the following steps to create LabVIEW FPGA code to interact with it.  In this example, we pass data from a host VI to the filter and read back the filtered results using DMA FIFOs.
 

  1. In the LabVIEW project, right-click the FPGA Target and select New >> FIFO. This will open the FIFO Properties window for a new FIFO.

  2. In the FIFO Properties window, configure the FIFO as follows:

 

  1. On the General category page, set the FIFO Name and set the Type to Host to Target – DMA.

 

  1. On the Data Type category page, set the Data Type to FXP and configure the Fixed-Point Configuration to match the data type of x_in.


  1. Click OK to finish configuring the DMA FIFO.

 

  1. Repeat the previous steps to create two Target to Host – DMA FIFOs configured for the y_out and delayed_xout signals. These will transfer the filtered and delayed data from the FPGA back to the host VI.

  1. Drag each of the DMA FIFOs from the LabVIEW project to the block diagram. This will create accessor methods for each FIFO.

  1. Right-click each FIFO accessor method and select Interface >> Handshaking. This converts the accessor from a timeout interface to 4-wire handshaking.


  1. Complete the block diagram as shown below.






     

    Note: The logic attached to the Ready for Input outputs of the FIFOs will latch a true value any time the DMA FIFO returns that it isn’t able to take input values. This is important when using Valid In and Valid Out signals as the interface because data will be dropped. That is, the FIR filter has no way to stall and will continue to the next data point.
     

  2. Set the h_in filter coefficient values to the same ones used in the original MATLAB Testbench or Simulink system.








    Note: The fixed-point representations of the filter coefficients will vary slightly from the original values due to the limitations of what a fixed-point configuration can represent.
     

  3. Save the FPGA VI and LabVIEW project.
     

Next Steps

At this point, the FPGA VI is completed and can be compiled or simulated. The HDL Coder design is fully imported and no further interaction with the generated HDL source files is needed to use the LabVIEW FPGA code. To confirm that the design operates as expected, proceed to HDL Coder and LabVIEW FPGA: Creating LabVIEW FPGA Host Code and Testing with Simulation.