Table of Contents
Overview
This project is an open-source in-circuit emulator for the 6502, 65C02, Z80, 6809 and 6809E 8-bit processors, built using an off-the-shelf programmable hardware device called a GODIL that can be purchased for just over $50. The device plugs into your CPU socket, replacing the CPU, and you can control it over a serial connection to debug your software or hardware.
What is In Circuit Emulation?
Here's Wikipedia's definition of in-circuit emulation:
In-circuit emulation (ICE) is the use of a hardware device or in-circuit emulator used to debug the software of an embedded system. It operates by using a processor with the additional ability to support debugging operations, as well as to carry out the main function of the system.
Here's a concrete example of how this might be used in practice...
Imagine you collect old computers as a hobby. You have just procured an old BBC Micro on eBay that was sold as "untested". You plug it in and all you get is a blank screen and the long beep of death. You stare at the circuit board for a while, re-seat a few chips that are socketed, probe around with an oscilloscope, but nothing obvious leaps out. If something subtle is preventing the host processor from executing code, it's often hard to know where to start. This is where an in-circuit emulator comes into its own, because it doesn't require the host system to be fully functional to be useful.
You unplug the 6502 processor (which is in a 40 pin DIP socket) and plug in the GODIL loaded with ICE-T65 design. ICE-T65 contains a fully functional 6502 processor, plus a second arduino compatible processor running an interactive debugger application via an independent serial port.
Now you have a set of powerful debugging tools at your disposal:
- You can run memory tests on the host RAM
- You can compute CRCs over the hosts ROM (and compare these with values from known good ROMs)
- You can peek or poke host I/O devices, or host memory, or even the screen
- You can set break points on certain pieces of code being executed, or certain memory locations being accessed
- You can disassemble bits of the host memory, do memory dumps, etc.
- You can reset the 6502 processor and single step through the operating system as it initialize
- You can even inspect the 6502 processor registers while it is stopped
In-circuit emulation is useful not only for fixing dead computers, but also if you are just trying to debug existing code, or develop new code. Most people now develop for old computers using software emulators. Most of the time these are great, but sometimes you hit issues that only show up on the real hardware. Or maybe you have some third-party hardware extension or device that isn't supported by the software emulator. This is where an in-circuit emulator will help.
The key difference between a software emulator and an in-circuit emulator is that the latter actually uses the real system, and just replaces the original processor with an alternative implementation that is usually cycle accurate, and has extensive debugging capabilities.
If this interests you, then please read on....
What is a GODIL?
This project uses an off-the-shelf hardware platform, a GODIL, which can be purchased here for just over $50:
https://shop.trenz-electronic.de/en/TE0261-00-GODIL40_XC3S250E-DIL-FPGA-module-40-pin-DIL
The GODIL includes a Xilinx XC3S250E FPGA, SPI FLASH ROM, power supply regulators and 3.3V-to-5V level shifters, all in a 40-pin DIL Package.
What makes the GODIL attractive for a multi-platform emulator is the GND and VCC power supply pins can be configured with links to be any combination of the 40 pins on the DIL. This allows it to exactly match the original pinout of any of the supported target processors. It is the only off-the-shelf solution that has this characteristic.
This project contains three versions of the in-circuit emulator, for the three processor families supported:
- ICE-T65 targets the 6502 and 65C02
- ICE-T80 targets the Z80
- ICE-6809 targets the 6809 and 6809E
Here's a picture of the ICE-T65 installed in a BBC Micro:
The grey cable is connected to the Xilinx programmer, which would not normally be needed.
You interact with the emulator via a terminal program on a PC.
Here's a sample session:
ICE-T65 In-Circuit Emulator version 0.72
Compiled at 13:40:03 on Nov 15 2015
8 watches/breakpoints implemented
Tracing every 1 instructions while single stepping
CPU free running...
Interrupted
12.941332: FE82 : BNE FE78
>> break ff3f
Ex Brkpt set at FF3F
>> watchw b003
Mem Wr Watch set at B003
>> watchr b400 fffc
Mem Rd Watch set at B400
>> c
CPU free running...
Ex Brkpt hit at FF3F
Interrupted
00.000007: FF3F : LDX #17
>> s
Stepping 1 instructions
00.000009: FF41 : LDA FF9A,X
>> s
Stepping 1 instructions
00.000013: FF44 : STA 0204,X
>> s
Stepping 1 instructions
00.000018: FF47 : DEX
>> s10
Stepping 10 instructions
00.000020: FF48 : BPL FF41
00.000023: FF41 : LDA FF9A,X
00.000027: FF44 : STA 0204,X
00.000032: FF47 : DEX
00.000034: FF48 : BPL FF41
00.000037: FF41 : LDA FF9A,X
00.000041: FF44 : STA 0204,X
00.000046: FF47 : DEX
00.000048: FF48 : BPL FF41
00.000051: FF41 : LDA FF9A,X
>> c
CPU free running...
00.000886: Mem Wr Watch hit at FF61 writing B003 = 8A
00.056218: Mem Rd Watch hit at E0AF reading B400 = 55
00.056350: Mem Rd Watch hit at E0AF reading B400 = AA
00.056481: Mem Rd Watch hit at E0C3 reading B400 = 55
00.057841: Mem Rd Watch hit at E64F reading B400 = 00
00.058495: Mem Rd Watch hit at E05E reading B400 = FB
Interrupted
15.408102: FE7B : BEQ FE85
>> watchw b400 fffc
Mem Rd Watch, Mem Wr Watch set at B400
>> c
CPU free running...
Ex Brkpt hit at FF3F
Interrupted
00.000007: FF3F : LDX #17
>> c
CPU free running...
00.000886: Mem Wr Watch hit at FF61 writing B003 = 8A
00.066079: Mem Wr Watch hit at E0A4 writing B400 = FE
00.066200: Mem Rd Watch hit at E0AF reading B400 = 55
00.066211: Mem Wr Watch hit at E0A4 writing B400 = FE
00.066332: Mem Rd Watch hit at E0AF reading B400 = AA
00.066342: Mem Wr Watch hit at E0B8 writing B400 = FE
00.066463: Mem Rd Watch hit at E0C3 reading B400 = 55
00.066479: Mem Wr Watch hit at E640 writing B400 = 80
00.067823: Mem Rd Watch hit at E64F reading B400 = 00
00.068356: Mem Wr Watch hit at E053 writing B400 = F0
00.068477: Mem Rd Watch hit at E05E reading B400 = FB
Interrupted
15.905846: FE7D : INC B000
>> crc c000 cfff
crc: D67D
>> test 2800 3bff
Memory test: Fixed 55: passed
Memory test: Fixed AA: passed
Memory test: Fixed FF: passed
Memory test: Fixed 00: passed
Memory test: Checkerboard: passed
Memory test: Inverse checkerboard: passed
Memory test: Address pattern: passed
Memory test: Inverse address pattern: passed
Memory test: Random: passed
Memory test: Random: passed
Memory test: Random: passed
>> d ff3f
FF3F : LDX #17
FF41 : LDA FF9A,X
FF44 : STA 0204,X
FF47 : DEX
FF48 : BPL FF41
FF4A : TXS
FF4B : TXA
FF4C : INX
FF4D : STX EA
FF4F : STX E1
>> d ff3f
FF3F : LDX #17
FF41 : LDA FF9A,X
FF44 : STA 0204,X
FF47 : DEX
FF48 : BPL FF41
FF4A : TXS
FF4B : TXA
FF4C : INX
FF4D : STX EA
FF4F : STX E1
>> m f000
F000 50 4C 4F 54 F5 4E 44 52 41 57 F5 42 4D 4F 56 45 PLOT.NDRAW.BMOVE
F010 F5 46 43 4C 45 41 52 F6 7B 44 49 4D F0 AE 5B F2 .FCLEAR.{DIM..[.
F020 A1 4F 4C 44 F5 31 57 41 49 54 F1 4C C5 50 A4 5E .OLD.1WAIT.L.P.^
F030 B1 05 C9 40 90 12 C9 5B B0 0E C8 D1 05 D0 09 20 ...@...[.......
F040 8B F0 20 4F C9 4C 62 C9 4C 24 CA A2 FF A4 5E C6 .. O.Lb.L$....^.
F050 5E B1 05 C9 40 90 09 C9 5B B0 05 C8 D1 05 F0 25 ^...@...[......%
F060 A4 5E E8 C8 BD 00 F0 30 0C D1 05 F0 F5 E8 BD FF .^.....0........
F070 EF 10 FA D0 EB 85 53 BD 01 F0 85 52 84 03 A6 04 ......S....R....
F080 E6 5E 6C 52 00 20 8B F0 4C F1 C3 C8 84 03 E9 40 .^lR. ..L......@
F090 48 20 BC C8 68 A8 B5 15 0A 36 24 0A 36 24 18 79 H ..h....6$.6$.y
F0A0 EB 02 95 15 B5 24 79 06 03 95 24 B0 D7 60 A5 01 .....$y...$..`..
F0B0 05 02 F0 22 20 34 C4 90 1E 20 BC C8 CA CA 86 04 ..." 4... ......
F0C0 B4 16 38 A5 23 99 21 03 75 17 85 23 A5 24 99 3C ..8.#.!.u..#.$.<
F0D0 03 75 26 4C 19 F1 00 A4 03 B1 05 C9 40 90 F7 C9 .u&L........@...
F0E0 5B B0 F3 C8 D1 05 D0 EE E9 40 48 C8 84 03 20 BC [........@H... .
F0F0 C8 68 A8 A5 23 99 EB 02 A5 24 99 06 03 CA 86 04 .h..#....$......
>> m ff00
FF00 C9 03 F0 34 C5 FE F0 2E AD 0C B8 29 0E F0 27 68 ...4.......)..'h
FF10 2C 01 B8 30 FB 8D 01 B8 48 AD 0C B8 29 F0 09 0C ,..0....H...)...
FF20 8D 0C B8 09 02 D0 0C A9 7F 8D 03 B8 AD 0C B8 29 ...............)
FF30 F0 09 0E 8D 0C B8 68 60 AD 0C B8 29 F0 B0 F4 A2 ......h`...)....
FF40 17 BD 9A FF 9D 04 02 CA 10 F7 9A 8A E8 86 EA 86 ................
FF50 E1 86 E7 A2 33 9D EB 02 CA 10 FA A9 0A 85 FE A9 ....3...........
FF60 8A 8D 03 B0 A9 07 8D 02 B0 2C 01 B0 50 11 AD FE .........,..P...
FF70 BF 29 10 F0 0A A9 83 8D FE BF 6C FE 7F EA EA 20 .)........l....
FF80 D1 F7 06 0C 0F 41 43 4F 52 4E 20 41 54 4F 4D 0A .....ACORN ATOM.
FF90 0A 0D EA 58 84 FD 4C 00 E0 EA 00 A0 EF F8 52 FE ...X..L.......R.
FFA0 94 FE 6E F9 E5 FA AC C2 AC C2 EE FB 7C FC 38 FC ..n.........|.8.
FFB0 78 C2 85 FF 68 48 29 10 D0 06 A5 FF 48 6C 04 02 x...hH).....Hl..
FFC0 A5 FF 28 08 6C 02 02 48 6C 00 02 6C 1A 02 6C 18 ..(.l..Hl..l..l.
FFD0 02 6C 16 02 6C 14 02 6C 12 02 6C 10 02 6C 0E 02 .l..l..l..l..l..
FFE0 6C 0C 02 6C 0A 02 20 E3 FF C9 0D D0 07 A9 0A 20 l..l.. ........
FFF0 F4 FF A9 0D 6C 08 02 6C 06 02 C7 FF 3F FF B2 FF ....l..l....?...
>> watchr fffc
Mem Rd Watch set at FFFC
>> watchr fffd
Mem Rd Watch set at FFFD
>> c
CPU free running...
00.740964: Mem Rd Watch hit at FE7D reading FFFC = 3F
00.740964: Mem Rd Watch hit at FE7D reading FFFD = FF
Ex Brkpt hit at FF3F
Interrupted
00.000007: FF3F : LDX #17
>>
Within the emulator, there are the following components:
- reclocking logic
- target processor core: 6502, Z80 or 6809
- custom bus monitor logic
- 512 word deep event FIFO
- support processor core: an arduino-compatible AVR8 soft core
- AVR8 Firmware, written in C, and compiled into FPGA Block RAM
Here's a more detailed block diagram showing the emulator hardware design. The signals on the left are brought out to the pins of the GODIL, and this is how it connects into the system under test.
Regardless of the target processor, the capabilities and command set of the emulator is roughly the same:
The emulator provides the following feature set:
- instruction breakpoints (which pause the target processor)
- memory read/write breakpoints (which pause the target processor)
- instruction watches (which are non-intrusive)
- memory read/write watches (which are non-intrusive)
- breakpoints and watches optionally support an address mask, so can cover a block of addresses
- single stepping/tracing every N instructions
- live disassembly when single stepping
- read/write individual target memory locations
- display the processor registers
- hex/ascii dump of a block of host memory
- disassembly of a block of host memory
- calculate a CRC of a block of host memory
- destructive memory test of a block of host memory
- two external trigger inputs, which can be used independently or can be used to make a breakpoint/watch conditional
- a 24-bit processor cycle counter (that is accurate even when single stepping/paused with breakpoints)
Some links:
- Stardot thread: http://stardot.org.uk/forums/viewtopic.php?f=44&t=9655
- 6502.org thread: http://forum.6502.org/viewtopic.php?f=4&t=3323
GODIL Hardware (now obsolete)
XC6SLX9 Mini Board (eepizza)
Tutorials:
User Manual
Hardware design notes
Software design notes