Lesson 0. Logic: 0 and 1, gates from transistors, an adder
In picturesThe foundation before the watch. What 0 and 1 are, the three operations on them (Boolean algebra), how a logic gate is made of transistors, and how gates make something useful — a circuit that adds two 4-bit numbers. Everything later in the kit is the same gates, just more of them.
Result: NOT (2 transistors), NAND and NOR (4 each), AND and OR (6 each), XOR (16), the full adder FA (50), the 4-bit adder ADD4 (200) — all 256 sums from 0+0 to 15+15 are correct.
0.1. The simulator
Everything is built in the browser: cs.khanin.info. No install, no sign-up; a computer with a mouse is the most comfortable.
This is a learning simulator, not a tool for designing real electronics. A transistor in it is an ideal switch (open or closed), and a signal is only 0 or 1. There are no voltages, currents, wire delays, heat or noise. That is more than enough to understand how logic, memory and a processor work; you can't design a real board with it — that needs resistors, power calculations and timing margins.
How to place parts, labels and chips is in "The simulator in five minutes" before the lessons. The key points: labels with the same name are connected, Ctrl+G turns a selection into a chip, Export saves your work.
0.2. Boolean algebra: 0, 1 and three operations
A signal is 0 or 1 (no/yes, false/true, off/on). Boolean algebra (George Boole, 1847) is the arithmetic of such values. There are only three operations:
- NOT — flips:
NOT 0 = 1,NOT 1 = 0. In the kit we write it with annprefix:nA= NOTA. - AND —
A·Bis 1 only when both inputs are 1. - OR —
A + Bis 1 when at least one input is 1.
Their combinations got names of their own because they come up all the time:
| A | B | A·B | A + B | NAND | NOR | XOR |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 1 | 0 | 1 |
| 1 | 1 | 1 | 1 | 0 | 0 | 0 |
- NAND = NOT(AND), NOR = NOT(OR).
- XOR ("exclusive OR",
A ⊕ B) — 1 when the inputs differ. It is one-bit addition without the carry:1 + 1 = 0, and the one goes to the carry (we'll need this in 0.5).
⚠ The plus in Boolean algebra is OR, not addition: 1 + 1 = 1.
The laws used to simplify formulas (each one checks out by substituting 0 and 1):
| Law | Example |
|---|---|
| with a constant | A·1 = A A·0 = 0 A + 0 = A A + 1 = 1 |
| with itself | A·A = A A + A = A |
| with its opposite | A·nA = 0 A + nA = 1 |
| double NOT | NOT(nA) = A |
| factoring out | A·B + A·C = A·(B + C) |
| merging | A·B + A·nB = A |
| De Morgan | NOT(A·B) = nA + nB NOT(A + B) = nA·nB |
De Morgan's law in words: "not (both)" = "at least one is not". It lets you swap AND for OR at the cost of inversions — that's how in lesson 3 the multiplexer is rebuilt from NANDs only and becomes cheaper.
0.3. A transistor is a switch
The palette has a Transistor part. It has three pins: the gate G on the left, top and bottom. The gate controls whether top and bottom are connected. Alt + click on the body (on a Mac — ⌥ or ⌘ + click) switches the type N ↔ P — a plain click leaves it alone:
- N: gate = 1 → top and bottom connected; gate = 0 → open.
- P: the other way round — connected when the gate = 0.
The CMOS rule (almost every chip since the 1980s is built this way): P transistors go on top, between VCC (the source of 1) and the output; N ones go at the bottom, between the output and GND (the source of 0). For any input exactly one half conducts — the output is always connected either to 1 or to 0. Never to both at once (a short) and never to nothing (an open, the output "floats").
0.4. NOT, NAND, NOR from transistors
NOT — two transistors. Input A goes to both gates: with A = 0 the top P is open and pulls the output to 1, with A = 1 the bottom N pulls it to 0.
INPUT PORTS: A · OUTPUT PORTS: Y
| Transistor | Gate | Top | Bottom |
|---|---|---|---|
| P | A | VCC | Y |
| N | A | Y | GND |
Make it a chip: Ctrl+G → NOT.
NAND — four. Two P in parallel on top: a single 0 on an input is enough to make the output 1. Two N in series at the bottom: the output connects to ground only when both inputs are 1. The point between the two N gets the label mid.
INPUT PORTS: A, B · OUTPUT PORTS: Y
| Transistor | Gate | Top | Bottom |
|---|---|---|---|
| P | A | VCC | Y |
| P | B | VCC | Y |
| N | A | Y | mid |
| N | B | mid | GND |
Make it a chip: Ctrl+G → NAND.
NOR — the mirror image: two P in series (output 1 only when both inputs are 0), two N in parallel (any 1 pulls the output to 0).
INPUT PORTS: A, B · OUTPUT PORTS: Y
| Transistor | Gate | Top | Bottom |
|---|---|---|---|
| P | A | VCC | mid |
| P | B | mid | Y |
| N | A | Y | GND |
| N | B | Y | GND |
Make it a chip: Ctrl+G → NOR.
AND, OR, XOR — from gates. No more transistors needed: the three missing gates are built from the NOT, NAND, NOR you have just made.
AND = NAND + NOT — "NOT-AND", then flip it:
INPUT PORTS: A, B · OUTPUT PORTS: Y
| Element | Inputs | Output |
|---|---|---|
| NAND | A, B | n |
| NOT | n | Y |
Make it a chip: Ctrl+G → AND.
OR = NOR + NOT:
INPUT PORTS: A, B · OUTPUT PORTS: Y
| Element | Inputs | Output |
|---|---|---|
| NOR | A, B | n |
| NOT | n | Y |
Make it a chip: Ctrl+G → OR.
XOR — "at least one, but not both": AND( OR(A, B), NAND(A, B) ):
INPUT PORTS: A, B · OUTPUT PORTS: Y
| Element | Inputs | Output |
|---|---|---|
| OR | A, B | o |
| NAND | A, B | n |
| AND | o, n | Y |
Make it a chip: Ctrl+G → XOR.
Check. Power: V (Power) with the label VCC and G (Ground) with the label GND; two switches X, Y; lamps (LED) on the outputs:
| Element | Inputs | Output |
|---|---|---|
| NOT | X | notX |
| NAND | X, Y | nandXY |
| NOR | X, Y | norXY |
| AND | X, Y | andXY |
| OR | X, Y | orXY |
| XOR | X, Y | xorXY |
| LED | notX | |
| LED | nandXY | |
| LED | norXY | |
| LED | andXY | |
| LED | orXY | |
| LED | xorXY |
Flip the switches — the lamps should follow the table from 0.2. Or select a chip and press T for its truth table.
Cost in transistors: NOT — 2, NAND and NOR — 4 each. But AND = NAND + NOT = 6, OR = NOR + NOT = 6: "AND" costs more than "NAND". That's why NAND and NOR are the native CMOS gates, and it pays to bring formulas down to them. XOR — 16 transistors.
These six chips — NOT, NAND, NOR, AND, OR, XOR — are now in your library on the right, and the whole kit stands on them. From here on we don't place transistors by hand: we use these gates.
0.5. Adding one digit
Binary numbers are added in a column, just like decimal ones: 0 + 0 = 0, 0 + 1 = 1, 1 + 1 = 10 — write 0, carry 1 to the next digit. Each digit adds three bits: A, B and the carry from the lower digit CI. There are two outputs: the sum bit S and the carry onward CO.
| A | B | CI | S | CO | ones |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 | 1 |
| 0 | 1 | 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 | 1 | 2 = 10 |
| 1 | 0 | 0 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 | 2 = 10 |
| 1 | 1 | 0 | 0 | 1 | 2 = 10 |
| 1 | 1 | 1 | 1 | 1 | 3 = 11 |
How we derived it:
S = 1when the number of ones is odd — that is exactly the XOR of three bits:S = A ⊕ B ⊕ CI.CO = 1when there are two or three ones. Either bothAandB(A·B), or exactly one of them (A ⊕ B) and the carry:CO = A·B + (A ⊕ B)·CI.
A ⊕ B is needed both for S and for CO — compute it once, label p.
INPUT PORTS: A, B, CI · OUTPUT PORTS: S, CO
| Element | Inputs | Output (→) |
|---|---|---|
| XOR | A, B | p |
| XOR | p, CI | S |
| AND | A, B | g |
| AND | p, CI | pc |
| OR | g, pc | CO |
Make it a chip: Ctrl+G → FA (full adder), inputs A B CI, outputs S CO, 50 transistors. Check: T — eight rows, as in the table above.
0.6. A 4-bit adder
Four FA in a chain: the carry CO of each digit goes to CI of the next. The lowest digit has no incoming carry — CI = GND (0). The carry out of the highest digit is the fifth bit of the sum S4: 15 + 15 = 30 = 11110 doesn't fit into four bits.
INPUT PORTS: A0 A1 A2 A3, B0 B1 B2 B3 · OUTPUT PORTS: S0 S1 S2 S3 S4
| Element | Inputs | Output (→) |
|---|---|---|
| FA | A=A0, B=B0, CI=GND | S→S0, CO→c1 |
| FA | A=A1, B=B1, CI=c1 | S→S1, CO→c2 |
| FA | A=A2, B=B2, CI=c2 | S→S2, CO→c3 |
| FA | A=A3, B=B3, CI=c3 | S→S3, CO→S4 |
Make it a chip: Ctrl+G → ADD4, 200 transistors.
This is a ripple-carry adder: the carry "ripples" from the lowest digit to the highest, as in column addition. The longest case is 0111 + 0001: the carry passes through all four digits. An adder is the heart of every processor: subtraction, comparison and counters are all made from it.
0.7. The canvas and the check
- Power:
V(Power) with the labelVCC,G(Ground) with the labelGND(skip if they are already there from the gate check). - Eight switches (
I) → labelsA0 A1 A2 A3andB0 B1 B2 B3. - The
ADD4chip, with labels of the same names on its pins:A0…A3,B0…B3,S0…S4. - Three Display (bus). On each: a click on ⚙ at the top left changes the width (4b / 8b / 16b / 32b), a click on
PINat the bottom left lets you type a bus name, and the display reads the labelsname0,name1, … by itself, no wires:
| Element | Width | Bus |
|---|---|---|
| Display (bus) | 4b | A |
| Display (bus) | 4b | B |
| Display (bus) | 8b | S |
The sum has 5 bits and there is no 5-bit display — use 8b: bits S5…S7 don't exist on the canvas, so the display reads them as zeros.
Check: 3 + 4 = 7, 7 + 1 = 8 (the carry runs through all digits), 15 + 15 = 30 (S4 lights up). Any two 4-bit numbers add correctly — all 256 pairs were checked.
Lesson 0 as a paste (Cmd+I)
In an empty project it creates all the kit's basic gates (NOT, NAND, NOR, AND, OR, XOR), FA, ADD4 and places power, the gate check with lamps and the adder with three displays.
# Lesson 0 — gates from transistors and a 4-bit adder.# Paste: Cmd+I into an empty project: builds all the kit's basic gates (NOT NAND NOR AND OR XOR), FA and ADD4.# Transistor: nmos/pmos(gate, top, bottom). VCC/GND are the shared power rails. # --- gates from transistors ---chip NOT { portIn(A) portOut(Y) pmos(A, VCC, Y) nmos(A, Y, GND)} # NAND: two P in parallel on top, two N in series belowchip NAND { portIn(A) portIn(B) portOut(Y) pmos(A, VCC, Y) pmos(B, VCC, Y) nmos(A, Y, mid) nmos(B, mid, GND)} # NOR: two P in series on top, two N in parallel belowchip NOR { portIn(A) portIn(B) portOut(Y) pmos(A, VCC, mid) pmos(B, mid, Y) nmos(A, Y, GND) nmos(B, Y, GND)} # --- gates from gates ---# AND = NAND + NOT (6 transistors)chip AND { portIn(A) portIn(B) portOut(Y) NAND(A, B, n) NOT(n, Y)} # OR = NOR + NOT (6 transistors)chip OR { portIn(A) portIn(B) portOut(Y) NOR(A, B, n) NOT(n, Y)} # XOR = "at least one, but not both": AND( OR(A,B), NAND(A,B) ) (16 transistors)chip XOR { portIn(A) portIn(B) portOut(Y) OR(A, B, o) NAND(A, B, n) AND(o, n, Y)} # --- full adder for one bit ---chip FA { portIn(A) portIn(B) portIn(CI) portOut(S) portOut(CO) XOR(A, B, p) XOR(p, CI, S) AND(A, B, g) AND(p, CI, pc) OR(g, pc, CO)} # --- 4 bits: the carry runs from the lowest bit to the highest ---chip ADD4 { portIn(A0) portIn(A1) portIn(A2) portIn(A3) portIn(B0) portIn(B1) portIn(B2) portIn(B3) portOut(S0) portOut(S1) portOut(S2) portOut(S3) portOut(S4) FA(A0, B0, GND, S0, c1) FA(A1, B1, c1, S1, c2) FA(A2, B2, c2, S2, c3) FA(A3, B3, c3, S3, S4)} # --- on the canvas: power, gate check, adder with displays ---power(VCC)ground(GND)input(X)input(Y)NOT(X, notX)NAND(X, Y, nandXY)NOR(X, Y, norXY)AND(X, Y, andXY)OR(X, Y, orXY)XOR(X, Y, xorXY)led(notX)led(nandXY)led(norXY)led(andXY)led(orXY)led(xorXY)input(A0)input(A1)input(A2)input(A3)input(B0)input(B1)input(B2)input(B3)ADD4(A0, A1, A2, A3, B0, B1, B2, B3, S0, S1, S2, S3, S4)display{bits=4, busSource=A}()display{bits=4, busSource=B}()display{bits=8, busSource=S}()Stuck? Something doesn't work →