The ZX Spectrum Reverse Engineering and Clone Desgin Blog

Harlequin

A site dedicated to the reverse engineering of the ZX Spectrum and related projects.

< 56 of 68 >

Clock Alignment and Stability

Oct 07, 2007

There are several areas of the Harlequin design that seem to work well in my prototype but not for other people, indicating some propagation delay sensitivity, also the exact timing of floating bus read has yet to be established. I've done a lot of investigation over the last few weeks, and the following improvements and clarifications are the result.


Wait Generator Alignment

The previous Blog entry introduced a memory contention model that matches the ULA exactly, and removes the need for two different cpu contention controls. Whilst designing the wait generator to incorporate these changes, I paid some attention to the timing of the contention period, wait generator and CPU clock. This is important to ensure that the wait-request signal is never activated or deactivated while the CPU clock is low.

The control signals generated by the Harlequin change state on the downwards transition of the CPU clock, which is half-way through a CPU clock cycle, but most importantly when it is going low. As DEN and memIOWait are both used in the wait generation, their transitions must be held until the next positive transition of the CPU clock.

The wait generator uses the product of DEN and memIOWait, so we can delay this product instead of the individual signals by passing it through a D-type flip flop, clocked by CLK7. This will delay the signal until the next CLK3.5 transition, which in our case will be the positive transition.


Clock and Floating Bus Alignment

As we're examining the timing of the CPU clock, a look at how it relates to the floating bus byte fetches would be useful. We currently delay the CPU clock by approximately 14ns by delaying it until the next positive Clk14 edge (half a Clk14 period is 35ns, but the clock is already delayed by 8-10ns or so) and this extra delay may not be necessary, or now desirable.

First a look at when IOREQ becomes inactive. A quick examination with the oscilloscope shows this to be 32ns after the CPU clock goes low - at least with the Zilog CMOS Z80A used in the Harlequin. The IO read will therefore take place approximately 32ns after the falling edge of the CPU clock during T3 of an IO instruction.

The timing of this read point is significant if the expected floating bus video values are to be returned. If it is too early then the data bus may not have stabilised; if it is too late we may be into the next byte fetch. Remember that the Harlequin control signals are aligned to the downward CPU clock transition, so AL1 will go low half-way through one CPU clock cycle and then high half-way through the next. As an IO read takes place 32ns after the falling edge of the CPU clock, the exact time relationship between the clock going low and AL1-2 going high is critical for a stable floating bus read.

The following scope picture shows the relationship between Clk3.5 going low and AL1 going low, this time difference is the same for Clk3.5 going low and AL1 going high, as AL1 is one clock cycle wide.

Note: Clk3.5 has been sampled directly from HC0 without any additional delay from Clk14, currently performed by clock-1.12.pdf.

The difference between the point when the signals start to go low is 22ns, however the rise and fall times are quite slow, 25ns or so.

The above trace shows the relationship between AL1 and Clk14, naturally the time difference is a little longer than with the Clk3.5 measurement, in this case by approximately 4ns, but as the clock trace is a little uneven it is difficult to track the start of the downward edge.

This diagram shows the relationship between the two clock signals. Interestingly the time offset comes out at 8ns, not 4ns as implied by the difference between the first two diagrams, but this should just be sampling error. The Clk3.5 edges are later than Clk14 due to the way it is produced - Clk14 is divided to give Clk7 which drives the horizontal counter, producing HC0 which we use as our Clk3.5 signal; each step adding it's own propagation delay.

Essentially the control signals AL1-2 and the related signal DEN start and end approximately 22-26ns after the downwards transition of Clk3.5, and have a slow rise and fall time.

The Z80 samples the bus during an IO instruction approximately 32ns after the falling edge of the clock, and based on the results above this happens while AL1, for example, is going high. The timing is perfect as the video byte is read by the video circuit on the rising edge of AL1. If the Clk3.5 transition had been later it may have read the next video byte as it was being deposited on the bus; if it had been very much earlier, the databus may not have been stable with the expected byte. I think it is safe to say that we can tolerate Clk3.5 being marginally earlier, but any later and we start moving into an unstable region.

Again, as stated above, these measurements were made without the delay of Clk3.5 (see also clock-1.12.pdf).


Identifying the IO Sample Point

I wanted to locate the exact point the floating bus read takes place during a byte-fetch, to be absolutely sure that it is at the end of the fetch and not at the start. To do this I wired up a 12bit 4040 counter clocked on the negative edge of Clk14 and reset by DEN being high. Using DEN ensures that the counter begins at the start of display row. The output of the counter is routed to the databus via a buffer activated on IOREQ + RD + A1 being low. To locate the exact bytefetch cycle, I read port 253 at the same T-state as the video byte fetches to return the value of the counter (using Ramsofts FloatSpy). This revealed how many Clk14 edges had occurred since DEN went low. By repeating the experiment with Clk14 instead, being 180° out of phase to Clk14, I could pinpoint the IO read to within half a 14MHz period, or 35ns.

The diagram below shows the timing discussed above, and the test-counter clock points labelled in red at the negative clock edges.

Reading T-state 14339 with the test-counter clocked by CLK14 returns the value 4, doing the same with CLK14 returns a value of 3. This places the IO read at somewhere between the two points labelled 4 on the diagram above. As an IO read occurs when IOREQ is going high, or just after, this also places IOREQ in this region. We know that IOREQ goes high 32ns after the falling edge of the clock, so we can be more precise here. Therefore the IO read of the floating bus occurs during the rise period of AL1-2.

Note: The CLK14 clocked values are later than the CLK14 values because the counter is held in reset mode until DEN goes low, approximately the same time as AL1 goes low. This prevents the CLK14 downwards transition nearest AL1 from being detected.


Idle Floating Bus Stability

During these tests the first idle floating bus value read after the four video bytes occasionally returned a value that was almost, but not quite 0xFF as should have been expected. Previously the CPU clock was delayed slightly so that the databus is sampled after it has had time to reach 0xFF. Ideally we don't want to delay the clock at all as this will decrease stability in other areas, as identified above. The alternatively then is to make the databus rise faster by reducing the value of the databus pull-up resistors a little, to pull the databus up harder, and a change from 10K to 8K2 works nicely. In fact, referring to the ZX Spectrum schematics shows Sinclair using 8K2 resistors for the databus pull-up.

The revisions to the Clock, cpuControl and waitGen schematics may be found in the schematics version 1.16.