Register Access Types Overview
Relevant source files
The following files were used as context for generating this wiki page:The regif tool is a "register interface verilog code generator" that automates the creation of RTL code from an Excel-based register specification. A core feature of this tool is its support for a wide variety of register field access types, which define the read and write behavior of each field. These access types are specified in the Excel template and are translated by the regif.py script into specific Verilog hardware implementations.
This document provides a detailed overview of each supported access type, the logic generated for it, and its intended use case. The behavior is primarily controlled by the Field and RegFields classes, which use a set of Verilog template strings to construct the final hardware module.
Sources: setup.py:9, readme.md:15, regif.py:1000-1003, regif/regif_template.xls
Summary of Access Types
The regif tool validates the access type for each field against a predefined list. The table below summarizes the access types available for register fields.
| Access Type | Description |
|---|---|
RO | Read Only |
WO | Write Only |
RW | Read/Write |
RC | Read/Clear (cleared by hardware signal) |
RWC | Read, Write to Clear |
RWT | Read, Write to Toggle |
RWW | Read, Write by Wire (set by hardware signal) |
RWP | Read, Write to Preset (resets to preset value) |
BP | Bitwise Protection (write enable per bit) |
CP | Condition Protection (write enable by condition) |
Note: The readme.md also lists WC, W1S, and W1C, but these are not found in the validation logic of regif.py and are thus not implemented.
Sources: regif.py:73, readme.md:46-57
Standard Read/Write Types
These are the most common access types for general-purpose configuration and status registers.
RO (Read Only)
A field with RO access type can only be read by the bus interface. Its value is driven by an input port to the register file module. The generator creates an input port for the field and connects it to the read data bus when the register is addressed. Write operations to this register have no effect on RO fields.
The diagram below shows the data flow for an RO field.
- Declaration: An
inputport is created for the field. - Read Logic: The value of the input port is placed onto
bmi_rdataduring a read cycle. - Write Logic: Writes are ignored.
Sources: regif.py:904-908, regif.py:756-760
WO (Write Only)
A WO field can only be written by the bus interface. The written value is registered and driven out on an output port. Reading a WO field returns all zeros.
The diagram below shows the data flow for a WO field.
- Declaration: An
outputport and an internalregare created. - Write Logic: The internal register is updated with
bmi_wdataon a write cycle. - Read Logic: The read path is tied to
0.
Sources: regif.py:141-142, regif.py:750-752, regif.py:961-965
RW (Read/Write)
This is a standard read/write field. The bus can write a value to it, and the same value can be read back. The field's value is also driven out on an output port for use by other hardware logic.
- Declaration: An
outputport and an internalregare created. - Write Logic: The internal register is updated with
bmi_wdataon a write cycle. - Read Logic: The value of the internal register is placed onto
bmi_rdataduring a read cycle.
The logic is a combination of RO (for read) and WO (for write), but it reads back the written value instead of an input port.
Sources: regif.py:73, regif.py:141-142, regif.py:753-755
Self-Modifying and Event-Based Types
These types modify their own state based on specific events like writes or hardware signals.
RWC (Read, Write to Clear)
An RWC field is typically used for status flags like interrupts. It is set by a hardware signal and cleared by a software write.
- Set Condition: A dedicated hardware input signal (
<field_name>_hw_clc) sets the register to its reset value. - Clear Condition: A write from the bus interface clears the register to
0.
The following diagram illustrates the logic for an RWC field.
The Verilog implementation uses a dedicated always block for the hardware clear condition.
// From RWC_RST_L1 template
if(<name>_hw_clc) begin
<if_name> <= <rstval> ;//RWC
end
Sources: regif.py:151-154, regif.py:648-652, regif.py:911-925
RWT (Read, Write to Toggle)
A write to an RWT field toggles its value. If the corresponding bit in bmi_wdata is 1, the internal register bit is inverted. If the bit is 0, the value remains unchanged. This is useful for trigger bits where the software only needs to signal an event without knowing the current state.
// From RWT_L1 template
<if_name> <= bmi_wdata<section>? ~<if_name>:<if_name>;//RWT
Sources: regif.py:145-146, regif.py:633-634
RC (Read/Clear)
An RC field is set by a hardware signal and cleared by a software write of 1 to the corresponding bit. This is often used for clearing interrupt status bits.
The Verilog implementation uses a dedicated always block.
// From RC_ALWYAS_L0 template
always @(posedge bmi_clk or negedge bmi_rstn)
if(!bmi_rstn) begin
<if_name><bitsel> <= 1'b0;
end else if(<name>_hw_set<syncd><bitsel>) begin
<if_name><bitsel> <= 1'b1;//RC
end else if(bmi_wr && (bmi_addr==`<reg_name>) && bmi_wdata<bmibitsel>) begin
<if_name><bitsel> <= 1'b0;//RC
end
Sources: regif.py:126-134, regif.py:926-936
RWW (Read, Write by Wire)
An RWW field's value can be set by a dedicated hardware signal (<field_name>_hw_set) and a corresponding value signal (<field_name>_hw_setval). This allows asynchronous hardware updates to the register field, which can then be read by software.
- Declaration: Creates inputs for
_hw_setand_hw_setval. - Logic: An
ifcondition is added to theelsepart of the main write block to handle the hardware set.
// From RWW_SET_L1 template
if(<name>_hw_set) begin
<if_name> <= <name>_hw_setval ;//RWW
end
Sources: regif.py:155-158, regif.py:648, regif.py:937-951
Protection Types
Protection types add a layer of conditional logic to write operations, preventing accidental or unauthorized modifications.
CP (Condition Protection)
A CP field acts as a write-enable for other fields within the same register. When a write occurs, the value of the CP field in the bmi_wdata is compared to a predefined value (its reset value). If they match, the write to the protected fields is allowed.
The diagram below shows the CP mechanism.
The generated Verilog uses a nested if statement.
// From W_PROTECTE_L2 template
if(bmi_wdata<p_section> == <w_valid_val>) begin
// ... write to protected fields ...
end
Sources: regif.py:163-166, regif.py:597-609
BP (Bitwise Protection)
A BP field provides bit-level write protection for another field. Each bit in the BP field acts as a write-enable for the corresponding bit in the protected field. This is only valid if the protected field and the BP field have the same bit width.
- Logic: A write to a bit in the protected field is only performed if the corresponding bit in the
bmi_wdatafor theBPfield is1.
// From BP_L0 template
if(bmi_wdata<bmibitselp>) <if_name><bitsel> <= bmi_wdata<bmibitsel>;//BP
Sources: regif.py:139-140, regif.py:597-609, regif.py:526-532
Conclusion
The regif tool provides a comprehensive set of register access types that cover a wide range of common hardware design patterns, from simple read/write registers to complex, event-driven, and protected fields. By abstracting the Verilog implementation behind simple Excel-based definitions, it accelerates RTL development and reduces the potential for manual coding errors. The logic for each access type is systematically generated from a series of well-defined templates and class methods within regif.py, ensuring consistent and predictable behavior. The inclusion of an empty __init__.py file ensures the regif directory is treated as a Python package.
Sources: regif.py, readme.md, regif/init.py