T27.AI

Blog

Two t27 courses of 27 lessons each: FPGA, then AI numbers

2026-10-07 · 9 min read

[no lesson trains a network; the tests of the 15 new lessons run in recordings of native t27c, not in the browser; 35 of 127 mutants survive and are not sorted; software only, no board] The t27 course is now two courses of 27 lessons, 9 modules of 3 lessons each (recordings for lessons 13 to 21 are pending t27#7400): From zero to a chip, on programming an FPGA, and AI numbers with t27, which starts with the 6 lessons that moved and adds 21 more, ending at a small ternary network. Each of the last 15 lessons plants a one-line bug in its spec and shows the one named test that fails. Over 14 of their functions, tri mutate spec made 127 mutants and the tests killed 92.

Three-panel engraved illustration for: Two t27 courses of 27 lessons each: FPGA, then AI numbers
View the complete triptych at full size
#t27#Ternary#MutationTesting

The t27 course had grown to 33 lessons in 11 modules: 27 on programming an FPGA, then 6 on number formats for AI. That is two topics in one course, and a link to it could not share either topic on its own. It is now two courses of 27 lessons each, and each course is 9 modules of 3 lessons. Course 1, From zero to a chip, keeps the FPGA lessons and its address. Course 2, AI numbers with t27, starts with the 6 lessons that moved and adds 21 more, ending at a small ternary network. Every lesson opens its own widget and one t27 spec, and each of the last 15 lessons plants one bug in its spec and shows the one test that catches it.

Why 27, and why two courses

27 is 3 x 3 x 3, the shape of a TRI-27 word, and every course is 9 modules of 3 lessons, 27 lessons in all. When a topic needs more than 27 lessons it becomes a second course, chained to the one before it: the last lesson of course 1 ends with a link to lesson 1 of course 2, and lesson 1 of course 2 links back. Each course has its own address in the app, its own page under t27.ai/learn/, its own preview card and its own line in the sitemap, so either one can be shared alone.

No link that worked before the split stops working. A lesson page stays at t27.ai/learn/<lesson>/ whichever course the lesson is in. In the app, the old address of a moved lesson, #/course/<lesson>, now opens it at #/ai-numbers/<lesson>. Progress is one list in your browser for both courses, so a lesson you marked done before the split is still done after it.

Course 2, part by part

LessonsPartWhat it teaches
1-3Lab: our own researchA number format of our own, an honest scoreboard, and a model's tables multiplied on the board.
4-6AI numbers: the MX blockHow AI chips keep weights in a few bits: one shared scale per block, the scale byte itself, and what one outlier does to its neighbours.
7-9Ternary weightsWeights that are only minus, zero or plus a scale, the five rules a ternary alphabet must pass, and a test pass that checked nothing.
10-12The Ternary Network FloatA rule the compiler enforces before any test runs, and a 17-bit float whose exponent is four balanced trits.
13-15Arithmetic on signed numbersMultiply two signed numbers, add them when their signs differ, and do both at once in a multiply-accumulate.
16-18Parts of a neuronA ReLU that bends at zero, a power of two for softmax, and an argmax that names the answer.
19-21Learning from a mistakeA loss that prices a wrong guess in bits, one step that moves a weight against its gradient, and the hidden layer that XOR needs.
22-24BitNet: ternary networksA threshold that squeezes a sum back to three values, one neuron that becomes a different function when its weights change, and a neuron that reads its inputs 27 trits at a time.
25-27The ternary MAC as a chipThe 27-trit dot product as wires with no register, the same sum added into a register on every clock, and a small whole network to close the course.

Course 1 keeps its 27 lessons in its 9 modules of 3: the chip, numbers in hardware, your t27 program, inside t27c, from spec to hardware, reading synthesis, place, route and timing, the bitstream, and on the board.

Every new lesson plants one bug

Lessons 13 to 27 each teach one spec from the ternary directory of t27. The widget of each is a recording of a terminal on our lab machine, where the native t27c compiler and Zig run the tests the browser cannot run yet. The recording shows the lines that matter and runs the spec's tests. Then tri mutate plant changes one line, runs the tests again and passes only if exactly the named test fails, and git diff shows the file back as it was. In all 15, exactly one named test fails.

Recordings pending for lessons 13 to 21. Their nine specs (gft_smul, gft_sadd, gft_signed_mac, gft_relu, gft_exp2, gft_argmax4, gft_nll, gft_sgd_step and gft_xornet) are recorded with tri test and tri mutate plant from t27#7400, which is not merged yet. Until it is, each of those lessons opens a placeholder page that says the recording is pending and shows no run; the lesson text says so too. Lessons 22 to 27 open their recordings now.

LessonSpecTestsThe planted bugThe one test that fails
13 A sign is one bitgft_smul.t273the sign of the product is always 0m2
14 Opposite signs subtractgft_sadd.t273adds the sizes when the signs differa2
15 Multiply, then addgft_signed_mac.t274the sign is set with OR, not XORpp
16 A bend at zerogft_relu.t274negative inputs pass throughnegz
17 Two to the xgft_exp2.t274drops the minus sign of k for negative xem1
18 Pick the largestgft_argmax4.t274> becomes >= for two positive scorestie_low
19 A loss in bitsgft_nll.t273neg turns 0 into a zero with the sign bit setperfect
20 One step downhillgft_sgd_step.t273multiplies g by itself, not by etaascend
21 XOR needs a bendgft_xornet.t274no relu on one hidden unitx00
22 Back to three valuesactivation_quantizer.t277> becomes >= at the thresholdquantize_boundary_hi
23 Same neuron, new weightsbitnet_majority.t2712one weight goes from P to Zmaj_p_n_n
24 A neuron in chunksbitnet_neuron_nchunk.t2711the loop reads one chunk, not all of themneuron_zero_chunks
25 A dot product made of wirescomb_ternary_dot.t274N times P gives +1dot_all_n_x_all_p
26 Add it up on every clockstream_ternary_mac.t274a P in a reads as Ndot_all_p_x_all_p
27 A whole networkbitnet_mlp.t274the third hidden trit lands on the wrong bitpack3_zzz

One planted bug shows that a test can fail. It says little about the tests that were never written. So each recording ends with tri mutate spec, which makes every one-line change it knows in the lesson's function and counts how many of them the tests notice.

What the mutants found

Over 14 of the 15 functions, tri mutate spec made 127 mutants. 92 were killed, every one of them by a failing test, and 35 survived; none hung and none failed to build. Eight functions killed every mutant. Six did not:

SpecFunctionMutantsKilledSurvived
gft_exp2.t27on_comb341717
gft_sadd.t27sadd18108
gft_smul.t27smul16124
gft_argmax4.t27gt963
comb_ternary_dot.t27tmul752
gft_relu.t27on_comb541

A survivor is a one-line change that no test notices. Either a test is missing, or the change does not change what the function returns. Both kinds occur in specs like these. In gft_relu.t27, line 11, if (x == 0) { return 0; }, can be deleted without changing any result, because line 13 returns x, and x is already 0. Which of the 35 survivors is which kind is not sorted yet; gft_exp2.t27, with 4 tests and 17 survivors, is where to look first. For gft_xornet.t27 the count printed no summary at all, so it is left out of the totals.

Making the recordings found two problems in the tools. tri test used to print a green line without running a single test, so a recording made with it proved nothing. Pull request t27#7400 makes it run the tests and fail when one fails or none ran, and adds tri mutate plant, which plants a bug, demands that exactly the named tests fail, and checks the file's hash before and after. t27c test-report still exits 0 when a test fails, so every verdict in these recordings is read from its text (t27#7370).

Where else to learn this

Before writing this, we read the pages of 16 other resources that teach or build ternary networks, quantized networks on FPGAs, or a network from scratch, on 7 October 2026. The table keeps 11 of them.

ResourceKindTernary weightsRuns whereTests behind it
The Era of 1-bit LLMs, S. Ma et al. (2024)paperyes, the definition of BitNet b1.58GPUsperplexity and accuracy against LLaMA
bitnet.cpp, Microsoftinference libraryyesCPUs, and GPUs since 2025no test suite named
Fine-tuning LLMs to 1.58bit, Hugging Face (2024)articleyes, the quantizer step by stepGPUsbenchmarks and loss curves
A Visual Guide to Quantization, M. Grootendorst (2024)illustrated articleyes, with worked numbersstatic figuresnone, there is no code
Ternary Weight Encoder, binarycon.cominteractive pagepacks weights that are already ternaryyour browsernone stated
FINN, AMD Researchcompiler and notebooksbinarized and quantized; ternary is not named on the pages readFPGA boards; Python, C++ and RTL simulationyes: each stage against a golden reference
TernaryCore (2026)Verilog libraryyes: a MAC, a dot product, a matrix multiplysimulation; Arty A7-100T and Tang Nano 9k boardstestbench pass counts and RTL against Python; tests not named
TeLLMe, Y. Qiao et al. (arXiv:2504.16266)paperyes, 1.58-bit weightsa Kria KV260 FPGAno correctness check described
micrograd and Neural Networks: Zero to Hero, A. Karpathylibrary and video coursenoPythongradients checked against PyTorch
MiniTorch, S. Rushteaching librarynoPython, and a CUDA moduleunit and property tests the learner must pass
nand2tetris, Project 2course and booknoa desktop hardware simulatora test script and a compare file per chip
This course, lessons 13 to 27courseyes: a 27-trit dot product, a MAC and a small networkspecs in your browser; tests in recordings of native t27cyes: 74 tests, one planted bug per lesson, 127 mutants

Each of these does something this course does not. The BitNet paper, bitnet.cpp and the Hugging Face article work at the scale of real models, from 700M to 70B parameters, with measured speedups; no lesson here touches a trained model. FINN compiles trained networks into FPGA accelerators and checks every stage in simulation, and TeLLMe runs a whole ternary language model on an edge FPGA. TernaryCore is the closest: open Verilog that goes from a ternary MAC to a dot product to a matrix multiply, with tests, and runs on real boards. micrograd, MiniTorch and nand2tetris have the learner build each piece against tests.

What we did not find on any of those pages is the shape of these lessons: one planted one-line bug per lesson that fails exactly one named test, with the file put back afterwards. nand2tetris and MiniTorch come near, since a learner's own mistake fails their tests, but they do not plant one and show it. That is a narrow claim about the pages we read, not about every course there is. Nor do the tests of these 15 lessons run in your browser yet; they run in the recordings.

What this does not show

Try it

What this does not settle

Receipts

Work with me

Want this kind of check on your own design?

I audit RTL and build independent, bit-exact models, then take the result through synthesis and, when useful, onto an Artix-7 board. The first conformance module is free.