Setnex ISA · Introduction

Designing a processor
for a number system
that never existed

Setnex is a RISC instruction set architecture for balanced ternary, the base-3 system whose digits are −1, 0, and +1. It is a side project, and it may never run on silicon. This article sets out why I am building it nonetheless.

Eric Tellier · Terias April 2026 · updated for v0.8 v0.8 specification

My day job is emergency medicine, with some teaching. Setnex is what I work on in the gaps—evenings, weekends, post-call days: a side project with no deadline and no deliverable other than the specification itself.

Why, then, spend that time designing a processor for a number system that no commercial hardware has used since 1958?

The premise

Every computer in common use thinks in binary: zeros and ones. It works, yet binary carries some baggage. Negative numbers require a special encoding (two's complement). Comparison produces a pair of flags—carry and zero—that must be interpreted together. And the absence of information—NULL in SQL, NaN in floating point, None in Python—is invariably a special case bolted on top.

Balanced ternary is different. Each digit, called a trit, takes three values:

N−1
Z0
P+1

Negative numbers are native: one simply flips every trit (P becomes N, N becomes P, Z stays Z). There is no two's complement, no sign bit, no special case. Negation is essentially free in hardware—it amounts to swapping two wires.

Comparison between two values likewise produces a single trit—N for less, Z for equal, P for greater—rather than a pair of bits. One trit suffices for three outcomes, where binary needs two.

And the unknown state is simply Z: not a special value, not a sentinel, not a nullable wrapper, but the middle of the scale.

Binary encodes a choice between two options. Balanced ternary encodes a position on a signed axis. The difference sounds academic until you start designing instructions around it.

What Setnex is

Setnex is a RISC instruction set architecture, inspired by RISC-V but designed from scratch for balanced ternary—not a binary ISA with ternary bolted on. Every design decision—register encoding, flag semantics, instruction formats, comparison operators—is re-examined through the lens of base 3.

ParameterValue
Word width27 trits
Registers27 general-purpose (r0–r26) + 27 vector (v0–v26)
Instruction width27 trits, fixed
Opcode4 trits (81 values, 60 used)
Formats5 (R, I, J, U, B)
Address space±3.6 × 10¹² words
Logic modes5 (Kleene, Łukasiewicz, Heyting, RM3, B3)
Floating-pointT26F (Tekum, tapered precision)
LicenseApache 2.0

The number 27 is 3³, and it is not incidental but a design principle: 27 trits per word, 27 general-purpose registers, 27 vector registers. The architecture is thus self-similar across scales.

Instruction formats

There are five instruction formats, determined solely by the opcode; the decoder never inspects payload fields to establish what it is looking at.

R format — register to register

opcode4 trits
rd3
rs13
rs23
funct14 trits

I format — immediate

opcode4
rd3
rs13
imm1717 trits ≈ ±64M

J format — conditional branch

opcode4
rs13
offset2020 trits ≈ ±1.7B

U format — unconditional jump

opcode4
offset2323 trits ≈ ±4.7 × 10¹⁰

B format — ternary three-way branch (v0.3)

opcode4
rX3
off_z10 trits ≈ ±29K
off_n10 trits ≈ ±29K

The U format folds the unused rs1 field of unconditional jumps into the offset, multiplying the range by 27 at no cost. The B format encodes a three-way branch in a single instruction: P falls through, while Z and N each carry an independent offset. No trit is wasted.

Where balanced ternary shows

The arithmetic and memory instructions are unremarkable—every ISA has ADD, LOAD, STORE, and branches. What makes Setnex specific to balanced ternary is a small set of features that have no meaningful equivalent in binary.

Ternary flags

After every ALU operation, the FLAGS register is updated with two trits:

TritNameValues
t[0]signN = negative, Z = zero, P = positive
t[1]carryN = underflow, Z = none, P = overflow

Both flags are fully ternary. The sign flag encodes three outcomes in one trit, and the carry flag records which direction an overflow went. In binary, the sign is one bit and the zero flag another, and the two must be combined mentally to obtain a comparison result. Here, CMP a, b writes a single trichotomy trit—N if a < b, Z if equal, P if a > b—and nothing more is needed.

Configurable logic

The LMODE register selects the truth tables for all logic instructions. Five modes—Kleene, Łukasiewicz, Heyting, RM3, and B3 (Bochvar)—differ in how they treat the indeterminate value Z. The logic instructions (TAND, TOR, TNOT, TIMPL) do not change; their meaning does. The same code thus expresses a different epistemology after a single register write.

This matters most for the implication operator TIMPL. In Łukasiewicz mode, TIMPL(a, b) = P if and only if a ≤ b, which makes it a trit-parallel order test; in Heyting mode, the same instruction is more conservative about the unknown state. The application layer selects a policy, and the hardware obeys. I discuss TIMPL and its consequences at greater length in a companion article.

The comparison trio

Three instructions for trit-parallel comparison:

InstructionQuestion it answersBinary equivalent
CONSWhat do A and B agree on?~AND (partial)
ACONSWhat's missing from the pair {A[i], B[i]}?Nothing. Binary has no absent value.
TCMPWho dominates at each position?XOR + SUB (2 ops)

These three are not redundant. CONS has a blind spot—CONS(Z,Z) and CONS(N,P) both return Z—which TCMP disambiguates. ACONS, for its part, has no binary equivalent at all: in a two-state system, if one state is known and differs, the other is determined; in a three-state system, it is not. Worked examples are given in the companion article.

What Setnex is not

It is not a product: there is no silicon and no operating system. There is, however, real tooling—a Python simulator (setnex-sim), a small language called Telo with a compiler down to assembly, an assembler, and a reference arithmetic library (tritlib)—all built against the specification. The specification is what truly defines Setnex: a document fixing encoding, semantics, and conventions precisely enough to implement against.

It is not a claim that ternary is "better" than binary. Both are Turing-complete, and neither can compute anything the other cannot. The observation is narrower: certain patterns—comparison, voting, three-valued logic, fault detection—seem to express more naturally in balanced ternary, and designing an ISA around it is, above all, a way to explore where that difference shows up.

Nor does it start from nothing. The theoretical foundation is over a century old (Łukasiewicz, 1920), and the Setun computer ran balanced ternary in hardware as early as 1958. More recently, over a hundred papers on ternary CNTFET logic gates appeared on IEEE Xplore between 2020 and 2024, and in early 2025 Huawei published a patent for a ternary logic gate circuit. The pieces, therefore, exist; what is missing is an ISA that thinks in ternary from the ground up, rather than one mapping binary conventions onto three-valued hardware.

Setnex is a side project. It may never run on real silicon. But the spec is real, the math checks out, and the territory is almost entirely unexplored.

The roadmap

v0.1 — Initial specification

Core architecture: 27-trit words, 27 registers, formats R/I/J, configurable ternary logic (Kleene, Łukasiewicz, Heyting, RM3, B3), CONS/ACONS, arithmetic, branches, exceptions, calling convention.

v0.2 — Ternary consistency

Fully ternary FLAGS (sign/carry). Trichotomy CMP and TCMP. Format U for jumps. IRET atomic exception return. Saturating arithmetic (ADDS/SUBS). Extended multiply (MULH). Symmetric Euclidean division.

v0.3 — Ternary flag exploitation

ADC/SBC carry chain with ternary carry. TSEL three-way conditional select. BF trit-masked branch. BRT3 three-way branch (format B, two independent offsets). First Python simulator setnex-sim with assembler toolchain.

v0.4 — Floating point

Ternary floating-point extension (FADD/FSUB/FMUL/FDIV), based on the T26F Tekum tapered-precision format.

v0.5 — System ABI

Syscall calling convention (ECALL flavors, a7 dispatch, ETVAL data channel). Documented prologue/epilogue and stack alignment.

v0.6 — Nested exceptions

Second bank of exception CSRs and STATUS.depth; one level of nesting tolerated before machine-check reset.

v0.7 — Protection & interrupts

Memory Protection Unit (9 regions, ternary per-axis permissions). Asynchronous interrupt controller (9 IRQ lines).

v0.8 — Vector extension (current)

27-lane trit-parallel SIMD: dedicated vector bank v0–v26 and eight opcodes (VADD, VMUL, VLOG, VSEL, VCMP, VRED, VPERM, VMOVE). Purely additive over v0.7.

v0.9 — Vector arithmetic (planned)

Fused multiply-accumulate (VFMA) and gather/scatter (VGATHER/VSCATTER), reusing the two reserved opcodes; possibly trybble/tryte lane modes.

Later — Hardware

An FPGA soft core through an open toolchain (yosys/nextpnr), if time allows; ASIC exploration remains hypothetical, contingent on CNTFET technology.

Why bother?

The honest answer is that it is interesting. Balanced ternary has a certain mathematical elegance—the symmetry around zero, the free negation, the trichotomy trit—and designing an ISA around it forces one to question conventions inherited from seventy years of binary computing. Why are flags binary? Why is division truncated toward zero? Why does comparison produce two bits rather than one? Most of the time the answer is simply "because binary"; in balanced ternary, other answers occasionally emerge.

There is also a more topical reason. Ternary neural networks (BitNet-style weights in {−1, 0, +1}) are an active area of research, CNTFET ternary gates are past the proof-of-concept stage, and patents are being filed. If ternary hardware ever arrives at scale, it would need an instruction set—ideally one that was ternary from the first trit rather than a binary ISA mapped awkwardly onto three-state transistors. Whether Setnex is that instruction set is not the point; thinking the problem through is.

And if it never arrives? Then I will have spent a few evenings designing a clean RISC architecture with some unusual comparison primitives and configurable multi-valued logic. There are worse ways to spend an evening.

· · ·

Read more

The Ternary Trio: CONS, ACONS, and TIMPL—A closer look at Setnex's comparison and logic primitives, with worked examples and application sketches.

Setnex ISA v0.8 specification—The full reference document (Apache 2.0).

setnex-sim—Python simulator and assembler toolchain. pip install setnex-sim.