Von Neumann Architecture

The problem

ENIAC, finished in 1945, was programmed with patch cables and switches. Its program was its wiring. Running a different program meant rewiring the machine, which took days.

In June 1945 John von Neumann circulated the First Draft of a Report on the EDVAC. It described a machine that keeps its program in the same memory as its data. A new program is a new set of words in memory, not new wiring. The ideas came out of the ENIAC group's work with Eckert and Mauchly, but the report carried only von Neumann's name, and the design is named after him. Nearly every general purpose computer since follows it.

The machine

Fig 1 is a card computer. Each part of it is one unit of the architecture. Press Play to run a five instruction program that adds two numbers, or press Step to run it one bus transfer at a time.

_01234567001234567890
The card on the busDrawers, keys and register windowsRails: the busThe shuttle carries one card at a time. Instruction cards and number cards share the same drawers, and the control unit fetches whichever drawer its PC window names.
0 steps

a 3 b 4
  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7

Memory, live. Green words are instructions, brown words are data. The filled address is the one in PC. The shaded slot is the drawer the shuttle is using.

The units

UnitIn Fig 1Job
InputKeypadMoves data from outside into memory.
MemoryCabinet, drawers 0 to 7Holds instructions and data. Each drawer holds one word. The drawer number is its address.
Control unitLeft half of the right case: PC window and lampFetches the next instruction, decodes it and directs the other units.
ALURight half of the right case: ACC window and crankDoes the arithmetic and logic.
OutputCard reader with a screenMoves results from memory to the outside.
BusRails and shuttleCarries one word at a time between the units.

The control unit and the ALU together form the CPU, which is why they share one case in the figure. Three registers matter for this program:

Stored program

Every drawer holds a 6 bit word. An instruction word is a 3 bit opcode followed by a 3 bit address. On the instruction cards in Fig 1, the back row of holes is the opcode and the front row is the address, one hole for each 1 bit.

OpcodeMnemonicEffect
001LOAD aACC ← M[a]
010ADD aACC ← ACC + M[a]
011STORE aM[a] ← ACC
100OUT aOutput ← M[a]
101HALTStop

The program in Fig 1, with the default inputs:

AddressWordMeaning
0001 101LOAD 5
1010 110ADD 6
2011 111STORE 7
3100 111OUT 7
4101 000HALT
5000 011Data: a = 3
6000 100Data: b = 4
7Result, written by STORE 7
Same bits, two readings. Memory does not mark a word as code or data. Address 5 holds 000 011. LOAD 5 reads it as the number 3. If PC ever reached 5, the control unit would decode the same word as opcode 000 with address 3. The only thing that makes a word an instruction is that PC points at it.

Fetch, decode, execute

The control unit repeats one cycle until it decodes HALT:

Fetch: IR ← M[PC]  ·  Decode: PC ← PC + 1, split IR into opcode and address  ·  Execute

A read copies a word and leaves the drawer as it was. A write replaces the drawer's contents. The figure shows this: the shuttle carries a copy of each card, and STORE 7 drops a new card into drawer 7. The Fetch-Execute Cycle article breaks each phase into register transfers.

InstructionMemory accessesPC afterACC after
LOAD 5fetch M[0], read M[5]13
ADD 6fetch M[1], read M[6]27
STORE 7fetch M[2], write M[7]37
OUT 7fetch M[3], read M[7]47
HALTfetch M[4]57

The von Neumann bottleneck

Adding two numbers took 9 memory accesses, and 5 of them were instruction fetches. Every one went over the same bus, one at a time. The CPU cannot fetch the next instruction while the bus is moving data.

As processors became much faster than memory, this shared path became the limit on performance. John Backus called it the von Neumann bottleneck in his 1977 Turing Award lecture. Modern CPUs work around it rather than remove it: caches keep recent words close to the CPU, separate level 1 instruction and data caches let a fetch and a data access happen together, and prefetching starts reads before they are needed.

Check your understanding

  1. Set a = 5 and b = 2. Before pressing Play, write down PC and ACC after each instruction. Then run it and compare.
  2. Suppose instructions and data had separate memories, each with its own bus. Does the program still need 9 accesses? What changes?
  3. Drawer 2 is overwritten with 000 011 before the program runs. What happens when PC reaches 2?
  4. Write a program for this machine that outputs a + a + b. Why does it not fit in 8 words unless the data moves?

Summary