The wiring layout is the logic
A UniCell program is a placement of cells: which of a fixed set of hardware cores sits where, and how each one is wired to its neighbours. There is no instruction stream to fetch. Values arrive, a cell computes on them, and the result moves on to the next cell. The architecture has been built in two hardware lines that share this principle and express it differently.
In the Arria 10 line, every cell holds eight cores at once, and a runtime configuration write chooses which one is active. Cells wire directly to their North/South/East/West neighbours, and there is no shared or addressed bus. A two-operand cell fires once it has received arrivals from two directions (a two-arrival firing model), so wire length and arrival order are part of the program. In the current Tang Nano 20K line, each cell is stripped to a single function with a dedicated port per role. The wiring between cells is generated from the program file, and the two families decide timing differently (below).
The pulse schedules, the ack controls, the freeze holds
There is a timing pulse, but it only schedules when data is passed from one cell to the next; the cell internals are unclocked. Most designs use the two-arrival model, where a cell waits for both of its operands, so skew between paths of different length can almost be ignored. What really controls the flow is the acknowledge: a value moves on only when the next cell has taken the previous one.
Freeze disconnects, it doesn't stop the clock
The freeze line disconnects a cell's inputs and outputs from the flow. A frozen cell can be reprogrammed without any data moving.
State you can save and reload
While frozen, each cell's state can be captured and its latch values stored as a series of data, to be reloaded into the design at any time.
No pre-firing on a partial load
Loading part of a design would normally let the loaded part start running. Holding freeze until the load is complete stops it from pre-firing in a half-built state.
sub and flex: cells stripped to the compute
Measured on the Tang Nano 20K, the general-purpose cell paid for features most cells never use. For example, every cell carried a 32-bit barrel shifter. So each function became its own small cell, with no add-on chain, no cardinal routing and no runtime routing decision. Each distinct role gets its own port: two operands means two ports. Shifts, masks and inverts become plain wiring in a generated design.
sub — fixed latency
32-bit, no flow control. Every cell takes exactly one clock cycle, so a design is timed when it is built: the generator pads the shorter path so both operands arrive together. One result per cycle.
flex — handshake
Width set at build time (18 bits on the Tang, matching its block RAM and multipliers). Each connection has its own valid/ack and the whole design has a global freeze, so no padding is needed. One item per two cycles per cell.
The cells
adder (with subtract), multiplier (logic or DSP block), comparator, accumulator, latch, sequencer, ram/constant, router, mask, shift, nano (a universal 2-input bitwise gate) and branch, plus a merge core on flex (arbitrate or join).
Second results get second ports
An adder can deliver its carry and a multiplier its high word on their own ports. These are built only when a program needs them, and they make multi-word arithmetic possible.
The program format never names its target
A design is saved as an ICM file: cells at grid positions, with their configuration. The file states what the design needs, such as a minimum bit width, a second result word or a shift amount. Each target either provides that or refuses at compile time. It never silently approximates. The same file can be run in the VM, generated as sub hardware, or generated as flex hardware. The VM has a mirror mode for flex, so the software model and the generated hardware are checked against each other at every width the cells build.
One 80-bit register configures a super carrier cell
Every physical cell's entire configuration lives in one register,
SUPER_LATCH[79:0], loaded by a plain synchronous write — no address
match, no partial-state ambiguity.
core_select- bits [4:0] — which of the 8 real cores is active (values 8-31 are real, deliberate future headroom)
core_config- bits [46:5] — per-core fields, reinterpreted depending on which core is selected
addon_config- bits [66:47] — the addon chain (nibble mask, shift/lane, invert), identical across every core
Genuinely different firing semantics, verified against the real RTL bodies
nano (NOR gate tree)
The only core with no upstream_mask at all — accepts an arrival from any physically wired neighbor unconditionally.
RAM & comparator
Single-shot, doubly-full-guarded: offer once per capture, refuse a second arrival until the first drains.
adder
Two-stage capture — the first arrival becomes A, the second becomes B, on independent registers.
accumulator & latch
Continuously live — never blocked, re-arm and re-offer their current value every idle tick, a genuine heartbeat.
sequencer
Holds a fixed 4-value sequence and steps through it, offering one value per real advance.
branch
A held-reference router: captures a first value as reference, then routes each later arrival out one of three faces depending on how it compares.
Every silicon rule becomes a compiler check
The compiler and VM are treated as the real heavyweights of the project. The working principle: every rule proven on real silicon should eventually become both a real compiler-time check and a VM behavioural model — so the software tools enforce, as much as possible, exactly what the fabric enforces in hardware.
A real, honest limit stated plainly: this is still fundamentally a configuration architecture, not a general-purpose one. There's no addressed memory and no program counter. Counted loops compiled from LLVM IR are unrolled, or lowered onto a proven 4-cell loop ring. Loops with a data-dependent exit are refused by the hardware generators. Floating point is being built as a fixed pipeline of ordinary cells, with no loops: alignment, normalise, sticky and round-to-nearest-even are working in generated RTL. Whether and how broader general-purpose programming could map onto this substrate remains a genuinely open architectural question.
The VIX Carrier — a real 9th core, sim-verified, no silicon numbers yet
Alongside the shell described above, a genuinely separate, parallel core generation was built: the same 8 cores plus a real 9th, the command core, each wrapped in its own cardinal control shell so control signals (freeze, hold, feedback) become real 4-way wired ports instead of flat wires — the mechanism that lets one cell genuinely freeze, hold, or reprogram a physical neighbor. The command core itself watches for a toggle pattern to trigger a burst, or drives a freeze-and-relay programming sequence onto a neighboring cell.
Real and sim-verified in both RTL and the VM — including a command core actually programming a fresh, never-configured neighbor end to end — but genuinely untested on real silicon: the Quartus license expired before a build could be run. On the Tang Nano 20K one carrier position is about 80% of the chip, which is what led to the sub and flex families (FIG. 03). A single VIX-generation sequencer core is the one that runs on the Tang today.