Gatefold — User Guide

A walkthrough of the interface and a reference for every primitive component and the simulator. Gatefold is a browser-based graphical designer and simulator for logic circuits: you place components, wire them together, group them into reusable parts, and simulate the result.


1. The interface

The screen is split into four areas:

Area Location Purpose

Toolbar

Top

Actions, simulation controls, navigation, save/load, theme

Sidebar

Left

Component tree, selected component’s properties, port editor

Canvas

Center

The schematic — place, select, wire, pan, zoom

Library

Right

The primitive palette and your custom components

Toolbar

Left to right:

  • Group — turn the current selection into a named composite component (enabled only with a selection).

  • Simulate / Exit — switch between design and simulate mode.

  • Run / Step / Stop / Reset — simulation controls (see §7). Run also enters simulate mode from design mode and starts running; Space toggles run/pause while simulating.

  • Settings (gear) — open the simulation settings dialog.

  • Breadcrumb — the path of components you’ve navigated into (main / adder / …); the button (or Escape) goes up one level. A template badge marks a library template.

  • Open / Save JSON — load or save the whole design as a .json file.

  • Export Verilog — generate synthesizable Verilog from the current design and download it as a .v file (see §8).

  • Save as default / Clear default — store the current design in the browser’s localStorage as the automatic launch state, or remove it so the app starts empty again.

  • Copy link — copy a shareable URL to the clipboard: the design is gzipped and base64-encoded into a ?d= query parameter, and opening that URL restores the design on launch (see §9).

  • Theme toggle — switch between dark and light.

Sidebar (left)

  • Components — a tree of the current sheet’s instances. Double-click a composite to enter it; single-click to select it on the canvas.

  • Ports — the current scope’s terminals (shown first). Add (+) / remove () terminals (when the primitive allows it), rename them, reorder by dragging the ⣿ handle, and toggle the inversion checkbox (the negation bubble).

  • Properties — for the selected component: its name, its type, its primitive properties (e.g. a CLOCK’s Period, a BUS’s Lanes), and an editable terminal list for that component, so you can add/remove/reorder/rename/invert its terminals without entering it. Values commit on Enter or blur.

Library (right)

  • Primitives — the built-in components (§6). Drag one onto the canvas to place it.

  • My components — your composite components. Drag to place; double-click to edit its template; × deletes it. Export / Import exchange your component library as JSON, and Apply to instances (shown when a template is selected) propagates that template’s edits (including its port names) to every matching placed instance. The list scrolls if it grows tall. A category dropdown above the list shows one category at a time; select a template and use the category dropdown below the buttons to move it to an existing category or + New category… (type a name and press Enter).

Dialogs

  • Group dialog — name the new component and its inferred inputs/outputs (press Enter to create).

  • Simulation settings — default gate delay (ps), the step mode, and the simulation speed.

  • Delete dialog — confirm deleting a library template.

  • Toast — transient messages (e.g. “Input already has a driver”).


2. Canvas controls

Action How

Select

Click a component

Multi-select

Marquee (drag empty space), or Shift + click to toggle

Move

Drag a component (moves the whole selection)

Move by its terminal

Shift + drag on a terminal marker moves the owning component (and the whole selection if it’s part of it)

Pan

Shift + drag (or Shift + drag anywhere in simulate mode)

Zoom

Mouse wheel, anchored at the cursor

Enter a component

Double-click it

Exit up one level

Escape (while over the canvas) or the ↑ button

When you enter a component, the canvas automatically zooms and pans to frame its internals; Escape restores the exact view you left. Opening a design (Open JSON) — or launching with a saved default — also auto-frames the top-level sheet to fit the canvas. In simulate mode, pressing Escape at the top level leaves simulate mode; deeper, it ascends one level.

Wiring

  • Draw a wire — press an output pin, drag, and release on an input pin.

  • Re-target / delete a wire — press an input pin that already has a wire, drag, and release on a new input (re-target) or on empty space (delete).

  • An input can have at most one driver; dropping a second wire onto a driven input is rejected with a message.

Keyboard shortcuts

Shortcut Action

Ctrl/Cmd + C

Copy selection

Ctrl/Cmd + V

Paste

Delete / Backspace

Delete selection

Ctrl/Cmd + Z

Undo

Ctrl/Cmd + Shift + Z / Ctrl/Cmd + Y

Redo

Escape

Go up one level (or leave simulate mode at the top level)

Space

Toggle run/pause (in simulate mode)

i

Toggle inversion on the hovered terminal


3. Building circuits

  1. Place — drag a primitive from the library onto the canvas.

  2. Wire — connect outputs to inputs.

  3. Configure — select a component and set its properties in the sidebar.

  4. Group — select a sub-circuit and press Group to turn it into a named composite. Inputs/outputs are inferred from the wires crossing the selection; floating pins become extra terminals. Components are copied when placed, so editing one instance never affects the template or other instances.

  5. Edit internals — double-click any component (composite or gate) to descend into it.

Terminal inversion

Any terminal can be logically inverted (a negation bubble). Toggle it by pressing i while hovering the terminal, or with the checkbox in the ports editor. Inversion is instance-level: a library template’s terminals stay clean, and inversion lives on the placed instance.

Inversion is external-only: it applies to a component instance’s terminals (as seen from the sheet it is placed on), never to a component’s own terminals from the inside. The current scope’s input/output port groups cannot be inverted and never show a bubble — to invert a composite’s terminal, select the composite instance on the parent sheet and invert it there.

Copy-on-place and templates

When you place or group a component, Gatefold deep-copies its definition (a copy), so every instance is independent. My components lists your templates; editing a template (via its library card) and pressing Apply to instances updates every matching instance — one whose terminals are the same (by id and order) as the template’s. Port names don’t affect matching and are overwritten with the template’s names, so renaming a template’s ports bulk-updates its instances.


4. Buses

A bus is a terminal carrying multiple wires (its width). Widths are derived, not stored — Gatefold solves them from the wiring. Hover a bus pin to see its ×n arity; an undetermined pin adopts the width of whatever it connects to and renders as a thin dashed wire (or a ? box on a display).

  • FAN-IN bundles n single wires into one n-wide bus.

  • FAN-OUT splits one n-wide bus into n single wires.

  • BUS-SPLIT splits one bus into two halves; BUS-MERGE joins two buses into one (twice the width).

  • BUS (the primitive) fixes a bus to a specific width (Lanes), and is a passthrough.

  • Connecting mismatched widths is rejected at wiring time (“Bus width mismatch”), and a bus splitter requires an even width (“Bus width must be even”).


5. Signals

Logic values are 3-state:

Value Meaning Wire color

1

high

red

0

low

black

x

unknown / floating

gray

x arises from unconnected inputs; it propagates through gates unless a dominant value determines the output (0 dominates AND, 1 dominates OR).


6. Primitive reference

Each entry lists the component’s terminals, its arity (which terminals can be added/removed), its properties, and what it does.

AND

  • Inputs: 2+ (A, B, … up to H) · Outputs: 1 (Y) · inputs variable

  • Output is 1 only when all inputs are 1; 0 dominates; x propagates otherwise.

OR

  • Inputs: 2+ (A, B, …) · Outputs: 1 (Y) · inputs variable

  • Output is 1 when any input is 1; 1 dominates.

XOR

  • Inputs: 2+ (A, B, …) · Outputs: 1 (Y) · inputs variable

  • Output is 1 on odd parity (an odd number of inputs are 1).

NOT

  • Inputs: 1 (A) · Outputs: 1 (Y, inverted)

  • Negates its input. Drawn as a triangle with a bubble (the bubble is the inverted output).

BUFFER

  • Inputs: 1 (A) · Outputs: 1 (Y)

  • Passes its input through unchanged. Useful for fan-out / signal cleanup.

CLOCK

  • Inputs: none · Outputs: 1 (CLK)

  • A source producing a periodic square wave. Property Period (picoseconds, default 100 000) sets the period. Its frequency (Hz / kHz / MHz) is shown above the component.

DFF

  • Inputs: D, CLK, RST · Outputs: 2 (Q, !Q) · Properties Edge (posedge / negedge, default posedge), Initial value (boolean, default off), Active-high reset (boolean, default on)

  • A D flip-flop. On the configured Edge of CLK, Q takes the value of D (after a clk-to-q delay); between edges Q holds.

  • !Q is always the complement of Q.

  • When RST is asserted (high by default, low with Active-high reset off), Q is forced asynchronously to the Initial value, overriding the clock. On power-on Q starts at the Initial value.

FAN-IN

  • Inputs: 2+ (single-wire), default 4 · Outputs: 1 (BUS) · inputs variable

  • Bundles its n single-wire inputs into one n-wide bus output.

FAN-OUT

  • Inputs: 1 (BUS) · Outputs: 2+ (single-wire), default 4 · outputs variable

  • Splits one n-wide bus input into n single-wire outputs.

BUS-SPLIT

  • Inputs: 1 (BUS, width n, even) · Outputs: 2 (Y1, Y2, width n/2 each)

  • Splits a bus into two equal halves. The input width must be even.

BUS-MERGE

  • Inputs: 2 (A, B, width m each) · Outputs: 1 (BUS, width 2m)

  • Concatenates two buses into one twice as wide.

BUS

  • Inputs: 1 (A) · Outputs: 1 (Y)

  • A passthrough that fixes the bus width. Property Lanes (default 8, 1–32) sets the width of both terminals; use it to pin a bus to a specific width regardless of its source.

NODE

  • Inputs: 1 (A) · Outputs: 1 (Y)

  • A single-wire join point: a filled dot whose input and output terminals coincide, drawn with no labels. It passes its input through unchanged, and multiple wires exit by fan-out from its single output. Drag a wire onto the dot to feed it; press the dot to start another outgoing wire; Alt+press grabs the incoming wire. To move it, drag the ring just around the dot (or region-select it first). The dot is wire-colored, signal-colored in simulation, and red while hovered.

  • Two shortcuts insert a NODE into an existing wire, splitting it in two:

    • Drop a NODE from the library straight onto a wire.

    • Ctrl/Cmd+drag across a wire — an imaginary dashed line is drawn, and on release a NODE is inserted where the line crosses the wire.

7-SEG

  • Inputs: 1 (BUS) · Outputs: none · Properties Mode (HEX / DEC / SIGNED DEC) and Order (asc / desc)

  • A multi-digit display. Its bus width must be a multiple of 4 and ≤ 64. The Mode controls how the bus bits are decoded:

    • HEX — one digit per 4-bit nibble (0–F), most-significant digit leftmost.

    • DEC — the bus as an unsigned decimal number, with enough digit slots for the full value (unused leading slots stay blank).

    • SIGNED DEC — the bus as a two’s-complement signed number, with a leading sign slot that lights when negative. Order selects which end of the bus is the least-significant bit.

SWITCHES

  • Inputs: none · Outputs: 1+ · Properties Terminal type (wire / bus, default bus), Initial value (boolean, default off), Value format (HEX / DEC / SIGNED DEC, default HEX), and Order (asc / desc, default asc)

  • A multi-lane interactive source. In wire mode each output terminal is one switch; in bus mode a single bus output carries one lane per wire. Every lane starts at the Initial value when simulation starts (and shows that state, colored, in design mode). In simulate mode, click an indicator circle to toggle its lane.

  • Value format is the radix used by the set-value dialog (see §7); Order selects which end of the bus is the least-significant bit (asc = lane 0 is the LSB).

LEDS

  • Inputs: 1+ · Outputs: none · Property Terminal type (wire / bus, default bus)

  • A multi-lane lamp. In wire mode each input terminal is one LED; in bus mode a single bus input lights one LED per lane. Each lane lights when its signal is 1.

Internal primitives (INPUT-PORT / OUTPUT-PORT) are not in the palette: they model a composite’s own input/output terminals internally and are created automatically when you group components or edit a composite’s ports.


7. Simulation

Press Simulate — or just Run — to enter simulation mode (it resets to the top-level sheet and builds a simulation of your design). The canvas background turns dark green while simulating. In this mode editing is disabled — you can’t place components from the library or enter a library template — but you can still pan, zoom, and navigate into the components on the canvas.

Controls

  • Run — enter simulate mode (if not already) and advance the simulation continuously.

  • Step — advance one step (see Step mode).

  • Stop — pause a running simulation.

  • Reset — rebuild the simulation from scratch.

  • Space — toggle between running and paused while simulating.

  • Settings — set the default gate delay (ps), the step mode, and the simulation speed.

Timing lamp

When the design has exactly one CLOCK, a small lamp appears in the toolbar next to the simulation controls and reports how fast the logic settles relative to that clock’s period:

  • green — the combinational logic settles within half a clock period.

  • yellow — it takes more than half a period (it doesn’t settle before the next clock edge).

  • red — it takes more than a full period (the clock is too fast for the logic).

A yellow or red lamp latches on and stays until the next Run/Reset. Hover the lamp for a tooltip.

Simulation speed

The Simulation speed setting is a multiplier of simulated time per real time: 1 means real-time, larger values run faster, smaller values run slower. While running, each tick advances a fixed slice of simulated time, so increasing a CLOCK’s period makes it cycle slower on screen (a period longer than the slice simply fires its edge on a later tick). At speed s, a clock with period P ps cycles at s × 10^12 / P Hz. The default speed (0.001) with the built-in 100 000 ps clock is therefore ~10 kHz — too fast to see — so use a much larger period (e.g. 1 000 000 000 ps for ~1 Hz) to watch slow motion. Set the speed to 1 for real-time behavior (again, with a much larger clock period).

While simulating, the current speed is shown as a small badge in the top-left corner of the canvas (e.g. 10x faster, 200x slower, or real-time at 1).

How it works

The engine is event-driven with inertial gate delays: a gate’s output changes a configured number of picoseconds after its inputs change. On start (or reset), driven nets begin at 0 (floating stay x), then a zero-delay settle pass resolves feedback loops (latches, flip-flops) to a stable state; a true oscillator is detected and shown as x.

Signals and probes

  • Wires and terminal markers are colored by their value: red = 1, black = 0, gray = x.

  • CLOCK toggles its output on a square wave with its Period.

  • SWITCHES lanes toggle by clicking their indicator circles (a double-click just toggles twice — it does not enter the component).

  • LEDS lanes light when their signal is 1.

  • 7-SEG displays the value of each 4-bit nibble of its bus.

Setting a switch value

Each SWITCHES component shows a small # badge in its top-left corner while simulating. Click it to type a value into that switch instead of clicking lanes one by one: a dialog titled "`enter N-bit value in …`" opens with a radix dropdown (HEX / DEC / SIGNED DEC, initialized from the instance’s Value format) and an input pre-filled with the current value (selected, so typing replaces it).

  • Enter parses the value (in the chosen radix) and sets the switches, closing the dialog; an out-of-range or malformed value shows an error and stays open.

  • Escape (or Cancel) closes without changing anything.

  • The radix chosen in the dialog only affects that dialog — it does not change the instance’s Value format. The instance’s Order is applied when the typed value is mapped onto the lanes.

Step mode

  • Quiescent — each Step advances until the circuit settles (no pending events).

  • Clock-edge — each Step advances to the next clock edge.

Navigating in simulate mode

Double-click a component to descend into it and inspect its internals live; Escape ascends back up. At the top level, Escape leaves simulate mode and returns to design mode.


8. Exporting Verilog

Press Export Verilog in the toolbar to generate synthesizable Verilog from the current design (the same JSON you get from Save JSON) and download it as design.v, so the circuit can be taken into an FPGA toolchain or an HDL simulator.

What the generator produces:

  • One module per composite, with the top-level sheet (main) as the top module.

  • Gates (AND/OR/XOR/NOT/BUFFER) as assign expressions, so terminal inversion becomes a ~.

  • DFF as always @(posedge clk …), with the async reset (when connected) and INIT from the Initial value property.

  • Buses as [n-1:0] vectors — FAN-IN/BUS-MERGE concatenate, FAN-OUT/BUS-SPLIT slice.

  • Hierarchy as nested module instantiations; composite ports become module ports.

Probes map to top-level I/O: CLOCK and SWITCHES become input pins, LEDS and 7-SEG become output pins. A SWITCHES placed inside a composite is exported as a constant fixed at its Initial value.

The export reports issues by severity:

  • Errors (shown as a toast and logged to the console): floating nets (an input/output with no driver) and a nested CLOCK (a clock inside a composite can’t be exported).

  • Info (console only): nested SWITCHES (fixed initial value) and nested LEDS/7-SEG (not exported).

The same generator is available as a CLI: pnpm --filter @gatefold/verilog cli <design.json> [out.v].


The Copy link toolbar button copies a URL that encodes the whole design: it is serialized to JSON, gzipped, then base64-encoded (URL-safe) into a ?d= query parameter. Pasting that URL into a browser opens Gatefold with that design loaded — it takes precedence over any saved default state. If the parameter is missing or corrupt, the app falls back to the normal launch path (localStorage default, then an empty design).

Saved designs (JSON files, the launch default, and share links alike) are stored compactly: built-in primitives are inline references (never stored as definitions), and component coordinates are rounded to two decimals.