The ZX Spectrum Reverse Engineering and Clone Desgin Blog


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

< 67 of 68 >

Stable Running

May 15, 2008

In an attempt to remove any noise or ground bounce from the implementation, I hooked up a 40 pin DIL socket directly above the CPLD breakout board to act as a plug, turned the whole thing upside down and inserted it into the ULA socket.

Click on image to enlarge

This immediately made a big difference as the Spectrum now resets and initialises perfectly every time! Currently only the RED video signal and CSync are hooked up to the TV, producing a very simple mono composite video output.

Running some tests

I ran through a number of tests, particularly those which crashed the machine in earlier tests:

  1. BEEP 1,10 (20 30)
  3. SAVE "TEST" CODE 1,2048
  4. LOAD ""
  5. The Snow Effect

Most of these tests exercises IORQ, RD and WR lines excessively, the Snow Effect test exercises a particularly aggressive and uncontended MREQ condition.

The results of the tests were interesting, but not perfect.

  1. BEEP 1,20

    This test showed some slight artifacts in the border at the boundary between the left border and main display rectangle. The number of these and the rate at which they move up and down depends on the frequency of the BEEP.


    This test worked as expected, with no crashing.

  3. SAVE "TEST" CODE 1,2048

    This test worked as expected, but the data being output has not been validated.

  4. LOAD ""

    This test corrupted the screen memory immediately after the LOAD was executed, and the machine crashed.

  5. The Snow Effect

    Corrupted the screen memory and crashed the machine.

Investigating The Failures

Writing to port 0xFE to control the speaker should not affect the screen border if the same RGB value is written to the port each time. The fact that an intermittent RGB value is being written to the port a fraction of a second before the video display memory is output, points to a problem in this area.

Just before the video display rectangle is output, the ULA takes control of the video memory and its data bus. If an out instruction to port 0xFE is in progress during this time, then it will be held until after the first four bytes have been read from memory. Cycle T2 of IO is contended during the video update, which results in WR or RD being held low for the duration of this video memory access.

It appears that if an OUT to port 0xFE is made just as as the CPLD is about to read from the video memory, then the CPLD appears to miss the value being OUTput by the CPU and instead sees the value being read from video memory. Looking at the CPLD implementation I notice that I have used Latches to store the border RGB value and not edge triggered flip-flops. This is incorrect, as the latch output will follow the input whilst the enable input is active, only storing the value when the enable goes inactive. So, an OUT occurring just as the CPLD accesses the video memory will be contended at T2 until the video access is complete. WR will remain low during this period, so the latch output, and hence border RGB value, will follow the data bus during this time.

Replacing the latches with positive edge triggered flip-flops obviously cures the problem, and is more correct.

The LOAD failure must be related to the BEEP failure, in that an IN is being executed rapidly. The same contention model applies, and RD will be held low for the duration of the contented IN. A combination of RD and ZXIOREQ (A0 + IORQ) will enable the CPLD bus output (outputting keyboard and EAR values) at a time when the CPLD is reading from the video memory, thus having two devices driving the bus. It's interesting that this causes a crash, as an opcode fetch occurs after the IN has finished. It probably causes some instability in the CPLD, and who knows what the 4116 DRAM is going to do.

Gating the output buffers with the nVMemEN will pull their active-high enable lines low during video memory access, stopping the CPLD from trying to load the data bus during a contended IN.

The Snow Effect also causes the machine to crash. It is understood how the snow effect works, so I hooked up the scope to see where the CPU RFSH occurs, and how this relates to the video RAS and CPU RAS. In doing so, I noticed that a CPU RAS was not being generated for a RFSH that occurred during a video memory access. Examining the CPU RAS and CAS generation showed that nVMemEN was incorrectly being used to pull the CPU RAS high during CPLD video memory access, potentially causing short RAS pulses that would destabilise the 4116 DRAM. The 4116 specification says that a RAS pulse must be a minimum of 150ns.

Removing the nVMemEN from the CPU RAS/CAS generation prevents the crash, and the Snow Effect works as expected.

A selection of programs should be loaded into the Harlequin-ified Spectrum as a final test, once a simple cassette interface is wired up.