This is a processor built out of individual transistors — 1,896 of them for one core, fewer than the 2,300 in an Intel 4004.
It knows exactly one instruction. Not a small instruction set: one instruction. It subtracts one number from another and jumps if the result came out zero or negative. That is the entire machine. Addition, multiplication, strings, pointers and loops are all built on top of it in software, which is possible because one instruction is enough to compute anything — a fact that is easier to prove than to believe.
The goal is not one of these but eight, wired in a ring and passing messages to each other. That part appears to be unoccupied ground: every discrete-transistor computer I can find is a single processor, and nearly all of them are NMOS rather than CMOS.
Nothing is soldered yet, and nothing will be for a long time. This is a CMOS homebrew computer being designed in the open, and these logs catch up on how it got here.
Why CMOS, when almost nobody else does
Nearly every discrete-transistor computer ever built is NMOS: one transistor pulling the output down, one resistor pulling it up. Half the parts of the alternative and a far simpler board. MOnSter 6502, discrete6502 and Spikeputor all take that route.
It has one problem, and it is not subtle. A gate holding a low output has its pull-down transistor on and its pull-up resistor still connected to the supply, so there is a complete path from rail to rail. With a 10 kΩ pull-up that is 0.5 mA, burned continuously, per gate.
This machine is on the order of a thousand gates, and at any moment about half of them sit low:
| Current per low gate | 0.5 mA |
| Gates, order of magnitude | ~1,000 |
| Standing current | ~250 mA |
| Standing power at 5 V | ~1.25 W |
Drawn while computing, while waiting, and while doing nothing at all. It does not depend on the clock, so slowing the machine down does not help — the loss is not switching, it is standing. NMOS builds compensate by running slowly anyway; Spikeputor is around 3 kHz, MOnSter 6502 around 50 kHz.
CMOS replaces the resistor with a P-channel transistor that is switched off precisely when the pull-down is switched on. There is never a path from rail to rail, so a gate that is holding a value draws essentially nothing. Current flows only while switching, which makes power proportional to clock rate rather than to gate count. Speed becomes a dial instead of a fixed bill.
The price is exact: two transistors where NMOS needs one. Every gate, across the whole machine.
That factor of two is the largest single cost decision in this project, and it is the reason everything else about the design is strange. One instruction instead of an instruction set, one bit at a time instead of sixteen, and a serial memory instead of a bus — all three exist to win back the transistors that CMOS costs. Take the CMOS decision away and there is no reason to build the machine this way at all.
Three ideas, and each makes the other two cheaper
One instruction. The machine only knows subleq — subtract, and branch if the result is less than or equal to zero. There is no opcode field, so there is nothing to decode, so the instruction decoder does not exist. What would be an instruction set lives in the assembler, as macros.
A few bits at a time. A serial datapath shrinks the ALU from a block to a handful of gates. You pay in clock cycles, which are cheap in CMOS while transistors are not.
One serial wire. Memory, display and input all speak SPI. There is no address bus, no data bus and no bus drivers — roughly six hundred transistors that would compute nothing.
Remove any one and the other two get worse. Serial arithmetic is only attractive because the memory interface is already serial. The result is that the machine is conceptually a single object: a large shift ring with a one-bit ALU in it.
Why a ring, and not just more memory
Measuring where the clock cycles actually go turned up something I did not expect. Over a real program, 52% of the machine's time is spent telling the memory which word it wants, 33% moving the word itself, and 15% doing arithmetic. The computing is the smallest slice by a wide margin.
That is not a flaw to be fixed — it is what a serial memory interface costs. One word access is 8 bits of opcode, 16 of address, 16 of data and one idle clock so chip select can go back up: 41 clocks, of which 25 are addressing.
Now compare a word handed to the next core along the ring. There is exactly one place it can come from, so there is nothing to address at all. Sixteen bits, sixteen clocks.
So on this machine a word from a neighbour is cheaper than a word from its own memory. That sounds like a boast and is really a consequence: memory is expensive here because memory is random, and SUBLEQ makes it maximally random — three addresses per instruction, and self-modifying code makes them unpredictable. Message passing is cheap because it is sequential.
Which is why the ring is not a way to scale a design that was finished without it. It is the direction the design was already pointing.
Two negative addresses carry it: −4 writes a word to the next core, −5 reads one from the previous. Both block. A core that asks for a word nobody has sent stands still until it arrives, and its program counter does not move, so it resumes on exactly the same instruction. That blocking is the synchronisation — there are no locks, no semaphores and no race conditions anywhere in the design. The model is INMOS's Transputer, via Hoare's CSP. The link logic costs 54 transistors per core.
The numbers
Every transistor count is built up from a cell library, gate by gate, rather than estimated. python3 cells/report.py prints it.
| Transistors per complete core | 1,896 |
| Intel 4004 | 2,300 |
| Room to spare | 404 |
| Clocks per instruction | 90 |
| Instructions/second at 5 MHz | ~55,800 |
| Word between neighbours | 16 clocks |
| Word from own memory | 41 clocks |
| Eight cores | 15,168 |
Two versions
They differ in exactly one cell type.
| v1 | v2 | |
|---|---|---|
| Storage cell | dynamic | static |
| Transistors | 1,896 | ~2,650 |
| Clock may stop | no | yes |
A dynamic cell holds a bit as charge: ten transistors instead of twenty-two, but the charge leaks, so there is a minimum clock rate and the clock can never stop. A static cell holds its value indefinitely and costs about 750 more transistors across the machine.
v1 is being built first, because it is smaller and gets to something demonstrable sooner. Running for months off a coin cell, or live off a solar panel, needs the clock to crawl or stop entirely — that is a v2 property and is not claimed for v1.
Try it
The emulator is the architectural reference: whatever gets built later in Verilog, on an FPGA, or out of transistors has to produce exactly the same answers. It needs nothing but Python 3.
$ python3 asm/runner.py asm/programs/multiply.sq 42 $ python3 asm/runner.py asm/programs/string.sq --text KRANSPUTER $ python3 asm/runner.py --ring asm/programs/ring-sum.sq asm/programs/ring-sum-worker.sq 42
multiply.sq computes 7 × 6 without a multiply instruction — or an add instruction, for that matter. The ring example is two cores: one walks an array and sends each value, the other adds up whatever arrives, with no idea how many are coming.
Status
Nothing is soldered, and nothing will be until the architecture is simulated, verified in Verilog and running on an FPGA.
What exists: a behavioural emulator, an assembler with macros and indirection, a bit-accurate model of the datapath, a designed sequencer and bit counter, a transistor count computed from primitives, and working two-core ring programs. 176 tests, and the models are checked against each other rather than only against themselves.
What is next: the same design in Verilog, then on an FPGA. Soldering starts at phase 6 of 7.
The build logs catch up on how the design got here — starting with a single 2N7000 and one resistor, and every place the plan turned out to be wrong.
Names
| Thing | Name |
|---|---|
| The project | Kransputer |
| One board / one core | 4003 |
| The first machine | Druppel |
Licence
Free to study, build and modify, but not to sell. Hardware design files and documentation under CC BY-NC-SA 4.0; software under PolyForm Noncommercial 1.0.0. Build one for yourself, for your class, for your hackerspace — that is exactly what this is for.
Code and full documentation: https://github.com/DDecoene/kransputer
Dennis Decoene