Page 1 of 1

In Circuit EPROM emulator and debugger

Posted: 17 Apr 2019, 13:25
by gesari
I'm planing to use the Gigatron as a teaching tool for computer science because I think it fills very well the link between simple digital circuits, like decoders or counters, and microprocessors. The main problem for this is the EPROM. Its erasing time is too long and you have to remove it every time you want to test an student code. So, I think the first thing I'm going to do after ordering a gigatron is to design a ROM emulator to overcome the burden of EPROM erasing and programming.
ISDebug.gif (15.57 KiB) Viewed 686 times
The block diagram of such a circuit is that of the figure. Here the EPROM role is played by an equivalent SRAM, whose contents have been previously loaded by a microcontroller.

Notice that the address lines of the RAM can't be generated by the microcontroller because that would create an electrical contention with the Gigatron's PC. Address lines are always inputs to the microcontroller. The main idea here is to use the PC as an address counter and, in order to do this, the clock signal of the Gigatron is also generated by the microcontroller. It is not necessary to remove the crystal, the low impedance output of the microcontroller is going to override the clock signal.

Program ROM emulation
The PC reset is not connected here, therefore the first thing we have to do to load a ROM image into the RAM is to reset the PC by means of these operations:

1 - Put a 'LD $00,Y' opcode in the data bus.
2 - Pulse CLK.
3 - Put a 'JMP Y,$00' opcode in the data bus.
4 - Pulse CLK.
5 - put a 'NOP' opcode in the data bus.
6 - Pulse CLK.

Using a similar trick we can load any address into the PC. After reset the RAM loading is going to be done this way:

1 - Put memory content in the data bus.
2 - Pulse /WE. This stores the data in the RAM.
3 - Put a 'NOP' opcode in the data bus.
4 - Pulse CLK. This increments the PC.

After loading another reset sequence will put the PC pointing at zero. Then we can change the data lines as inputs to the microcontroller, lower the /OE signal, and start to pulse the CLK signal at maximum speed to execute the newly loaded code.


This circuit can also do a lot of interesting things. In fact, it can debug programs step by step. This means the microcontroller has to:

1 - Stop execution. No problem because we are controlling the clock.
2 - Load and save the Gigatron state. This means reading the values of the Gigatron's registers and also possibly some of the data RAM.
3 - Show the state to the user and wait for it's command.

A resume execution command will need to:

4 - Restore the Gigatron state by writing the modified registers with their original values.
5 - Continuing applying clock pulses.

Reading state

Lets see how to read the Gigatron state:

1 - The PC value can be read directly from the EPROM address bus.
2 - Executing a 'JMP Y,xx, NOP' we can get the value of the Y register in the high address lines.
3 - Executing a 'LD AC,Y, JMP Y,xx, NOP' sequence we can read the accumulator value.
4 - Executing a 'LD IN,Y, JMP Y,xx, NOP' sequence we can read the input register.
5 - The X register is more difficult to read, but not impossible. One possible way would be:

5.1 - Read the page zero data. This data is also of interest, so this step was going to be taken anyway. This is achieved by executing 256 'LD [nn],Y, JMP Y,xx, NOP' sequences.
5.2 - Write all the zero page bytes with zeros by executing a 'LD $0,AC' followed by 256 'ST AC,[nn]' instructions.
5.3 - Execute a 'LD $1,AC, ST AC,[X]' sequence.
5.4 - Read the zero page data and stop when the value read is one. The count gives us the value of the X register.

The OUT and XOUT registers can't be read, but as they are used for video/audio generation their particular value is of little interest. And the LED value can be read by just looking at the Gigatron.

Restoring state

This is going to be easier. Let see:

1- X, OUT, and XOUT registers were unchanged.
2- The page zero data has to be written with its original values. This can be done with 256 sequences of 'LD dd,AC, ST AC,[nn]'
3- The AC value is restored with a single 'LD dd,AC'
4- Then follows the PC. First compute PC-1, and then execute 'LD hh,Y, JMP Y,ll',where hh and ll are the high and low bytes of PC-1.
5- Finally we restore the Y register by executing 'LD nn,Y'. This also increments the PC, which now points to the same address it has when the execution was stopped.

More features

The contents of the program memory and data memory can be read, allowing for disassembling and memory dumps.

The first one requires to change the data pins to input in the microcontroller and to enable the /OE line of the program RAM for read. Then disable /OE, put the data pins as outputs, place a NOP in the data pins, and pulse clock for the next address.

For the data RAM any position can be read with the instruction sequence 'LD hh,Y, LD [Y,ll],AC, LD AC,Y, JMP Y,xx, NOP', where hh and ll are the high and low bytes of the address.

Breakpoints can also be implemented in two different ways:

- Address breakpoint: The PC value is read in each clock cycle, compared to the breakpoint, and if a matching is found the clock is stopped. This will slow down the clock generation, and should be restricted to a single breakpoint.

- Instruction breakpoint: First we need an unused op-code, like 'LD IN,[Y,X++],OUT' to be used as a breakpoint. Then we replace with this op-code the places of the program memory where the execution is going to stop. For each clock cycle we read the op-code at the output of the program memory and if it is a BREAK the clock is stopped. Then the original content of the program memory can be restored before resuming execution.

Clock generation

In order to run code real time a fast microcontroller will be needed. I'm thinking about using an LPC1114 (ARM cortex-M0) running at 48MHz for this project. Also, the clock signal can be mapped to a PWM output, obtaining up to 24MHz. Unfortunately, the 6.25MHz is not obtainable, but 6MHz is and I hope a -4% error in the frequency is going to be tolerated by most VGA monitors.

If the clock is generated by program its frequency is going to be lower, but still the MHz range can be achieved. We'll probably have to generate the clock while checking the address or data for breakpoints. This will require about 14 cycles of the ARM CPU per one Gigatron cycle, lowering the frequency to around 3MHz.

Re: In Circuit EPROM emulator and debugger

Posted: 17 Apr 2019, 17:39
by marcelk
Thanks, this is a promising, cool and useful project! I remember at67 built a ROM switcher one year ago, but this takes it a whole lot further...

Re: In Circuit EPROM emulator and debugger

Posted: 19 Apr 2019, 10:23
by gesari
A first schematic is attached.

Re: In Circuit EPROM emulator and debugger

Posted: 25 Apr 2019, 19:10
by gesari

I completed the layout of the board. Finally I included a 10MHz crystal to get the micro running at 50MHz, so the 6.25MHz can be obtained dividing the clock by 8.
lay_top_corner.gif (87.57 KiB) Viewed 623 times
Here you can see how the emulator gets placed on the EPROM socket of the Gigagtron. I had to make room at one corner to avoid colliding with the Gigatron's crystal. In any case long pins for the socked would be a good idea.

More figures and gerber files can be downloaded from here:

Re: In Circuit EPROM emulator and debugger

Posted: 14 May 2019, 20:56
by gesari
Today I received the PCBs for the ROM emulator.
idrd1.jpg (238.02 KiB) Viewed 561 times
And I assembled one board...
isrd2.jpg (289.4 KiB) Viewed 561 times
isrd3.jpg (260.02 KiB) Viewed 561 times
And after plugging it into the Gigatron, and of course some software tweaking, I was able to load a ROMv3 image from an SD card and to run it
isrd4.jpg (391.02 KiB) Viewed 561 times
isrd5.jpg (379.46 KiB) Viewed 561 times
There is still a lot of software to be done before getting a full featured debugger, but the basic functionality seems to be working.

Re: In Circuit EPROM emulator and debugger

Posted: 24 May 2019, 07:40
by gesari
It was hard to achieve, but I finally can run the ROM emulator at full speed (6.25MHz) with breakpoints enabled.
I had to use a NOP op-code for breakpoints because these instructions are executed before stopping the clock. This gives me an extra 8 ARM cycles to disable the PWM wave of clock, and the timing is still tight...
I choose the op-code 0x4E (OR AC,AC with [Y,X] in MAU) for the breakpoint. I hope nobody is planning to use this instruction for program ROMs...

Re: In Circuit EPROM emulator and debugger

Posted: 04 Jun 2019, 10:27
by gesari
A first working version of the ROM emulator firmware is attached here.
(37.58 KiB) Downloaded 12 times
It requires an ANSI serial terminal program like "minicom" (linux) or Hyperterminal (windows, not tested).
And the program "lpc21isp" for loading the firmware into the microcontroller.

Re: In Circuit EPROM emulator and debugger

Posted: 04 Jun 2019, 17:51
by gesari
A few terminal captures, using 'minicom -c on'
isrd1.gif (76.4 KiB) Viewed 394 times
isrd2.gif (81.13 KiB) Viewed 394 times
isrd3.gif (80.82 KiB) Viewed 394 times
isrd4.gif (80.27 KiB) Viewed 394 times

Re: In Circuit EPROM emulator and debugger

Posted: 04 Jun 2019, 20:54
by marcelk
It's nice to see very familiar code on an unfamiliar screen :-)

Re: In Circuit EPROM emulator and debugger

Posted: 14 Jul 2019, 10:15
by cmpxchg
Nice, I think EPROM emulators are great for hardware experimentation and testing changes to the ROM, as well as testing and tuning timing to other hardware interfaces.
Having both an SDcard and USB interface to change contents is great too.
Do you plan to sell boards or even kits for your gigatron project ?