labview-fpga-hdl-tools 0.1.13
LabVIEW FPGA HDL Tools
License: MIT
Requires Python: <4.0,>=3.8

Pre-release LabVIEW FPGA HDL Tools for use with the ni/flexrio repo

# Getting Started
This document is a reference guide for the LabVIEW FPGA HDL Tools.  

To better understand the workflows and architecture, please visit the Theory of Operation.

To see how these tools are used to develop a custom FPGA design, please visit the HDL Workflow CLIP Migration Guide.


## Environment Setup
From the target folder (e.g. c:/dev/git/flexrio/targets/pxie-79xx), run: 
> pip install -r requirements.txt

This will install the LV FPGA HDL Tools module as well as any other dependent modules using pip

## Running Commands
All commands run from the target folder (e.g. c:/dev/git/flexrio/targets/PXIe-7903).  This is the folder that contains the projectsettings.ini file.

The LabVIEW FPGA HDL Tools are accessed by running `nihdl` commands at the command prompt

Type `nihdl --help` for a list of commands

# Source Files
The LabVIWEW FPGA HDL Tools use a couple files sourced in the FPGA target's GitHub repo to perform its commands.

## Project Settings File
The tools use the projectsettings.ini file to specify file paths and other configurations.  It is broken up into multiple sections.

### GeneralSettings

* <b>TargetFamily</b> - NI device product family (e.g. FlexRIO, cRIO)
* <b>BaseTarget</b> - The NI product model number that is being customized (e.g. PXIe-7903)
* <b>LabVIEWPath</b> - The disk path where LabVIEW is installed

### VivadoProjectSettings
This section is used by the create-project and launch-vivado commands

* <b>TopLevelEntity</b> - Top level entity (same as its HDL file name) that gets set in the Vivado project
* <b>VivadoProjectName</b> - The name of the Vivado project that is created (no spaces allowed)
* <b>VivadoToolsPath</b> - Path to where the Vivado tools are installed.  You may point to the tools installed by NI LabVIEW FPGA Comile Tools or your own Vivado installation folder.
* <b>VivadoProjectFilesLits</b> - Text files containing relative paths of source files that will be included in the Vivado project.  Specifying a directory path within the text file will recursively include all files within it.
* <b>UseGeneratedLVWindowFiles</b> - Boolean (True/False) to specify whether to use the window netlist and supporting files specfied in <b>TheWindowFolder</b>.  If set to False, the Vivado project will use a default stub for TheWindow.vhd which will produce a successful (but non-functional) bitfile.
* <b>ConstraintsTemplates</b> - Template XDC constraint files that will be processed to generate the final constraint files
* <b>VivadoProjectConstraintsFiles</b> - List of XDC constraint files to include in the Vivado project
* <b>TheWindowFolder</b> - Folder containing the LabVIEW Window netlist files (EDF) and supporting files to be included in the Vivado project when UseGeneratedLVWindowFiles is set to True

### LVFPGATargetSettings
This section is used by the gen-target and install-target commands

#### Inputs
* <b>LVTargetBoardIO</b> - Path to CSV file that specifies names and datatypes of custom board IO that will appear on the generated custom LV FPGA target
* <b>IncludeCLIPSocket</b> - Boolean (True/False) to specify whether to include the CLIP socket on the generated custom LV FPGA target
* <b>IncludeLVTargetBoardIO</b> - Boolean (True/False) to specify whether to include the custom LV Target Board IO on the generated custom LV FPGA target
* <b>LVTargetName</b> - The LabVIEW project display name of your customized FPGA target.  This is also used to create the folder that contains the custom LV FPGA target plugin.
* <b>LVTargetGUID</b> - Global Unique Identifer for your custom LV FPGA target plugin - generate one here https://www.guidgenerator.com/
* <b>LVTargetInstallFolder</b> - Folder where the custom LV FPGA target plugin is installed.  For now, this must be set to "C:\Program Files\NI\LVAddons\flexrioii\1\Targets\NI\FPGA\RIO\79XXR" for the PXIe-7903.  In the future we may support locations outside of NI\LVAddons
* <b>LVTargetConstraintsFiles</b> - List of constraint files to include in the LabVIEW FPGA target plugin

#### Templates
* <b>WindowVhdlTemplate</b> - Path to the mako template for TheWindow.vhd.  This file is processed depending on the settings in the Inputs above.
* <b>TargetXMLTemplates</b> - List of paths to the mako templates for the target resource XML.  These files are processed depending on the settings in the Inputs above.

#### Outputs
* <b>WindowVhdlOutput</b> - Stub for TheWindow.vhd used to make signal connections in the top-level HDL file and for early synthesis.  This file will be overridden by TheWindow.vhd that is generated by LabVIEW FPGA during the Export Top VI workflow.
* <b>WindowInstantiationExample</b> - Instantiation example to help with connecting the many ports of TheWindow.vhd.  This code is not intended to be a complete cut-and-paste into the top level HDL file.  The LVTargetBoardIO signal port assignments will be most useful.
* <b>LVTargetPluginFolder</b> - Folder where the outputs of the custom target generation script are placed
* <b>BoardIOXML</b> - Custom board IO resource XML for the custom LV FPGA target
* <b>ClockXML</b> - Clock resource XML for the custom LV FPGA target

### CLIPMigrationSettings
This section is used by the migrate-clip command

#### Inputs
* <b>CLIPXML</b> - Path to the CLIP's XML file
* <b>CLIPHDLTop</b> - Path to the CLIP's top-level HDL file
* <b>CLIPXDCIn</b> - Path(s) to the CLIP's XDC constraint files (this setting supports multiple paths)
* <b>CLIPInstancePath</b> - Instantiation path to the top-level entity of the CLIP within the design hierarchy of the FPGA's top-level entity.  If entity "MyCLIP" is place directly in the FPGA's top level entity, then this setting would simply be "MyCLIP".  If it is placed deeper in the FPGA hiearchy, then that path is specified here.  This is used to process XDC constraint files.

#### Outputs
* <b>LVTargetBoardIO</b> - The LabVIEW interface IO of the CLIP XML becomes board IO on the generated custom LV FPGA target.  This CSV file is output from the CLIP migration process and will serve as an input to the generate custom LV FPGA target process.
* <b>CLIPInstantiationExample</b> - Instantiation example to help with connecting the many ports of the CLIP.  This code is not intended to be a complete cut-and-paste into the top level HDL file and will require some adjustments when using it.  
* <b>CLIPtoWindowSignalDefinitions</b> - Signal definitions for all of the ports in the CLIP entity.  This is used to copy/paste the signal definitions for the ports that connect between the CLIP and TheWindow.vhd.  These signals will need to be defined in the top-level HDL entity.
* <b>CLIPXDCOutFolder</b> - The CLIP XML is processed to use the new CLIPInstancePath to set the correct entity hierarchy within the constraints.  The contents of these XDC files will be merged into the target's XDC files.

### LVWindowNetListSettings
This section is used by the get-netlist command

#### Inputs
* <b>VivadoProjectExportXPR</b> - Path to the .xpr file of the Vivado Project Export created from the LabVIEW FPGA project

#### Outputs
* <b>TheWindowFolder</b> - The Window netlist and constraints are extracted from the Vivado Project Export and placed into this folder.  The contents of this folder are pulled into the GitHub Vivado project.

## LVTargetBoardIO CSV File
The LVTargetBoardIO.csv file defines the I/O interfaces that appear in the LabVIEW FPGA project as Board I/O.

The CSV file contains the following columns:
* **LVName** - Hierarchical name of the signal in LabVIEW using backslash notation (e.g., IO Socket\Port0\Tx\TData0)
* **HDLName** - Signal name in VHDL/Verilog (e.g., uPort0AxiTxTData0)
* **Direction** - Signal direction from LabVIEW's perspective:
  * input - Signal coming from HDL into LabVIEW
  * output - Signal going from LabVIEW to HDL
* **SignalType** - Type of signal:
  * clock - Clock signal
  * data - Data signal
* **DataType** - Data type of the signal:
  * Simple types: Boolean, U8, U16, U32, U64, I8, I16, I32, I64
  * Fixed-point: FXP(word_length,int_word_length,Signed/Unsigned)
  * Arrays: Array<ElementType>[Size]
* **UseInLabVIEWSingleCycleTimedLoop** - Whether the signal can be used in Single-Cycle Timed Loops:
  * Required - Must be used in SCTL
  * Allowed - May be used in SCTL
  * Empty - Cannot be used in SCTL
* **RequiredClockDomain** - Specifies the clock domain this signal must be synchronized to
* **ZeroSyncRegs** - Whether to use zero synchronization registers:
  * TRUE - No synchronization registers
  * FALSE - Use default synchronization registers
* **OutputReadback** - For output signals, whether to provide readback:
  * TRUE - With readback
  * FALSE - Without readback
* **DutyCycleHighMax** (for clock signals only) - Maximum duty cycle percentage
* **DutyCycleHighMin** (for clock signals only) - Minimum duty cycle percentage
* **AccuracyInPPM** (for clock signals only) - Clock accuracy in parts per million
* **JitterInPicoSeconds** (for clock signals only) - Clock jitter in picoseconds
* **FreqMaxInHertz** (for clock signals only)- Maximum clock frequency
* **FreqMinInHertz** (for clock signals only) - Minimum clock frequency


This file serves several purposes:
* Generating BoardIO XML - Used to create the XML that defines the I/O structure in the LabVIEW FPGA target
* Window VHDL Generation - Used to create the TheWindow.vhd interface file that connects LabVIEW to your custom HDL
* Resource Definition - Defines the resources that appear in the LabVIEW FPGA Project Explorer
* Clock Configuration - Defines clock domains and their parameters


# Commands

## Extract Dependencies
From the target folder, run:
> nihdl extract-deps

In addition to the target source code found in the GitHub repo, there are many dependency files needed to compile the bitfile.  These are delivered as a zip file in the artifacts of the GitHub repo release.  The zip file should be copied into the repo's dependencies folder on your computer (e.g. C:\dev\github\flexrio-custom\dependencies).

The dependencies are a collection of NI HDL exports that have very deep folder hierarchies.  The Windows unzip utility can error due to long file paths.  The nihdl extract-deps commands ensures that the dependencies can be unzipped into the proper location.

## Create Vivado Project
From the target folder, run:
> nihdl create-project

If this is not the first time creating the Vivado project, one of these command line options are required:
> --overwrite - Overwrites the existing Vivado project and creates a new one </br>
> --update - Only updates the files in the existing Vivado project </br>

This runs the create_vivado_project.py script to generate the Vivado project.  It performs these functions:
1) Copy dependency files from dependencies/github deps into objects/gathereddeps.  The dependencies come from many NI HDL exports that have deep folder hierarchies.  Vivado can produce errors when loading files with long paths.  We put all of these dependency files in a flat folder that is used for the Vivado project.  Each target may have a different subset of dependencies used for their Vivado project so this gathereddeps folder goes into the target-specific objects folder.
2) Override HDL with generated LabVIEW window files.  The HDL in the target GitHub repo will successfully build a bitfile without importing a LabVIEW FPGA VI.  To do this, the repo contains a number of stub files that are created as part of the LabVIEW FPGA code generation process.  When you are using a top-level VI exported from a LabVIEW FPGA project (UseGeneratedLVWindowFiles = True), these stub files are replaced by the LabVIEW FPGA generated files for the Vivado project.  The LabVIEW window files come from the folders pecified in TheWindowFolder setting.
3) Process constraints files.  The target constraints XDC file is single sourced for both LabVIEW FPGA and Vivado compile workflows.  It contains constraints for everything that is outside of the LabVIEW window.  When LabVIEW FPGA generates compilation files, it inserts constraints for the VI into the XDC file.  For the Vivado workflow, if you are using a LabVIEW FPGA window (UseGeneratedLVWindowFiles = True), then we will insert the VI's constraints into the XDC file during the create-project function.
4) Runs the Generate LV Target Support command (equivalent of running nihdl gen-target) which is needed to generate TheWindow.vhd stub that is dependent upon LV FPGA target settings in the ini file (like whether to include custom board IO)
5) Generates a TCL script.  Using the files listed in VivadoProjectFilesLists (and any files that are overridden by generated LabVIEW FPGA window files), we generate a TCL script that is used to create the Vivado project.
6) Run TCL script to create the Vivado project.  We execute the Vivado version specified by the VivadoToolsPath setting to run the create project TCL script 

## Launch Vivado
From the target folder, run:
> nihdl launch-vivado

## Migrate CLIP
From the target folder, run:
> nihdl migrate-clip

In LabVIEW FPGA, the CLIP HDL is defined by an XML file that specifies its  ports.  The ports are grouped into three interfaces:
* LabVIEW - These ports appear in the LabVIEW project as CLIP IO
* Socket - These ports are automatically connected by LabVIEW FPGA to the ports on TheWindow.vhd that connect to the FPGA top-level fixed logic
* Fabric - These ports are automatically connected by LabVIEW FPGA to the ports on TheWindow.vhd that connect to the FPGA top-level fixed logic

![CLIP in LV FPGA](docs/clip_in_lv_fpga.png)

When the CLIP HDL is instantiated directly in the top-level HDL file, the CLIP LabVIEW interfaces become Board IO LabVIEW interfaces.  And the Socket/Fabric interfaces to the CLIP are manually connected in the top-level HDL.

![CLIP in Top Level](docs/clip_in_top_level.png)

To make this migration process easier, we use the CLIP migration script to process the CLIP's files and generate code that is used to instantiate the CLIP HDL directly into the top-level FPGA design.

The migrate-clip command will perform the following functions:
1) Generate the LVTargetBoardIO CSV file.  The CLIP's LabVIEW FPGA interfaces are defined in the CLIP XML file.  In LabVIEW, these show up as IO of the socketed CLIP.  When moving the CLIP HDL into the top-level design of the FPGA (so that it is not instantiated by LabVIEW FPGA), we need these IO interfaces to show up in the LabVIEW FPGA project as IO of the FPGA target (also known as board IO).  The FPGA target board IO for custom targets is defined in the LVTargetBoardIO CSV file.  To make it easier to migrate CLIP HDL into the new architecture, the migrate-clip command transforms the LabVIEW interfaces from the CLIP XML into the LVTargetBoardIO CSV file.  Note that this gets you 90% of the way there but there are some changes you need to make in the generated CSV file to make it fully work as the FPGA target board IO.  
2) Generate a CLIP instantiation example.  The CLIP HDL file may have many ports that may make it tedious to create the CLIP instantiation by hand.  The migrate-clip command generates an instantiation example that can be copy/pasted into the FPGA target's top-level HDL file.  This example simply connects all of the CLIP ports to signals of the same name.  You will likely need to make modifications to some of the port names, but the example is a good start.  
3) Generate signal definitions example.  Similar to the CLIP instantiation example, the migrate-clip command generates signal definition code that can be copy/paste into the FPGA target's top-level HDL file to help migrate the CLIP HDL into it.
4) Process XDC files.  Some CLIPs provided by NI for FlexRIO products have %CLIPInstance% tokens embedded in their constraints XDC file.  This token is replaced by the HDL hierarchy instance path during LabVIEW FPGA code generation to ensure that the constraints are applied to objects at the correct hierarchy level of the  design.  When using the CLIP HDL in the top-level of the FPGA target, the hierarchy is fixed and the migrate-clip command replaces the %CLIPInstance% token with the hierarchy path in the CLIPInstancePath setting.

See the HDL Workflow CLIP Migration Guide for examples of how these are done.


## Generate LV Target Support
From the target folder, run:
> nihdl gen-target

This runs the gen_labview_target_plugin.py script to create a custom LV FPGA target plugin.  The output of this script is placed in the target's objects directory. 

This command will perform the following functions:
1) Generate LabVIEW FPGA target plugin Resource XML.  LabVIEW FPGA uses an XML file to define the IO and other parameters of the FPGA target.  The gen-target command uses settings in the INI file to generate the XML for the custom LabVIEW FPGA target plugin.  It may include the socketed CLIP and/or custom-defined board IO if those are enabled in the INI file.  
2) Generate a TheWindow.vhd HDL file stub.  If you are using custom board IO in the LabVIEW FPGA target, interfaces to these will be created as ports on TheWindow.vhd file that LabVIEW FPGA generates.  To connect these ports within the top-level file of the FPGA target VHDL, we generate a TheWindow.vhd stub during the gen-target command.  This stub is an empty VHDL file that only contains the interface ports so that you can synthesize the design in Vivado without errors.  Using the stub in the Vivado project will produce a non-functional bitfile because the necessary code that goes inside TheWindow.vhd (generated by LabVIEW FPGA) is not present.
3) Generate a TheWindow.vhd instantiation example.  The custom board IO may be many signals that can be tedious to manually add to TheWindow.vhd instantiation in the top-level HDL file.  The gen-target command generates a simple example that maps all custom board IO ports to signals with the same name.  We do not recommend copy/pasting the entire instantiation example into the FPGA target top-level HDL file because many of the ports (that aren't board IO) go to signals with different names.  You can copy/paste just the section of board IO into TheWindow.vhd instantiation of the top-level HDL file.  See the HDL Workflow CLIP Migration Guide for examples of how this is done.
4) Copy FPGA target plugin files.  The LabVIEW FPGA target plugin contains a folder of all the HDL files needed to compile the target in LabVIEW FPGA.

## Install LV Target Support
From the target folder, run:
> nihdl install-target

This runs the install_labview_target_plugin.py script to install the custom LV FPGA target plugin into the LVAddons folder.  This allows the LabVIEW to discover this new custom FPGA target so that you can add it to the LabVIEW project.

The LabVIEW FPGA target plugins are installed in the Program Files folder which may require administrator access.  If needed, you will be prompted to allow the installation.

## Get LV Window Netlist Files
To bring the netlist for the LabVIEW FPGA top-level VI into the GitHub Vivado project flow, you must first perform a Vivado Project Export of the top-level LabVIEW FPGA VI.

After you have the Vivado Project Export, go to the GitHub target folder and run:
> nihdl get-netlist

This runs the get_window_netlist.py script to extract the netlist for the LV FPGA top-level VI as well as HDL packages and metadata files needed to build the FPGA bitfile using the GitHub Vivado workflow.

Files are placed into <b>TheWindowFolder</b> specified in projectsettings.ini

The following files are extracted from the Vivado Project Export:
* TheWindow.edf - netlist for the LV FPGA window containing your top-level VI's code
* Pkg*.vhd - various package files generated by LabVIEW FPGA
* TheWindowConstraints.xdc - constraints specific to the HDL in the window netlist that get automatically merged into the custom FPGA target's constraints file
* CodeGenerationResults.txt - metadata (e.g. NI-RIO host interface FIFOs, controls, indicators) produced by LabVIEW FPGA needed to generate the bitfile .lvbitx for download by the NI-RIO driver

## Create LabVIEW .lvbitx Bitfile
After implementation, Vivado generates a bitstream for the FPGA.  This file is packed into a .lvbitx file that also contains metadata about the LabVIEW FPGA project and VI that was used to create the bitstream.  This enables the NI-RIO host interface to get information (DMA FIFOs, controls, indicators, target type, etc.) about the contents of the FPGA bitstream when it loads the .lvbitx file onto the FPGA.

This step is automatically done by Vivado when it runs the PostGenerateBitfile.tcl script.

This function is automatically run from within the Vivado implementation directory.  You can run it manually from there (e.g. C:\dev\github\flexrio\targets\pxie-7903\VivadoProject\MySasquatchProj.runs\impl_1)
> nihdl create-lvbitx

This may be useful to debug errors if the .lvbitx file is not created during the Vivado compile.