Simten

Overview

A digital logic simulator for learning and building hardware designs

Simten is a browser-based platform for learning digital hardware design. You write circuits in TypeScript using the circuit() factory, see them rendered live on an interactive canvas, and simulate them with time-travel debugging. An AI tutor (Claude) can help you build, debug, and understand circuits in real time.

What you can build

Everything runs in the browser — no toolchain, no installation, no FPGA required.

  • Logic gates and adders — start from AND, OR, XOR and build up to full adders and ALUs
  • Sequential circuits — counters, shift registers, state machines using registers and flip-flops
  • Games in hardwareSnake and Pong, built entirely from logic gates with no CPU
  • A complete CPU — a 5-stage pipelined RISC-V processor that runs compiled C code
  • Accelerators — a TPU systolic array doing matrix multiplication, a CORDIC unit computing trigonometry
  • Networking hardware — an Ethernet switch with frame parsing, buffering, and forwarding

Hardware & FPGA

Circuits that export to Verilog can go all the way to a physical FPGA bitstream. The Hardware & FPGA page covers the full pipeline — Yosys synthesis, nextpnr place-and-route, ecppack, and flashing — using Snake running on a ULX3S ECP5 board over HDMI as a worked example.

Verilog export

Circuits export to synthesizable Verilog. The exporter maps 60+ primitives to standard RTL constructs — assign for combinational logic, always @(posedge clk) with synchronous active-low reset (rst_n) for sequential logic. Every module containing sequential primitives gets input clk and input rst_n ports auto-emitted (no clock or reset wiring in your circuit() definitions); on rst_n low, registers snap to their value arg, memories preserve contents, RV32I register files zero. The output is verified against Icarus Verilog via a containerized verification service.

import { exportVerilog } from '@simten/core/verilog';

const { verilog, files } = exportVerilog(circuit, library, { target: 'synthesis' });
// `verilog` is the .v source; `files` is a map of sidecar filename → contents
// (hex files referenced by $readmemh for large preloaded memories).

The target: 'synthesis' option strips simulation-only constructs (initial blocks) for FPGA-ready output. Memories above inlineMemoryThreshold (default 2048 words) are emitted as $readmemh("<file>.hex", reg) with the hex contents returned alongside — matching the Yosys/Vivado/Quartus convention for large ROM/RAM initialization.

AI tutor over MCP

Connect an MCP-capable assistant — Claude Code, Codex CLI, Gemini CLI, Cursor, and others — to get an AI tutor that can see your circuit, push changes to the browser, run simulations, and answer questions in real time:

claude mcp add simten npx @simten/mcp

Ask it to build a counter or debug your ALU — it writes the TypeScript and the circuit appears on your canvas instantly.

See the MCP Integration guide for per-client setup, available tools, and how the MCP viewer works.

Circuit code runs in an isolated sandbox — see Security Architecture for how Simten protects your credentials and filesystem from untrusted circuits.

Packages

@simten/core       ← headless engine (no UI)

@simten/ui         ← visual components (nodes, canvas, editor)

@simten/embed      ← batteries-included wrapper + web components
PackageDescription
@simten/coreTypeScript builder, compiler, validator, simulator engine, SimulationSession, Verilog export
@simten/uiCanonical node components, shared canvas, ELK layout, sandbox context, ClockControls
@simten/embedCircuitEmbed convenience wrapper, useCircuitSimulator hook
@simten/mcpMCP server for Claude Code integration

Embed a circuit

Drop an interactive circuit into any React app:

import { CircuitEmbed } from '@simten/embed';
import { circuit, bit } from '@simten/core/circuit';
import { Xor, And } from '@simten/core/std';

const HalfAdder = circuit('HalfAdder', {
  inputs:  { a: bit, b: bit },
  outputs: { sum: bit, carry: bit },
  nodes:   { xor1: Xor, and1: And },
  connect: ({ inputs, outputs, nodes: { xor1, and1 } }) => [
    inputs.a.to(xor1.a, and1.a),
    inputs.b.to(xor1.b, and1.b),
    xor1.out.to(outputs.sum),
    and1.out.to(outputs.carry),
  ],
});

<CircuitEmbed circuit={HalfAdder} height={250} showControls />

The embed auto-wraps the circuit with switches for inputs and LEDs for outputs.

Here's that exact code running live:

Compiling...
Half Adder
Toggle the switches to see sum and carry

On this page