Verilog to schematic: How RTL elaboration works
Converting abstract code like always @(posedge clk) into visible
wires, multiplexers, and registers is known as RTL elaboration.
This guide explains how Yosys and the Eclipse Layout Kernel (ELK) turn
Verilog into readable, orthogonal circuit diagrams.
1. The elaboration pipeline: HDL to RTLIL to JSON
A text editor cannot show you if an adder is connected to the wrong multiplexer branch or if a control net was accidentally left floating. RTL Bench transforms HDL into diagrams through a multi-pass compiler pipeline:
-
Front-end Parsing: Yosys parses your Verilog (
read_verilog -sv) or VHDL (via the GHDL plugin), verifying syntax and resolving parameters. -
Proc Pass: The
procpass translates procedural behavioral blocks (initial,always,always_comb,always_ff) into explicit multiplexer trees, priority selectors, and D flip-flops. -
RTLIL Intermediate Representation: Design elements become cells
in Yosys's RTL Intermediate Language (e.g.
$add,$dff,$mux,$eq). - JSON Netlist Serialization: Yosys serializes the elaborated AST into a normalized netlist format listing ports, cell types, attributes, and bit-level connection vectors.
src attribute pointing to the exact line number of your original HDL.
Clicking any block in the schematic instantly highlights the corresponding Verilog line in the editor.
2. Orthogonal graph layout with ELK
Translating a netlist of cells and wires into an understandable schematic is an NP-hard graph layout problem. Without intelligent layout rules, circuits become unreadable tangles of overlapping diagonal wires.
RTL Bench uses the Eclipse Layout Kernel (ELK) with a specialized layered orthogonal routing algorithm:
| Layout Stage | Algorithm Action | Engineering Benefit |
|---|---|---|
| Layer Assignment | Sorts cells into topological ranks from primary inputs to outputs. | Data flows cleanly left-to-right through logic pipelines. |
| Crossing Reduction | Heuristic node-reordering (barycenter sweep) within each layer. | Minimizes wire crossings between pipeline stages. |
| Orthogonal Routing | Routes all interconnects using horizontal and vertical segments with 90ยฐ bends. | Eliminates diagonal wire clutter, matching standard electrical engineering schematics. |
Synthesizable example: Arithmetic logic unit (ALU) slice
Here is a 4-bit ALU slice demonstrating how conditional assignments synthesize into multiplexers and arithmetic logic blocks:
module alu_slice (
input wire clk,
input wire rst_n,
input wire [3:0] a,
input wire [3:0] b,
input wire [1:0] op,
output reg [3:0] result
);
reg [3:0] comb_out;
// Combinational multiplexing
always @(*) begin
case (op)
2'b00: comb_out = a + b; // Infers $add
2'b01: comb_out = a - b; // Infers $sub
2'b10: comb_out = a & b; // Infers $and
2'b11: comb_out = a ^ b; // Infers $xor
default: comb_out = 4'b0000;
endcase
end
// Sequential register stage
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
result <= 4'd0;
else
result <= comb_out; // Infers $dff
end
endmodule
3. Vector bus collapsing & net-tracing
In modern 32-bit and 64-bit architectures, rendering every signal line individually would produce 32 parallel wires for a single addition operation.
-
Vector Bus Collapsing: RTL Bench groups multi-bit nets sharing the same
destination into a single thick bus line annotated with its bit width (e.g.
[3:0]or[31:0]). - Interactive Net-Tracing: Clicking on any wire, port, or pin highlights its full connection tree in bright green, tracking data fan-out across intermediate buffers and multiplexer inputs.
-
Constant Folding & Inline Badges: Fixed parameters and bit-masks
(such as
4'b0000) are embedded directly inside cell badges as hex labels (e.g.,0x0) to prevent dummy net clutter.
4. Coarse-grain vs. gate-level views
RTL Bench offers two distinct schematic perspectives depending on your debugging goal:
| Feature | Coarse-Grain (Default) | Gate-Level View |
|---|---|---|
| Cell Primitives | High-level operators: +, โ, MUX, ==, DFF |
Basic logic gates: NAND, NOR, NOT, XOR, standard flip-flops |
| Hierarchy | Submodules remain collapsed as black-boxes with named ports. | Flattened down to atomic gates across the entire design. |
| Best Used For | Verifying architectural datapath flow and state machine transitions. | Counting total gate depth and assessing hardware area. |
$latch or $dlatch) instead of a pure combinational
multiplexer, check your Verilog always @(*) blocks. An incomplete if
statement or missing default case in a case block forces the synthesizer
to retain state.
Frequently asked questions
The Verilog code is parsed by Yosys into an abstract syntax tree and elaborated into the RTL Intermediate Language (RTLIL). It is then emitted as a structured JSON netlist where ports, cells, and nets are laid out into clean orthogonal wires using the Eclipse Layout Kernel (ELK).
Coarse-grain schematics display high-level arithmetic blocks like adders, multipliers, multiplexers, and word-level registers. Gate-level schematics map those blocks to standard discrete logic cells (NAND, NOR, AND, DFF) from an ASIC foundry library or FPGA Look-Up Table primitives.
Vector bus collapsing groups individual parallel wires into a single annotated bus (e.g., [31:0] data). This avoids routing hundreds of separate lines, keeping data pipelines and processor buses readable.