Post by jmpff3d on Nov 6, 2018 16:21:32 GMT
Found this document below (in Word format) deep inside my archives.
I reproduce it here, with only a few minor spelling corrections and cleanup of the graphic insert, in the interest of C-128 Emulator authors.
*** Scanned from "Commodore 128 Programmer's Reference Guide", page 576 ***
I reproduce it here, with only a few minor spelling corrections and cleanup of the graphic insert, in the interest of C-128 Emulator authors.
Andrew J. Kroll, FTSOY priest, SAASTLA member.
While developing software for a few new C128/C64 I/O devices, which are targeted for CP/M mostly (z80 side of the c128) I have discovered a very interesting bug in the c128 and c128d with respect to the I/O timing cycle when used from the z80. I was optimizing the code to get the absolute best native transfer rate, and things stopped working. Upon looking at the C128 hardware reference guide, and comparing the timing diagrams of the Z80 CPU, I discovered that CBM missed one case as far as the translations from a Z80 cycle to an AEC cycle.
Normally, the z80 is clocked on the opposite cycle of the VIC chip, and gets to perform 2 T-cycles. While this works, it fails on but a few handy instructions. The instructions that end up out of sync with theta2 (the main clock on the 64/128 CPU bus) are:
OUTI
OUTIR
OUTD
OUDR
The reason for this is quite obvious, if one looks at the cycle timings of the instructions. The only way to get around this hardware bug is to use plain out (c),X instructions. The loss in T-states will cause a drop in performance, unfortunately. A hardware fix would involve trapping the 4 cases in hardware, and inserting a wait state on the z80.
Here is a diagram of any of the above opcodes, overlayed on an AEC access.
*** Scanned from "Commodore 128 Programmer's Reference Guide", page 576 ***
Note how the Z80 gets 2 clocks to do it's work. On the second clock, depending on the state of the read and write lines from the Z80, will depend on if data is presented to the Z80 from an on-board latch from the previous AEC cycle while it is low. If it is a write, the data is written from the Z80 via a buffer chip. This is done to synchronize with on-board I/O cycles and form a 65xx family access cycle, page 575 describes it fully.
In order to understand the effect, one needs to look at what the Z80 cycle looks like during the instruction. In plain words, without the need for another timing diagram, the each clock cycle is considered a T-state. The automatic out timing (with instruction fetch) does the following:
OUTI:
(C) <- (HL), B = B - 1, HL =HL + 1
16 T-states (4, 5, 3, 4), 4 M cycles
M1 gets the data from (HL)
M2 saves the data to (BC)
M3 decrements B
M4 increments HL
Note that M2 is an odd number. This is important, since the data won't make it to the hardware. Outputs on an EVEN cycle do.
Compare to:
OUT (C),r
(C) <- r
12 T-states (4,4,4) 3 M cycles
All 3 M cycles are EVEN, thus work! I'm not certain what M cycle does the actual work, but if you look thru the entire Z80 opcode timings, all others do the access on an even T-state count, thus they function without trouble on the C128.
All Z80 cycle counts and timing diagrams can be compared to the graphic on this page. The document is available at www.zilog.com/docs/z80/um0080.pdf