Skip to content

Design

Why Logix Catalog is shaped the way it is, how it grows, and how Logix Engine uses it. The format itself is in model.md. The design was settled with the user in a review (2026-11-07 and 2026-11-08); this document and model.md replace that review's doc.

Goals

  • Readable. A person opens a board's file and understands it without reading docs first.
  • Partial knowledge. The FPGA is always fully known. Everything else is either listed, so known, or not known yet.
  • Grows in small steps. Users, board makers, developers and importers add facts one at a time, each with where it came from.
  • Useful. Enough to generate a blinky, a pin file or an example, and to check that a design's pins fit the board.
  • Convertible. To and from LiteX and Amaranth board definitions, keeping everything either records about pins.

Not goals: describing the FPGA itself (fpgas/ holds only what tools need), full schematics, or power and analog details.

Decisions

Decision Why
A repo of its own, logix-catalog, and a first-level product with its own page Board data changes more often than engine code, and contributors shouldn't need the engine repo
Open Logix's products, scripts and agents read the catalog only through Logix Engine's API; only this repo's maintenance (checker, importers, tests, CI) reads the files. For everyone else that's the intended, supported way, not enforced: the data stays free to use and copy, and reading the files directly is at one's own risk (2026-11-08) One version of the data, custom boards read and checked the same way, the engine's derived facts in one place, and freedom to change the files' layout. The board file format stays public for writing boards
One JSON file per board, named by its ID A contribution touches one small file; boards copy between the catalog and a project's boards/ folder as files
One board schema, logix-board-v1.json; custom boards are folders of the same files One format everywhere; no wrapper files
One FPGA file per family, fpgas/<family>.json, named like the chips (ice40, ecp5, gw1n, gw2a, gw5a, artix7, spartan7, zynq7000); boards never name a family or toolchain A family is a fact about the chip, and the file's name states it once, so fields it implies (such as yosys's Gowin family and Project X-Ray's family folder) aren't repeated per FPGA. Only the engine knows toolchains (2026-11-08)
Families with the same fields share an FPGA schema, logix-fpgas-<schema>-v1.json, named after their toolchain (ice40, ecp5, gowin, openxc7) Their files would have identical schemas: one per family would only repeat it (2026-11-08)
resources, a map from port name to a typed resource Amaranth's and LiteX's term, so imports map 1:1; names are unique because they're port names
Each type with its own fields (pin, red, tx, leds, colors) A reader never decodes a pin list by position
One pin gives a plain port, several a vector Natural for beginners; blinkies are per board anyway
Resources may share pins; designs may not A pin is often wired to two things, such as an LED on a PMOD pin
unclassified makes a board complete Lists every wired pin no other resource covers, so absence can be stated without a marker per type
requires on boards and resources, of two types: drive (the design) and setup (a person) Generators can tell what a design must include and what needs a jumper, without reading notes; more types only with a real case (the user's idea, 2026-11-08)
ai_hints on boards and resources: a list of short lines for AI agents (and people) writing designs, only what the structured data can't express, always the entity's last field (2026-11-09) Some facts a design needs don't fit a field yet, such as an LED that goes through the FPGA's RGB LED driver. Named for its main reader, like user_notes; "hints" because it's advice to weigh, since anyone can contribute it. Lines keep files readable in JSON viewers. Board and resource level only: FPGA facts stay out of the catalog, as AI agents know them from the datasheets. A hint leads with a board fact, decided by where the fact comes from, since boards often share wiring; a short phrase of context naming the FPGA feature helps people who don't know the datasheet, but no how-to, which would be copied unchecked onto many boards (the user's decisions, 2026-11-09)
No pull or drive fields: generators derive them from the FPGA family and the resource type (clock: no pull; outputs such as LEDs: the family's default drive; buttons and switches: pull toward the inactive level) The examples' settings were the toolchains' defaults or template copies (apicula's Gowin defaults are PULL_MODE=UP, DRIVE=8); max drive barely brightens an LED behind its resistor and adds noise and risk. A board that needs other values gets a pull or drive requirement on that resource later, with a source (2026-11-08)
No Gowin CLOCK_LOC or BANK_VCCIO Tested with oss-cad-suite 2026-10-22: nextpnr puts a clock on a general-purpose pin onto the global clock network by itself (nextpnr #1518, since 2025-07; identical bitstream with the hint), a dedicated clock pin needs no BUFG (forcing one lowered the Primer 20K Lite's max clock from 96.5 to 94.4 MHz), and BANK_VCCIO=3.3 beside LVCMOS33 changed nothing. Rerun when the toolchain changes (2026-11-08)
No pin file lines in board files; FPGA configuration settings (such as the ULX3S's SYSCONFIG) left out for now Lines are one tool's dialect: nextpnr, Diamond, Gowin EDA and Vivado accept different ones, other catalog users can't use them, and they go stale unchecked. A setting a board really needs will be a typed, neutral {"setting": …, "value": …} that each pin file writer translates, like io_standard, added with its first real case (likely CONFIG_IOVOLTAGE with a ULX3S flash resource). None of the ULX3S's settings is needed today: compression is always on, MCCLK_FREQ only speeds up start from flash, MASTER_SPI_PORT=ENABLE breaks designs that use USRMCLK (2026-11-08)
One common io_standard name, translated per FPGA family Board files stay family-neutral; the checker knows each family's set
One value and one source per resource; review settles disagreements No history of reports to manage; git keeps the history
A board's USB device is board data; matching stays the engine's Useful facts about the board, while match criteria stay internal to the engine
MIT or Apache 2.0, like every Open Logix repo MIT lets GPL-2.0 projects use the data, Apache 2.0 gives a patent grant
Contributions through commits and pull requests Standard review, nothing special to learn
Motto: "Every FPGA board, described once."

Sources and importing

Every resource can say where it came from (source, see model.md). Kinds rank, strongest first: hardware, schematic, maker, litex and amaranth, user. Importers never overwrite a resource from a stronger source; they report the difference instead.

LiteX's and Amaranth's board files cover 57 of the 81 boards (LiteX 51, Amaranth 35; checked 2026-11-08), so importing fills most resources. Both describe boards in Python, so importers are Python scripts in tools/ (planned). The mapping:

LiteX or Amaranth Our type
clk12, clk25, clk100 (frequency from the name or the period) clock
user_led, led (by index); Amaranth's invert or PinsN gives active: low leds
rgb_led with r, g, b rgb_led
user_btn, button buttons
user_sw, switch switches
serial, uart with tx, rx uart
pmod connectors (12 positions) pmod (the 8 signal pins)

Names the table doesn't know are reported, never guessed. LiteX rarely records LED polarity, so where only LiteX has a board, active stays unknown. Export, writing an Amaranth Platform class or LiteX _io and _connectors lists from a board's file, comes later, when someone needs it.

Logix Engine and the catalog

Contributors change boards here, never in the engine repo. The engine downloads the catalog as a package, as it downloads its tools (decided 2026-11-10):

  • The package: logix-catalog-<yyyymmdd>.tgz, built by this repo's build-pre-release workflow (tools/package.py) into a dated pre-release on every change on main and daily; the 5 newest pre-releases are kept, and a release an engine release ships with is made stable, so it stays. It holds boards/, fpgas/, schemas/, the licenses and logix-catalog.json, and is reproducible: the same files give the same bytes and SHA-256. It's small, so it arrives first on a new install, and a frontend can list boards while the engine's tools (the logix-core package, from openlogix/logix-core) download.
  • Each engine release pins one catalog release (its tag, size and SHA-256), as it pins logix-core. get_engine_info reports the catalog's version, and frontends show it, such as in Logix IDE's System Info. Engines already on users' machines will get a newer catalog without an engine release, once the engine's remote config names it (a stable release, tested with the engine first; designed, not implemented yet).
  • The engine reads the catalog only from the downloaded package; it has none built in. Until its first catalog arrives, board lists are empty.
  • Custom boards: requests name a folder of board files (custom_boards_folder), read with the same code as the catalog.
  • The engine keeps the code that reads and checks the catalog.

Frontends' examples follow Examples and boards.