Generating a Register Tree
The register_tree_gen.py script in the HotRIO firmware tools is used to generate a VHDL register tree from a JSON configuration file. This allows microcontroller interfaces to access registers in a clean and organized hierarchical structure.
Input Format
The input to the script is a JSON file describing the register tree. Each register entry includes address, name, type (read-only, read-write, constant), and its contents. Here’s an example format:
json:
{
"generic_regs": [
{
"address": "0x00",
"name": "fw_version",
"type": "const",
"contents": [
{
"name": "Bitstream version",
"description": "Contains the identification code of the bitstream",
"signal_name": "cfg_fw_version",
"start_bit": 0,
"end_bit": 15,
"default": 20225
}
]
}
],
"pcs_regs": [
{
"address": "0x01",
"name": "pcs_controls",
"type": "rw",
"contents": [
{
"name": "TX Dual 0 enable",
"description": "Enables Dual 0 of the PCS",
"signal_name": "cfg_tx_d0_en",
"start_bit": 0,
"end_bit": 0,
"default": 1
},
{
"name" : "TX Dual 1 enable",
"description": "Enables Dual 1 of the PCS",
"signal_name": "cfg_tx_d1_en",
"start_bit": 1,
"end_bit": 1,
"default": 0
}
]
},
{
"address": "0x02",
"name": "pcs_status",
"type": "ro",
"contents": [
{
"name": "TX Dual 0 ready",
"description": "High when Dual 0 of the PCS is ready to transmit",
"signal_name": "cfg_tx_d0_rdy",
"start_bit": 0,
"end_bit": 0,
},
{
"name" : "TX Dual 1 ready",
"description": "High when Dual 1 of the PCS is ready to transmit",
"signal_name": "cfg_tx_d1_rdy",
"start_bit": 1,
"end_bit": 1,
}
]
}
]
}
Rules:
Categories, such as “generic_regs” or “pcs_regs”, are only used as thematic groups for documentation. They do not affect the generation of the register tree.
Address, name, type and contents are mandatory fields for each register. The address can be expressed as hex or decimal string.
Available types are “rw”, “ro” and “const”. Signals must have a “default” in a “const” register, and they must not have it in a “ro” register. In a “rw” register the default is optional.
A register may contain any number of signals, as long as their bit ranges are all within the 15 downto 0 range and they are not overlapping.
Each signal must have name, description, signal_name, start_bit and end_bit. The start_bit must be less than or equal to the end_bit, even if the range is interpreted in the opposite bit order.
Defaults can be specified as decimal integers (without quotes) or as binary, octal or hexadecimal strings (with quotes), using the following format: “0b” prefix for binary, “0o” prefix for octal and “0x” prefix for hexadecimal.
The name field of registers and the signal_name field of signals will be modified by the script to be usable in VHDL code. Whitespace is replaced by underscores, and any non-alphanumeric character (except for underscores) is removed.
Usage
Run the tool in hotrio-software using:
python3 Firmware/Scripts/register_tree_gen.py -h
This prints:
usage: register_tree_gen.py [-h] [-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}] [-n NAME] [-o OUTPUT_PATH] -c CONFIG_PATH [-v VSG_CFG_PATH] [-b BRANCHING_FACTOR] [-a ADDR_CMD] [-r READ_CMD] [-w WRITE_CMD] [-u]
Generate register map from JSON file
options:
-h, --help show this help message and exit
-l {CRITICAL,ERROR,WARNING,INFO,DEBUG}, --loglevel {CRITICAL,ERROR,WARNING,INFO,DEBUG}
Log level, one of: CRITICAL, ERROR, WARNING, INFO, DEBUG
-n NAME, --name NAME Name of the vhdl module
-o OUTPUT_PATH, --output_path OUTPUT_PATH
Output file path (relative to cwd)
-c CONFIG_PATH, --config_path CONFIG_PATH
Configuration file path (relative to cwd)
-v VSG_CFG_PATH, --vsg_cfg_path VSG_CFG_PATH
Path to a VSG configuration file. If this argument is not specified, VSG will not be used to fix output code formatting
-b BRANCHING_FACTOR, --branching_factor BRANCHING_FACTOR
Branching factor
-a ADDR_CMD, --addr_cmd ADDR_CMD
8-bit value of the set_address command
-r READ_CMD, --read_cmd READ_CMD
8-bit value of the read command
-w WRITE_CMD, --write_cmd WRITE_CMD
8-bit value of the write command
-u, --update_addresses
Update addresses in the configuration file to make them consecutive
Example
Assume your current path is inside the root folder of a vertical project.
You can generate the register tree VHDL module using:
python3 Libs/hotrio-software/Firmware/Scripts/register_tree_gen.py -n registers -o Source/modules/registers/hdl/registers.vhd -c Source/registers.json -v Libs/hotrio-software/Firmware/Scripts/QA/vsg.cfg -u
This command:
Names the VHDL module as registers
Generates the output VHDL and testbench files
Rewrites all register addresses to make them consecutive (-u)
Formats the code for readability using the provided configuration (-v)
Notes
Usage of -u is suggested unless the addresses need to be kept as specified. When -u is not used, the resulting register map may be larger than needed.
The register tree module and the connected SPI slave interface require a reset pulse before starting to operate correctly after power-up. On Lattice FPGAs, if the reset is transferred through the primary clock network, it may not be properly received by the modules until the first falling edge of the reset signal.