The Generation Workflow
Relevant source files
The following files were used as context for generating this wiki page:The regif tool provides an automated workflow for generating Verilog RTL and Microsoft Word documentation for register interfaces from a single Excel spreadsheet source. This process streamlines hardware design by ensuring consistency between the specification, implementation, and documentation. The core of the workflow involves parsing a specially formatted Excel file, performing extensive validation, and then using a series of templates to generate the final output files.
The entire generation logic is encapsulated within the regif.py script. It relies on external libraries xlrd for Excel parsing and python-docx for document creation. The workflow is initiated from the command line, taking an Excel file as input and producing Verilog (.v) and Word (.docx) files as output.
Sources: regif.py:1-18, 1373-1399, readme.md:14-15, setup.py:25-28
Workflow Overview
The generation process follows a clear, sequential path from user input to final artifact generation. The user first creates a register specification in an Excel file, either from scratch or by using the provided template. The regif script is then executed with this file as an argument. The script performs parsing, validation, and finally, code and documentation generation.
The following diagram illustrates the high-level generation flow.
This diagram shows the end-to-end process, from template creation to the generation of Verilog and documentation files.
Sources: readme.md:27-31, regif.py:1373-1399
Input: The Excel Template
The primary input to the generation workflow is an Excel (.xls) file that defines the register map, individual registers, and their bit-fields. The script expects a specific structure for parsing.
Sources: regif/regif_template.xls, regif.py:1388-1391
Header Configuration
The first few rows of the Excel sheet are used for global configuration of the generated module.
| Row | Column | Parameter | Description | Example |
|---|---|---|---|---|
| 2 | B | moudle | The base name for the generated module and files. | my_ip |
| 4 | F | addr_wdith | The width of the address bus (bmi_addr). | 8 |
| 5 | F | data_width | The width of the data bus (bmi_wdata, bmi_rdata). | 32 |
| 6 | B | SYNC/ASYNC | Determines if Clock Domain Crossing (CDC) logic is generated. ASYNC enables CDC. | ASYNC |
| 7 | F | reg_pre | A prefix to be added to all internal register field signals. | "if_" |
| 4 | K | rw_cg | Enables clock gating for RW, RWT, and WO type registers. Set to YES. | YES |
| 5 | K | group_size | Groups read logic to reduce complexity. Must be a power of 2. 0 disables grouping. | 32 |
| 6 | K | reset-macro | Use Verilog macros for reset logic (ctrl_always_ff_begin) if set to YES. | YES |
Sources: regif.py:91-96, 1145-1160
Register and Field Definitions
Following the header, the file contains register and field definitions. Each register block starts with a register definition row, followed by one or more rows for its fields.
Register Definition Format
| Column | Name | Regex Validation | Example |
|---|---|---|---|
| A | offset | 0x[\da-fA-F]+\Z | "0x001C" |
| B | regname | [a-zA-Z]\w*\Z | "M_DMA_CFG" |
| C | reg_des | .* | some description |
| D | width | [1-9]\d{1,2}\Z | 32 |
Sources: regif.py:53-57
Field Definition Format
| Column | Name | Regex Validation | Example |
|---|---|---|---|
| E | section | `[(\d+ | \d+:\d+)]\Z` |
| F | fd_name | [a-zA-Z]\w*\Z | dma_en |
| G | RW | (RW|RC|...|RWP)\Z | RW |
| H | reset | (\d+'(h|H)...|0\Z) | "1'b0", "8'hFF" |
| I | wprotect | BITWISE|...|\A\Z | "[0]", bitwise |
| J | locksig | [a-zA-Z]\w*\Z|\A\Z | cfg_lock |
| K | fd_des | .* | Enable for DMA |
| L | other | .* |
Sources: regif.py:59-67
The tool supports a wide range of access types for fields, which dictate the generated hardware behavior.
| Access Type | Description |
|---|---|
RO | Read Only |
WO | Write Only |
RW | Read/Write |
RC | Read, Clear on HW event |
RWC | Read, Write to clear |
RWT | Read, Write to toggle |
RWP | Read, Write-pulse (clears to reset value) |
RWW | Read, HW Write |
BP | Bitwise Protection field |
CP | Condition Protection field |
Sources: readme.md:33-44, regif.py:61
Core Processing Logic
The script's entry point orchestrates the entire process, from parsing arguments to invoking the generation functions.
Execution Flow
The main execution sequence is controlled by the if __name__ == "__main__" block.
This sequence diagram shows the interaction between the command line, the main script, and the core classes/functions during generation.
Sources: regif.py:1373-1399
Data Modeling and Validation
Before generation, the script parses the Excel data into a set of Python objects and performs rigorous validation.
Class Structure
The data is modeled using three main classes: Regif, Reg, and Field.
This class diagram illustrates how the Excel data is structured into objects, with Regif as the main container.
Validation Checks
The script performs two stages of validation to prevent generating broken Verilog:
-
Static Check (
_static_check): This runs first and checks for basic formatting and uniqueness.- Verifies that register names and addresses are unique.
- Verifies that field names within a register are unique.
- Checks that all header, register, and field values match the expected regex patterns defined in
other_format,reg_format, andfield_format.
Sources: regif.py:1014-1045, 1172-1183
-
Dynamic Check (
_dynamic_check): This runs after the initial object model is built and checks for logical consistency.- Section Continuity: Ensures bit-field sections are contiguous, start at 0, and end at
data_width - 1. - Reset Value Width: Confirms that the width of a field's reset value matches the field's bit width.
- Protection Logic: Validates that protection fields (
CP,BP) are correctly configured and that the fields they protect exist and have compatible widths.
Sources: regif.py:441-445, 447-465, 467-486, 1185-1196
- Section Continuity: Ensures bit-field sections are contiguous, start at 0, and end at
Verilog Generation
The genverilog method orchestrates the creation of the Verilog output files. It uses a set of f-string templates to build the different sections of the Verilog module.
Sources: regif.py:1325-1370
File Structure
Two files can be generated:
{modulename}_regif.v: The main module containing the register logic. It is always generated.{modulename}_regif_wrap.v: A wrapper module generated only if any fields use thelocksigfeature. This wrapper instantiates the main_regifmodule and adds the lock control logic.
The generated files are explicitly ignored by version control.
Sources: regif.py:302-323, 1364-1369, .gitignore:10-12
Logic Generation
The script iterates through the Reg objects and calls their methods to generate different pieces of Verilog logic.
-
Write Logic (
w_block): TheRegFields.w_blockmethod generates thealwaysblock for register writes. It handles different field types:- Normal writes for
RW,WO. - Toggle-on-write for
RWT. - Write-to-clear for
RWC. - Protection logic for
CPandBP. - Clock gating logic if
rw_cgis enabled, using a separatealwaysblock for clock-gated registers. - The core templates used are
W_ALWAYS_L3andW_CG_ALWAYS_L3.
# Snippet from regif.py showing the main write-logic template W_ALWAYS_L3 = \ '''{always_ff_begin}{field_rst} end else if(bmi_wr && (bmi_addr==`{reg_name})) begin{normal_wr}{rwt_wr}{protect_wr}{else_part} end '''Sources: regif.py:130-135, 595-620
- Normal writes for
-
Read Logic (
read_express): TheRegFields.read_expressmethod generates acaseitem for the main readalwaysblock. It concatenates all fields of a register to form thebmi_rdataoutput. ForWO,BP,CP, orRESERVEDfields, it correctly assigns0. TheR_ALWAYStemplate assembles all register reads into a singlecasestatement. Ifgroup_sizeis configured, the read logic is split into multiple smalleralwaysblocks to improve synthesis results.
Sources: regif.py:200-216, 659-674, 1283-1303 -
Lock Logic (
gen_lock_segment): If any field has alocksigdefined, this method generates an additionalalwaysblock in the wrapper file. This block prevents writes to locked fields by re-asserting their current value when the lock signal is active.
Sources: regif.py:276-284, 1259-1281 -
FIFO Interface (
fifo_if): If a register is marked withFIFO_IFin its description, the tool generates a simple write-pulse signal ({reg_name}_push) instead of a full register implementation. This is useful for interfacing with FIFO modules.
Sources: regif.py:113-118, 332, 622-629
Documentation Generation
The gen_regif_doc function is responsible for creating the _Register_Manual.docx file.
- It initializes a
Documentobject from thepython-docxlibrary. - It iterates through the list of registers extracted from the Excel file.
- For each register, it calls
creat_regs_detail, which adds:- A heading with the register name and address.
- Paragraphs for the offset address and description.
- A table (
creat_reg_table) detailing each field: bit position, name, access type, reset value, and description.
This ensures the documentation is always synchronized with the register specification in the Excel file.
Sources: regif.py:1403-1442