Skip to content

The Verilog generator

The Verilog generator (src/gen/) lowers the same elaborated model into synthesizable Verilog. It runs as a small pipeline, auto-routes I/O across the module hierarchy, gives every signal a systematic name, and writes each module in a fixed pool order.

GenController::start (src/gen/controller/genController.cpp) drives three passes in sequence:

void GenController::start(){
initEle();
routeIo();
generateEveryModule();
}
  1. initEle — recruit the model and build each module’s generation metadata (createModuleGen, setTopModule, startInitEle), including the global input and output elements.
  2. routeIo — route I/O signals to the correct place across the module tree (startRouteEle, finalizeRouteEle).
  3. generateEveryModule — dump the routed model to Verilog, one master file (and optionally one file per module).
flowchart LR
    M["Elaborated model"] --> A["initEle<br/>createModuleGen, setTopModule<br/>build gen metadata"]
    A --> B["routeIo<br/>startRouteEle then finalizeRouteEle<br/>hierarchical I/O wiring"]
    B --> C["generateEveryModule<br/>startWriteFileMaster<br/>write .v files"]
    C --> V["synthesizable Verilog"]

When a signal in one module is read or driven from another, the generator wires it through every intermediate module automatically. moduleRouting.cpp (src/gen/proxyHwComp/module/) creates three kinds of auto-generated wire, each with a fixed name prefix:

PrefixKindRole
AIP_auto input portpulls a signal down into a module as an input
AOP_auto output portpushes a signal up out of a module as an output
ABD_auto bridgethe connecting (inter) wire at the common ancestor

The routing walks up to the common ancestor of the source and destination modules, creates one ABD_ bridge there, then descends generating AIP_ / AOP_ wires along each side. In the emitted tutorial.v, the top module’s sub-module connection looks like this:

//bridgeVec
////input of submodule
wire [0: 0] WIRE78_AIP_0_rstWire_SYS;
wire [0: 0] WIRE77_ABD_1_rstWire_SYS;
...
assign WIRE78_AIP_0_rstWire_SYS = WIRE77_ABD_1_rstWire_SYS;
assign WIRE77_ABD_1_rstWire_SYS = WIRE1_rstWire_SYS;

Every emitted signal carries a type prefix, its global id number, and its source name, e.g. REG13_d or SR_ST4_startNode. The prefixes seen in the real tutorial.v:

PrefixComponent
REGregister
WIREwire
EXPRexpression (continuous assign)
VALconstant value / literal
SR_STflow-block state register
MODULEsub-module instance

MEM_BLOCK and MEM_BLOCK_INDEXER are the corresponding prefixes for memory blocks and their indexers (there are none in this example). Output is pool-ordered, not source-ordered: the layout follows the component pools, not the order you wrote the design.

  • Parameter filesgenFolder, topFileName, topModName, and the testType values that trigger generation.
  • The Hybrid Simulator — the other backend that reads the same model.