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. Atemplatebadge marks a library template. -
Open / Save JSON — load or save the whole design as a
.jsonfile. -
Export Verilog — generate synthesizable Verilog from the current design and download it as a
.vfile (see §8). -
Save as default / Clear default — store the current design in the browser’s
localStorageas 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) |
|
Toggle inversion on the hovered terminal |
3. Building circuits
-
Place — drag a primitive from the library onto the canvas.
-
Wire — connect outputs to inputs.
-
Configure — select a component and set its properties in the sidebar.
-
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.
-
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
nsingle wires into onen-wide bus. -
FAN-OUT splits one
n-wide bus intonsingle 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 |
|---|---|---|
|
high |
red |
|
low |
black |
|
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 toH) · Outputs: 1 (Y) · inputs variable -
Output is
1only when all inputs are1;0dominates;xpropagates otherwise.
OR
-
Inputs: 2+ (
A,B, …) · Outputs: 1 (Y) · inputs variable -
Output is
1when any input is1;1dominates.
XOR
-
Inputs: 2+ (
A,B, …) · Outputs: 1 (Y) · inputs variable -
Output is
1on odd parity (an odd number of inputs are1).
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, defaultposedge), Initial value (boolean, default off), Active-high reset (boolean, default on) -
A D flip-flop. On the configured Edge of
CLK,Qtakes the value ofD(after a clk-to-q delay); between edgesQholds. -
!Qis always the complement ofQ. -
When
RSTis asserted (high by default, low with Active-high reset off),Qis forced asynchronously to the Initial value, overriding the clock. On power-onQstarts at the Initial value.
FAN-IN
-
Inputs: 2+ (single-wire), default 4 · Outputs: 1 (
BUS) · inputs variable -
Bundles its
nsingle-wire inputs into onen-wide bus output.
FAN-OUT
-
Inputs: 1 (
BUS) · Outputs: 2+ (single-wire), default 4 · outputs variable -
Splits one
n-wide bus input intonsingle-wire outputs.
BUS-SPLIT
-
Inputs: 1 (
BUS, widthn, even) · Outputs: 2 (Y1,Y2, widthn/2each) -
Splits a bus into two equal halves. The input width must be even.
BUS-MERGE
-
Inputs: 2 (
A,B, widthmeach) · Outputs: 1 (BUS, width2m) -
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, defaultbus), Initial value (boolean, default off), Value format (HEX/DEC/SIGNED DEC, defaultHEX), and Order (asc/desc, defaultasc) -
A multi-lane interactive source. In
wiremode each output terminal is one switch; inbusmode 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, defaultbus) -
A multi-lane lamp. In
wiremode each input terminal is one LED; inbusmode a single bus input lights one LED per lane. Each lane lights when its signal is1.
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
moduleper composite, with the top-level sheet (main) as the top module. -
Gates (AND/OR/XOR/NOT/BUFFER) as
assignexpressions, so terminal inversion becomes a~. -
DFF as
always @(posedge clk …), with the async reset (when connected) andINITfrom 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].
9. Sharing a link
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.