Complete 8-bit processor with all 56 instructions, 13 addressing modes, BCD arithmetic, and a 26-state control unit FSM. The heart of the Apple II, Commodore 64, and NES.
26-state FSM, instruction decoder
ADD, SUB, AND, OR, XOR, shift, BCD
A, X, Y, SP, PC, status
| Parameter | Value |
|---|---|
| Data width | 8 bits |
| Address space | 64KB (16-bit) |
| Registers | A (accumulator), X, Y (index), SP, PC, P (status) |
| Instructions | 56 unique, 151 opcodes total |
| Addressing modes | 13 (immediate, zero page, absolute, indexed, indirect, etc.) |
| ALU operations | ADC, SBC (with BCD), AND, ORA, EOR, ASL, LSR, ROL, ROR |
| Interrupts | IRQ (maskable), NMI (non-maskable), RESET |
| Control FSM | 26 states with microcode-style control signals |
The control unit FSM decodes each instruction into a sequence of micro-operations, managing the fetch-decode-execute pipeline.
class ControlUnit < RHDL::Sim::SequentialComponent
input :clk, :rst
input :opcode, width: 8
input :flags, width: 8
output :alu_op, width: 4
output :src_sel, width: 3
output :dst_sel, width: 3
output :mem_rw, :addr_sel
state_machine :phase,
clock: :clk, reset: :rst,
states: [
:fetch_opcode,
:fetch_low,
:fetch_high,
:execute,
:write_back,
# ... 21 more states
] do
transition :fetch_opcode => :fetch_low
transition :fetch_low => :fetch_high,
when: needs_high_byte?(opcode)
transition :fetch_low => :execute,
unless: needs_high_byte?(opcode)
end
end
The ALU handles all arithmetic and logic operations, including BCD mode for decimal arithmetic used in financial calculations.
class ALU6502 < RHDL::Sim::Component
input :a, width: 8
input :b, width: 8
input :carry_in
input :bcd_mode
input :op, width: 4
output :result, width: 8
output :carry, :zero,
:negative, :overflow
behavior do
raw = case_select(op, {
0 => a + b + carry_in, # ADC
1 => a - b - ~carry_in, # SBC
2 => a & b, # AND
3 => a | b, # ORA
4 => a ^ b, # EOR
5 => a << 1, # ASL
6 => a >> 1, # LSR
})
result <= mux(bcd_mode,
bcd_adjust(raw), raw)
zero <= result.eq?(0)
negative <= result[7]
end
end
The instruction decoder maps all 151 opcodes to their instruction type, addressing mode, and cycle count using a lookup table generated from the 6502 opcode matrix.
class InstructionDecoder < RHDL::Sim::Component
input :opcode, width: 8
output :instr, width: 6 # 56 instructions
output :addr_mode, width: 4 # 13 addressing modes
output :cycles, width: 3 # base cycle count
# Decode using opcode matrix pattern:
# bits [1:0] = group (cc), [4:2] = operation (aaa), [7:5] = mode (bbb)
behavior do
cc = opcode[1..0]
aaa = opcode[4..2]
bbb = opcode[7..5]
instr <= decode_instruction(cc, aaa)
addr_mode <= decode_addr_mode(cc, bbb)
cycles <= base_cycles(addr_mode)
end
end