Import existing Verilog and VHDL designs into RHDL. Integrate legacy IP, vendor cores, and third-party modules into your Ruby hardware workflow.
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.
Source files (.v, .sv, .vhd)
Extract modules, ports, parameters
Map to RHDL internal graph
Native RHDL interface
Typed ports, width inference
Resolve params, validate hierarchy
Importing a Verilog or VHDL file is a single method call. The imported module becomes a first-class Ruby component.
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"
)
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.
| Format | Extensions | Standard | Coverage |
|---|---|---|---|
| Verilog | .v | IEEE 1364-2005 | Full synthesizable subset |
| SystemVerilog | .sv | IEEE 1800-2017 | Synthesizable subset (interfaces, packages, structs) |
| VHDL | .vhd, .vhdl | IEEE 1076-2008 | Full synthesizable subset |
| EDIF Netlist | .edf | EDIF 2.0.0 | Gate-level netlist import |
| Liberty | .lib | Synopsys Liberty | Timing/area annotations |
Verilog module with parameters and multi-bit ports is imported and used directly in Ruby.
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.
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
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.
# 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.
# 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