Advanced Feature: FIFO Generation
Relevant source files
The following files were used as context for generating this wiki page:The regif tool provides an automated way to generate a Verilog register interface from an Excel specification. A key feature, introduced in version 1.20, is the ability to generate a simple hardware interface for a First-In, First-Out (FIFO) buffer. Instead of creating a standard read-write register, this feature generates a write-strobe signal that can be used as a 'push' enable for an external FIFO module.
This functionality is designed to simplify the integration of write-only data FIFOs into a larger system. When a register is designated as a FIFO interface, a bus write operation to its address will generate a single-cycle pulse, signaling that valid data is on the bus and should be pushed into the FIFO. This is listed as one of the key scenarios supported by regif.
Sources: regif.py:12, readme.md
Configuration
To enable the FIFO interface generation for a specific register, the user must add the keyword FIFO_IF to the register's description column in the input Excel spreadsheet.
| Column in Excel | Required Value |
|---|---|
reg_des (C) | Must contain the string FIFO_IF |
The presence of this keyword is detected during the initialization of a Reg object.
# regif.py:340-342
class Reg:
def __init__(self, reg, regifdict):
# ...
self.fifo_if = True if "FIFO_IF" in reg[2] else False
# ...
This boolean property fifo_if then dictates the kind of Verilog code that will be generated for that register's write logic.
Sources: regif.py:12, 340-342
Generated Verilog Logic
When a register is configured with FIFO_IF, the script generates a dedicated logic block for a FIFO push signal instead of a standard register write block.
This process is illustrated by the following data flow:
This diagram shows how the FIFO_IF keyword in the input Excel file triggers a specific code generation path for FIFO interfaces.
Sources: regif.py:342, 347, 622
Push Signal Generation
The core of the generated logic is a wire that acts as a push signal. This signal is asserted for one clock cycle when the bus master performs a write operation (bmi_wr) to the specific register's address.
The Verilog is generated from the FIFO_PUSH_L4 template string in the script.
// regif.py:107-112
FIFO_PUSH_L4 = \
'''//-------------------------------------------------------------------
//{addr} : {reg_name:{reg_align}} {if_Comment}
wire {reg_name}_push ;
assign {reg_name}_push = bmi_wr && (bmi_addr==`{reg_name});
{fifo_filed_assign}\n'''
The key part of this template is the assignment:
assign {reg_name}_push = bmi_wr && (bmi_addr=={reg_name});`
This creates a combinational signal {reg_name}_push that goes high only when a write to the register's address is detected. This signal is also declared as an output of the regif module.
Sources: regif.py:107-112, 701-705
Data Path Fields (WO Type)
For fields within the FIFO register that are marked as Write-Only (WO), the generator produces a commented-out assignment. This serves as a template or reminder for the designer to connect the FIFO's read data path back to the register map if needed.
The FIFOMAP template is used for this purpose:
// regif.py:99
FIFOMAP = "//assign {pn:20} = fifo_rdata{section:8} ;\n"
For a WO field named FIFO_DATA, the generated output would be:
//assign FIFO_DATA = fifo_rdata[...];
This logic is handled by the Field.fifomap() method, which is only invoked for fields of type WO. This implies that the tool does not generate a functional read path for the FIFO data; it must be implemented manually by the user outside the generated module.
Sources: regif.py:99, 878-880
Class Architecture
The FIFO generation logic is implemented across several Python classes. The relationship and responsibility of each class are key to understanding the feature.
This diagram shows that the Regif class orchestrates the generation, while the Reg, RegFields, and Field classes handle the specifics for each register and its fields based on the configuration.
Generation Sequence
The following sequence diagram illustrates the method calls during the generation of a FIFO interface register.
- The
Reg.writeproperty is accessed during Verilog generation. - It checks the
self.fifo_ifflag. - If
True, it callsself.fields.fifo_push_declar()to generate the FIFO push logic. - This method uses the
FIFO_PUSH_L4template and callsfifo_filed_assign_L2()to handle anyWOfields. - The final Verilog string for the FIFO interface is returned and included in the output file.
Sources: regif.py:347-349, 616-622, 607-614
Summary
The FIFO generation feature in regif is a specialized function for creating a simple write-strobe interface. By adding the FIFO_IF keyword to a register's description, the tool generates a {reg_name}_push output signal that pulses high upon a write to that register's address. This is intended to drive the push logic of an external FIFO. The tool does not generate the FIFO module itself, nor does it create a functional read-back path for FIFO data, instead providing commented-out code as a guideline for manual implementation. This feature streamlines the creation of control logic for write-only FIFO buffers in a register-based system.
Sources: regif.py:12, 107-112, 342