Last modified on 20 July 2011, at 06:44

FPGAmstrad

Revision as of 06:44, 20 July 2011 by Freemac (Talk | contribs) (Third schematic Z80+ROM+RAM+VGA)

This is a VHDL version of Amstrad CPC 6128 running on FPGA starter-kit NEXYS2 500k-gates from Digilent. A starter-kit is a standard board made for learning FPGA, so it is standard.

Games running on it are : Tempest, Fruity Frank, Boulder Dash, Classic Invader, Xevious, Wiz'lair, Ghost'n'Goblins, Chase HQ, Xor, P47, Bruce Lee.

Inconvenience known is that PS/2 keyboard has timeout and can't press more that a certain number of key at same time. So it's really encouraged to plug joystick (don't do as me, don't cut directly wires, just weld a male serial port lol), and sure to plug sound ;)


How to assemble it

You need :

- a "NEXYS2 500kgates" starter kit

- a "PMODSD" module for reading sdcard

- a alimentation (cause they don't give it with starter kit)

- optionally a DIGILENT USB JTAG (normally starter kit can be programmed directly by usb, but I didn't have test this way)

- a 4Go SDCARD (no more)

- The binary of this project, available by there : [[1]]

- Several ROM files :

-- OS6128.ROM BASIC1-1.ROM AMSDOS.ROM (from JavaCPC)

-- MAXAM.ROM (from CPCWiki)

- Several DSK files (one or more) :

-- TEMPEST.DSK ARKANOID.DSK FRUITY.DSK BRUCELEE.DSK CHASEHQ.DSK WIZLAIR.DSK XEVIOUS.DSK BOULDER.DSK CLASSIC_AXIENS.DSK CLASSIC_INVADERS.DSK


You have to :

- program FPGA with the binary file "amstrad_switch_z80_vga_sd.bit" of this project, for it I use Digilent Adept software and my USB JTAG cable

- format your 4Go SDCARD in FAT32 4096 byte allocation size

- copy ROM and DSK on SDCARD

- plug PMODSD on slot JC1 of starter kit, and set all switches to 0

- plug VGA, and turn on starter kit

You can :

- plug a PS/2 keyboard, and type "cat"

- increment switch to select another disk at boot, if screen became RED, it's that binary value done by switches is too big, leds are doing a small animation when a disk is correctly loaded

- plug joystick on slot JA1 (Vcc 3.3v is common)

- plug another joystick on slot JB1 (Vcc 3.3v is common)

- plug a jack on slot JD1, one at upper GND plug, and second wire at next plug, just at left of it (if it was 3.3v Vcc, is that in fact you had to take the right one)


Tests done

Several bug could disappear in TV mode... but TV mode is not implemented yet.

prince.dsk gryzor.dsk donkey.dsk : critical bug : always writing on memory, certainly performance, have to test it on TV mode to know if it came from my asynchronous RAM.

buggyboy.dsk barbarian.dsk : raster bug can be fight with anti-raster switch (last switch is anti-raster, stopping ink rotate...)

longshot : VSYNC alternate cut bug, it's so warrior dam

crazycar2.dsk : simple overscan, my vga buffer is full lol

a lot of demos don't pass, in fact I didn't find one that pass dam.

Others bugs is about dsk format, in fact a dsk is uncompressed into RAM at startup, so all dsk access are direct :

- ucpm format : normally it run, but in fact... it don't

- protected format : all format with sector size changed, and then not standard didn't pass

- double side format : you can change disk and then reboot to insert it, so it's not done for changing disk while you are playing

- save : save is done in RAM, so when you turn off or reset Amstrad, all change is lost. It's done for let's games saving score running correctly


Effort done

Instruction timing : I tested instruction timing of T80 compare to instruction timing of JavaCPC emulator, I deduce also the memory access that had to be slow down

Test of a real Zilog, in fact T80 of opencore run on rising_edge, and zilog run during low state, so for testing I had to indirectly do a downclock, it run, perhaps if I put buffer on zilog access I could clock it at normal speed, but as it run...

Alignment of HSYNC : a button of starter kit display HSYNC loopback lines, it's usefull to compare to a Maxam test that alternate color on them

Sniffing of real Amstrad, I listen on some wires of my Amstrad CPC 6128 plus, but I can't access to VSYNC/HSYNC output of CRTC, so I have to buy another model to do this test. In fact you can listen at clock of Amstrad and overclock it after using FPGA DCM component, resulting a clock sequence insertion that permit to insert 4 operations during one tic of real Amstrad, that's it with FPGA DCM you can overclock output Amstrad clock signal for insert more operation, I use this tips for listening signals and saving it in stater kit asynchronous RAM (write, stop write, write, stop write... i'm a perfectionist paranoid...)


Agile method

This project result of a experiment of applying Agile method. Finally this project has taken 5 months. The result is a standalone platform that can run several games of Amstrad. Normaly, I had to dedicate 2 months on this project, but as the result was so great, I continue to a standalone and better version.

This project was done for my father birthday, so sorry that I can't deliver it yet :^)

One day one book, or a lot of wiki page by there, presenting step by step adventure :)

But I want really to validate project before doing it. So it will stand a few I think.

TODO :

-sniffing Classic Amstrad HSYNC and VSYNC CRTC output directly (validation test)

-implement a SCART TV mode (validation test)

-unlock in consequence Prince of Percia and Gryzor !

-wait JavaCPC plus version ;)

-unlock 1943 (I think that it run better in plus model, no ?)

-add USB keyboard for no more key timeout (but as joystick run... it's not important yet)

Minimal Amstrad Architecture : Build your own Z80 Amstrad Computer

I explain here my first great experiment, for having Amstrad saying hello :)

First schematic : Z80+RAM+ROM

Z80 can address from 0x0000 to 0xFFFF

RAM is from 0x0000 to 0xFFFF

You have lower and upper ROM, so starting at address 0x0000 you put OS464.ROM, and at address xC000 you put BASIC1-0.ROM

When Z80 do READ MEMORY, you read ROM

When Z80 do WRITE MEMORY, you write RAM

When Z80 do WRITE IO, you do nothing

When Z80 do READ IO, you response it DATA=0x00

If you run this schematics on FPGA, RAM change !

Second schematic RAM+VGA

With JavaCPC, when you do a snapshoot, and edit result file, you see that RAM content starting at a certain address.

Do "paper 2", "cls" on JavaCPC, the screen became RED, and then save a snapshoot, you can see that last part (from 0xC000 to 0xFFFF) had change from a lot of 0x00 into a lot of 0xFF

So last part of RAM is used for video (it's shown on Quasar [[2]] and other legend website...)

For making my VGA module, I take a look at unix "modeline" command that give you all timing for VGA signals, and it run :)

After having a VGA module displaying a RED screen (yeah !), I made it scanning last part of RAM (from 0xC000 to 0xFFFF), and I solved the puzzle.

RAM contain lines of 0xFF, each finishing by 0x00, but lines are not in great order

Third schematic Z80+ROM+RAM+VGA

So the game is : RAM is empty at startup, if I turn on it display something.

So you put the two last schematic together and tadam... got a problem.

The problem is that two component are accessing RAM in the same time : the Z80 and the VGA, so you had to make a sequencer. A sequencer is simply a counter fed by a clock : 00, 01, 10, 11. And you manage work task like this :

00 RAM WRITE start from Z80

01 RAM WRITE end from Z80

10 RAM READ start from VGA

11 RAM READ end from VGA

You plug sequencer(1) on z80 clock and not(sequencer(1)) on VGA...but another problem : VGA uses 25MHz speed for scanning RAM. so Z80 has to use same speed xD

To solve this problem you can use a special RAM done for this problem, a RAM that you can WRITE at a certain speed, and READ at another speed, this magic component is called ramb16_s16_s16. Note that they have no problem to write simultaneously on two RAM components, so that you can dump video RAM content using starter kit RAM, and you can display VGA using FPGA internal ramb16_s16_s16 RAM.

Bootloader

I have written a FAT32 SDCARD bootloader that :

- deploy ROM file on physical RAM

- deploy Nth DSK file on physical RAM, N being the binary number selected by 8 switches

bootloader run only at boot, it just here for deploying informations in RAM at start up :)

Clock sequence

Original Gatearray of Amstrad is a sequencer, it manage synchronization between video card and z80 and memory access.

Historically there are a link between CU of CU/ALU, and... control bus and... making a own sequencer. But I will say no more in order to not disturb these text part xD

Whatever, I made my own sequencer here in form of a bus of 4 wires called CLK4. CLK4 execute a simple repetitive sequence like 0001 0010 0011... CLK4(3), the last wire is directly connected to Z80 clock entry. Component not using explicit CLK4 as clock entry are generally using a not(CLK4(3)) entry, in order to do operation not as same time than z80.

Real Amstrad use buffer memory in front of each address and data access, and real z80 is clock low state active. Normally if you follow datasheet of z80 you know how to map memory following CU comportment. Or you do as Amstrad, saying that z80 CU sucks, I create my own sequencer, managing all my memories access, alternating CRTC work and z80 work with little synchronization, insert by the way more pixels that can support my small CRTC...

Why NEXYS2 500kgates starter kit

The first response is that it's the one I have xP

Xilinx schematics

Xilinx webpack permit drawing schematics as book schematics, My point of view is : "For programming a FPGA, you draw a schematics as old book and just press one button. Each component on this schematic can be edit, in a language called VHDL".

My source code is not Altera compatible because of schematics drawn, but webpack can export vhdl code from schematics if you want.

RAM dump

A starter kit that contain a RAM component can dump it.

During power is on you can :

-programming FPGA with a program/schematics done for filling RAM

-programming FPGA with a program/schematics done for using RAM

-programming FPGA with a program/schematics done for dumping RAM

My own made program do it with poor serial port, so for dumping all RAM content it takes about 3 hours, and for dumping Amstrad RAM part it is about 15 minutes.

FPGA internal RAM size

It's to know that a FPGA chip contain 96KB internal RAM so you can't insert a dsk inside. This internal RAM is already used in part be T80 (z80 from opencores), the soundchip, and special RAM ramb16_s16_s16 (RAM with two different speed one for writing another for reading, in fact two RAM with a common part) that I use for VGA mode.

VHDL components size

T80 (z80 processor) take 100kgates

Yamaha sound chip (from fpgaarcade) take 50kgates

InterruptGenerator + VGA mode take 50kgates

Bootloader (for standalone) take about 120kgates (FAT32 protocol, SPI protocol, DSK protocol)

Actually the project take about 99.9% of 500kgates. But I think that TV mode will take a lower size. A bigger size shall be great for Amstrad CPC Plus version, if JavaCPC evolve, and then if I evolve ;)


Source code

The project download contain in fact source code and the binary file (.bit)

It is in fact a simple zip of project folder.

The project was done using Xilinx webpack

It contains some direct drawn schematics, and VHDL components


Schematics

I explode into a task by component, so the schematics is big.

Starter kit use only one RAM physical component for RAM ROM and DSK, so I had to manage accesses (it is possible in fact because Z80 is a sequential processor)

My clock take 4 wires, in fact it exists a clock sequence #Clock_sequence (during 1 z80 tic, I do several things)

RAM is done for being dump


Components

sound chip is fpgaarcade one, patched.

PPI chip is CPCWiki one, patched.

PWM chip is fpga4fun one.

VGA display component use same parameters than unix modeline command

A component is dedicated to interrupt generation

Big components as SPI on BOOTLOAD use state-machine led debug : an integer contain the state of state machine, and this integer is displayed on 8 leds so you know where you are, it's for that I add several crash state in order to understand why and where component crash.

This project don't use IBM ROM of NEXYS2. Be careful if playing one day with it, physical IBM ROM is plugged on bottom of physical RAM and can put death bit for some byte address. In fact my 8th byte is death, it's why I turn always my upper RAM address bit into 1. I think that I have written one time on a ghost part of ROM, and it was fatal...