Giter Site home page Giter Site logo

c128-z80-8mhz's Introduction

C128 and 8MHz Z80

With a simple daughterboard, a GAL and a 74LS74 the Z80 in C128 can run at dot clock frequency (almost 8MHz) during its 1MHz phase of the system clock, effectively doubling the speed.

Basic benchmarks written in Turbo Pascal show that indeed it is about twice faster.

CP/M is visibly snappier, to the point of being usable.

Tower of development daughterboards

This circuit works fine, during tests it was stable for several hours, busy with drawing fractals and calculating pi using Monte-Carlo method.

The CPU doesn't even get warm to the touch.

Disk I/O worked fine, as well as REU ram disk M: (emulated by UII+).

BACKGROUND

There was a message sent to cbm-hackers mailing list back in 2002, about a PCB for C128 that boosted Z80 to 8MHz

Unfortunately that device was not fully reverse-engineered and it seems that it was never mentioned again.

PREPARING C128

I haven't tried to overclock the original Z80B, I replaced it some time ago by a Z84C0020 that uses much less energy.

Following modifications can be done using bending Z80 pins and soldering to the mainboard, but having a daughterboard will keep everything tidy.

We need to isolate /WAIT input (pin 24) from the mainboard because it is tied to /NMI there. We will also disconnected from CPU the onboard CLK signal (pin 6). We will use it as an GAL input to have an option of switching between the original clock (4MHz half of the time) and fast mode (8MHz half of the time). The new CLK will be generated by GAL. We will also use few other lines from Z80 as GAL inputs.

We need two more inputs not available on the Z80 chip/Z80 socket. We want DOT CLOCK from the expansion port (pin 6) and the system clock 1MHz signal (called CLK1MHZ below and D1MHZ on C128 schematic) from U12 (pin 11).

OPERATION

This is the normal timing of Z80 in C128. During system clock CLK1MHZ low phase VIC generates two clock ticks for Z80.

Oscilloscope view of D1MHZ and Z80 CLK

We use DOT CLOCK instead to pass four ticks.

Whenever Z80 wants to read or write to/from memory or I/O we have to stop it until the start of the next 1MHz clock low phase.

Latched data from 74LS74 will hold the /WAIT line low until the end of current low phase of CLK1MHZ (Z80 turn). During the following high phase (VIC's turn) 74LS74 will stay in reset and release WAIT to inactive (high) state, but during that time we will not output any clock pulses - just like in the original setup.

I had to add a case to CLKOUT to handle memory writes. Waitstate is not enough, the CPU had to be really stopped. That's not an issue for reads because they are buffered with U12.

Here is the effect - for two clocks Z80 was running at 1MHz because of memory write, then picked up the speed:

Oscilloscope view of D1MHZ and Z80 CLK

CIRCUIT

The Kicad project is in z80-dotclock-gal-and-latch/ folder.

Schematic is also available in PDF form.

PCB

Gerber files generated from PCB project that should fit C128 and C128DCR are in z80-dotclock-gal-and-latch/gerbers/ folder.

LOGIC EQUATIONS

PLD file to be used with WinCUPL to generate JED file for programming GAL is available in two versions:

You will find there all the files generated by WinCUPL, including JED files ready to be flased to GAL devices.

They differ only in pin numbering. I just happened to have an ATF22V10 available. The circuit is ready for both options - just align pin 1 of 16V8 with pin 1 of the socket.

74LS74 and bus timing

Here is how it is supposed to work:

  1. VIC cycle phase starts, latch is in reset state, latch D input is constant 1, but due to reset Q output is 0 and negated /Q is 1; Z80 is stopped as its clock is held low
  2. Z80 cycle phase starts, latch goes out of reset, /Q output = WAITLATCH stays 1, Z80 sees that as inactive /WAIT and runs program, without bus access requests WAITTRIGGER stays 0
  3. Z80 wants to access the bus, WAITTRIGGER will rise to 1; this will cause latch D input connected to 1 be copied to the output, so /Q becomes 0, Z80 will see that as an active /WAIT and will stop
  4. This state will not change until start of the next VIC cycle phase
  5. VIC cycle phase starts, latch is reset - will set latch /Q to 1, so for Z80 /WAIT now becomes inactive; but Z80 won't run because during this half-cycle the CPU clock signal is not passed at all
  6. Z80 cycle phase starts, it can continue because after latch reset /WAIT is inactive; Z80 accesses the bus so WAITTRIGGER stays 1 until Z80 gets what it needs from data lines - then it goes back to 0

The idea of this is that during Z80 clock phase when WAITTRIGGER goes from inactive to active we can latch /WAIT line low to hold it low at least until the start of VIC cycle.

We release it before/at the start of Z80 cycle it so /WAIT becomes high again - even though the latch trigger condition is still active.

CLKOUT

The simplest way to handle CLKOUT I did was:

  CLKOUT = !DOTCLK & !CLK1MHZ;

C128 started fine, but CP/M wouldn't boot. With pieces of Z80 code I was able to confirm that this works for I/O reads and writes but only memory reads. Memory writes never happened, hence the special case with MREQ & WR.

16MHZ?

I tried using the 16MHz clock signal from VDC (pin 2) instead of dot clock.

The C128 will start, but CP/M won't boot. However all my simple tests passed. I suspect that memory access is still an issue and some of the memory writes fail.

A possible reason is that exact 16MHz signal is not a true double of the dot clock, which depends on PAL/NTSC.

If this is the reason, then one solution could be to double the dot clock using MAX9010. This idea was already mentioned on Reddit, but that circuit would never work. But it depends on specific values of R/C pair.

Using a part specifically designed for that purpose - ICS501 seems more reliable.

OPEN QUESTIONS

  1. How can we keep it simple but run at full speed all the time and stall only on memory and I/O access? It's not clear if the device mentioned in 2002 was really working at 8MHz all the time or just during Z80's turn.

  2. Since I already used ATF22V10 which has asynchronous reset for registers, it should be possible to get rid of 74LS74 with different assignment of pin 1 (GAL CLK input). I wasn't able to do it. I'm probably doing something wrong - messing up high/low vs active/inactive or my CUPL skills are lacking (they are).

  3. What is the problem with 16MHz clock? Maybe it should be created by doubling the dot clock to keep things in sync? (No need to bother if (1) is possible).

c128-z80-8mhz's People

Contributors

ytmytm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

go4retro

c128-z80-8mhz's Issues

OUTI bug present?

A C128 hardware bug: https://dr.ea.ms/c128hardwarebug.html

OUTI
OUTIR
OUTD
OUDR

Don't work on C128. A bit surprisingly they don't seem to work with 8Mhz speedup too, even though the CPU should be stopped as soon as /IORQ is requested. The test program stores only zeros to $d020 (also - why zeros?).

Test code for Double-Ass:


10  *= $8000
20  .lis s
30  .obj memory
40  sei
50  lda $d505 :pha
60  lda $ff00 :pha
70  lda #$c3  :sta $ffee
80  lda #<z80 :sta $ffef
90  lda #>z80 :sta $fff0
100 lda #$3e  :sta $ff00
110 lda #$00  :sta $d030
120 lda #$00  :sta $d020 :sta $d021
130 lda #$b0  :sta $d505
140 nop
150 pla       :sta $ff00
160 pla       :sta $d505
165 lda #$cf  :sta $ffee
499 cli       :rts
500 :
510 z80 .mod 1
515 :
520 jp testing
525 testdata:
530 .byt 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
535 testing:
537 ld de, $2000
542 outloop:
545 ld hl,testdata  ; index of the test data
550 xor a           ; zero the counter
555 tlp:
556 ld bc, $d020    ; border
560 outi            ; send test data
570 inc a           ; increment counter
580 cp 16           ; 16 bytes yet?
585 jp nz,tlp       ; no, do more
590 dec de
595 jp outloop
999 jp $ffe0        ; back to 8502

RUN and start in MONITOR: J 08000

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.