Skip to content

Refactoring for VHDL Libraries

Benjamin Reese edited this page Nov 8, 2019 · 11 revisions

VHDL Libraries

SURF and many other firmware repositories will soon transition to using proper VHDL libraries. This explainer will help you refactor your code for this change.

The VHDL language allows modules to be grouped into "library" namespaces. This is similar to the namespace/package features found in every modern software language (C++, Python, etc). VHDL libraries prevent naming conflicts between modules from different codebases.

For a long time, we have been punting on proper VHDL library use and instead dropping everything in the default work namespace. This is becoming a problem as some of our projects use code from CERN that also has modules with names like: Synchronizer, etc.

An upcoming release of SURF will finally fix this by placing all SURF modules and packages in a surf VHDL library. This is implemented in the VHDL code itself as well as the Ruckus TCL scripts that build Vivado projects. Since almost every other firmware repository uses SURF, this changes will create a ripple effect requiring those repositories to use proper VHDL libraries as well. (E.g. AmcCarrierCore, axi-pcie-core, etc).

Refactoring

All projects that use SURF will need to refactor their code as shown below.

Old code with SURF modules and packages in work:

use work.StdRtlPkg
use work.AxiLitePkg
...
U_Synchronizer : entity work.Synchronizer
   port map(
      clk => clk,
      rst => rst,
      dataIn => din,
      dataOut => dout);

New code with SURF modules and packages in surf library:

library surf;
use surf.StdRtlPkg
use surf.AxiLitePkg
...
U_Synchronizer : entity surf.Synchronizer
   port map(
      clk => clk,
      rst => rst,
      dataIn => din,
      dataOut => dout);

The Refactoring Script

We have developed a script that can refactor any code base in a matter of seconds. The script can be found at surf/python/tools/vhdlib.py

# General usage
> python3 firmware/submodules/surf/python/tools/vhdlib.py \
--libname <name> --libpath <path/to/library/code> \
--refactor <path/to/your/code | [another/path/to/your/code]>

# surf example usage
> python3 firmware/submodules/surf/python/tools/vhdlib.py \
--libname surf -libpath firmware/submodules/surf \
--refactor firmware/targets firmware/common

What the Script Does

The script first finds every .vhd and .vhdl file recursively in --libpath. It then parses those VHDL files and makes lists of all of the package and entity names that it finds. These lists make up the library namespace.

The script then parses every .vhd and .vhdl file recursively in --refactor. (You can also specify multiple --refactor paths). It looks for packages and entities from the namespace that have been declared in the work namespace and replaces work with the correct library name. It also adds a library surf; declaration when necessary.

Other libraries

The script is not SURF specific. It will work to refactor code from any library. Every VHDL library maintained by TID AIR ES will transition to using libraries at the same time, so you will have to run the script once for each library that your project uses in order to fully refactor it.

# Refactor code using AmcCarrierCore
> python3 vhdlib.py --libname amc_carrier_core --libpath firmware/submodules/AmcCarrierCore --refactor firmware/targets

Library naming conventions

The VHDL naming convention for libraries is lower_case_with_underscores. Various libraries are therefore named as follows: AmcCarrierCore -> amc_carrier_core lcls-timing-core -> lcls_timing_core axi-pcie-core -> axi_pcie_core

Basicaly, the library name should be the github repository name with underscore separators instead of (-) dashes or CamelCase.

Project Code

Our firmware projects also tend to dump all local project code into work as well. You can now easily fix that using the script:

# Put local project code into its own library
> python3 vhdlib.py --libname project_name --libpath firmware/common firmware/targets \
--refactor firmware/common firmware/targets

Note that the --libpath and --refactor arguments are the same. The script finds all entities and packages in the --libpath and then refactors those same packages and entities to use project_name instead of work.

You will also have to edit your ruckus.tcl to tell Vivado to put your code into a library. This is done with the -lib argument to the loadSource function:

loadSource -lib project_name -dir "$::DIR_PATH/hdl"

Trying It Out

The vhdl-lib branch of SURF has all of the changes that put things into a VHDL library. This is also where you will find the refactoring script. You are encouraged to check out this branch in your own projects' submodules to test it all out before this branch gets put into a release.

Other libraries also have vhdl-lib branches where the transition to libraries has been applied. You will need to checkout the vhdl-lib branch of each library that your project uses.

Pull Requests

The following are the related pull requests for each slaclab VHDL library