Back to features

Verilog Export

Generate clean, synthesizable Verilog HDL from your Ruby designs. Ready for FPGA synthesis and ASIC flows.

Verilog Synthesis FPGA ASIC

Export Pipeline

RHDL lowers your Ruby hardware descriptions through a multi-stage pipeline. First, the Ruby DSL is elaborated into an intermediate representation (IR) that captures the full circuit structure. Then, the IR is optimized and lowered to synthesizable Verilog HDL. Each stage preserves the design intent while producing industry-standard output.

Ruby DSL

Classes, ports, behavior blocks

Elaboration

Resolve params, flatten hierarchy

IR Graph

Nodes, nets, connections

Verilog Output

Synthesizable .v files

Code Generation

Map IR to Verilog constructs

Optimization

Dead code, constant folding

Exporting to Verilog is a single method call. You can export individual components or entire hierarchies.

export.rb
require 'rhdl'

# Export a single component
counter = Counter.new(width: 8)
counter.to_verilog("output/counter.v")

# Export with all sub-components
cpu = CPU6502.new
cpu.to_verilog("output/", hierarchy: :flat)
# Creates: output/cpu6502.v (all modules in one file)

cpu.to_verilog("output/", hierarchy: :split)
# Creates: output/cpu6502.v, output/alu.v,
#          output/control_unit.v, output/decoder.v, ...

Generated Code Quality

RHDL generates clean, readable Verilog that passes lint checks and synthesizes efficiently. Signal names are preserved from your Ruby source, making debugging and waveform analysis straightforward.

Ruby source: a parameterized shift register with configurable depth and width.

shift_register.rb
class ShiftRegister < RHDL::Sim::SequentialComponent
  def initialize(depth: 4, width: 8)
    input  :clk, :rst, :en
    input  :din,  width: width
    output :dout, width: width

    depth.times do |i|
      register :"stage_#{i}",
        width: width
    end
  end

  behavior clock: :clk,
           reset: :rst do
    if en
      stage_0 <= din
      (1...depth).each do |i|
        send(:"stage_#{i}") <=
          send(:"stage_#{i-1}")
      end
      dout <= send(:"stage_#{depth-1}")
    end
  end
end

Generated Verilog: clean, synthesizable output with preserved signal names and proper reset logic.

shift_register.v (generated)
module shift_register (
  input  wire        clk,
  input  wire        rst,
  input  wire        en,
  input  wire [7:0] din,
  output reg  [7:0] dout
);
  reg [7:0] stage_0;
  reg [7:0] stage_1;
  reg [7:0] stage_2;
  reg [7:0] stage_3;

  always @(posedge clk or
          posedge rst) begin
    if (rst) begin
      stage_0 <= 8'b0;
      stage_1 <= 8'b0;
      stage_2 <= 8'b0;
      stage_3 <= 8'b0;
      dout    <= 8'b0;
    end else if (en) begin
      stage_0 <= din;
      stage_1 <= stage_0;
      stage_2 <= stage_1;
      stage_3 <= stage_2;
      dout    <= stage_3;
    end
  end
endmodule

Synthesis Compatibility

Generated Verilog targets the synthesizable subset of IEEE 1364-2005 (Verilog-2005). The output has been tested with major FPGA and ASIC synthesis tools to ensure broad compatibility.

ToolVendorTargetStatus
VivadoAMD/XilinxFPGA (7-series, UltraScale)Fully supported
Quartus PrimeIntel/AlteraFPGA (Cyclone, Stratix)Fully supported
YosysOpen sourceFPGA (iCE40, ECP5, Gowin)Fully supported
Lattice DiamondLatticeFPGA (MachXO, ECP)Fully supported
Design CompilerSynopsysASICCompatible
GenusCadenceASICCompatible
Icarus VerilogOpen sourceSimulationFully supported
VerilatorOpen sourceSimulation / LintFully supported

The export pipeline avoids unsynthesizable constructs. All generated Verilog uses only blocking/non-blocking assignments, continuous assigns, and standard always blocks.

synthesis_flow.rb
# Full synthesis workflow
design = MyProcessor.new

# Export with synthesis-friendly options
design.to_verilog("rtl/",
  hierarchy:     :split,       # one file per module
  reset_style:   :async,       # async reset (default)
  clock_edge:    :posedge,     # rising edge triggered
  naming:        :snake_case,  # signal naming convention
  vendor_pragma: :xilinx,     # include synthesis attributes
)

# Verify with Verilator lint
design.lint!  # raises on warnings