Excel Template: Defining Bitfields
Relevant source files
The following files were used as context for generating this wiki page:- regif.py
- readme.md
- setup.py
- regif/regif_template.xls (Referenced in
regif.pyandreadme.md) - img/regif.png (Referenced in
readme.md)
The regif tool uses a structured Microsoft Excel (.xls) file as its primary input for defining register maps, registers, and their individual bitfields. This template-driven approach allows for a readable and manageable way to specify the hardware register interface. The script parses this Excel file to automatically generate Verilog RTL code and a corresponding register documentation file in .docx format.
The generation process is initiated by running the regif command on a populated Excel template. The script relies on the xlrd library to read the spreadsheet data. The core logic is encapsulated within the Regif, Reg, RegFields, and Field classes, which parse, validate, and transform the Excel data into Verilog constructs.
Sources: readme.md, regif.py:1330-1342, setup.py:22-25
Parsing and Generation Flow
The script reads the Excel file, performs extensive validation, and then generates the output files. The process can be visualized as follows:
This diagram shows the high-level execution flow from command invocation to file generation, including the critical validation steps.
Sources: regif.py:1330-1348
Template Structure
The Excel template is organized into three main sections: Global Configuration, Register Definitions, and Bitfield Definitions. The script uses regular expressions to validate the format of each cell.
Sources: regif.py:53-80, img/regif.png
Global Configuration
The top section of the spreadsheet contains global settings for the generated module. These settings are validated against predefined formats.
| Cell Position | Parameter | Expected Format (Regex) | Example | Description |
|---|---|---|---|---|
| C2 | moudle | [a-zA-Z]\w* | my_ip | The base name for the generated Verilog module. |
| F4 | addr_wdith | ([2-9]|[1-9]\d{1,2}) | 8 | Address bus width (2-999). |
| F5 | data_width | ([4-9]|[1-9]\d{1,2}) | 32 | Data bus width (4-999). |
| F7 | reg_pre | \"[a-zA-Z_]\w*\"|\"\" | "if_" | A prefix for internal register/wire names. |
| K4 | rw_cg | YES / NO | NO | Enables clock gating for RW/RWT/WO registers. |
| K5 | group_size | \d+ | 32 | Groups read logic to reduce complexity. Must be a power of 2. |
| B6 | cdc | SYNC / ASYNC | ASYNC | Defines if CDC (Clock Domain Crossing) logic is needed. ASYNC enables it. |
| K6 | reset-macro | YES / NO | YES | Use a Verilog macro for the reset condition in always blocks. |
Sources: regif.py:76-80, regif.py:1120-1130
Register Definition
Each new register definition starts in column A. A register can span multiple rows if it contains multiple bitfields.
| Column | Parameter | Expected Format (Regex) | Example | Description |
|---|---|---|---|---|
| A | offset | 0x[\da-fA-F]+\Z | "0x001C" | The register's address offset. |
| B | regname | [a-zA-Z]\w*\Z | "M_DMA_CFG" | The unique name of the register. |
| C | reg_des | .* | some description | A description of the register's purpose. Special keywords like RTL_FREE or FIFO_IF can be included. |
| D | width | [1-9]\d{1,2}\Z | 32 | The total width of the register. This is checked against the sum of its bitfields. |
Sources: regif.py:53-57, regif.py:410-412
Bitfield Definition
For each register, one or more rows define its bitfields. If a register has multiple bitfields, the subsequent rows for that register leave columns A-D empty.
| Column | Parameter | Expected Format (Regex) | Example | Description |
|---|---|---|---|---|
| E | section | \[(\d+|\d+\:\d+)\]\Z | "[0]" or "[15:7]" | The bit position or range (MSB:LSB). |
| F | fd_name | [a-zA-Z]\w*\Z | dma_en | The name of the bitfield. RESERVED is a special value. |
| G | RW | (RW|RC|...|RWP)\Z | RW | The access type of the field. See Access Types. |
| H | reset | (\d+'(h|H)...|0\Z) | "1'b0" or "8'hFF" | The reset value for the field. |
| I | wprotect | BITWISE|...|\A\Z | "[0]" or bitwise | Defines a write-protection condition. See Protection Logic. |
| J | locksig | [a-zA-Z]\w*\Z|\A\Z | reg_lock | An external signal that can lock this field from being written. |
| K | fd_des | .* | DMA enable bit | A description of the bitfield's purpose. |
| L | other | .* | Reserved for future use. |
Sources: regif.py:59-66
Data Structures and Processing
The script parses the Excel data into a hierarchy of Python objects for processing and validation.
This diagram illustrates the main classes used to model the register map. Regif is the top-level container, which holds a list of Reg objects. Each Reg object contains a RegFields object, which in turn manages a list of individual Field objects.
Sources: regif.py:397-405, regif.py:440-454, regif.py:734-750, regif.py:1116-1136
Validation Checks
Before generating any code, regif performs two stages of validation.
Static Check
This initial check, performed by the static_check function, validates the format and uniqueness of entries in the Excel file.
- Format Validation: Each cell in the global, register, and field sections is matched against a regular expression defined in
other_format,reg_format, andfield_format. - Uniqueness: It ensures that all register names (
regname) and address offsets (offset) are unique across the entire definition. It also checks for unique field names (fd_name) within a register.
Sources: regif.py:1059-1089
Dynamic Check
After parsing the data into objects, the dynamic_check method in the Reg and RegFields classes performs logical checks.
- Section Continuity: Verifies that the bitfield sections (
[msb:lsb]) within a register are contiguous, start at bit 0, and end atdata_width - 1. - Reset Value Width: Ensures the width of a field's reset value matches the field's bit width.
- Protection Logic: Checks that write-protection fields (
wprotect) are correctly configured and that the protected fields and protection-condition fields have matching widths where required (e.g., forBITWISEprotection).
Sources: regif.py:503-532, regif.py:534-551, regif.py:796-819
Access Types
The RW column in the bitfield definition specifies the hardware access behavior.
| Type | Description | Source File |
|---|---|---|
RO | Read Only: The field can be read by the bus, but not written. Its value is driven by hardware inputs. | readme.md |
WO | Write Only: The field can be written by the bus, but not read. Its value is an output to the hardware. | readme.md |
RW | Read/Write: The field can be read and written by the bus. | readme.md |
RC | Read, Clear by HW: A readable field that is cleared to '0' by a hardware signal. | readme.md |
RWC | Read, Write, Clear by HW: A read/write field that can also be cleared to its reset value by a hardware signal. | regif.py:61 |
RWT | Read, Write-Toggle: A read/write field where a write of '1' to a bit toggles its value. | regif.py:61 |
RWP | Read, Write-Pulse: A read/write field that is cleared to its reset value on the next clock edge after a write. | regif.py:61 |
RWW | Read, Write by HW: A readable field that can be set to a specific value by hardware signals. | regif.py:61 |
BP | Bitwise Protection: A write-only field where each bit serves as a write-enable for the corresponding bit in another field. | regif.py:61 |
CP | Condition Protection: A write-only field where a write of a specific value enables a one-time write to another field. | regif.py:61 |
Sources: readme.md, regif.py:61
Special Features
The Excel template supports special keywords and configurations to enable advanced features.
Protection Logic
The wprotect column is used to create conditional write logic.
- Conditional Protection (
CP): If a fieldAhaswprotectset to[X], where[X]is the section of aCPfieldB, thenAcan only be written if the value being written toBmatchesB's reset value. - Bitwise Protection (
BP): If a fieldAhaswprotectset toBITWISEand anotherBPfieldBexists in the same register, a write toAis masked by the value being written toB.
Sources: regifpy:63, regif.py:650-681
FIFO Interface
By including FIFO_IF in a register's description (reg_des), the tool generates a simple write-strobe interface for that register address, suitable for pushing data into a FIFO.
// Example generated for a FIFO_IF register
//-------------------------------------------------------------------
//{addr} : {reg_name:{reg_align}} FIFO interface
wire {reg_name}_push ;
assign {reg_name}_push = bmi_wr && (bmi_addr==`{reg_name});
//assign {pn:20} = fifo_rdata{section:8} ;
Sources: regif.py:118-122, regif.py:411, regif.py:700-706
Lockable Registers
By providing a signal name in the locksig column for a field, the generated _wrap.v module will include logic to prevent writes to that field when the locksig is active. This is handled in a separate wrapper module to keep the core register file clean.
Sources: regif.py:64, regif.py:377-386, regif.py:1200-1213