Fundamentally, FINS is a code generator that uses a Python-processed JSON specification file as its input. Multiple JSON files may be stored for a single IP, each representing a different "configuration" of the IP. For instance, one configuration may set a specific part that is desired for build and/or test. The code generation was built with a plugin architecture using Python setuptools. Each plugin is referenced as a code generator "backend", and this architecture permits additional backends to be added in the future. FINS generates both source code and vendor-specific automation scripts. The diagram below shows the templates used in each backend and the output directories of each template set.
As the diagram above demonstrates, the "core" backend only generates source code while the "quartus" and "vivado" backends generate automation scripts. The "core" backend is automatically executed when either the "vivado" or "quartus" backend is used. To generate the different backends, use the fins
executable with the --backend
(-b
) switch. The code below demonstrates examples of using FINS to generate the different backends.
# Generates the "core" backend by default
$ fins fins.json
# Generates the "core" backend explicitly
$ fins --backend core fins.json
# Generates the "core" and "vivado" backends
$ fins -b vivado fins.json
# Generates the "core" and "quartus" backends
$ fins -b quartus fins.json
Within the "core" backend, FINS generates the following:
- Default Top-level Code: FINS generates both a top-level testbench (
name
_tb.vhd) a top-level wrapper source file (name
.vhd). For many firmware IP designs, the default top-level code may be used as-is with no modification and will be updated in-place as the FINS Node JSON file is updated. For designs with special requirements, this default code gives developers a starting point for the top-level design of their IP. - User Stub Code: FINS generates a stubbed core source file (
name
_core.vhd) that is intended to be a starting point for user code development. - Package Code: FINS generates an HDL package (
name
_pkg.vhd) that contains "parameters" definitions and the record definitions for both "ports" and "properties". FINS also generates simulation-support Python and Octave/MATLAB packages (name
_pkg.py,name
_pkg.m) to automatically update simulation scripts with code generation. - Properties Code: FINS generates an AXI4-Lite decode module (
name
_axilite.vhd) for read and write of firmware properties from software. - Ports Code: FINS generates an AXI4-Stream decode module (
name
_axis.vhd) to standardize data and metadata communication. - Verification Code: FINS generates testbench verification modules (
name
_axis_verify.vhd,name
_axilite_verify.vhd) for the top-level testbench (name
_tb.vhd) to use to verify the ports and properties interfaces.
The code generated by the "core" backend fits together as shown in the diagram below.
The "quartus" and "vivado" backends automate the build and simulation of a FINS Node for rapid integration into Intel Quartus Platform Designer and Xilinx Vivado IP Integrator, respectively. The auto-generated TCL scripts are called by the auto-generated Makefile with the following targets:
NOTE: When running the
make
command, you have the option of viewing the console output and watching the GUI-based tools execute the scripts. To use this mode in the IP build and simulation process, set the "UseGui" make variable to 1 like this:make sim UseGui=1
. Note that in this mode the developer will need to close the GUI-based tool windows to proceed at different steps during the process.
all
: (Default) Builds and packages the intellectual propertysim
: Runs the simulation, depends onall
targetclean
: Deletes all temporary and project files for this repository onlyclean-all
: Deletes all temporary and project files for this repository and all sub-IP repositories
The following diagram shows the sequence of operations that takes place when running the FINS code generation and then executing the make
targets.
The first step in the development of a FINS Node is the creation of a FINS Node JSON file with the name
, parameters
, ports
, and properties
top-level keys. These keys should be defined first since they will setup both our top-level code wrappers and the user core code stub. Here are a few helpful notes when developing this initial FINS Node JSON file:
- The top-level schema of a FINS Node JSON file is located in the section below.
- Choose a unique and descriptive value for the
name
key. - The
parameters
key contains constants that are propagated throughout the design with code generation, so set values that could potentially change as the design evolves or is adapted. Theparameters
schema is located here. - The
ports
key defines the data and metadata interfaces that will be connected to other FINS Nodes. Theports
schema is located here. - The
properties
key defines the software control interface. Theproperties
schema is located here.
The next step is to generate the "core" backend for the FINS Node. Make sure you have installed FINS! Run the following command to generate the "core" backend.
NOTE: This workflow is assuming that your FINS Node JSON is called fins.json. The value of the
name
top-level key of the FINS Node JSON file will be referenced withname
.
$ fins fins.json
The code generation output of the "core" backend will be located in the ./gen/core/ directory. Browse this directory to notice the files described in the section above. The one file in particular that we are interested in is the name
_core.vhd file, which is the user core code stub - i.e. the place for your functional HDL code. Execute the commands below to copy this user core code stub into a folder that will contain all manually maintained HDL code.
$ mkdir hdl
$ cp ./gen/core/`name`_core.vhd ./hdl/
By copying this code out of the ./gen/core/ directory, you are transferring "ownership" of this file to yourself. It will no longer automatically update when you change the fins.json file and re-run the fins
code generator so that your user code is preserved. The record interfaces, however, will update with code generation changes to the ./gen/core/name
_pkg.vhd file. If you have special interface requirements for your firmware IP (meaning you need HDL ports other than the standard AXI4-Lite properties interface or the AXI4-Stream ports interfaces), you will also need to copy and "own" the top-level wrapper ./gen/core/name
.vhd file and the top-level testbench ./gen/core/name
_tb.vhd files.
Develop your user core code in the ./hdl/name
_core.vhd file, interacting with the FINS Ports and Properties record interfaces. The ports_in
and ports_out
record interfaces are described in detail here. The props_control
and props_status
record interfaces are described in detail here. If you have an existing HDL module, you will need to instantiate this module in the user core and then translate the record interfaces to the HDL ports of your module.
Once your code files are in place (all development doesn't have to be finished!), the next step is to define the top-level key filesets
in the FINS Node JSON file. Defining the filesets
key enables the Xilinx Vivado/Intel Quartus project creation and simulation execution flows. The filesets
key is explained in detail here, but a few special notes are below:
- Intel Quartus requires source files to be in the correct compile order.
- Vendor IP cores are best created with a TCL script, and this TCL script should be added to the
filesets::scripts::vendor_ip
key. Any TCL scripts appearing in this key will be sourced within the IP creation script, and the script will have access to any Parameters defined in theparams
key of the FINS Node JSON file. - If files are defined in the
filesets::source
key, they do not have to be added to thefilesets::sim
key as well. Thefilesets::sim
key is for simulation-only files. - Auto-generated code must be manually added to the
filesets::source
andfilesets::sim
keys. FINS does not assume that the auto-generated code will be a part of your project, so make sure you add the files you need from./gen/core/
! - The
filesets::scripts::presim
key is a good place to add scripts that create simulation input ("sim_source") files. Thefilesets::scripts::postsim
key is a good place to add scripts that validate simulation output ("sim_sink") files. These scripts should source thename
_pkg.m andname
_pkg.py package files to take advantage of auto-generated Parameter, Property, and Port specifications. The package files themselves should not be listed in thefilesets
key. - The
filesets::scripts::prebuild
key is a good place to add scripts that create coefficient or RAM initialization files.
With the filesets
key defined, you may now build and simulate your design. Follow the commands below as an example of generating the Xilinx Vivado backend and then building the IP.
$ fins -b vivado fins.json
$ make
By default, the Makefile targets will use a command line flow and store their output to corresponding files in the ./log/ directory. If you would like to view the command output in the terminal window and execute the flow using the GUIs, set the UseGui
make variable like this: make sim UseGui=1
.
If there are errors in your params
, ports
, or properties
top-level keys, regenerate the code with the core backend like this: fins fins.json
. The Xilinx Vivado projects will be automatically updated, but Intel Quartus projects may need to be regenerated with the make
command. If there are errors in your filesets
top-level key, the project should be regenerated with the make clean
and the make
commands.
The JSON schema for FINS Node is composed of the following top-level fields:
Key | Type | Required | Default Value | Description |
---|---|---|---|---|
name | string | YES | The name of the IP. | |
description | string | NO | The description of the IP. | |
version | string | NO | 1.0 | The version of the IP. |
company_name | string | NO | The name of the company which created the IP. | |
company_url | string | NO | user.org | The base URL of the company which created the IP. Quartus uses this field as the AUTHOR. |
company_logo | string | NO | The relative filepath of the logo image to use for display purposes. | |
license_file | string | NO | The relative filepath of the license file containing the string to be inserted in all files generated by FINS. | |
library | string | NO | user | The name of the category or group of which this IP belongs. |
user_ip_catalog | string | NO | A directory location where third-party sub-IP is stored, meaning only sub-IP that were not already explicitly referenced in the FINS ip key. |
|
part | string | NO | The programmable logic part number. While a default is not selected for the JSON, the auto-generated vendor scripts use the following default parts: Vivado uses the Zynq weback part xc7z020clg484-1 and Quartus uses the Cyclone V 10CX220YF780I5G. | |
top_source | string | NO | name |
The name of the top-level synthesizable source HDL module. For Quartus, this field MUST be the same as the top-level source HDL's filename without the extension. |
top_sim | string | NO | name _tb |
The name of the top-level testbench simulation HDL module. For Quartus, this field MUST be the same as the top-level testbench HDL's filename without the extension. |
params | dict[] | NO | An array of parameter definitions. See the parameters documentation here. | |
filesets | dict | NO | A dictionary of fileset definitions. See the filesets documentation here. | |
ip | dict[] | NO | An array of sub-IP references. See the sub-IP documentation here. | |
ports | dict | NO | A dictionary of ports definitions. See the ports documentation here. | |
properties | dict | NO | A dictionary of properties definitions. See the properties documentation here. |
FINS Applications and Systems are used for integration of multiple FINS Nodes and a platform. See FINS Integration for more information.