Project 5 · The Computer
The whole machine: wiring three chips together
The CPU can execute instructions, but it does not know which instruction it fetched or which memory it wrote. This page does two things: build Memory (RAM + screen + keyboard), then wire CPU + ROM32K + Memory into a machine.
01Three chips, that is the whole machine
| Chip | Role | Source |
|---|---|---|
| ROM32K | Stores instructions, read by address | Built in (provided, not implemented here) |
| CPU | Executes instructions | Built on the previous page |
| Memory | Data + screen + keyboard | Built on this page |
The whole machine is six wires: pc, instruction, addressM, outM, writeM, inM.This is the Harvard architecture from the prologue: ROM32K and Memory are two separate memories with separate address lines, so one cycle can fetch and access memory at the same time.
02Memory: one address space, three devices
Outside it is a memory with a 15-bit address and 16-bit data; inside it splits reads and writes by the top address bits:
| Address | Who | How it is selected |
|---|---|---|
| 0 – 16383 | RAM16K | address[14] = 0 |
| 16384 – 24575 | Screen | address[14] = 1 and address[13] = 0 |
| 24576 | Keyboard | address[14] = 1 and address[13] = 1 |
On a write, a DMux sends load to the right device; on a read, Mux16 selects it back. RAM16K sees only the low 14 address bits and the screen only the low 13 — so each device sees “its own” address.
03The HDL for Memory
Keyboard has no inputs (it only outputs), and Screen and RAM16K are built-in chips. Everything else is address decoding:
CHIP Memory { IN in[16], load, address[15]; OUT out[16]; PARTS: // address[14]: 0 → RAM, 1 → screen / keyboard DMux(in=load, sel=address[14], a=loadRAM, b=loadDevice); // address[13]: 0 → screen, 1 → keyboard (read-only, no load) Not(in=address[13], out=notA13); And(a=loadDevice, b=notA13, out=loadScreen); RAM16K(in=in, load=loadRAM, address=address[0..13], out=outRAM); Screen(in=in, load=loadScreen, address=address[0..12], out=outScreen); Keyboard(out=outKbd); // read: pick screen/keyboard first, then RAM vs device Mux16(a=outScreen, b=outKbd, sel=address[13], out=outSK); Mux16(a=outRAM, b=outSK, sel=address[14], out=out); }
RAM16K (0–16383), Screen (16384–24575) and Keyboard (24576) sit side by side, decoded by address[14] and address[13].
04Why ROM32K is not implemented
ROM is read-only: give it an address and it returns the 16 bits stored there. The course provides ROM32K as a built-in chip,
ROM32K(address=pc, out=instruction);
with no load and no clock — the program is already installed before the machine runs. Think of it as an array of 32768 rows.
That also explains why Hack cannot modify its own program: ROM is read-only, and program and data live in two places from the start.
05The HDL for Computer
The whole machine is one CHIP that connects the three chips:
CHIP Computer { IN reset; PARTS: ROM32K(address=pc, out=instruction); CPU(inM=inM, instruction=instruction, reset=reset, outM=outM, writeM=writeM, addressM=addressM, pc=pc); Memory(in=outM, load=writeM, address=addressM, out=inM); }
Three chips make the whole machine: ROM32K (built in), CPU and Memory. pc points the way, instruction carries it back, addressM/outM/writeM go out, inM comes back.
06One fetch, step by step
| Step | Who carries it |
|---|---|
| PC points at an instruction | the CPU’s pc → ROM32K.address |
| 16 bits come out | ROM32K.out → the CPU’s instruction |
| Execute | inside the CPU (ALU + registers) |
| Touch memory | addressM / outM / writeM → Memory; inM comes back |
| PC advances | inside the CPU (+1 by default, A on a jump) |
There is no bus arbitration, no cache, no pipeline: in one beat the signals travel this chain once, then the next beat starts.
07Boot: what happens after reset
When reset = 1 the CPU sets PC to 0. On the next beat ROM32K returns the instruction at address 0 — the first line of the program.
So “power on and run” is one sentence on Hack: clear PC, then keep executing. No operating system, no loader; the program is the numbers in ROM.
08Hardware done, software enters: how Tetris runs
Congratulations: from nothing but NAND gates you have welded together a general-purpose computer that runs programs on its own.
But the sobering fact: the hardware ticks millions of times a second and knows only the 0 and 1 levels in memory. To write Tetris, would a programmer hand-write hundreds of thousands of lines of binary?
That is the six-storey tower of computing (five layers of software plus the hardware at the bottom):
| Layer | Who | Responsible for | Now |
|---|---|---|---|
| Layer 6 | Tetris | Game logic: rotation, collision detection, scoring | empty |
| Layer 5 | Jack language & OS | A small object-oriented language plus a runtime (Math/Memory/Screen/Output) | empty |
| Layer 4 | Compiler | Compiles Jack source into stack-based VM bytecode | empty |
| Layer 3 | VM translator | Expands push/pop/call bytecode into sequences of Hack assembly | empty |
| Layer 2 | Assembler | Turns Hack mnemonics and symbols into 16-bit machine code | built |
| Layer 1 | Computer hardware | The machine you just built: ROM emits instructions, the CPU throws switches, pixels light up | built |
No magic, only layer upon layer of abstraction and encapsulation. You are standing on the most solid foundation of that tower — look back at every gate and the picture becomes clear.