____ __ ______ __
/ __ \/ / / / __ \/ /
/ /_/ / /_/ / / / / /
/ _, _/ __ / /_/ / /___
/_/ |_/_/ /_/_____/_____/
Ruby Hardware Description Language
RHDL is a Domain Specific Language (DSL) for designing hardware using Ruby's flexible syntax and exporting to synthesizable Verilog. It provides Ruby developers with a comfortable environment to create hardware designs leveraging Ruby's metaprogramming capabilities.
Demo: Web Simulator
- Component DSLs: Ruby-based DSLs for combinational, sequential, memory, and state machine components
- Verilog Export: Generate synthesizable Verilog from Ruby definitions
- HDL Simulation: RTL-level and Gate-level simulation using a fast Rust backend
- Component Library: Gates, flip-flops, registers, ALU, memory, CPU examples, and more
- Gate-Level Synthesis: Lower components to primitive gate netlists (AND, OR, XOR, NOT, MUX, DFF)
- Diagram Generation: Multi-level circuit diagrams with SVG, PNG, and DOT output
- Web Simulator: WASM based simulator for running your designs in the browser
| Document | Description |
|---|---|
| Overview | Introduction to the HDL framework |
| CLI Reference | Command line interface reference |
| DSL Guide | DSL reference for synthesizable components |
| Components | Complete reference for all HDL components |
| Simulation | Core simulation engine infrastructure |
| Export | Verilog and gate-level export |
| Gate-Level Backend | Gate-level synthesis and simulation |
| Diagrams | Multi-level circuit diagrams |
| Debugging | Signal probing, breakpoints, and TUI |
| 8-bit CPU | Sample 8-bit CPU reference |
| MOS 6502 | MOS 6502 CPU implementation |
| Apple II | Apple II emulation |
| Game Boy | Game Boy (DMG/GBC/SGB) emulation |
| RISC-V + Linux/xv6 | RISC-V RV32I CPU implementation with Linux and xv6 build/boot workflows |
| Web Simulator | Browser simulator (WASM + VCD + Apple II runner) |
RHDL includes a browser-based simulator with WASM backends, live VCD tracing, Apple II runner tooling, memory dump workflows, and component/source exploration.
- Demo: https://skryl.github.io/rhdl
- Docs: Web Simulator Guide
gem install bundler -v '~> 2.5'
bundle installRHDL provides several DSL constructs for synthesizable hardware:
class SimpleALU < RHDL::Sim::Component
input :a, width: 8
input :b, width: 8
input :op, width: 2
output :result, width: 8
behavior do
result <= case_select(op, {
0 => a + b,
1 => a - b,
2 => a & b,
3 => a | b
}, default: 0)
end
endclass Counter < RHDL::Sim::SequentialComponent
input :clk
input :rst
input :en
output :count, width: 8
sequential clock: :clk, reset: :rst, reset_values: { count: 0 } do
count <= mux(en, count + 1, count)
end
endclass RAM256x8 < RHDL::Sim::Component
include RHDL::DSL::Memory
input :clk
input :we
input :addr, width: 8
input :din, width: 8
output :dout, width: 8
memory :mem, depth: 256, width: 8
sync_write :mem, clock: :clk, enable: :we, addr: :addr, data: :din
async_read :dout, from: :mem, addr: :addr
endclass TrafficLight < RHDL::Sim::SequentialComponent
include RHDL::DSL::StateMachine
input :clk
input :rst
input :sensor
output :red
output :yellow
output :green
state_machine clock: :clk, reset: :rst do
state :RED, value: 0 do
output red: 1, yellow: 0, green: 0
transition to: :GREEN, when_cond: :sensor
end
state :YELLOW, value: 1 do
output red: 0, yellow: 1, green: 0
transition to: :RED, after: 3
end
state :GREEN, value: 2 do
output red: 0, yellow: 0, green: 1
transition to: :YELLOW, when_cond: proc { in_val(:sensor) == 0 }
end
initial_state :RED
end
endBuild complex components from sub-components using instance, wire, and port:
class MyDatapath < RHDL::Sim::Component
input :clk
input :rst
input :a, width: 8
input :b, width: 8
output :result, width: 8
# Internal wire
wire :alu_out, width: 8
# Sub-component instances
instance :alu, ALU, width: 8
instance :reg, Register, width: 8
# Port connections
port :a => [:alu, :a]
port :b => [:alu, :b]
port [:alu, :result] => :alu_out
port :alu_out => [:reg, :d]
port :clk => [:reg, :clk]
port :rst => [:reg, :rst]
port [:reg, :q] => :result
endrequire 'rhdl'
# Export a component to Verilog
component = MyComponent.new
verilog_code = RHDL::Export.verilog(component)
# Or use the class method
verilog_code = MyComponent.to_verilog
# Batch export with CLI
# rhdl export --all
# rhdl export --all --scope libGenerated Verilog example:
module simple_alu(
input [7:0] a,
input [7:0] b,
input [1:0] op,
output [7:0] result
);
assign result = (op == 2'd0) ? (a + b) :
(op == 2'd1) ? (a - b) :
(op == 2'd2) ? (a & b) :
(a | b);
endmodulerequire 'rhdl'
# Create an ALU
alu = RHDL::HDL::ALU.new("my_alu", width: 8)
alu.set_input(:a, 10)
alu.set_input(:b, 5)
alu.set_input(:op, RHDL::HDL::ALU::OP_ADD)
alu.propagate
puts alu.get_output(:result) # => 15RHDL includes four comprehensive example implementations demonstrating the framework's capabilities for building complex hardware systems.
| Example | Type | CPU | Description |
|---|---|---|---|
| MOS 6502 | Processor | 8-bit | Classic 1970s microprocessor |
| Apple II | Computer | 6502 | Complete 1977 personal computer |
| Game Boy | Console | SM83 | Nintendo handheld (DMG/GBC/SGB) |
| RISC-V | Processor | 32-bit | RV32I cores with xv6 readiness and UART/virtio validation |
Complete behavior simulation of the MOS 6502 with all 56 instructions, 13 addressing modes, and BCD arithmetic.
+----------------------------------------------------------+
| MOS6502::CPU |
+----------------------------------------------------------+
| +----------------------------------------------------+ |
| | Datapath | |
| | +-------+ +-------+ +-------+ +-------------+ | |
| | | A(8b) | | X(8b) | | Y(8b) | | Status(8b) | | |
| | +-------+ +-------+ +-------+ | N V B D I Z C | |
| | +--------+ +-------+ +-------------+ | |
| | | PC(16b)| | SP(8b)| | |
| | +--------+ +-------+ | |
| | +-------------------------------------------------+ |
| | | ALU (14 operations) | |
| | +-------------------------------------------------+ |
| +----------------------------------------------------+ |
| +----------------------------------------------------+ |
| | Control Unit (26-state FSM) | |
| +----------------------------------------------------+ |
| +----------------------------------------------------+ |
| | Instruction Decoder (151 opcodes) | |
| +----------------------------------------------------+ |
+----------------------------------------------------------+
CLI Options:
rhdl examples mos6502 --demo # Run demo program
rhdl examples mos6502 --karateka # Play Karateka gameQuick Example:
require_relative 'examples/mos6502/cpu'
cpu = MOS6502::CPU.new
cpu.assemble_and_load(<<~ASM, 0x8000)
LDA #$42 ; Load 0x42 into accumulator
STA $00 ; Store to zero page
BRK ; Break
ASM
cpu.reset
cpu.run
puts cpu.status_string # A:42 X:00 Y:00 SP:FD PC:8006Complete Apple II emulation with video modes, keyboard, speaker, and Disk II controller.
+-----------------------------------------------------------------------+
| Apple II System |
+-----------------------------------------------------------------------+
| +-----------+ +----------+ +--------------------------+ |
| | MOS 6502 | | Timing | | Video Generator | |
| | CPU |<--->|Generator |---->| - Text (40x24) | |
| | 1 MHz | | 14 MHz | | - Lo-res (40x48) | |
| +-----------+ +----------+ | - Hi-res (280x192) | |
| | +--------------------------+ |
| +-----+--------------------------------------------------+ |
| | Address/Data Bus | |
| +--+--------+--------+--------+--------+---------+-------+ |
| | | | | | | |
| +--+--+ +--+--+ +--+--+ +--+--+ +--+---+ +--+--+ |
| | 48KB| | 12KB| | I/O | |Disk | |Key- | |Speak| |
| | RAM | | ROM | | Page| | II | |board | | er | |
| +-----+ +-----+ +-----+ +-----+ +------+ +-----+ |
+-----------------------------------------------------------------------+
CLI Options:
rhdl examples apple2 --appleiigo # Run with AppleIIGo ROM
rhdl examples apple2 --karateka --hires # Play Karateka in hi-res
rhdl examples apple2 --appleiigo --disk g.dsk # Load disk image
rhdl examples apple2 --demo # Run demo programNintendo Game Boy emulation based on MiSTer reference, supporting DMG, GBC, and SGB modes.
+-----------------------------------------------------------------------+
| Game Boy System |
+-----------------------------------------------------------------------+
| +---------+ +-------+ +---------------------------+ |
| | SM83 | | Timer | | PPU (Video) | |
| | CPU |<-->|Counter|--->| - Background layer | |
| | 4.19MHz | +-------+ | - Window layer | |
| +----+----+ | - 40 sprites (8x8/8x16) | |
| | | - 160x144 LCD | |
| +----+--------------------------------------------------+ |
| | Address/Data Bus | |
| +--+------+------+------+------+------+------+----------+ |
| | | | | | | | |
| +--+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+----+ |
| |ROM | |VRAM| |WRAM| |OAM | |HRAM| |I/O| | APU | |
| |0-8M| |8KB | |8KB | |160B| |127B| | | | 4ch | |
| +----+ +---+ +----+ +----+ +----+ +---+ +------+ |
+-----------------------------------------------------------------------+
CLI Options:
rhdl examples gameboy cpu_instrs.gb # Run test ROM
rhdl examples gameboy --demo # Run demo display
rhdl examples gameboy --pop # Load Prince of Persia ROM
rhdl examples gameboy game.gb --audio # Enable audioModern 32-bit RISC-V processor with single-cycle and 5-stage pipelined implementations.
Single-Cycle Datapath:
+-----------------------------------------------------------------------+
| RV32I Single-Cycle Datapath |
+-----------------------------------------------------------------------+
| +------+ +------+ +-------+ +-------+ |
| | PC |--->| Inst |--->|Decoder|--->|Control| |
| | Reg | | Mem | | | |Signals| |
| +--+---+ +------+ +-------+ +---+---+ |
| | | |
| +--+-------------------------------------+--+ |
| | Datapath Muxes | |
| +--+--------+-------------------+-----------+ |
| | | | |
| +--+--+ +--+--+ +---+--+ +------+ |
| | PC | | Reg | rs1/rs2 | ALU |--->| Data | |
| |+4/Br| |File |----------->| | | Mem | |
| +-----+ |32x32| +------+ +------+ |
| +--+--+ | | |
| ^ v v |
| +--------[ Write Back ]<--------+ |
+-----------------------------------------------------------------------+
5-Stage Pipeline:
+------+ +------+ +------+ +------+ +------+
| IF |--->| ID |--->| EX |--->| MEM |--->| WB |
+------+ +------+ +------+ +------+ +------+
Fetch Decode Execute Memory Write
Inst Regs/Imm ALU/Br Access Back
Usage:
require_relative 'examples/riscv/hdl/ir_harness'
harness = RHDL::Examples::RISCV::IRHarness.new(backend: :jit, allow_fallback: false)
harness.load_program([
0x00500093, # addi x1, x0, 5
0x00A00113, # addi x2, x0, 10
0x002081B3, # add x3, x1, x2
])
harness.reset!
harness.run_cycles(10)
puts "x3 = #{harness.read_reg(3)}" # => 15CLI Options:
# Run a RISC-V binary in the terminal runner
# Defaults: --mode ir --sim compile
rhdl examples riscv path/to/program.bin
# Choose mode/backend and display mode
rhdl examples riscv --mode ir --sim compile --io mmap path/to/program.bin
# Core selection (default is single)
rhdl examples riscv --core pipeline path/to/program.bin
rhdl examples riscv --core single path/to/program.bin
# Show live debug panel (ESC toggles command mode)
rhdl examples riscv -d --io uart path/to/program.bin
# Launch xv6 (forces UART mode automatically)
./examples/riscv/software/build_xv6.sh
rhdl examples riscv --xv6 -d
rhdl examples riscv --xv6 --mode verilog
rhdl examples riscv --xv6 --mode circt
# Build Linux kernel artifacts (Phase 0 source workflow)
git submodule update --init --recursive examples/riscv/software/linux
./examples/riscv/software/build_linux.sh
# Buildroot for prebuilt toolchain defaults to linux/amd64 Buildroot host images.
# Run Linux via the top-level CLI (forces UART mode automatically)
rhdl examples riscv --linux
rhdl examples riscv --linux --mode verilog
rhdl examples riscv --linux --mode circt
# Optional Linux artifact overrides (initramfs + custom DTB)
rhdl examples riscv --linux \
--initramfs path/to/initramfs.cpio \
--dtb path/to/riscv.dtb
# Headless run for CI/smoke tests
rhdl examples riscv --headless --cycles 200000 path/to/program.binLinux milestones are covered in spec/examples/riscv/linux_boot_milestones_spec.rb.
Additional Linux compatibility specs live under spec/examples/riscv/linux_*_spec.rb.
xv6 shell I/O coverage across IR/Verilator/Arcilator lives in spec/examples/riscv/xv6_shell_io_spec.rb.
See each example's documentation for complete details on architecture, instruction sets, and CLI options.
rhdl/
├── lib/rhdl/ # Core library
│ ├── dsl.rb # HDL DSL for component definitions
│ ├── export/ # Verilog export backends
│ ├── simulation/ # Simulation engine
│ ├── hdl/ # HDL component library
│ │ ├── gates.rb, sequential.rb, arithmetic.rb, ...
│ │ └── cpu/ # HDL CPU implementation
│ ├── debug/ # Signal probing & debugging
│ ├── tui/ # Terminal GUI
│ └── diagram/ # Diagram rendering
├── examples/ # Example implementations
│ ├── mos6502/ # MOS 6502 CPU (8-bit, 189+ tests)
│ ├── apple2/ # Apple II computer emulation
│ ├── gameboy/ # Game Boy (DMG/GBC/SGB)
│ └── riscv/ # RISC-V RV32I CPU (single + pipelined)
├── export/ # Generated output files
│ ├── verilog/ # Generated Verilog
│ └── gates/ # Gate-level JSON netlists
└── docs/ # Documentation
RHDL provides a comprehensive CLI for common operations. See CLI Reference for complete documentation.
# Interactive TUI debugger
rhdl tui sequential/counter # Debug a counter component
rhdl tui RHDL::HDL::ALU --signals inputs # Debug ALU, show only inputs
rhdl tui --list # List available components
# Diagram generation
rhdl diagram --all # Generate all diagrams
rhdl diagram RHDL::HDL::ALU --format svg # Single component diagram
# Verilog export
rhdl export --all # Export all components
rhdl export --lang verilog --out ./out RHDL::HDL::Counter
# Gate-level synthesis
rhdl gates --export # Export to JSON netlists
rhdl gates --stats # Show synthesis statistics
# Example emulators
rhdl examples apple2 --demo # Run Apple II demo mode
rhdl examples gameboy --demo # Run Game Boy demo mode
rhdl examples riscv --xv6 -d # Run RISC-V xv6 with debug panelRHDL provides multiple simulation backends with different performance/flexibility tradeoffs:
Pure Ruby execution at the behavior block level. Best for development and debugging.
sim = RHDL::Sim::Simulator.new
sim.add_component(alu)
sim.add_clock(clk)
sim.run(100) # 100 clock cyclesSimulates primitive gate netlists (AND, OR, XOR, NOT, MUX, DFF). Four backend options:
| Backend | Speed | Startup | Use Case |
|---|---|---|---|
| Ruby SimCPU | 22K iter/s | Immediate | Development, small circuits |
| Rust Interpreter | 427K iter/s (20x) | Immediate | Functional verification |
| Rust JIT (Cranelift) | 50-100M gates/s | 0.1-0.5s | Fast interactive simulation |
| Rust Compiler (SIMD) | 100M+ gates/s | 1-2s | Maximum throughput, batch testing |
The compiler supports AVX2/AVX512 for 256-512 parallel test vectors.
ir = RHDL::Codegen::Netlist::Lower.from_components([alu])
sim = RHDL::Codegen::Netlist::NetlistSimulator.new(ir, backend: :interpreter, lanes: 64)
sim.poke('a', 0xFF)
sim.evaluate
result = sim.peek('y')Word-level bytecode simulation for complex designs like CPUs:
| Backend | Speed | Startup | Use Case |
|---|---|---|---|
| Interpreter | 60K cycles/s | Immediate | Interactive CPU debugging |
| JIT (Cranelift) | 600K cycles/s (10x) | 0.1-0.5s | Moderate simulations |
| AOT Compiler | 2.3M cycles/s (38x) | 0.5-2s | Long simulations, games |
sim = RHDL::Codegen::IR::IrSimulator.new(ir_json, backend: :jit)
sim.compile
sim.run_ticks(1_000_000)Export components to Verilog for synthesis or simulation with industry-standard tools:
# Export component to Verilog
verilog_code = RHDL::Codegen.verilog(component)
File.write('alu.v', verilog_code)External simulators:
| Tool | Speed | Use Case |
|---|---|---|
| iverilog | ~100K cycles/s | Functional verification, golden reference |
| Verilator | ~5.7M cycles/s | High-performance RTL simulation, benchmarking |
| CIRCT/MLIR (Arcilator) | Workload-dependent | Native RTL simulation from FIRRTL/MLIR flows |
# Compile and run with iverilog
iverilog -o sim alu.v testbench.v && vvp sim
# Compile with Verilator for maximum performance
verilator --cc alu.v --exe testbench.cpp
# Compile FIRRTL/MLIR with CIRCT + Arcilator
firtool design.fir --ir-hw -o design.mlir
arcilator design.mlir --state-file=state.json -o design.llWhen iverilog is installed, RHDL automatically runs gate-level verification tests comparing synthesized Verilog against behavioral simulation.
rake native:build # Build all Rust extensions
rake native:check # Check availabilityAll backends include automatic fallback to Ruby when native extensions aren't available.
See Simulation and Gate-Level Backend for complete details.
RHDL includes benchmarking tasks to measure simulation performance across backends:
rake bench:native[gates] # Benchmark gate-level simulation
rake bench:native[cpu8bit,cycles] # Benchmark 8-bit CPU FastHarness (compiler vs arcilator_gpu)
rake bench:native[mos6502,cycles] # Benchmark MOS 6502 CPU
rake bench:native[apple2,cycles] # Benchmark Apple II full system
rake bench:native[gameboy,frames] # Benchmark GameBoy with Prince of Persia
rake bench:web[apple2,cycles] # Benchmark Apple II web WASM backends
rake bench:web[riscv,cycles] # Benchmark RISC-V web WASM backendsSample Results (1M cycles):
| System | JIT | Compiler | Verilator | Compiler Speedup |
|---|---|---|---|---|
| MOS 6502 | 0.23M/s | 1.58M/s | ~5.6M/s | 6.8x vs JIT |
| Apple II | 0.06M/s | 0.28M/s | ~5.6M/s | 4.8x vs JIT |
| GameBoy | - | 1.27 MHz | ~5.8 MHz | 30% real-time |
Backend Selection Guide:
- < 100K cycles: Use JIT (fast startup)
- 100K - 1M cycles: Use JIT or Compiler
- > 1M cycles: Use Compiler, Verilator, or CIRCT/MLIR (Arcilator)
- Maximum RTL speed: Use Verilator or CIRCT/MLIR (requires external tools)
See Performance Guide for detailed benchmarks and optimization tips.
# Testing
bundle exec rake spec # Run all tests
bundle exec rake spec[riscv] # Run RISC-V specs
bundle exec rake pspec # Run tests in parallel
bundle exec rake pspec[riscv] # Run RISC-V specs in parallel
# Test and simulation benchmarks
bundle exec rake spec:bench[riscv,20] # Benchmark 20 RISC-V spec files
bundle exec rake bench:native[ir,5000000] # Benchmark IR runners
bundle exec rake bench:native[gates] # Benchmark gate-level simulation
bundle exec rake bench:native[cpu8bit,5000000] # Benchmark 8-bit CPU compiler vs arcilator_gpu
bundle exec rake bench:web[apple2] # Benchmark Apple II web compiler vs arcilator vs verilator
bundle exec rake bench:web[riscv] # Benchmark RISC-V web compiler vs arcilator vs verilator
# Dependency checks
bundle exec rake deps:check # General dependency status
bundle exec rake deps:check_gpu # Fail-fast ArcToGPU toolchain check
RHDL_ENABLE_ARCILATOR_GPU=1 bundle exec rspec spec/examples/8bit/hdl/cpu/arcilator_gpu_parity_spec.rb # Enable ArcToGPU parity test
# Native backends
bundle exec rake native:build # Build native extensions
bundle exec rake native:check # Check extension availability
# Web simulator
bundle exec rake web:build # Generate web simulator WASM artifacts
bundle exec rake web:generate # Generate web fixtures/artifacts
bundle exec rake web:bundle # Bundle web app + runtime assets with Bun (web/dist/)
bundle exec rake web:start # Start local web server with COOP/COEP headers
# Desktop app (Electrobun)
bundle exec rake desktop:install # Install desktop dependencies (bun install in web/desktop)
bundle exec rake desktop:dev # Build and launch desktop app in dev mode
bundle exec rake desktop:build # Build desktop app package (development target)
bundle exec rake desktop:release # Build desktop app package (stable target)
bundle exec rake desktop:clean # Remove desktop build artifacts| Category | Components |
|---|---|
| Gates | AND, OR, XOR, NOT, NAND, NOR, XNOR, Buffer, Tristate |
| Flip-flops | DFlipFlop, TFlipFlop, JKFlipFlop, SRFlipFlop, SRLatch |
| Registers | Register, ShiftRegister, Counter, ProgramCounter, StackPointer |
| Arithmetic | HalfAdder, FullAdder, RippleCarryAdder, Subtractor, Multiplier, Divider, ALU |
| Combinational | Mux2/4/8/N, Demux, Decoder, Encoder, BarrelShifter, ZeroDetect |
| Memory | RAM, DualPortRAM, ROM, RegisterFile, Stack, FIFO |
MIT License
