Updated 11 October 2026

1bICS

The 1-bit Industrial Control System (pronounced as "one-bicks") is a single-bit processor designed for use in systems requiring decisions based on sequence of single-bit information. The design is directly based on the MC14500B CMOS microprocessor from Motorola.

It has a remarkably low transistor count, with my current iteration of the design requiring only ~250-300 discrete transistors for the entire chip, which I have physically built and documented the results of in this post. In comparison, even the first microprocessor the 4-bit Intel 4004 (1971) contained about 2250 transistors.

Link to my GitHub Repository

The image of the board above is the complete Logic Unit, using Manhattan circuit construction technique.

The chip has an unusual architecture, hosting only a 1-bit data bus and a 4-bit instruction set. It does not include any support for features that a typical microprocessor has. The program counter, instruction fetches, memory, jumps and subroutine calls will need to be implemented with external circuitry.

Instruction Code Mnemonic Action
0 0000 NOPO RR → RR, Flag O → HIGH
1 0001 LD Data → RR
2 0010 LDC !Data → RR
3 0011 AND RR & Data → RR
4 0100 ANDC RR & !Data → RR
5 0101 OR RR | Data → RR
6 0110 ORC RR | !Data → RR
7 0111 XNOR !(RR ^ Data) → RR
8 1000 STO RR → Data, Write → HIGH
9 1001 STOC !RR → Data, Write → HIGH
A 1010 IEN Data → IEN
B 1011 OEN Data → OEN
C 1100 JMP JMP Flag → HIGH
D 1101 RTN RTN Flag → HIGH, and skip next instruction
E 1110 SKZ Skip next instruction if RR = 0
F 1111 NOPF RR → RR, Flag F → HIGH

With the use of a rudimentary assembler and access to sufficient memory, the processor proves itself to be more than capable of performing complex computational tasks.

The example below shows a basic arithmetic subroutine performing a 4-bit addition.

Assembly code:

	; enable data input/output
0x00:	IEN HIGH
0x02:	OEN HIGH

0x04:	JMP 0x20	; goto main code

	; FULL-ADDER SUBROUTINE
0x06:	LD   A
0x08:	XNOR B
0x0A:	STOC A_XOR_B	; store A ^ B

0x0C:	LD   A
0x0E:	AND  B
0x10:	STO  A_AND_B	; store A & B

0x12:	LD   A_XOR_B
0x14:	XNOR C
0x16:	STOC B		; S = (A ^ B) ^ C

0x18:	LD   A_XOR_B
0x1A:	AND  C
0x1C:	OR   A_AND_B
0x1E:	STO  C		; C = ((A ^ B) & C) | (A & B)

0x20:	RTN  0		; exit

	; z0 = x0 + y0
0x22:	LD   X0		; load x0 as 1st argument
0x24:	STO  A
0x26:	LD   Y0		; load y0 as 2nd argument
0x28:	STO  B
0x2A:	JMP  0x04	; call to subroutine
0x2C:	LD   B
0x2E:	STO  Z0		; store result to z0

	; z1 = x1 + y1 + c
0x30:	LD   X1
0x32:	STO  A
0x34:	LD   Y1
0x36:	STO  B		; carry is stored from
0x38:	JMP  0x04	; previous subroutine call
0x3A:	LD   B
0x3C:	STO  Z1

	; z2 = x2 + y2 + c
0x3E:	LD   X2
0x40:	STO  A
0x42:	LD   Y2
0x44:	STO  B
0x46:	JMP  0x04
0x48:	LD   B
0x4A:	STO  Z2

	; z3 = x3 + y3 + c
0x4C:	LD   X3
0x4E:	STO  A
0x50:	LD   Y3
0x52:	STO  B
0x54:	JMP  0x04
0x56:	LD   B
0x58:	STO  Z3

Memory dump:

0x00:   0100000000000000
0x10:   0100000000000000
0x20:   0000000000000000
0x30:   1110000000000000
0x40:   0100000000000000
0x50:   1001000000000000
0x60:   0000000000000000
0x70:   0000000000000000
0x80:   0000000000000000
0x90:   0000000000000000
0xA0:   0000000000000000
0xB0:   0000000000000000
0xC0:   0000000000000000
0xD0:   0000000000000000
0xE0:   0000000000000000
0xF0:   0000000000000000

Memory address 0x30 holds the first value (0b0111), and 0x40 for the second value (0b0010). The result of this addition is stored at 0x50 with the output 0b1001, which agrees with the fact that 0b0111 + 0b0010 = 0b1001 and assures that the program is running as expected.

For a more detailed description of how such a microprocessor works, visit Ken Shirriff's excellent blog post: "A one-bit processor explained: reverse-engineering the vintage MC14500B"


Project History

I have first started out this project with the goal of fully building a computer from discrete electronic components (no integrated circuits). Being terribly unmotivated to follow any courses or guides, I began working with digital logic circuitry (NAND, NOR, NOT, etc.) one unit at a time. From registers to counters to arithmetic units, it became increasingly apparent to me the time and financial cost required to build a homebrew computer was much too great for the resources I had available to me.

Thus, I begin the process of extreme pruning, learning about the history of computing and the creative solutions people came up with. Even with a complex ALU, the biggest offender to the cost of computing was usually always memory.

Let's say, if one bit (not byte!) of memory requires 5 transistors, and I desire a full 256 bytes of RAM, and each 2N2222 transistor costs around $0.08... I would require a whopping 10,240 transistors. That's $819.20 in transistors alone! That is not including all the resistors required to make it work, nor the decoder that's required to make it addressable! Don't forget all the labour, time, and soldering too!

If we insist on using only discrete electronic components, we would have to be very selective and reserved with our use of transistors.

Discrete transistorised version of the 4-bit instruction register

To make the project more approachable, I had to reduce the scope down to the CPU. Even then, a basic 8-bit ALU would still require hundreds of transistors. This has forced me to continue searching until I came across 1-bit microprocessor designs, where the ALU (or the Logic Unit in this case) only required 35-40 or so transistors!

With a small 4-bit instruction set and a couple of 1-bit registers, this discovery made the project a lot more feasible within the time span and finances I had to work with.

A fully working simulation of 1bICS I made on Digital Logic Sim (Sebastian Lague)

Once I got the logical aspects of the chip working, I began to learn more about digital electronics and schematic design. Prototying units using electronic simulations and then breadboards, incrementally piecing parts together such that they work in predictable and synchronous manner.

Clicking on some of the pictures above will lead you to the videos of the circuits working in action. I certainly could have made some optimisations in the design, by utilising electronic "trickery" to save a transistor here or there, but at some point the concept of "good enough" applies.

This project has been an overall success, and it has achieved the goals I have set out to do. However, not all of the circuits were fully built as it is now apparent to me that manual prototyping methods can be incredibly time consuming. So far, every circuit has behaved exactly as I expected, thus I will make the move to create PCB designs and get them printed in the future.


Many thanks for reading!