My very first 6502 SBC, more simulation than machine, is back from the board house, built up and works.
It's a 3-chip system with a real 6502 and two AVRs simulating the address space. The DIP40 AVR ran out of pins necessitating the twin-AVR solution. The system features:
- An Admin UART to control ( single step, trace bus state, upload ROM, reset) the system from a laptop. There is some funky potential such as simulating ( really slowly) bus devices over the Admin UART, or running tests on the 6502 by controlling the system like a puppet
- Simulated bus devices:
- Up to 15K of RAM. The ATmega128 has 16K but needs some for itself. I currently have this as 8K of RAM at $0000 and 4K of "ROM" at $f000
- Up to 128K ( minus the size of the master AVR firmware) of ROM ( simulated from program memory - not implemented yet because I haven't finalised my ROM)
- 4K of EEPROM ( not implemented yet)
- SPI ( The register file is 65SPI compatible except for the slave select register)
- UART ( simulated on the ATtiny2313 complete with a 16-byte RX queue)
- Timers ( not implemented yet. Timers on the master would need an SPI exchange to interrupt since the slave drives IRQB. Timers on the slave will have unusual periods because of the UART-friendly 18M432 system clock)
- Blitter ( not implemented yet - the master AVR could copy around chunks of RAM must faster than the 6502)
- The ATmega128 has a hardware multiply that could be made available as a bus device
Because all 16 bits of the address bus and 8 bits of the data bus are decoded by the master AVR, few pins remain. PHI2, RWB, MOSI, MISO, SCK, RX and TX for the Admin UART and the /SS for the slave AVR account for the rest. The slave AVR is in control of RESB, IRQB, the SS* lines on the SPI bus and the 6502-driven UART.
Here's the bus trace after powering up:
Code:
Initialization in progress..
PHI2: L, ADDR: 0000, RWB: L, DATA: 00
PHI2: H, ADDR: ea00, RWB: H, DATA: ea
PHI2: L, ADDR: ea00, RWB: H, DATA: ea
PHI2: H, ADDR: ea00, RWB: H, DATA: ea
PHI2: L, ADDR: ea00, RWB: H, DATA: ea
PHI2: H, ADDR: ea00, RWB: H, DATA: ea
PHI2: L, ADDR: ea00, RWB: H, DATA: ea
PHI2: H, ADDR: ea00, RWB: H, DATA: ea
PHI2: L, ADDR: ea00, RWB: H, DATA: ea
PHI2: H, ADDR: ffff, RWB: H, DATA: ea
PHI2: L, ADDR: ffff, RWB: H, DATA: ea
PHI2: H, ADDR: ea01, RWB: H, DATA: ea
PHI2: L, ADDR: ea01, RWB: H, DATA: ea
PHI2: H, ADDR: 0100, RWB: H, DATA: ea
PHI2: L, ADDR: 0100, RWB: H, DATA: ea
PHI2: H, ADDR: 01ff, RWB: H, DATA: ea
PHI2: L, ADDR: 01ff, RWB: H, DATA: ea
PHI2: H, ADDR: 01fe, RWB: H, DATA: ea
PHI2: L, ADDR: 01fe, RWB: H, DATA: ea
PHI2: H, ADDR: fffc, RWB: H, DATA: 00
PHI2: L, ADDR: fffc, RWB: H, DATA: 00
PHI2: H, ADDR: fffd, RWB: H, DATA: ff
PHI2: L, ADDR: fffd, RWB: H, DATA: ff
PHI2: H, ADDR: ff00, RWB: H, DATA: 4c
PHI2: L, ADDR: ff00, RWB: H, DATA: 4c
PHI2: H, ADDR: ff01, RWB: H, DATA: 00
PHI2: L, ADDR: ff01, RWB: H, DATA: 00
PHI2: H, ADDR: ff02, RWB: H, DATA: ff
PHI2: L, ADDR: ff02, RWB: H, DATA: ff
PHI2: H, ADDR: ff00, RWB: H, DATA: 4c
The simulated ROM contains:
Code:
$f000: JMP $f000
..and the RESB vector is $f000 just to prevent the 6502 running amok before a ROM is uploaded via the Admin UART and these things can be seen in the trace above. Also above, the WDC65C02S does seem to access the stack just prior to the RESB vector but doesn't write at any point.
When I'm developing the ROM, the workflow is:
- Press F9 in my editor, which runs "make", which assembles the ROM to /tmp/ROM.prg
- A daemon that I call "dude" after avrdude notices that /tmp/ROM.prg has been changed and uploads the ROM via the Admin UART. The .prg format allows me to place the ROM where I like
- "dude" then resets the system via the Admin UART, the ROM runs and happy boot messages come from the 6502 via the slave UART
- I can then interact with the 6502 via the slave UART like it's a real system!
This is what the system looks like so far:
Code:
Neil's 6502 SBC R1
15K RAM SYSTEM
READY
SP:ff
> t ; Does a BRK #ea so I can test the stack manipulation magic
SP:fd ; 2 bytes less because of a JSR
SP:f7 ; 6 bytes of retaddr, status, A, X and Y from the BRK
> r
f160 A:74 X:24 Y:2e S:fd --1B-I--
> df160
f160 brk #ea
f162 lda #62
f164 jsr f00d
f167 jsr f2bf
f16a jsr f3ec
f16d sta 23
f16f jsr f3ec
f172 sta 22
> ih ; Interpret as hex rather than instructions
> d01c0
01c0 ea ea ea ea ea ea ea ea
01c8 ea ea ea ea ea ea ea ea
01d0 ea ea ea ea ea ea ea ea
01d8 ea ea ea ea ea ea ea ea
01e0 ea ea 31 30 34 34 65 64
01e8 33 63 33 33 20 4f f4 19
01f0 f2 07 08 f2 2f f1 a2 f0
01f8 2e 24 74 34 62 f1 a2 f0
>
The system is very slow ( I guess about 250 kHz) although it's fast enough to feel nice and responsive using the monitor over the serial port.
I feel like a bit of a heretic next to you lot with your crystal oscillators and address decode logic but this system is more capable than I expected and I'm having a lot of fun writing a machine-code monitor for it. I'll also be able to develop SPI peripherals and write 6502 drivers for them that will work on "real" machines later on.