retro-silicon

Components

cpu/6502

NMOS 6502, cycle-exact on the bus, with optional decimal mode

Portable Sim: passing (18 passed). Used by Nintendo Entertainment System. Source.

BoardStateRun
Sipeed Tang Nano 20Kverified2026-10-28, at ac84cec
Sipeed Tang Console 138Kverified2026-10-25, at f2536e6
TUL PYNQ-Z2verified2026-10-28, at ac84cec

Verified: the latest run on that board of a system using it passed every test, and the component hasn't changed since. Stale: it has changed since that run.

README

An NMOS 6502 that is cycle-exact on the bus: one access per CPU cycle, including the original’s dummy reads and writes, so memory-mapped hardware sees what it would on the real chip. The NES’s 2A03 is this CPU with DECIMAL = 0; the Atari 2600’s 6507 and the C64’s 6510 keep decimal mode.

Module cpu_6502 (the folder name can’t start a module name).

Timing

Ports

PortDirWidthMeaning
clk, rstin1Clock; synchronous reset, after which the CPU runs its reset sequence (three dummy stack reads, then the vector at $FFFC)
cein1One CPU cycle per clock with ce high
addrout16This cycle’s address
weout1This cycle writes dout
doutout8Data written
dinin8Data read, needed by the edge that ends the cycle
rdyin1Low stalls the CPU on read cycles; writes always complete
irq_nin1Interrupt request, level-sensitive, active low
nmi_nin1Non-maskable interrupt, falling-edge-sensitive
syncout1This cycle fetches an opcode
haltedout1A JAM or unsupported opcode stopped the CPU; only reset restarts it
dbg_pc, dbg_a, dbg_x, dbg_y, dbg_s, dbg_pout16, 8Registers, for traces; P as PHP pushes it but with B clear
st_addr, st_rdata, st_we, st_wdata2, 32, 1, 32Save-state port (below)

Parameters

ParameterDefaultMeaning
DECIMAL1NMOS decimal mode, including its flag quirks (ADC: N and V from an intermediate result, Z from the binary sum; SBC: binary flags). 0 for the NES’s 2A03, where ADC and SBC are binary whatever D says

Save state

The port follows docs/conventions.md: four words, readable and writable while ce is low, mid-instruction included.

WordHolds
0A, X, Y, S (A in bits 31-24)
1PC, then the internal address register
2Opcode, data latch, base address low, then N V D I Z C, page-cross, RMW carry
3Bits 1-0 phase, 4-2 cycle, 6-5 interrupt source, then interrupt go and snapshot, IRQ and NMI samples, NMI pending, NMI vector

Opcodes

Every official opcode, and the stable unofficial ones: LAX, SAX, DCP, ISC, SLO, RLA, SRE, RRA, ANC, ALR, ARR, AXS, SBC $EB and the NOPs. The JAM opcodes, and the unstable ones (XAA, LAX #imm, AHX, SHX, SHY, TAS, LAS), stop the CPU with halted set.

Status

Sim tests:

On a Tang Nano 20K, in systems/nes: nestest’s 26,554 cycles give the same bus-trace CRC as the sim bench (harness/golden/nes_trace_crc32.txt).

Gaps:

About 2,500 LUTs and 110 flip-flops on a GW2A-18C with DECIMAL = 0; not optimised yet.

References