ZX Spectrum on an FPGA

Introduction

The Speccy was the first computer I ever used. We had the 48K rubber key version, and it probably only had to share the living room TV with 3 channels when we first got it. I still have it in my possession and it is still fully functional, although it has few original parts – I repaired it a couple of years ago, requiring the replacement of the CPU, ROM and most of the DRAM. Luckily the ULA was still alive!

Manic Miner in-game screenshotSeveral years ago I implemented most of the 48K ULA in VHDL on a MAX7000 CPLD, mainly as an exercise to brush up on my HDL. I didn’t have enough space to fit the keyboard interface so it was pretty useless, but it did boot! The complete system used a pair of SRAMs, real Z80 and the Sinclair ROM in flash.

Back at the beginning of last year I decided to brush up on my HDL again and I bought myself an Altera DE1 development kit. The heart of this board is a Cyclone II FPGA with a range of support hardware including 512 KB SRAM, 8 MB SDRAM, 4 MB Flash, an I2S audio codec, VGA port and the usual switches, LEDs and buttons. I would highly recommend it for anyone looking for a relatively cheap way to play with FPGAs.

This is an implementation of the complete ZX Spectrum for the DE1 board. It can be configured to synthesise a 48K, 128K or +2A model, and it has a ZXMMC+ compatible interface. ZXMMC+ allows programs to be loaded from SD card, and it also allows extra RAM and Flash to be paged in over the top of the ROM. This feature makes it possible to run ResiDOS.

Architecture

All of the Spectrums used a Zilog Z80A CPU running at roughly 3.5 MHz (there is some variation between the different models). The display was generated by a custom Ferranti ULA, which was also responsible for the cassette interface and beeper. In the 128K models and later there was additional logic to handle bank switching, as well as the familiar AY-3-8912 sound generator.

16K/48K

In the earliest Spectrum model the memory map is completely linear. The first 16 KB is the ROM and the second 16 KB is a bank of DRAM which is shared with the ULA. The ULA takes priority, so CPU accesses to this region are slower than to the uncontended parts of the memory map. The 48K model has a further 32 KB of RAM in the upper half of the address space.

The ULA also presents a single IO port, nominally on port 0xFE, but actually visible at all even IO addresses (the Z80 has separate IO and memory address space). Writes to the port control the beeper, tape output and the colour of the screen border. Reads provide access to the keyboard and to the tape input.

128K

The 128K Spectrum adds a simple write-only paging register at port 0x7FFD, again incompletely decoded and actually appearing on all odd ports with A1 and A15 clear. Writes to this register select one of eight 16 KB banks of RAM to appear in the top quarter of the address space, with two of the banks also permanently accessible at 0×4000 and 0×8000. A further bit controls which of two 16 KB ROMs appears at the bottom of the memory map.

Proper sound hardware is also present – a General Instrument AY-3-8912, which was also found in many other machines at the time.

Spectrum +2A boot menu

Spectrum +2A boot menu

+2A/+3

The last of the Spectrums, the +2A and +3 were essentially the same machine but with the +3 adding a 3” disk drive. These were Amstrad machines, being made after the 1986 sale of the rights to Sugar’s company, and were styled similarly to the Amstrad CPC range of machines.

Hardware was comparable with that of the 128K Spectrum, with additional IO ports decoded for access to the floppy disk controller (where fitted) and to another paging register giving access to special paging modes. Two more ROM banks, four in total, were needed for the DOS and other extra features, although these are implemented as a pair of 32 KB ROMs in the real hardware.

Display

In all the machines the display is bitmapped 256×192 with an 32×24 attribute plane. The bitmap plane selects whether each pixel is displayed as background or foreground colour, and the attribute plane allows foreground and background colour, bright and flashing modes to be selected for all pixels within the corresponding 8×8 square.

The design allows for display of up to 15 different colours on screen at once for less than 7 KB of display memory, but results in the blocky “two colours per 8×8 square” style that makes Spectrum screenshots so easy to spot.

FPGA

The original DE1 implementation that I published last year supported only the 48K Spectrum. This has now been extended to support the 128K models as well, and SD card support has been added using logic compatible with the ZXMMC interface. The particular model to be synthesised can be selected using VHDL generics.

The design fits into 3252 Cyclone II logic elements in its most complex configuration (compiled on Quartus 9.1), and requires 32 Kbits of on-chip RAM for lookup tables if the 128K sound is included. The ROMs are now accessed out of the external Flash device and must be programmed using the DE1 tools prior to loading the Spectrum design.

CPU

The CPU is included on the FPGA and uses the T80 from OpenCores with fixes from Pace Dev.

Clocks

A 28 MHz master clock is used to allow the video to run out of phase with the CPU and other peripherals. This makes it possible to time-slice access to the SRAM, eliminating the contended memory present in the real Spectrum, but also necessary because the RAM here is in a single chip connected over a single bus.

Memory

The external SRAM is accessed over a 16-bit interface to enable the full 512 KB to be addressed. The first 128 KB is used for the Spectrum’s internal RAM, and the upper 256 KB is made available through the ZXMMC+ interface. The remaining 128 KB is not mapped.

Flash is accessed over a separate 8-bit interface and mapped in to the bottom 16 KB of address space. Different pages are selected depending on the type of Spectrum that was synthesised, and the condition of the ROM select bits in the paging registers, where applicable. Extra banks can also be used via the ZXMMC+ feature.

Display

The video logic generates an address for the SRAM on alternate clock phases, enabling it to fetch display data without interrupting the CPU. Attribute and bitmap data are assembled to produce the necessary RGB bitstream to drive the monitor, along with the related timing signals. In areas of active video that lie outside of the bitmapped screen area the logic generates a constant “border” colour, the particular colour of which is held in a 3-bit latch accessed through the single ULA register.

DE1 Spectrum

ZX Spectrum on Altera DE1

IO

Bus routing and address decoding are handled at the top level along with the paging registers present if synthesising one of the higher-end models. All the ports are incompletely decoded in the same way as in the real Spectrum.

Sound

The codec I2S signals are converted internally to 16-bit parallel buses for both input and output. A simple state machine drives the I2C bus necessary to program the required register settings into the codec when the board is first reset.

The beeper, present in all versions of the Spectrum, is driven by toggling a bit in the ULA register in software. The value of this bit drives the sign bit of the output to the Wolfson audio codec. Sound from the AY-3-8912 (actually a YM2149 core from FPGA Arcade) is mixed in as well.

The sign of the I2S input value is used to drive the EAR input in the ULA register to enable loading from tapes. A simple comparator and latch arrangement is used to provide a small amount of hysteresis to improve noise immunity.

Keyboard

The Spectrum keyboard is row-scanned by the 8 upper address bits, with 5 column outputs fed into the ULA and appearing as the bottom 5 bits in its only register. This topology is mimicked here by using an array of 5-bit registers, the appropriate one presented to the ULA depending on the value on the address bus. Further logic is used to set or clear bits in the registers according to press/release codes from the PS/2 keyboard interface.

Some key combinations (caps lock, backspace, escape and the cursor keys) are decoded into the required combination of keys automatically. The SHIFT keys operate CAPS SHIFT, and the CTRL keys operate SYMBOL SHIFT.

ZXMMC+

The latest release of the design supports access to the DE1′s SD card interface using logic compatible with the ZXMMC+. This also allows an additional 256 KB of both RAM and Flash to be paged in. Software support for SD cards is available through modified ROMs for the +2A and +3 computers (+3e by Garry Lancaster), and through an operating system extension called ResiDOS. More information about ZXMMC and ResiDOS (which is also supported) can be found on their respective websites.

Interfacing

The ULA implementation includes extensions to drive a VGA monitor directly (not through a scan doubler). Alternatively, a PAL TV can be connected through a SCART lead connected to the DE1′s VGA port. In this mode the HSYNC pin generates PAL compatible CSYNC and a small wire-mod is required in order to connect +5V to pin 9 of the VGA connector, which is in turn connected to pin 16 of the SCART plug. The need for the wire mod is historical and will be removed in a future release.

Beeper, tape and AY sound are all available on the green line-out connector, and the blue line-in connector can be used to load programs from a tape player (or from a PC running something like PlayTZX).

The PS/2 port needs to be connected to a PC keyboard.

ROMs

The Spectrum ROMs can be obtained from an emulator package and need to be loaded into the DE1′s Flash at the following addresses:

Offset ROM
0×00000 48K (Sinclair Research)
0×04000 Blank
0×08000 128K 0 (Sinclair Research)
0x0C000 128K 1 (Sinclair Research)
0×10000 +3 0 (Amstrad), or +3e 0 (Garry Lancaster)
0×14000 +3 1 (Amstrad), or +3e 1 (Garry Lancaster)
0×18000 +3 2 (Amstrad), or +3e 2 (Garry Lancaster)
0x1C000 +3 3 (Amstrad), or +3e 3 (Garry Lancaster)

A further 16 banks of 16 KB starting at 0×40000 can be paged in over the normal ROM using the ZXMMC+ feature.

If you want to use the +3e ROMs to access the SD card then you can download the bundle from World of Spectrum.  The mmcen3eE.rom image can be written to 0×10000 in one go, as it contains all four of the +3 ROMs.

Switches

Some of the switches on the DE1 affect the operation of the design:

  • SW9 controls system reset (up to run)
  • SW8 is used with the debugger, which is normally disabled
  • SW7 selects PAL mode (down) or VGA mode (up)
  • SW1 selects boot from normal ROM (down) or ZXMMC+ banks (up)
  • SW0 selects ZXMMC+ boot from RAM (down) or Flash (up)

Known Issues

Cycle accuracy – there is no memory contention and the CPU core doesn’t match the timing of the real Z80. This causes problems with games (and particularly demos) that do high-resolution colour by changing the attribute values at precise times. Multi-colour border effects also suffer.

Running “ulatest3” results in an immediate reset. This is suspected to be a CPU issue but has not been investigated extensively at this stage. Fixing this needs to happen before contention emulation can be considered.

The design currently fails timing, apparently due to the way in which the YM2149 is implemented. It seems to work alright, though.

Credits and Links

The following VHDL cores were used in the design:

These pages were of use during development and may be of interest:

Downloads

Leave a comment

23 Comments.

  1. Nelson Antonio Gomes

    Hello Mike, first of all congratulations for the project! I am having trouble trying to write the roms in flash DE1? What is the procedure? I have to use control panel DE1? If that’s how I do? Thank you very much! Nelson.

  2. Hello Nelson,

    Yes you need to use the control panel tool that came with the DE1 board. One of the tabs allows you to write a binary file to the flash at a specific location. You need to erase the flash first, then you can either join the ROM images into one file and write that once, or you can write the individual files one at a time.

    For the control panel to work you need to have the right logic loaded on the board. My board came with this pre-loaded in EEPROM, so it would normally boot in this mode (the LEDs will be flashing). If you have re-programmed the EEPROM you will need to use Quartus to load the correct bitstream first from a .sof file. Here is the .sof file (note – this is an external web site that I can’t vouch for, but it worked for me).

    Mike

  3. Nelson Antonio Gomes

    Hello Mike,
    Thank you very much! Now Worked!
    Regards,
    Nelson.

  4. Nelson Antonio Gomes

    Hello Mike,
    Please, how do you write residos in flash? Because every time I turn off the DE1 residos disappear
    Thanks,
    Nelson.

  5. I guess you could use the DE1 tool to copy the contents of the SRAM bank into one of the extra flash banks, but I have a feeling that Residos may actually need to run from RAM, so maybe it’s not possible.

    I contacted Garry Lancaster to ask permission to redistribute Residos on this site (which he gave – I just haven’t got round to uploading it yet). Maybe if there is enough interest he would produce a ROMable version.

  6. Nelson Antonio Gomes

    Hello Mike, a ROMable version could be a solution!

    But, Thank you!
    Nelson.

  7. Hello Mike.
    .. I need some help .. :-)
    I’ve connected the Altera De1 via USB. I wrote the ROM +3 mmcen3eE.rom at 0×10000 address via DE1 control panel and after I programmed the unit via the Quartus software.. I’ve controlled the switches position, but nothing happens … :shock: .. Could you please help me ?!

  8. Hi there. The hardware should generate video once you set SW9 to the UP position, even if nothing else is working. Most things that could go wrong would give you random colours on the screen.

    Are you using a TV or VGA monitor? Does the monitor do anything at all when you release reset?

  9. Hi.
    I’m using a VGA monitor.
    My steps are the following:
    1) I set up the unit to PROG position.
    2) I turn on the unit. (USB-blaster OK).
    3) I erased the EEPROM (chip erase).
    3) I wrote the ROM +3.
    - (DE control panel, flash tab, sequential write (address 0×10000, length 0, file lenght selected)
    4) I programmed the Altera DE1 via Quartus v.11 (JTAG).
    All seem to be ok.
    After I turned off the unit. (Is it correct?).
    I set up the unit to RUN position.
    I turned on the Altera DE1.
    I see the led flashing and a colored squares on the monitor. :-) Nothing happened…
    :roll:

    Nothing happen when I release the reset switch..
    M.

  10. I did have trouble making it work from EEPROM so try running it from RAM first. Try the .sof file from downloads page and load it directly using the Quartus programmer. The RUN/PROG switch should be in the RUN position at all times. Set the other switches to: SW9 UP, SW7 UP (for VGA), SW1 DOWN, SW0 DOWN. As soon as the programmer finishes downloading you should see the Spectrum boot. If you see a border with coloured squares then either your ROM is bad or not flashed properly, or you have SW1 in the wrong position.

  11. Thanks.. now is a little better!
    I see the “wrong” spectrum boot (small colored squares and a border around).. so, I think that I’ve probably a wrong 48k rom, or I’m not able to flash the SDRAM correctly.. :-)
    Thanks a lot for your support!
    M.

  12. Hi Mike.
    Are the ROMs from this site good for using with the Altera DE1 Project ?
    LINK : http://www.shadowmagic.org.uk/spectrum/roms.html:roll: , or I need something else?

    Thanks in advance!
    M.

  13. Now is all OK !!!!!!!!
    It’s running….
    ;-)
    Thanks !
    M.

  14. Hi Mike,
    i flashed the mmcen3eE.rom into the DE1 Flash as you described. The core shows on its startscreen : 0 flopyy, 1 MMC Logical Drives: M.
    In +3 Basic the cat command No files found
    58K free. It doesnt´matter wether a sd card is inserted or not. The SD card contain some spectrum files and works without problems with other cores which has sd access. I tried several different sd cards.
    Do you have i idea what could be the problem ?
    Dirk

  15. The card has to be specially formatted using IDEDOS, then you can use a utility to copy files to it from Windows. It is supposed to be possible to read FAT formatted cards using a plugin, but I haven’t tried it.

    Look at “Setting up your disk” in the +3E documentation: http://www.worldofspectrum.org/zxplus3e/
    Remember that the contents of the card will be wiped out!

    Windows GUI and +3 tool (download separately and extract in the same directory): http://www.angelfire.com/games6/atari2600/spxfr/3eStrowSaw.html

  16. Thank you very much for your fast help.
    Now its works for me.
    But i found another issue.
    After loading The Hobbit, the program stays in the start screen. It continous only when pressing a cursor key or shift lock. Same behavoir after painted a graphic screen.
    On a real spectrum “The hobbit” needs pressed any key.

    Dirk

  17. Hello Mike,
    it seems to everythimg is OK afetr Programming but my VGA_monitor gives me an error: not supported signal can I do something with the timig?

    Regards
    Michael

  18. Hello Michael.

    Assuming you don’t just have switch 7 in the wrong position then you are probably out of luck. I have found that some VGA monitors don’t seem to support the required 50 Hz VGA mode – I think this is particularly the case with cheaper widescreen TFTs.

    As the video and CPU run on separate clock phases you should be free to mess with the timing. If you reduce the blanking time, for example, you may be able to get the refresh rate up to 60 Hz which is more likely to work on awkward monitors.

    Mike

  19. Hello Mike,

    you are right, it was the frequency. I found a monitor that runs with 50Hz. Thanks a lot. Your Sinclair-Project is really great. I built my first Sinclair-Clone in 1983.

    I wish you a merry Christmas
    Michael

  20. Hi!
    ZX Spectrum 48K (rubber key version) was also my first home computer, back in 1985. Besides playing games I started learninig BASIC since i had it as facultative class in primary school (although experimental at that time)…Those were the days!
    2 years later I replaced it with 128K version

  21. Hi.

    Myself and another chap are currently in the feasibility/Early stages of putting a Memotexh MTX512 onto a FPGA board.

    Having looked at your website I was VERY impressed at what you’d done for the ZX Spectrum!

    However we are having some timing issues and incompatibility problems with the T80. As it seems not to work like a true Z80A!

    I wondered if it was possible to ‘pick’ your large Brain and get some hints on what may be the problem ??

    Any guidance and help would be much appreciated.

    Kind Regards

    Lez

  22. Hi Lez,

    This sounds interesting like an interesting project. You are correct about the T80 not being cycle accurate, although it is not something I have had time to look into yet. I think a major problem with achieving perfect timing when modelling these old devices is that many of them are wholly or partly asynchronous in their design. With the speeds at which modern FPGAs operate it is an absolute necessity to keep the design completely synchronous, and this necessarily introduces extra clock cycles that can affect the relative timing of different operations.

    You should also take a look at the ZX Prism, as I know that Jeff has spent some time investigating timing accuracy.

    Mike

Leave a Reply


[ Ctrl + Enter ]