== How to assemble it ==
'''You need :'''
*a "NEXYS2 500kgates" starter kit [[http://www.digilentinc.com/Products/Detail.cfm?Prod=NEXYS2]] (1200kgates should be better for future version)
*a 4GB SDCARD (no more), I have exactly a "SDHC 4GB class4 Verbatim"
*the binary of this project (candidate 002) : source+500k-gates binary [[http://yunyunaof.free.fr/BuildYourOwnZ80Computer_amstrad_vhdl_002_repack.zip]] ; 1200k-gates binary [[http://yunyunAoF.free.fr/amstrad_switch_z80_vga_sd_orion_candidate_002_1200k_binary.zip]]
*several ROM files : OS6128.ROM BASIC1-1.ROM AMSDOS.ROM (from JavaCPC[[http://sourceforge.net/projects/javacpc/]]); MAXAM.ROM[[http://www.cpcwiki.eu/index.php/MAXAM#Download]]
*one or more DSK files : TEMPEST.DSK[[http://www.cpcgamereviews.com/t/index2.html#tempest]] ARKANOID.DSK[[http://www.cpcgamereviews.com/a/index7.html#arkanoid]] FRUITY.DSK[[http://www.cpcgamereviews.com/f/index7.html#fruity_frank]] BRUCELEE.DSK[[http://www.cpcgamereviews.com/b/index11.html#bruce_lee]] CHASEHQ.DSK[[http://www.cpcgamereviews.com/c/index3.html#chase_hq]] WIZLAIR.DSK[[http://www.cpcgamereviews.com/w/index4.html#wizards_lair]] XEVIOUS.DSK[[http://www.cpcgamereviews.com/x/index.html#xevious]] BOULDER.DSK[[http://www.cpcgamereviews.com/b/index10.html#boulder_dash]] CLASSIC_AXIENS.DSK[[http://www.cpcgamereviews.com/c/index5.html#classic_axiens]] CLASSIC_INVADERS.DSK[[http://www.cpcgamereviews.com/c/index6.html#classic_invaders]] GRYZOR.DSK[[http://www.romnation.net/srv/roms/3452/amstrad/Gryzor-UK-1987.html]] PRINCE.DSK[[http://www.cpcgamereviews.com/p/index7.html#prince_of_persia]] BUGGY.DSK[[http://www.cpcgamereviews.com/b/index12.html#buggy_boy]] TRAIL.DSK[[http://www.cpcgamereviews.com/t/index8.html#trailblazer]] P47.DSK[[http://www.cpcgamereviews.com/p/index3.html#p-47_the_freedom_fighter]] SUPER_SKI.DSK[[http://www.cpcgamereviews.com/s/index23.html#super_ski]] ACTION_FIGHTER.DSK[[http://www.cpcgamereviews.com/a/index.html#action_fighter]]
A package that contains minimum set of ROM and DSK for filling simply sdcard [[http://yunyunAoF.free.fr/OS6128_BASIC1-1_AMSDOS_MAXAM.zip]]
<br> '''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
[[File:FPGAmstrad_minimal_plug.jpg]]
'''You can :'''
*plug a PS/2 keyboard, and type "cat"
Wires are plugs at upper part of pmod D.
From bottom to upper : [nothing : Vcc 3.3v] [blue : GND] [red : sound]
Sure you can connect a jack...
[[File:FPGAmstrad_joystick_plug.jpg]]
On pmod B : bottom is (both) 3.3v, so joystick's common, next is (both) GND (not used), and others are joystick connections, to test manually :)
[[File:FPGAmstrad.jpg]]
Future version will use NEXYS2 1200kgates, because last version of FPGAmstrad used 99% of 500kgates, and that I have so much things to add.
In september September 2011, I have done research about USB Joystick, joystick; I plug it successfully on another FPGA project. Not tested on FPGAmstrad.
In november 2011, I merge several code (a better SD module and other small things), I debug dsk_select (the last amstrad disk was in fact not inserted, you had to put another dsk file on SD card to detect it...), I recode interrupt correctly (no real changes feel, perhaps a better speed feel), I pass VRAM from 16Ko to 32Ko (so crazy car II startup image is displayed fully) and I start a new way of implementation of VGA display solution that allows address derail [[http://quasar.cpcscene.com/doku.php?id=assem:crtc] "amstrad rupture"]
Several bugs could disappear in TV mode... but TV mode will not be developed (I am trying to solve theses problem for VGA)
*'''moktar.dsk prehistorik.dsk''' : lag (key/joystick press lag)*'''macadam.dsk''' : ps/2 timeout evidence (can't launch ball with PC keyboard)*'''aigle_d_or.dsk''' : keyboard keys bad mapping evidence (pressing right arrow press also F3, then display "impossible" in this game in same time of moving, in fact it is not a joystick playable game) - this bug is located (some values appears double on keymap array)*'''super_cauldron.dsk''' : strange sector size evidence (not implemented yet)*'''ACPC_logon_system.dsk''' : text scrolling lag. This demo will be used for horizontal ink calibration (when i'll I’ll buy a luxurious FPGA platform... I need in fact 224Ko of internal RAM to do it), and CRTC overcounts.*'''ecole.dsk''' : It did run on candidate 000 because top of vertical_counter was fixed to 312, since top of vertical_counter evolves it freezes.
Arkanoid.dsk stars use rupture address (changing address several time during display of one image), it is now supported on "candidate 001" version of FPGAmstrad
A lot of demos don't pass, in fact I didn't find one that pass damn.
Others bugs are about dsk format, in fact a dsk is uncompressed into RAM at startup, so all dsk access are direct :
*CP/M format : normally it runruns, but in fact... it doesn't *protected format : all format with strange sector size fail*double side format : as you need to reboot in order to change disk, it's impossible to change disk while you are playing *save : disk disks are writable, save is done in RAM, it's and it’s not persistent.
----
=== Instruction timing ===
I tested instruction timing of T80 compare to instruction timing of JavaCPC emulator. I deduce synchronization of Z80 with CRTC on M1 signal by WAIT_n insertion in order to have a multiple of 4 Tstates per instruction. I deduce also one WAIT_n inserted during MEM_WR operation (yes I log testbench T80, i'm I’m crazy)
I just made a testbench test bench log of T80 (log of instruction's M1, and first M1 coming after knowing that I send a lot of NOP after my instruction), and compare it to a JavaCPC timing array. Some instructions was not tested (interrupt wait, and special timing (instructions with change timing)), but all others passed correctly.
=== Test of a real Zilog 80 ===
Code name : Z80fx2bb, real Z80@2MHz (instead of 4MHz) on fx2bb extension card.
For it I plug all wires simply from 1 to 40. Some wires are cut, somes some are Vcc, others GND. Z80 output are directly connected, Z80 input are pullup pull-up with red-red-red resistors (I like red), Z80 is powered 5v (pmod can give 5v using jumper). In fact z80 is so old component that powering it 5v do output 3.3v.
In fact the only difference between T80 of opencore and real Z80 is that T80 run on rising_edge, and Z80 run during low state. Test past with little modification of sequencer forcing it do nothing during low state of z80, resulting a clockdown downclock (memory are is too overclocked with this sequencer modification), perhaps using buffer on address bus and data bus could solve this detail... but as it runs for me it is not a problem.
=== Alignment of HSYNC Interrupt ===
JavaCPC running norecess's "using-interrupts" code [[http://www.norecess.net/using-interrupts.html]]
Could It could be interesting to test this asm code on next version of FPGAmstrad.
=== ram_palette ===
=== Sniffing of a real Amstrad ===
[[File: cpc_plus_m1.jpg]]
Code name : Raptor
I listen to some wires of my Amstrad CPC 6128 plus, but I can't access VSYNC/HSYNC output of CRTC, so I have to buy another model in order to do this test. In fact you can listen at clock of Amstrad and transmit it to FPGA DCM component, resulting a accelerated clock sequence, that's it, with FPGA DCM you can overclock output Amstrad clock signal in order to insert more operations, I use this tip for listening signals and save them inside starter kit asynchronous RAM (write, stop write, write, stop write... i'm I’m a perfectionist paranoid...)
You can power Amstrad CPC using extension port, applying 5v. By doing it, power down button of Amstrad don't doesn’t run. Using this way you reach a common 5v power between starter-kit and Amstrad. I connected wires from extension port directly to FPGA, as they are used just for listening.
----
This project results of a experiment applying Agile method.
Finally this project has taken 5 months. The result is a standalone platform that can run several games of Amstrad.
NormalyNormally, I had to dedicate 2 months on this project, but as 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 :^)
But I want really to validate project before doing it. So it will stand a few I think.
'''TODO :'''
1. Use another RAM to save ink/mode information per line (need more internal RAM, I need in fact a NEXYS2 1200k-gates)
2. unlock Unlock in consequence Prince of Percia and Gryzor ! (bug is known : [[http://www.youtube.com/watch?v=cegYl8NFunc]] - FPGAmstrad test monochrome with mode lock to 0)
3. wait Wait JavaCPC plus version ;)
4. add 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, having Amstrad saying hello :)
==== First schematic : Z80+RAM+ROM ====
Z80 can address from 0x0000 to 0xFFFF.
*When Z80 do READ IO, you response it DATA=0x00
When you run this schematic on FPGA, RAM change changes!
==== Second schematic RAM+VGA ====
With JavaCPC, when you do a snapshoot, and hex edit result file, you see 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 [[http://quasar.cpcscene.com/doku.php]] and other legend websites...)
For making my VGA module, I take a look at unix UNIX "modeline" command that give us 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.
[[File:crtc_puzzle.jpg]]
==== Third schematic Z80+ROM+RAM+VGA ====
Goal is : RAM empty at startup, VGA displays hello after run.
So you put the two last schematic schematics together and tadam... got a problem.
The problem is that two component components 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
*11 RAM READ end from VGA
You plug sequencer(1) on z80 clock and not(sequencer(1)) on VGA...but another problem appears: VGA uses 25MHz speed for scanning RAM. so 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.
After having a running Amstrad, I had to turn it into as standalone version. In fact before this step Amstrad ROM was put into RAM using serial port ([[#RAM_dump]]), it was slow, and Amstrad ROM was lost when I unplug electricity.
Bootloader FAT32 SDCARD is the only component playing with sdcard. Its tasks, all launched at boot, are :
- deploying ROM file on physical RAM
Original Gatearray of Amstrad is a sequencer, it manage synchronization between video card and z80 and memory access.
Historically there are is a link between CU of CU/ALU, and... control bus and... how making a your 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.
}
Figura 2. Basic Emulator Algorithm.
extracted Extracted from the book [[http://www.scribd.com/doc/53571848/27/Appendix-A-Space-Invaders-i8080-tutorial]],
Using this way, emulators reach a better running time. They don't need to implement the system-bus architecture[[http://en.wikipedia.org/wiki/System_bus]] (CONTROL DATA ADDRESS) crossing Von Neumann architecture[[http://en.wikipedia.org/wiki/John_von_Neumann]] (CU ALU MEM IO).
==== Component Architecture ====
Java is object language, so having new, set, get, for each of its objects.
In real Amstrad, main component is GateArray.
Choosing The fact of choosing Z80 as main component just respect respects the emulation architecture.
==== Java debug mode ====
When we cut a input wire, we generally plug it to GND or Vcc.
For cutting a function, you have to insert a cut on it. A cut it's a return. You can insert a (very bad) forcing cut as :
if (1==1) return 0;
everywhere. So function is ended at this moment and next lines became death code. It exists quality code program for checking death code, because it's generally a bug of development, normally we put code in comment.
=== USB joystick ===
==== Sniffing USB frames ====
USB use two wires in order to transmit frames, green and white, each with two logical values : 0v and 5v.
Let's plug a joystick on PC, if you listen at its two wires, you can sniff a USB transmission. Saving Finally you can save it for example on RAM.
These two wires can be traduce traduced into one with four states : 00 01 10 11.
One of this state states is sleep state, in fact it depends on USB mode you use.===== USB mode : USB1 or USB2 ; low speed, full speed or high speed =====For sampling, I speed up five times the saving speed on RAM. I succeed sampling an USB1 transmission : "Logitech dual action USB joystick", and an USB2 : "Sony PS3 USB joystick". PS3 joystick is not stable enough with my FPGA, but Logitech joystick is correct.
===== pull up and pull down =====
If you respect USB protocol, you have to plug some pull-up and pull-down resistors and some capacitors. But as I am a bad electrician, I just simulate then in VHDL, they are important because they cause USB speed negotiations. You also have an electronic mechanism in order to detect presence of joystick plug, I don't care about it.
One time sample is done, it is not readable. In fact USB frames are synchronized (they started with a certain synchronization pattern), encoded (NRZI), and checked (CRC). CRC type depends on frame length. Encoding is done for synchronization optimization.
Then using USB HID manual, you can understand type of frames, and author of them, and remark that the author alternate : USB master (PC) or USB slave (joystick)
You can use some "USB sniffer software" in order to understand more easily some frame frames contain, but they generally don't give all frame, and full frame.
[http://www.usb.org/developers/whitepapers/crcdes.pdf great crc check example in perl - offered by www.usb.org]
Objective here is to build a minimum state-machine graph, having for transaction between state a "frame transmission". It is normal on USB protocol to have error of transmission, so you have also to put "error frame transmission" on the graph.
At stabilisationstabilization, you finally switch between two states, one sending a certain frame that contains at different offset simply certain values of joystick button.
At start, some frames are employed for "next frame description", they can generally be ignored, as our USB architecture is fixed and minimal (one USB joystick, that's all)
=== Why NEXYS2 500kgates starter kit ===
==== Xilinx schematics ====
Xilinx webpack software permit drawing schematics as book schematics, My point of view is : "For programming a FPGA, you draw a schematic as old books and just press one button. Each component on this schematic can be editedited, 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.
A starter kit that contains a RAM component can dump it.
While power is on you can :
*programming FPGA with a program/schematics done for filling RAM
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 doesn’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...