RHDL is a Ruby-based Hardware Description Language framework that provides a complete environment for designing, simulating, and exporting digital circuits. From primitive logic gates up through complex CPUs, RHDL lets you describe hardware using expressive Ruby code and then simulate, synthesize, or export it to Verilog.
Architecture
RHDL is organized into several core subsystems:
lib/rhdl/
├── simulation/ # Core simulation engine
│ ├── sim_component.rb # Base component class
│ ├── simulator.rb # Simulation runner
│ ├── wire.rb # Signal wires
│ └── clock.rb # Clock signal
├── hdl/ # HDL component library
│ ├── gates/ # Logic gate primitives
│ ├── sequential/ # Flip-flops, registers, counters
│ ├── arithmetic/ # Adders, ALU, comparators
│ ├── combinational/ # Multiplexers, decoders, encoders
│ ├── memory/ # RAM, ROM, register files
│ └── cpu/ # Sample CPU implementations
├── dsl/ # Component definition DSL
├── export/ # Verilog/gate-level export
├── debug/ # Debugging tools
├── tui/ # Terminal UI
└── diagram/ # Diagram generation
Key Concepts
Signal Values
Signals in RHDL represent digital values:
- Binary values —
0or1for single-bit signals, multi-bit integers for buses - Unknown (X) — uninitialized or conflicting values
- High-impedance (Z) — disconnected or tri-state outputs
Wires
Wires connect components and propagate signal changes:
wire = RHDL::HDL::Wire.new("my_signal", width: 8)
wire.set(0x42)
wire.get # => 66
wire.bit(0) # => 0 (LSB)
wire.bit(6) # => 1Components
Components are the building blocks of every design. They inherit from SimComponent and define ports using class macros:
class MyGate < RHDL::HDL::SimComponent
port_input :a
port_input :b
port_output :y
behavior do
y <= a & b
end
endComponent Library
RHDL ships with a rich library of pre-built components:
| Category | Components |
|---|---|
| Gates | AND, OR, XOR, NOT, NAND, NOR, XNOR, Buffer, Tristate |
| Bitwise | BitwiseAnd, BitwiseOr, BitwiseXor, BitwiseNot |
| Flip-flops | DFlipFlop, TFlipFlop, JKFlipFlop, SRFlipFlop, SRLatch |
| Registers | Register, ShiftRegister, Counter, ProgramCounter, StackPointer |
| Arithmetic | HalfAdder, FullAdder, RippleCarryAdder, Subtractor, ALU, Multiplier, Divider |
| Combinational | Mux2–MuxN, Demux, Decoders, Encoders, BarrelShifter, PopCount |
| Memory | RAM, DualPortRAM, ROM, RegisterFile, Stack, FIFO |
Simulation Flow
Designing with RHDL follows a straightforward cycle:
- Create components with their ports defined
- Connect components by linking output wires to input wires
- Set inputs on the top-level component
- Propagate to compute outputs
- Clock sequential components to update state
# Create an AND gate
and_gate = RHDL::HDL::AndGate.new("my_and")
# Set inputs
and_gate.set_input(:a0, 1)
and_gate.set_input(:a1, 1)
# Propagate to compute output
and_gate.propagate
# Read output
and_gate.get_output(:y) # => 1For larger designs, the Simulator class manages multiple components and clocks:
sim = RHDL::HDL::Simulator.new
alu = RHDL::HDL::ALU.new("alu", width: 8)
reg = RHDL::HDL::Register.new("reg", width: 8)
sim.add_component(alu)
sim.add_component(reg)
clk = RHDL::HDL::Clock.new("clk")
sim.add_clock(clk)
sim.run(100) # Run for 100 cyclesGetting Started
If you are new to RHDL, start with the Installation guide to set up your environment, then explore the Ruby DSL Fundamentals to write your first hardware description.