FuseSoC is a package manager and a set of build tools for HDL code.
Its main purpose is to increase reuse of IP cores and be an aid for creating, building and simulating SoC solutions.
The package manager part can be seen as an apt, portage, yum, dnf, pacman for FPGA/ASIC IP cores. A simple ini file describes mainly which files the IP core contains, which other IP cores it depends on and where FuseSoC shall fetch the code.
A collection of cores together with a top-level is called a system, and systems can be simulated or passed through the FPGA vendor tools to build a loadable FPGA image.
Currently FuseSoc supports simulations with ModelSim, Icarus Verilog, Verilator, GHDL, Isim and Xsim. It also supports building FPGA images with Project Icestorm, Xilinx ISE and Altera Quartus.
Core description files
capi (Core API) is the format for core description files. Current version is version 1.0. A capi 1.0 file is identified by the string "CAPI=1" in the beginning of a file. The rest of the file is a standard INI file that is compatible with Python’s configparser module. The options available for
.core files are described in the Core API definition
This tutorial describes how to create your own .core files
Core naming rules
VLNV tags to uniquely identify a core.
VLNV is a concept borrowed from the IP-XACT and stands for Vendor Library Name Version. This means that the name of the cores consists of four parts, which are generally separated by :, such as
librecores.org:peripherals:uart16550:1.5. In FuseSoC, it is allowed to leave out all parts of the VLNV tag except for the name part, e.g
::uart16550. In those cases, the Vendor and Library parts will be empty strings, and the version will be set to 0.
As the VLNV concept was introduced in FuseSoC after many core files had already been created, FuseSoC still supports parsing files with the legacy naming convention. These can either be of the format
name, in which case they will be translated internally to VLNV tags with the Name field set, and Version set to 0, or they can be of the format
name-version, which will also set the Version field.
FuseSoC will pick up the core identifer from the
name option in the
[main] section of
.core files. If no identifier is specified there, the name of the core file without the
.core suffix will be used and treated as a legacy name.
As an extension to the VLNV naming scheme, FuseSoC also support specifying a revision of a core file. This is a fifth field that can be added to both legacy and VLNV names by adding
-r<revision> as a suffix (e.g.
uart16550-r1). This is used to make updates to the
.core file even if the source of the core is unchanged.
A collection of one or more cores in a directory tree is called a core library. FuseSoC supports working with multiple core libraries. The locations of the libraries are specified in the FuseSoC configuration file,
To find a configuration file, FuseSoC will first look for
fusesoc.conf in the current directory, and if there is no file there, it will search next in
~/.config/fusesoc on Linux and
%LOCALAPPDATA%\fusesoc in Windows) and lastly in
fusesoc init after FuseSoC is installed, the standard libraries will be installed, and a default configuration file will be created in
$XDG_CONFIG_HOME/fusesoc/fusesoc.conf with the following contents:
[main] cores_root = ~/.local/share/fusesoc/orpsoc-cores ~/.local/share/fusesoc/fusesoc-cores
Core search order
Once FuseSoC has found its configuration file, it will parse the
cores_root option in the
[main] section of
fusesoc.conf. This option is a space-separated list of library locations which are searched in the order they appear. Additional library locations can be added on the command line by setting the
--cores-root parameter when FuseSoC is launched. The library locations specified from the command-line will be parsed after those in
For each library location, FuseSoC will recursively search for files with a .core suffix. Each of these files will be parsed and addded to the in-memory FuseSoC database if they are valid
.core file is encountered in a directory and successfully parsed, FuseSoC will not search its subdirectories. Several
.core files can reside in the same directory and they will all be parsed.
1 and 2 reside in the same directory and are both parsed. 5 is not parsed since it resides in a subdirectory of 4
If several cores with the same VLNV identifier are encountered the latter will replace the former. This can be used to override cores in a library with an alternative core in another library by specifying them in a library that will be parsed later, either temporarily by adding
--cores-root to the command-line, or permanently by adding the other library at the end of the
cores_root parameter in the configuration file.
Making changes to cores in a library
A common situation is that a user wants to use their own copy of a core, instead of the one provided by a library, for example to fix a bug or add new functionality. The following steps can be used to achieve this:
Create a new directory to keep the user-copies of the cores (this directory will be referred to as
$corelibfrom now on)
Download the core source (the repository or URL can be found in the
[provider]section of the original core)
If the downloaded core already contains a .core file, this step is ignored Copy the original .core file to the root of the downloaded core. Edit the file and remove the
[provider]section. (This will stop FuseSoC from downloading the core and use files from the directory containing the .core file instead)
$corelibto the end of your library search path, either by editing
fusesoc.confor by adding
--cores-root=$corelibto the command-line arguments
Verify that the new core is found by running fusesoc core-info $core. Check the output to see that "Core root: " is set to the directory where the core was downloaded
FPGA implementation flows are used to build binary FPGA configuration files (bitstreams) to be downloaded to an FPGA target. The FPGA implementation flows are uusually tied to a single FPGA vendor’s devices
Simulation flows are used to simulate HDL designs and are generally independent of the intended target device. Exceptions to this are when vendor-specific modules are instantiated in the source code, which might require vendor-specific libraries that are only available for some simulators.
To run a simulation with FuseSoC, the
sim subcommand is used followed by general simulator options, the core to simulate and core-specific options.
fusesoc sim <core> --help lists all core-specific options
fusesoc sim --sim=modelsim de0_nano --vcd --timeout=100000 --bootrom_file=spi_uimage_loader.vh
The above command would build a simulation model and run a simulation of the de0_nano core using the core’s default testbench and explicitly using modelsim. If no simulator is selected, FuseSoC will use the default simulator which is selected by the core. A different testbench can be selected by setting the --testbench option. Use
fusesoc sim --help to list all general simulator options
The parameters vcd, timeout and bootrom_file would be passed to the simulator. While all three parameters look the same on the CLI (expect for vcd, which has no value associated with it), they are handled differently inside of FuseSoC.
timeout would be passed as plusargs to the simulator at run-time, while
bootrom_file would be passed as a top-level parameter during compile-time.
The cores themselves are responsible for describing in the .core file which externally accessible parameters they support. This is what the corresponding sections in the .core file look like
[parameter timeout] datatype = int description = Abort test case after n cycles paramtype = plusarg scope = public [parameter vcd] datatype = bool description = Enable VCD logging paramtype = plusarg scope = public [parameter bootrom_file] datatype = file description = Initial boot ROM contents (in Verilog hex format) paramtype = vlogparam scope = private
An observation to make here is that only the last parameter is actually defined in de0_nano.core. The first two parameters are specified in the .core file for vlog_tb_utils, which is a dependency of de0_nano. By setting their
scope=public, these parameters become available for other cores which depend on them.
As new features are added to FuseSoC, some older features become obsolete. Read the migration guide to learn how to keep the .core files up-to-date with the latest best practices