Day 1 of 5
⏱ ~60 minutes
How CPUs Work in 5 Days — Day 1

Transistors and Logic Gates

A CPU with 50 billion transistors is built from a single repeated idea: a transistor is a switch. Everything else — math, memory, programs — emerges from switches connected in patterns.

The Transistor: A Switch

A MOSFET transistor has three terminals: gate, source, drain. Apply voltage to the gate and current flows from source to drain — the switch is ON. Remove voltage and current stops — the switch is OFF. At 3nm process nodes, each transistor is 3 nanometers wide. An Intel Core i9-13900K has 25 billion transistors packed on a fingernail-sized die.

Logic Gates from Transistors

Connect two NMOS transistors in series: current only flows if BOTH gates are high — that's an AND gate. Connect two in parallel: current flows if EITHER gate is high — OR gate. Invert the output and you get NAND/NOR. Every logic gate is 2–6 transistors. Every digital computation is built from these.

Boolean Algebra and Truth Tables

Logic gates implement Boolean algebra. AND: A·B. OR: A+B. NOT: Ā. XOR: exclusive-or, true when exactly one input is true. Every arithmetic operation, every comparison, every data movement in a CPU is ultimately AND/OR/NOT operations on bits. The CPU doesn't understand numbers — it understands voltages that we interpret as 0s and 1s.

python
# Logic gates in Python — simulate transistor behavior

def NAND(a, b): return not (a and b)  # 2 transistors
def NOT(a):     return NAND(a, a)     # 2 transistors
def AND(a, b):  return NOT(NAND(a,b)) # 4 transistors
def OR(a, b):   return NAND(NOT(a), NOT(b))  # 6 transistors
def XOR(a, b):  return AND(OR(a,b), NAND(a,b))  # 10 transistors

# Half adder: 1-bit addition
def half_adder(a, b):
    sum_bit   = XOR(a, b)   # sum
    carry_bit = AND(a, b)   # carry
    return sum_bit, carry_bit

# Full adder: adds two bits plus carry-in
def full_adder(a, b, cin):
    s1, c1 = half_adder(a, b)
    s2, c2 = half_adder(s1, cin)
    return s2, OR(c1, c2)

# 4-bit ripple-carry adder
def add4(a4, b4):
    result = []
    carry = 0
    for i in range(4):
        s, carry = full_adder(a4[i], b4[i], carry)
        result.append(s)
    return result, carry

# Test: 5 + 3 = 8
a = [1,0,1,0]  # 5 in binary (LSB first)
b = [1,1,0,0]  # 3 in binary
result, cout = add4(a, b)
print(f"5 + 3 = {int(''.join(str(b) for b in reversed(result)),2)} carry={cout}")
💡
NAND is the universal gate — every other gate can be built from NAND alone. Real CPUs use NAND-based standard cells extensively. If you can implement NOT, AND, OR, and XOR from NAND, you can build a CPU.
📝 Day 1 Exercise
Build a 1-Bit Adder from Gates
  1. Run the code above. Verify that 5+3=8 and 7+9=16 (with carry).
  2. Draw the truth table for XOR by hand: all 4 combinations of (0,0), (0,1), (1,0), (1,1).
  3. Implement an 8-bit ripple-carry adder by chaining 8 full adders. Test with 127+1=128.
  4. Research 'carry-lookahead adder' — why is it faster than ripple-carry? At what bit-width does it matter?
  5. Look up how many transistors a 64-bit adder requires in a modern CPU. Why do CPUs have multiple adder circuits?

Day 1 Summary

  • Transistors are switches — voltage on the gate controls current flow between source and drain
  • Logic gates (AND, OR, NOT, XOR) are built from 2–10 transistors
  • NAND is universal — every digital circuit can be built from NAND gates alone
  • Addition, comparison, memory addressing — all of it is Boolean algebra on bits
Challenge

Implement a 1-bit multiplier (AND gate) and extend it to an 8-bit multiply-by-2 using a shift register. Then research how modern CPUs implement 64-bit integer multiplication. How many transistors does a hardware multiplier require vs a software loop that adds N times?

Finished this lesson?