Skip to main content
NESdev Wiki
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Another example

LDA #$20 / STA $2006 Low-Level Hardware Flow

1. Instruction Overview

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

2. LDA #$20 Execution Flow

  1. 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.
  1. CPU Fetch Operand
  • CPU increments PC → next byte address.
  • PRG ROM CE active, outputs **operand `20`**.
  • CPU reads operand into instruction register.
  1. Execute LDA
  • CPU loads operand `20` into **Accumulator (A)**.
  • No external bus activity is required during execution.

3. STA $2006 Execution Flow

  1. CPU Places Address on Bus
  • CPU puts `$2006` on A0–A15.
  • Address decoder activates **PPU CE**, disables other devices.
  1. CPU Drives Data Bus
  • CPU puts **Accumulator value (0x20)** on D0–D7.
  • CPU asserts **WR (write)** signal.
  1. 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.

4. Cycle-Level Timing

InstructionCPU CycleAction
LDA #$201Fetch opcode from PRG ROM
LDA #$202Fetch immediate operand from PRG ROM
LDA #$203Load accumulator
STA $20061Place $2006 on address bus, assert PPU CE
STA $20062Place data (A=20) on data bus, assert WR, PPU latches high byte
STA $20063Next write latches low byte of VRAM address

5. NES Bus & Signal Summary

StepCPU Address BusCPU Data BusCERD/WRNotes
Fetch Opcode (A9)PCD0–D7PRG ROM CE activeRDPRG ROM outputs opcode
Fetch Operand (20)PC+1D0–D7PRG ROM CE activeRDPRG ROM outputs operand
STA $2006$2006D0–D7 = AccumulatorPPU CE activeWRPPU latches VRAM address

6. Address Decoder Mapping

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.

7. PPU $2006 Latch Behavior

  • 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

8. Diagram Overview

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)

9. Notes

  • 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.

Edit this page on GitHub