Back to features

Verilog/VHDL Import

Import existing Verilog and VHDL designs into RHDL. Integrate legacy IP, vendor cores, and third-party modules into your Ruby hardware workflow.

Verilog VHDL IP Integration Legacy Support

Import Pipeline

RHDL parses Verilog and VHDL source files into an intermediate representation, then wraps them as native Ruby components. Imported modules expose their ports as typed Ruby interfaces, enabling seamless composition with DSL-defined components.

Verilog / VHDL

Source files (.v, .sv, .vhd)

Parser

Extract modules, ports, parameters

IR Mapping

Map to RHDL internal graph

Ruby Component

Native RHDL interface

Port Binding

Typed ports, width inference

Elaboration

Resolve params, validate hierarchy

Importing a Verilog or VHDL file is a single method call. The imported module becomes a first-class Ruby component.

import.rb
require 'rhdl'

# Import a single Verilog module
UartRx = RHDL.import("vendor/uart_rx.v")

# Import a VHDL entity
FifoCtrl = RHDL.import("ip/fifo_ctrl.vhd")

# Import with parameter overrides
SpiMaster = RHDL.import("vendor/spi_master.v",
  params: { CLK_DIV => 4, DATA_WIDTH => 16 }
)

# Import all modules from a directory
RHDL.import_all("vendor/xilinx_ip/",
  pattern: "**/*.v"
)

Supported Formats

RHDL supports importing from all major HDL formats and common IP packaging standards. The parser handles the synthesizable subset of each language, covering the constructs used in real-world IP cores and vendor libraries.

FormatExtensionsStandardCoverage
Verilog.vIEEE 1364-2005Full synthesizable subset
SystemVerilog.svIEEE 1800-2017Synthesizable subset (interfaces, packages, structs)
VHDL.vhd, .vhdlIEEE 1076-2008Full synthesizable subset
EDIF Netlist.edfEDIF 2.0.0Gate-level netlist import
Liberty.libSynopsys LibertyTiming/area annotations

Verilog module with parameters and multi-bit ports is imported and used directly in Ruby.

spi_master.v (original)
module spi_master #(
  parameter CLK_DIV  = 8,
  parameter DATA_W   = 8
)(
  input  wire              clk,
  input  wire              rst_n,
  input  wire              start,
  input  wire [DATA_W-1:0] tx_data,
  output reg  [DATA_W-1:0] rx_data,
  output reg              busy,
  output wire             sclk,
  output wire             mosi,
  input  wire             miso
);
  // ... implementation ...
endmodule

The imported module is used in Ruby just like a native RHDL component with full port access.

system.rb
SpiMaster = RHDL.import(
  "vendor/spi_master.v",
  params: { DATA_W => 16 }
)

class SensorHub < RHDL::Component
  def initialize
    input  :clk, :rst_n
    output :sensor_data, width: 16

    # Instantiate imported module
    @spi = add SpiMaster.new

    # Connect ports naturally
    @spi.clk   <= clk
    @spi.rst_n <= rst_n
    sensor_data <= @spi.rx_data
  end
end

Integration Patterns

RHDL supports common integration workflows for bringing external IP into your designs. Whether wrapping vendor primitives, reusing legacy blocks, or pulling in open-source cores, the import system handles hierarchy, port mapping, and clock domain crossings.

Wrap a vendor memory IP with a Ruby interface, adding address decoding and error handling in the DSL while preserving the original HDL implementation.

memory_wrapper.rb
# Import vendor BRAM primitive
BramTDP = RHDL.import("xilinx/BRAM_TDP_MACRO.v",
  params: {
    BRAM_SIZE  => "36Kb",
    DATA_WIDTH => 32,
    ADDR_WIDTH => 10
  }
)

class MemoryController < RHDL::Component
  def initialize(banks: 4)
    input  :clk, :rst
    input  :addr, width: 12
    input  :wdata, width: 32
    input  :we
    output :rdata, width: 32

    # Instantiate multiple BRAM banks
    @banks = banks.times.map do
      add BramTDP.new
    end

    # Address decoding in Ruby DSL
    bank_sel = addr[11..10]
    @banks.each_with_index do |bank, i|
      bank.clk  <= clk
      bank.addr <= addr[9..0]
      bank.din  <= wdata
      bank.we   <= we & (bank_sel == i)
    end

    rdata <= mux(bank_sel, @banks.map(&:dout))
  end
end

Import a VHDL entity and use it alongside Ruby components. RHDL handles the cross-language port type mapping automatically.

mixed_design.rb
# Import VHDL FIR filter IP
FirFilter = RHDL.import("ip/fir_filter.vhd")

# Import Verilog ADC interface
AdcInterface = RHDL.import("vendor/adc_spi.v")

# Compose in Ruby
class SignalChain < RHDL::Component
  def initialize
    input  :clk, :rst
    input  :adc_miso
    output :filtered, width: 16

    @adc = add AdcInterface.new
    @fir = add FirFilter.new

    # Wire: ADC -> FIR -> output
    @adc.clk  <= clk
    @adc.miso <= adc_miso
    @fir.clk  <= clk
    @fir.din  <= @adc.data_out
    filtered  <= @fir.dout
  end
end