Implementing RTL Variants
This guide explains how to implement RTL backend variants for FINN hardware layers.
Overview
RTL variants generate SystemVerilog/Verilog HDL code that instantiates finn-rtllib modules. Unlike HLS layers which share common templates, each RTL layer requires its own Verilog wrapper template in finn-rtllib.
Location: src/finn/custom_op/fpgadataflow/rtl/<layer>_rtl.py
Inherits from: Base layer + RTLBackend
Verilog Wrapper Requirement
Vivado IP Integrator expects Verilog (.v) files during IP stitching, even though finn-rtllib components are written in SystemVerilog (.sv).
So, each RTL layer needs:
SystemVerilog implementation (e.g.,
layernorm.sv) - The actual hardware logicVerilog wrapper template (e.g.,
layernorm_wrapper_template.v) - AXI interface wrapper for Vivado
Template keywords: Each wrapper has layer-specific keywords (e.g., $N$, $SIMD$, $TOP_MODULE_NAME$) that get replaced during code generation.
Example: LayerNorm_rtl
Wrapper template: finn-rtllib/layernorm/layernorm_wrapper_template.v
Contains Verilog module with AXI stream interface
Instantiates
layernorm.svSystemVerilog moduleUses template keywords:
$TOP_MODULE_NAME$,$N$,$SIMD$
RTL layer implementation: src/finn/custom_op/fpgadataflow/rtl/layernorm_rtl.py
Inherits from
LayerNorm+RTLBackendgenerate_hdl()createscode_gen_dictwith layer parameters and substitutes into templateCopies SystemVerilog files (
layernorm.sv,queue.sv,accuf.sv, etc.) to code_gen_dirReturns HDL file list and Vivado IPI TCL commands
Reference implementation: See src/finn/custom_op/fpgadataflow/rtl/layernorm_rtl.py for complete example.
Required Methods
Method |
Purpose |
|---|---|
|
Generate Verilog wrapper from template, copy SystemVerilog files |
|
Return list of all HDL files (SystemVerilog + Verilog wrapper) |
|
Generate Vivado IPI TCL commands (add_files + create_bd_cell) |
RTL Simulation
RTL variants can provide rtlsim execution using XSI (Xilinx Simulator Interface). The execute_node() method dispatches based on exec_mode:
cppsim: Falls back to base layer Python executionrtlsim: UsesRTLBackend.execute_node()via XSI
Adding a New RTL Layer
Step 1: Create finn-rtllib module
Create directory
finn-rtllib/<layer_name>/Implement SystemVerilog module
<layer_name>.svCreate Verilog wrapper template
<layer_name>_wrapper_template.vwith layer-specific keywordsAdd any helper SystemVerilog modules needed
Step 2: Create RTL variant in FINN
Create
src/finn/custom_op/fpgadataflow/rtl/<layer>_rtl.pyInherit from base layer +
RTLBackendImplement
generate_hdl()to: - Definecode_gen_dictwith template keywords - Substitute keywords into wrapper template - Copy SystemVerilog files to code_gen_dirImplement
get_rtl_file_list()to list all HDL filesImplement
code_generation_ipi()to generate TCL commands
Step 3: Register in FINN
Add import to
src/finn/custom_op/fpgadataflow/rtl/__init__.pyUpdate SpecializeLayers if needed
Add tests in
tests/fpgadataflow/
See Also
CustomOp Class Hierarchy - CustomOp class hierarchy
Implementing HLS Variants - Implementing HLS variants
SpecializeLayers: HLS vs RTL Selection - HLS vs RTL selection
HDL_STYLE_GUIDE.md - SystemVerilog coding conventions
finn-rtllib - RTL module library