Sorry it took so long, but I’ve finally cleaned up the source code ready for publishing, and here it is. This contains a Quartus project file, so it should load and compile straight away. I used Quartus 9.1 Web Edition, available from the Altera website. There is also a pre-compiled .sof image which should work straight away if you have a DE1.
A full write-up will follow, but here is a quick summary:
The implementation is of a standard PAL 48K Spectrum. IO is via the DE1’s existing interfaces, with the video hardware able to drive either a normal TV (via RGB SCART) or a PC monitor. In the latter case the picture is double-scanned to obtain the required line scan rate. A PS/2 keyboard can be connected although you will probably need a picture of a real Speccy to work out what all the keys do! Some key combos like caps-lock and escape (BREAK) do actually work, though. Audio input and output are both available through the normal jacks, and programs can be loaded from tape or by using something like playtzx on a PC. Loading images from SD card is planned but not yet implemented.
The design runs from a PLL-derived 28 MHz clock with clock-enables used to time-slice RAM access between the CPU and video hardware. The CPU runs for one cycle in eight, resulting in the required 3.5 MHz cycle time. Note that because of this time-slicing there is no RAM or IO contention, so this is slightly faster than a real Spectrum meaning that some games and turbo-loaders don’t yet work properly. The CPU is a synchronous T80 core connected to the rest of the hardware through some address decoding and multiplexing logic. The ROM image is contained on the FPGA, but the external SRAM is used for the Spectrum’s RAM, and the entire 48K is accessed over one time-sliced bus. The address applied to the SRAM comes from either the CPU address bus or the video logic depending on whose turn it is.
On the IO side the ULA’s single IO port is implemented. The PS/2 keyboard interface applies key up/down events to an 8×5 matrix representing a real Spectrum’s keyboard. This matrix is addressed by the CPU and routed to the ULA IO port as in the real thing, so no changes to the ROM are needed. Audio is fed both ways through the Wolfson codec which has its settings loaded on reset by a simple I2C loader block. The register settings are hard-coded into this logic. A bidirectional I2S<>parallel interface is used to interface the audio bus with the ULA register. For recording (EAR in) the sign-bit from the capture side is used – some hysteresis would probably be beneficial here. Note that the audio codec has its own 24 MHz clock and operates asynchronously with the rest of the design.
Four of the slide switches are used:
- SW9 – /RESET – Down to reset, up to run
- SW8 – PLL reset – Leave this down
- SW7 – Slow mode – Allows CPU operation to be traced on the LEDs – Normally leave down
- SW6 – PAL/VGA – Down for PAL (SCART) or up for VGA (PC monitor)