Another example
Instruction sequence:
LDA #$20 ; Load immediate value 0x20 into accumulator
STA $2006 ; Store accumulator to PPUADDR register
Purpose: Sets the PPU VRAM address via $2006 register.
Key hardware involved:
- CPU (Ricoh 2A03)
- PRG ROM
- NES Address Decoder
- PPU (Picture Processing Unit)
- System buses: Address (A0–A15), Data (D0–D7)
- Chip Enable (CE) and Read/Write (RD/WR) control signals
- CPU Fetch Opcode
- CPU places **PC** on address bus (A0–A15).
- NES address decoder asserts **PRG ROM CE**.
- PRG ROM outputs **opcode `A9`** on data bus (D0–D7).
- CPU reads opcode into instruction register.
- CPU Fetch Operand
- CPU increments PC → next byte address.
- PRG ROM CE active, outputs **operand `20`**.
- CPU reads operand into instruction register.
- Execute LDA
- CPU loads operand `20` into **Accumulator (A)**.
- No external bus activity is required during execution.
- CPU Places Address on Bus
- CPU puts `$2006` on A0–A15.
- Address decoder activates **PPU CE**, disables other devices.
- CPU Drives Data Bus
- CPU puts **Accumulator value (0x20)** on D0–D7.
- CPU asserts **WR (write)** signal.
- PPU Latches Data
- PPU detects **CE active + WR active**.
- Internal $2006 latch:
* First write → high byte of VRAM address
* Second write → low byte of VRAM address
- Flip-flop tracks first/second write for scrolling & VRAM updates.
| Instruction | CPU Cycle | Action |
|---|---|---|
| LDA #$20 | 1 | Fetch opcode from PRG ROM |
| LDA #$20 | 2 | Fetch immediate operand from PRG ROM |
| LDA #$20 | 3 | Load accumulator |
| STA $2006 | 1 | Place $2006 on address bus, assert PPU CE |
| STA $2006 | 2 | Place data (A=20) on data bus, assert WR, PPU latches high byte |
| STA $2006 | 3 | Next write latches low byte of VRAM address |
| Step | CPU Address Bus | CPU Data Bus | CE | RD/WR | Notes |
|---|---|---|---|---|---|
| Fetch Opcode (A9) | PC | D0–D7 | PRG ROM CE active | RD | PRG ROM outputs opcode |
| Fetch Operand (20) | PC+1 | D0–D7 | PRG ROM CE active | RD | PRG ROM outputs operand |
| STA $2006 | $2006 | D0–D7 = Accumulator | PPU CE active | WR | PPU latches VRAM address |
CPU A0–A15 → NES Address Decoder → CE signals:
$0000–$1FFF → Internal RAM
$2000–$2007 → PPU registers
$4000–$4017 → APU / I-O
$8000–$FFFF → PRG ROM
- Only one device drives the data bus at a time to prevent conflicts.
- First write → high byte of VRAM address
- Second write → low byte
- Internal flip-flop tracks write sequence
- Important for scrolling, raster effects, and VRAM access timing
PRG ROM
| (D0–D7) <-- CE active
v
CPU (Accumulator, PC)
| (A0–A15)
| (D0–D7)
v
NES Address Decoder
|----> PPU CE active -> PPUADDR latch (high/low byte)
|----> Other CE inactive (tri-state)
- CPU cycles, CE activation, and bus usage are critical for timing-sensitive NES operations.
- Mirroring and PPU latch behavior affect scrolling and background updates.
- This low-level understanding is useful for NES hardware emulation, demo scene effects, and precision programming.