2023-09-02
This is the approach I have decided upon.
- Use GAL chips to mop up the small-scale TTL logic
- Merge ZX81 and G007 logic together
- TTL chip for keyboard input buffer
- TTL chip for NOP driver
- TTL chip parallel-to-serial shift register (74HC165)
- 8K "Shoulders-of-Giants" ZX81 BASIC fixes some bugs and improves speed.
- 2K G007 firmware
- 2K ZX81 monitor
- 16K ROM containing all the firmware above
- 32K RAM expansion
- 1K,2K,8K or 32K RAM on ZX81 side
- GAL chip for memory decoder
- GAL chip for slow mode NMI generator, normal or square pixels
This has the following advantages
- Single ROM instead of BASIC plus graphics ROM.
- BASIC is pre-patched, so G007 patch at 3CXX is free.
- 4K G007 ROM space holds G007 and Monitor firmware, or a larger graphics ROM.
- CMOS static RAM can be battery backed.
The memory map should look like this:
/* RAM onboard: a a a a a a a a 1 1 1 1 1 1 5 4 3 2 1 0 9 8 00h,02h 0 0 0 0 0 0 x 0 ZX81 RAM patches at 00XXh and 02XXh 0x20 0 0 1 0 0 x x x G007 RAM (2k space) 0x30 0 0 1 1 0 x x x Spare RAM ROM unified: 0x0c 0 0 0 0 1 1 0 0 ZX81 ROM patch 0x28 0 0 1 0 1 x x x G007 ROM (2k space) 0x38 0 0 1 1 1 x x x Spare ROM RAM expansion: 0x40 0 1 0 x x x x x RAM expansion (8k) 0x40 0 1 x x x x x x RAM expansion (16k) 0x80 1 x x x x x x x RAM expansion (above 32k) Intermediate terms: */ RAM_patches = !a15 & !a14 & !a13 & !a12 & !a11 & !a10 & !a8 ; ROM_8k_at_0000h = !a15 & !a14 & !a13 ; RAM_2k_at_2000h = !a15 & !a14 & a13 & !a12 & !a11 ; ROM_2k_at_2800h = !a15 & !a14 & a13 & !a12 & a11 ; RAM_2k_at_3000h = !a15 & !a14 & a13 & a12 & !a11 ; ROM_2k_at_3800h = !a15 & !a14 & a13 & a12 & a11 ; /* The terms above simplify if you wish to minimise logic: */ RAM_at_2000h_and_3000h = !a15 & !a14 & a13 & !a11 ; ROM_at_2800h_and_3800h = !a15 & !a14 & a13 & a11 ; /* However I shall leave them unsimplified so they can be modified more easily: */ /* Drive pins: */ RAM_expansion = mreq & a15 // at 8000h, above 32 + mreq & a14 // at 4000h or C000h RAM_onboard = mreq & RAM_2k_at_2000h + mreq & RAM_2k_at_3000h; /* NB if onboard RAM is 8K or less, then RAM at 00XX and 02XX are aliased at 20XX and 22XX respectively. If you have more, then they are not, and the higher addresses are free for your use. */ ROM_unified = mreq & ROM_8k_at_0000h & !(RAM_patches) + mreq & ROM_2k_at_2800h + mreq & ROM_2k_at_3800h ; /* NB the logic above will probably expand to something like: */ ROM_unified_alt = + mreq & ROM_8k_at_0000h & a11 // 1000h + mreq & ROM_8k_at_0000h & a10 // 0800h, 1800h + mreq & ROM_8k_at_0000h & a8; // 0400h, 0600h, 1400h, 1600h /* So the memory address decoder uses 9 inputs and 3 outputs in: A15...8 !mreq out: ROM_unified RAM_onboard RAM_expansion That leaves 10 pins, up to 7 outputs and 3 inputs or 1 output and 9 inputs. */ memory_refresh = mreq & rfsh; /* clocks a D-type latch to set text or high-res mode */ pixel_latch = graphics_mode & mreq & cpu_clk ; pixel_output = graphics_mode & rfsh ; force_nop_2 = graphics_mode & m1 & A15 ; _rd = rd & a15 + rd & a14 + rd & something ; u9a_latch_d = mreq & _rd & force_nop_2 ; u9a_latch.d = u9a_latch_d; u9a_latch.ar = u9a_latch_d; d7 = _d7 ; d6 = _d6 ; d7.oe = _rd ; d6.oe = _rd ; _d7 = d7 ; _d6 = d6 ; _d7.oe = u9a_latch ; _d6.oe = u9a_latch ;
I suspect the RAM patches may not need to be RAM, but I want to keep it working as near to the original for compatibility reasons.
2023-09-07
Spent a long time thinking.
I think I can get the memory decoder working in a way compatible with the G007 board.
Ian Bradbury's design uses an ATV750 which is like two 22V10 chips in one package, and each output macrocell can have its own clock and set/reset signals.
His logic makes much use of the latter, which is useful because the ZX80 circuit also has multiple clocks and set/reset signals. For that reason I am currently keeping the 74HC74 D-type latches.
The HSYNC logic of the ATV750 will not fit in a 22V10, so I decided to use a 74HC393 counter and a 22V10.
At this point I wonder if I am actually saving much by using PAL chips, but I am saving many chips and even more if I integrate the pixel graphics board as well.
Andy Rea's ULA replacement design is interesting. There is no /RFSH signal to the ULA so obviously this has to be recreated inside. Andy uses a 3-bit counter that is reset by the /M1 signal and clocked by twice the CPU clock. We know when refresh occurs after /M1, and thus when to force a NOP instruction on the bus.
It seems there are several ways to implement the ZX81 logic.
2023-09-08
Had look at my genuine original ZX81 board to see why it was not working.
I printed out the circuit and went to work with a meter and highlighter pens.
I noticed that some of the data lines do not connect between the RAM and the ROM.
Either my meter is faulty or many connections are faulty.
Have the solder joints started going dry from age?
With this many faults, I'm considering buying a replacement because this will be cheaper in the value of my time.
Meanwhile, I shall set it aside and proceed with using the ZX80 board, which is at least running ZX81 BASIC.
I suspect I was in the middle of modding my boards to use a single ROM, and didn't leave it in a working condition.
2023-09-10
Installed WinCUPL on an old Intel i3 laptop. It is slow, but maybe upgrading it to an SSD might fix that. Right now, compiling small GAL chips is not a processor-intensive task.
I started it compiling logic so I shall be able to try some experiments soon.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.