ZX Spectrum on FPGA


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, although I was a bit too young to remember its actual arrival! 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.


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.


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.


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 0x4000 and 0x8000. 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


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.


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.


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.


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


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.


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.


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


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.


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.


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.


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.


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.


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
0x00000 48K (Sinclair Research)
0x04000 Blank
0x08000 128K 0 (Sinclair Research)
0x0C000 128K 1 (Sinclair Research)
0x10000 +3 0 (Amstrad), or +3e 0 (Garry Lancaster)
0x14000 +3 1 (Amstrad), or +3e 1 (Garry Lancaster)
0x18000 +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 0x40000 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 0x10000 in one go, as it contains all four of the +3 ROMs.


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:


Update 2016-01-13: The files are now also available on GitHub

85 thoughts on “ZX Spectrum on FPGA

  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. Mike Post author

    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).


  3. Nelson Antonio Gomes

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

  4. Mike Post author

    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.

  5. Massimino Boccardi

    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 … 😯 .. Could you please help me ?!

  6. Mike Post author

    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?

  7. Massimino Boccardi

    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 0x10000, 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…

    Nothing happen when I release the reset switch..

  8. Mike Post author

    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.

  9. Massimino Boccardi

    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!

  10. Dirk

    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 ?

  11. Mike Post author

    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

  12. Dirk

    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.


  13. Michael

    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?


  14. Mike Post author

    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.


  15. Michael

    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

  16. Silvestar

    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

  17. Lez Anderson


    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


  18. Mike Post author

    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.


  19. Kamikadze

    congratulations for you project! I’m trying to do something similar, ZX Spektrum 48K emulator for Xilinx Spartan 3 board but I have a problem with T80 processor core (synchronous with clock enable T80se). I’ve noticed you used the same CPU core so I’d like to ask you for a little help if possible. When I’m watching the CPU work in ISim, most of the instructions work well but at least one doesn’t.
    First I run operation LD HL, 8011 which stores 8011 address into HL register. This operation works well. Then I run LD (HL) 02 which should write 02 into address 8011 stored in HL register. 02 is written into DO address, both MREQ_n and WR_n goes to 0 but the adress on adress bus is undefined (UUUU). This operation is very important, it’n one of the earliest instructions stored in ZX Spectrum 48K ROM and cant run without it. I tried many version of T80 including version from open cores, your project, your link to “T80 Z80 core with fixes” etc but every version doesnt work the same way 🙁 I’m almost sure the problem is in T80 processor so I think you had to struggle with this too.

    I will appreciate any help.

    King regards

  20. Mike Post author

    Have you tried running it on hardware yet? The simulator will be very strict about when it generates undefined (UUUU), but on real hardware the undefined inputs will take a default value. Maybe it will just work? It certainly isn’t something I had any problem with on Altera, and I think there are others using the same core on Xilinx.

    I assume you have written a test-bench to run the CPU in the simulator? Do make sure you are driving all the unused inputs to 0 or 1, otherwise that may explain the undefined outputs.

    You will certainly find that the synchronous T80 is not completely cycle-accurate, but this won’t prevent the computer from booting. It does break some games and demos, though.


  21. Kamikadze

    Thank you very much for your help. Yes I’ve written a test bench and I watched the signals. Every other instruction I tried seems to work fine. I did make sure myself all unused input signals are tied to 1.
    I also tried hardware implementation. First few instructions read from 16K ROM work fine. I get to address 11DC when RAM is loaded with 0x02 (vertical red lines (ink) on black background (paper). I know it works because I can properly see it on my LCD. But soon after that some problems occur and screen starts to be crazy (unexpected colors and other bugs, anomalies are different every time). Interesting fact is no input except clock signal and reset button is connected to the project (keyboard block is not implemented yet) so I think the problem is caused by wrong T80 core but I don’t know how to verify this when you say test bench is not reliable.

    Thank you very much for your help

  22. Mike Post author

    The crazy colours thing is something I have come across, caused by a problem with the RAM timing in my case. Are you sharing the RAM between ULA and CPU in the same way that I am (accesses on different clock phases), or do you have a different scheme?

    Assuming you are using an external SRAM make sure you re-register all the control signals as well as the address bus. I had problems where the write strobe would be skewed relative to the address, which would occasionally result in data corruption. The skew was tiny – almost invisible on a 100 MHz scope – but enough to be a problem. Of course this re-registration leads to an extra cycle delay, which is why I output the video address during CPU cycles and the CPU address during video cycles. Search for “Synchronous outputs to SRAM” in spectrum_de1.vhd.

  23. Kamikadze

    Let me thank you once more for all your advices, I really appreciate them. I’ve been working on my project for a few hours again and it seems you were right — the simulator isn’t absolutely reliable and the CPU seems to run well. I found a mistake in my VGA block. I read VGA data for printing first sign when pixel_x = 0 but this state lasts for a really long time (because of synchronization). I fixed this issue and now I got to state when the screen is white and there’s a black text 1982 Sinclair Research on the bottom of the screen.
    If I’m right the Spectrum is waiting for some key to be pressed and after that I will be able to see flashing cursor and my written text/commands. I tried to import my PS2 keyboard block but it doesn’t seem to work. I have a counter running at same clock as T80 (3,5 MHz) counting to 69888 (~20 ms on 3,5 MHz clock). Then I set INT_n to 0 and wait for 32 T states. Then I raise INT_n back to 1 and count again (these numbers I read in book The ZX Spectrum ULA: How to Design a Microcomputer). So I think INT_n generator is fine and T80 should call keyboard scanning routine. I write data from keyboard to DATA_IN bus of T80 if MREQ_n = ‘1’ and IORQ_n = ‘0’ and RD_n = ‘0’. I’m not sure if this condition is correct. The memory/PS2 keyboard block is in my opinion fine, solo it runs well both in simulation and hardware (switches = address bus, LEDs = D_IN bus).

  24. Kamikadze

    it seems I’ve successfully dealt with all the problems. I got almost fully working ZX Spectrum 48K emulator on Xilinx Spartan 3 board, yesterday I played Pac-Man (i use TZX tape images). Last thing missing is sound system and decoding for a few TZX ID blocks. Thank you very much for your help with T80 processor.

  25. Mike Post author

    Glad to hear you made some progress and sorry I never got chance to reply sooner. Looking forward to seeing a write-up! Are you loading the tzx images over a tape interface using something like playtzx or did you implement something to load them directly?

  26. Ben

    Heh, having recently got a DE1 board this is quite interesting. The most annoying thing is my monitor happily displays the video output while having a big “Unsupported” box on the screen. My other monitor refuses to output anything. At least it works 🙂

    I wondered, how did you get started with FPGAs, I’ve spent a while messing around with other peoples projects, Zet, your two and some others but don’t know where to start myself.

  27. Ben

    Hmm, and my TV also refuses the signal. I did try reducing the blanking period although I just managed to make the screen dark..I don’t really know what I’m doing 😛

  28. Mike Post author

    Hi Ben. The video output is quite true to the real thing, which was not particularly PAL compliant. It should work fine with a CRT television in PAL mode, but YMMV with a flat screen because it will depend on how picky the video decoder is. The VGA mode is simply a double-scanned version of the TV line timings (so each line is scanned out twice in half the time). This results in a 50 Hz VGA signal that one of my TFT monitors has no problem displaying, but another newer one refuses. I suspect that any issues your TV might have with PAL mode would be because it is non-interlaced. Perhaps modifying the vertical sync logic to generate the necessary half line offset on alternate fields would solve that problem. There shouldn’t really be any change to the display as long as the same video data was output on each field. To get the VGA mode to work with newer monitors it would be necessary to implement a framebuffer to decouple the ULA video timing from the display. Someone has implemented such a thing on the BBC project as part of a port to a Xilinx board with only HDMI out. As a quick hack you could just change the speed of the entire design such that the video refresh rate was 60 Hz, but this will speed up the Spectrum as well, and you might need to tweak the blanking to keep everything in spec.

    To answer your previous comment, I guess you need to start with an idea for something you want to implement. Anything with strict timing requirements or a lot of high-speed parallel operations would often be better suited to FPGA implementation rather than, say, using a microcontroller or even a DSP. Video processing and high-end software radio are good examples. An as-yet unreleased project I used the board for was to do a digital capture of a S/PDIF digital audio stream onto SD card as a means for ripping Minidiscs to FLAC. Some extra logic read the track number from the subcode data and used this to build an index on the SD card for automating the encoding process.

    There are a lot of interesting building-blocks and whole projects on Opencores, and also check out the DE1 port of Minimig if you haven’t already.

    I’m afraid family commitments are going to be taking up a lot of my time for the foreseeable future, so further replies are likely to be sparse. I do still read all the comments, though, and will endeavour to answer anything quick all the same.


  29. Domenico-Roma-Ita

    Hello Mike ! Thank you for your strong design of the Spectrum for Altera DE1.
    I touched the keyboard of the spectrum for many years now and I dusted off my old tapes to try to load them on the memory card.
    A small problem, I created 4 partitions on a 512MB SD with the command
    New Data” nnn “, 16
    but I can activate only 2 at a time eg.
    move “a:” in “games” asn – return the message OK, 0:1
    move “B:” in “utils” asn – return the message OK, 0:1
    move “c:” in “snap48” asn – return the message “Out of XDPBs, 0:1
    so if I use C: I have to remove A: or B:
    One other question, there are plans to connect a joystick to GPIO Connector of the DE1? On another site I found the pattern for the Joy of Minimig (amiga 500 on DE1) Very Simple, 14 resistor 2,7Kohm and 2 connectors Canon 9 Male.
    Thank You and Happy Easter !!!

  30. Mike Post author

    Hi Domenico,

    I remember having the same problem using more than 2 partitions at once (in ResiDOS I assume?) I don’t have a solution I’m afraid, but the behaviour should be exactly the same as a real ZXMMC, so if you find a solution for the real Spectrum then it should still work on the DE1.

    It would be very easy to make the Minimig joystick interface work with the Spectrum design, but I don’t have time to work on it at the moment. I remember the Kempston joystick interface was just a latch mapped to IN 31 (in fact I think it was selected whenever A4-A0 = 1). The VHDL to implement this would be trivial. If you want to have a go at adding it then you should find it similar to the ULA input latch for the keyboard and tape.


  31. Bernd

    Hi Mike,

    thank you very much for your superb ZX-Spectrum FPGA clone. I think this is really the work of a FPGA master.

    Thanks again,

  32. Jan

    Looks like a great project, I have a DE2 board

    I have been trying to mod the program to get it to run on the DE2 board.

    I get the 8888 up on the board but does not appear to do anything else.

    I remapped the pins for the DE2 board.

    I can see there is not a Clock_24 on the DE2 board
    and only 1 CLOCK27 pin as well.

    I have tried to make 2 extra PLL clocks
    one with 50mhz input and 2 24 mhz outputs
    and one with 27mhz input and 2 27mhz outputs.

    But not quite sure how you map these into the design.

    Not sure if I am on the right track or not

    Any idea what do you need to modify to get it to run on this board.


  33. Dirk

    Hi, the Core works really nice.
    But how can i get the ZXMMC+ feature into flash rom ?

  34. Lee Sylvester

    So, let me get this straight. All I need is:

    Altera DE1 FPGA dev card
    SD card
    PS/2 Keyboard

    and I can have a fully working Spectrum +2A? Have I missed anything out? If not, I’m off to go by me an FPGA dev card 😀

  35. Mike Post author

    Correct. Not quite cycle-accurate, which causes problems with a few games, but essentially fully working. You can even load stuff off tape through the line-in on the board. Don’t forget to download the free edition of Quartus from Altera.

  36. Mike Post author

    Hi Jan,

    Sorry for the slow reply – there were a couple of comments waiting for approval that I hadn’t been notified about for some reason.

    Assuming you have remapped all the IOs correctly it sounds like you just need to replace the PLL block. You don’t need to generate the 24, 27 and 50 MHz clocks shown as input to the top level, as these just represent the clocks that are available on the DE1. The Spectrum needs 24 MHz and 28 MHz only, which you should be able to generate with a single PLL from the 50 MHz clock. It should be sufficient to edit pll_main.vhd (via the megafunction wizard) so that it runs from a 50 MHz input instead of 24 MHz, then in spectrum_de1.vhd just change the PLL clock source from CLOCK_24(0) to CLOCK_50 (obviously make sure you remapped this pin as well).

    Hope it works, and apologies once again for the two month delay!


  37. Pingback: ZX Spectrum: post scriptum « Focusrite Development

  38. Doug Barry

    Hi Mike,

    Would it be possible to port this to the DE0 board?

    At first glance the differences between the DE0 and DE1 that may affect it are the DE0 has a Cyclone III, but doesn’t include a Line in/out.

    I’d love to give this a go, having recently sold my spectrum hardware and thought I could make do with emulation. Its just not the same 🙂 I already have a DE0 spare from another project.


  39. Mike Post author

    I don’t see why not. You would need to update the pin assignments accordingly and then check for any changes to the clock tree. The DE0 doesn’t seem to have any SRAM, so unless there is enough spare RAM in the FPGA to make up for it you might have the pain of writing an SDRAM controller.

    I’m thinking of putting the Speccy and BBC VHDL on GitHub, to make it easier for people to do forks like this. Will aim to get that done over the next couple of days if that would be of use to you.


  40. Doug Barry

    That would be very useful Mike, thanks. Hopefully I’ll get time to do some work on it over the summer, I’m more accustom to the world of microcontrollers, but in order to keep up I’ve decided to have a crack at FPGAs. Something like this might be a bit above me now but you have to challenge yourself to learn.

  41. Ash

    Hi, Mike,

    Thanks so much for the writing the Speccy and Beeb cores.
    I can imagine a lot of effort went into coding and debugging it.

    I’ve been busy trying to champion the benefits of FPGA based retro stuff on some Facebook retro gaming groups.

    I’ve been having problems running the Speccy on my DE1 though….

    I only bought the DE1 a few months ago, but it has the ISSI branded SDRAM + SRAM, and the Spansion FLASH.
    I’ve also had problems getting Minimig DE1 to run properly from the latest source, and I heard that newer boards have different chips on them which can cause issues?

    When I first tried flashing the Speccy ROMs for your source, I did a file compare for all the ROMs (48K / 128K etc.) to make sure I definitely had the correct ones.

    I then erased the Flash using the DE1 Control Panel (v2.0.1 from the v1.0.1 CD), then wrote the ROMs at the correct offsets.

    When I first tried to power up (VGA mode), I only got either vertical lines on the screen, or garbage flashing squares depending on the mode switches.

    So, I tried reading back the Flash to make sure it matched the ROMs, then I tried erasing the Flash again and writing all the ROMs at once using a merged file.

    I found that it only appeared to boot when I compiled it with the default +3 MODEL option, and with the mmcen3eE.rom image in Flash.
    But, I was still getting random dots at the top of the screen, and it would often crash when going into +3 or 48k Basic?

    To cut a longer story short, I think I’ve made an important discovery about Quartus.
    (I was compiling from the latest source because the .sof file you posted above appears to boot directly into 48k mode)…

    The 48k mode .sof file appeared to be booting normally with no garbage on the screen, so I was convinced it was an issue with the way Quartus 12.1 was compiling it.
    Sure enough, I found if in Unchecked the default “Power-Up Don’t Care” box in Assignments > Settings > Analysis and Synthesis, it compiled and ran perfectly. 😀

    I haven’t tried any games yet, but it no longer has ANY garbage on the screen, and doesn’t crash any more.

    So, it seems there are some registers that are not being initialized at power-up / config, or it could just be Quartus itself deciding it knows best (more then likely)?

    I did try your BBC Micro core as well earlier, but I wasn’t getting any sync pulses at all? (both the Hsync and Vsync pins were stuck High?).
    When I step through using the debugger mode, it goes 0000 0002 0004 etc. up until about 000c, then jumps back to FFFF?

    I’ll keep trying though, and I’ll be disabling that pesky “Power-Up Don’t Care” feature in Quartus in ALL my projects from now on!

    Many thanks,
    Ash. 😎

    P.S. I was worried for a long while that my Flash or SRAM may be faulty, but it now seems like it’s just another FPGA caveat. lol

  42. Mike Post author

    Hi Ash,

    Glad you got it to work in the end. I haven’t compiled it on a recent Quartus so I’ve not run into the issue you described. All registers should be cleared on reset, so although this issue may cause problems on power up, it should all work fine if you cycle the reset switch (but I guess you tried that).

    BBC issue could be ROM related, because unlike the Spectrum the BBC’s CRTC needs to be initialised before you will get any sensible video. I can’t remember if it will generate a default raster on power up, but it’s quite possible it doesn’t, which would explain the total lack of syncs.


  43. Ash

    Thanks for the reply, Mike!

    Yep, I suspect a ROM issue too, but will give it another try soon. I did try the ROMs from a few different sites.

    I tried the switches many times, but couldn’t see why it was failing. I suspect it’s the ROMs though, as I tried your precompiled .sof file too.

    Just to confirm btw, the OS12 ROM is the “MOS” one, correct?

    So, they load into…

    0×28000 – Sideways ROM <= "supermmc.rom"
    0x2C000 – Sideways ROM <= "basic2.rom"
    0x3C000 – MOS <= "os12.rom"

    Is this map still the same in the latest source files, or does it have a new bank switching method?

    I'm assuming the reset vector for the Beep is still at $FFFC / $FFFD?

    Would it be OK if I send you the ROM files I'm using so you can compare with yours?

    I'm learning a bit more about the CRTC now, as it's almost the one in the Quantel Paintbox that I'm helping to diagnose.

    I think it generally outputs some rather weird sync pulses until it's initialized?

    I'm sure I'll figure it out soon. I'll stick a SignalTap in there to see what's going on.


  44. Ash

    OK, finally figured it out (took me most of the day)…

    It’s always something ridiculously simple in the end isn’t it? lol

    I tried everything to get the Beeb running on my DE1. I tried uploading DE1_USB_API.sof from the old v0.8 Control Panel and using the v0.8 s/w, erasing then reflashing. No joy.

    I then suddenly realized the difference between the Speccy and the Beeb – the 48K ROM is being written at offset 0x00000, and the Beeb ROMs are higher up, so it must be an offset problem…

    I knew your code must be working fine, because there are thousands of people using it just fine.

    So, it turns out – the DE1 Control Panel needs WORD offsets for the Flash, not BYTE offsets!!! 😳

    This was causing everything to be written in the wrong place in Flash, even though I thought I’d checked that by reading it back again earlier??

    Basically, I just used the latest v2.0.1 DE1 Control Panel software (which uploads the bitstream itself), erased the flash, then wrote all the ROMs like this…

    0x00000 <= 48k.rom
    0x04000 <= 128k-0.rom
    0x06000 <= 128k-1.rom
    0x08000 <= mmcen3eE.rom

    0x14000 <= SUPERMMC.ROM
    0x16000 <= Basic2.rom
    0x1e000 <= OS12.ROM

    Finally! Both cores running fine! 😀

    I haven't made a SCART cable for the Beeb yet, but I saw the Csync pulses and touched a composite cable to pin 13 on the VGA plug to test it.

    I also hear the nice "Beep!" when the Beeb is reset, and could see the text if I joined pin 1 to pin 13 temporarily (NOT recommended btw!).

    I never even dreamt that they'd use WORD offsets in the damned software. lol
    It's just a case of dividing the offsets by two when writing to flash.
    The Control Panel even wants WORD offsets for the "Length" parameter!

    It doesn't make much sense, 'cos as you know, the upper bits of the Flash aren't even connected on the DE1, and the /BYTE pin is tied to Ground!?

    I guess it was my fault for not reading the manual? hehe

    Anyway, mystery solved.
    It probably explains why I was having so much trouble with the older Minimig cores as well (which require the Kick ROM to be written to Flash).

    btw, I read back the full 0x40000 BYTES from Flash and compared against the Speccy and Beeb images.
    Would it be OK to post a link to the image here so people can write to their Flash in one go?

    (ofc, it's fine when writing a file to Flash starting at offset 0x00000.)

    I only just got two "real" BBC Model B's from eBay after not owning one for about 18 years.
    They were quite grimey, but both power up just fine. One of them has a fault keyboard, but it just needs some new logic chips.

    Thanks again, Mike.
    FPGA's are good fun once you get past the gotcha's!

    Oh, one last thing I noticed – when you reset the Beeb with the debug switch set to "Halt", the very first you see on the Hex display is 0xD9CD, which is the proper entry point for MOS (OS 1.2).

    So, by that time, the CPU has already read the reset vector at 0xFFFC / 0xFFFD. Also makes sense now.

    Best Regards,
    A much happier Ash.

    P.S. I might have a go at adding a scandoubler to the Beeb core. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *