Grant Searle (http://home.micros.users.btopenworld.com) came across a timing issue with the CLKWait signal when building a Harlequin Clone with the HCT family of chips.
What he found was some instability with the action of memWait on the clock during a contended memory access:
"With waitGen-1.14, when MREQ is pulled low, the clock is pulled back up as quick as possible. This however results in a clock-low which is quite a bit shorter than the 110nS minimum in the datasheet. As a result, I'm never sure if the brief clock has resulted in a clean T-state. waitGen 1.13 had it delayed so there wasn't this problem, as it occurred in the high clock time, and there weren't the shortened lows. That version was more stable for me.
I'd also noticed that this was occurring, but I hadn't seen it becoming a problem, and began to expect it in my traces...
A complete analysis of the problem is therefore needed, and for that a look at the Z80 signals involved:
|Memory Access||IO Access|
Consider an access to the lower 16K of memory that begins whilst the display is being updated, memWait is low and IOWait is high (memory access diagram above). Consider also the waitGen circuit.
waitGen relies on the address bus alone to determine whether or not there is any memory contention. However, it does use MREQ to select the appropriate contention pattern: Memory or IO.
Our address of between 0x4000 - 0x7FFF appears on the address bus at the rising edge of T1. Because the display is being updated, waitGen tried to generate a CLKWait signal immediately. However, this is before MREQ has gone low, so IOWait is incorrectly selected - and is at that time HIGH, making CLKWait inactive. MREQ goes low just after the downward clock transition of T1 causing MEMWait to be selected, and the clock to be suddenly pulled high.
This results in a very short clock low half cycle, and as MREQ goes low at most 85ns after the falling edge of the clock, means that the clock will be low for at most 85ns. This is too short, and the design of waitGen never intended for this to happen anyway.
If we make sure that the memWait and IOWait transitions are synchronised with the next clock transition, then we can avoid CLKWait being generated anywhere but at a clock edge.
IOWait has already been synchronised with the clock transitions in an effort to maintain overall clock phase during an IO operation (IOREQ goes low for an incomplete number of cycles). This design feature was quickly obsoleted by instead generating the clock from a stable 3.5MHz source, HC0. The delay of IOWait has however remained in place.
Thus previous analysis of memWait's timing, which caused up to seven contended cycles, was therefore incorrectly interpreted.
The reason that CLKWait comes out too long when MEMWait is delayed by half a cycle, is that is picks up the IOWait when 0x4000-7fff appears on the address bus before MREQ goes low (the switch over), adding to the start of the wait. As we're delaying the end of memWait by half a cycle as well, we also lengthen the end: resulting in an overall longer wait signal.
If we shorten the MEMWait by one cycle, and then add the half cycle delay, it will finish on the positive edge of the 6th cycle instead of the positive edge of the 7th.
To shorten MEMWait we can take the AND of C7 in addition to C0 and C1
IO contention will only select IOWait, and so CLKWait generated from it will always be the correct length,
The revisions to the wait generator are shown in waitGen version 1.15.