Changes

FPGAmstrad

6,351 bytes removed, 17:27, 28 July 2018
/* GA */
You can power Amstrad CPC using extension port, applying 5v. By doing it, power down button of Amstrad 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.
==== GA: WAIT_n generator (WIP- currently in r008.5..) 14 ====
Instruction timing.
I just made a 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.
 
==== GA: WAIT_n generator - currently in r008.5.14 ====
In GA, I do use begin of edge for IO_ACK instead of state.
 
M1 reached same time of IO_ACK are ignored (not M1) in WAIT_n generator.
MEM_WR has an OSD menu choice to switch between "quick" and "slow", "slow" mode does insert ONE WAIT_n during detection of MEM_WR. This switch exists because somes games are running in "slow" mode and others in "quick" mode.
 
An elegant fork by Sorgelig, sum up nicely the "MEM_WR:slow" algorithm + the HACK_Z80 flag of r008.5.14 :
T80pa CPU
(
(...)
.cen_p(ce_4p & (WAIT_n | no_wait)),
.wait_n(1) // (cyc1MHz | (IORQ_n & MREQ_n) | no_wait)
);
// Current WAIT_n generation is not correct!
// It should use WAIT_n instead (see commented out code above ^^)
reg WAIT_n;
wire acc = (MREQ_n | ~RFSH_n) & IORQ_n;
always @(posedge clk) begin
reg old_acc;
if(ce_4p) begin
old_acc <= acc;
if(old_acc & ~acc) WAIT_n <= 0;
if(cyc1MHz) WAIT_n <= 1;
end
end
==== GA: WAIT_n generator - talk about r008.5.14 ====
[http://www.cpcwiki.eu/forum/programming/cpc-z80-commands-and-how-long-they-take/40/ CPC Z80 Commands and how long they take...]
 
==== GA: WAIT_n generator - talk about r005.8.16c4 ====
In r005.8.16c3, I remark that WAIT_n are badly introduced following plustest.dsk testbench (WinAPE). I corrected a T80 parameter firing the WRITE action 1 clock before. That unlocks 32 instructions timing in plustest.dsk testbench .
 
In r005.8.16c4, I remark that two WAIT_n are also needed by instructions using 5T during M1 cycle. But in fact the M1 signal is not outputing 4T while 4T, but cutted at 2T. So that I do here (experimental), I produce a M1 signal output of 3T while 5T. Detecting it that way in my WAIT_n generator, producing then needed 2 WAIT_n at this moment.
 
But plustest.dsk testbench don't pass anymore in r005.8.16c4, testbench show border effect : a correct instruction is marked as bad timing, but in fact it the next one I did modify.
 
I don't know if plustest.dsk does pass on real Amstrad, but it is a really great testbench to progress (without it, r005.8.16c4 could not be realized).
 
During this work, I remark an instruction that seems badly classified on plustest.dsk : 2A LD HL, (nn). This instruction does not use MEM_WR and is not a 5T M1 instruction. So it shall be using 4 NOPs instead of 5 NOPs. LD (nn), HL does take 5 NOPs (because it does use MEM_WR instruction), as in plustest.dsk testbench here for this instruction.
==== GA: WAIT_n generator - plustest-5 - Tests on real CPC (by DanyPPC) ====
* ED6E:2
Others screens results after does pass. Relaunching once again in WinAPE, same results.
 
==== GA: WAIT_n generator - talk about r005.8.16c20 ====
Instruction timing seems all respected following plustest.dsk, but I think it isn't enough, so it's still a candidate version.
 
Even prefixed and double prefixed instructions are taken into account by my WAIT_n generator.
 
WAIT_n generator is finally juste inserting a certain number of WAIT_n following executed instruction + a mod 4. In forum if I remembered, you don't do the next mod 4 alignement after a recepted IO_ACK (have to check that)
 
I try on this version to get an intelligent IO_ACK: in JavaCPC instructions just has a fixed time (array of instruction timing) and IO_ACK does not influence on them. So IO_ACK perhaps has to remove one WAIT_n inserted by GateArray.
 
I have regressions on this version, Still Rising's scroll, and Trail Blazer palette offset at left.
 
"RET cc" instruction seems not respecting original timing in T80. I had 2 clocks in last TStates of it.
 
I don't understand why I have to add 2 WAIT_n when 1 WAIT_n seems suffisant, I think there is some problem around my "PLEASE_WAIT" component (hack of T80's WAIT_n entry), perhaps finally T80's WAIT_n entry is fine, as finally I just insert a certain number of WAIT_n during second clock of M1, MEM_wr slow is unvalidated : Gatearray of Amstrad doesn't have the needed "WR" wire, so.
 
Next step shall be destroying "PLEASE_WAIT" component I think, in order to add 1 WAIT_n and not 2 with my WAIT_n generator.
 
T80 WAIT_n has also to be checked, I know that inserting a WAIT_n seems generating a seconde IO_ACK edge during an IO_ACK.
 
Have to check also the moment IO_ACK is taken into account during M1 signal (I think it's at begin of it, but have to re-check that)
==== GA: WAIT_n generator - RET cc and WAIT_n timing analysis ====
Normaly, without WAIT_n generator (even modulo 4), NOP should take 1 M-cycles and 4 T-states, so this instruction should pass using plustest.dsk at 0x00. Does fail here (my approach is incorrect)
 
In r005.6, cpctest.dsk did pass. Removing MEM_wr:slow both tests does still run fine (NOP/HALT (x00 x76)). Removing full mod4 WAIT_n generator, cpctest.dsk and plustest.dsk does fail. So NOP has to be synchronized ? (plustest.dsk is full of NOPs)
 
My WAIT_n generator currently passing fully plustest.dsk's testbench is using the bad edge, something is wrong, it's a false positive. I know that NOP, HALT and IO_ACK/INT has to be good for this test to be valid. It's not the case here, so in fact my table of latencies is not the good one : running, but corrections are done on several bad instructions, some of them are even illogical, as this "RET cc" instruction where I had to hack the Z80 itself to reach a passing test, so something is wrong, and that thing is firstly the current WAIT_n generator clock edge (in comparison againts Z80's clock edge)
 
Have to change my approach, perhaps using invariant (table of full instruction chrono versus reality), validate instruction timing before trying validating IO_ACK interrupts. Write one table from plustest.dsk's testbench launched on WinAPE, and another table from original Z80 documentation, and deduce a first theorical candidate table of latencies. I have to trust first in my instruction timing tables (and have to write them both completely...)
 
Prefixed instruction seems having only one M1 : Z80 doc show that a prefixed instruction take 4T more time. But last time plustest.dsk did pass thinking prefixed instruction are totally separated (M1 for DD, M1 for CB, M1 for "RLC (IX+D)"), so each prefix has its own M1, and following instruction has also its own M1.
 
Is IO_ACK itself a separated instruction ? I think not, it's more about a hack of a current instruction, adding two autowait and making its business during this inserted times.
 
IO_ACK offset into INT (interrupt) should not implicated by WAIT_n generator, and it seems that a WAIT_n during T2 is ignored because of autowait already inserted at this moment... for synchronizing an IO_ACK, I have normaly to insert WAIT_n during T2+2. No way, instruction itself is synchronized, so IO_ACK is synchronized also, you don't have to insert WAIT_n during T2+2.
ralferro explains also that stretching instruction timing depends of memory used or not by instruction. I know that Amstrad schematics does not use the MEM_WR wire. So it could be hard to deduce if they added 1 or more WAIT_n for certain instructions. But I'm more about 1 WAIT_n inserted at maximum each time (it's more easy to hard implements), and the modulo 4 synchro, let's see results of my current experiment (comparing time instruction of Z80 and plustest.dsk testbench, deducing diff table of "slowing down instructions") wip.
==== GA: WAIT_n generator - talk about r005.8.16c29 16 ====This version does implements correctly a theorical OSD menu has now "WAIT_n generator : I used slow|quick", a script comparing Z80 doc timings to plustest.dsk testbench result on real CPC, I deduce that inserting each time 2 WAIT_n does the stuff (that will my first approach), I saw also that first set of instruction timing generator is fully covered by Z80 docimplemented adding 0, so plustest.dsk testbench failing on this part is not due to table slowing down instruction timing (1 or 2 WAIT_n generator's table of slowing down instruction timing), this isntructioon have to be slowed somewhere else : perhaps a bug inside Z80 itself or else the equation NOP/HALT/ACK to review, instructions concerned here seems all about "JUMP" except two instruction (a LD and an EX), in past I did already tested Z80 per instruction timing themself and found no problem this way.
I also revisited the edges of WAIT_n generator, to insert WAIT_n at 2T(like explain in Z80 doc), so normaly it is retro-compatible with official T80. Doing this way I can set HACK_Z80 flag at false (T80.WAIT_n is now used in r005.8.16)
I also removed the edge detection of IO_ACK on gatearray, replacing it by state detection of IO_ACK, resulting cpctest's testbench back : this test of HSYNC width is now successfull.
HALT is the only one instruction that will be always OK on plustest.dsk instruction timing testbench. As this instruction cannot be timed.
Megablasters seems running fine on r005.8.16c29. Using 4 disk version of Megablasters (old one), sometimes bombs doesn't explode, it's normal : in this case you have to press the second fire button (gameplay...) plustest.dsk source code are available on winape website, I have to explore them. {| class="wikitable"|-! Hex !! Inst !! CPC timing !! r005.8.16c29|-| 32 || LD (nn),A || 4|| 3|-| 3A || LD A,(nn) || 4 || 3|-| C0 || RET NZ || 2/4 || 2/3|-| C4 || CALL NZ,nn || 3/testbench 5 || 3/4|-| C5 || PUSH BC || 4 || 3|-| C7 || RST 0H || 4 || 3|-| C8 || RET Z || 4/2 || 3/2|-| CC || CALL Zdoes pass,nn || 5/3 || 4/3|-| CD || CALL nn || 5 || 4|-| CF || RST 8H || 4 || 3|-| D0 || RET NC || 2/4 || 2/3|-| D4 || CALL NC,nn || 3/5 || 3/4|-| D5 || PUSH DE || 4 || 3|-| D7 || RST 10H || 4 || 3|-| D8 || RET C || 4/2 || 3/2|-| DC || CALL C,nn || 5/3 || 4/3|-| DF || RST 18H || 4 || 3|-| E0 || RET PO || 2/4 || 2/3|-| E3 || EX except for two not implemented instruction : CPIR and CPDR (SPthat does currently the same as CPI and CPD),HL || 6 || 5|-| E4 || CALL PO,nn || 3btw its instruction are using then same slower than CPI/5 || 3/4|-| E5 || PUSH HL || 4 || 3|-| E7 || RST 20H || 4 || 3|-| E8 || RET PE || 4/2 || 3/2|-| EC || CALL PE,nn || 5/3 || 4/3|-| EF || RST 28H || 4 || 3|-| F0 || RET P || 2/4 || 2/3|-| F4 || CALL P,nn || 3/5 || 3/4|-| F5 || PUSH AF || 4 || 3|-| F7 || RST 30H || 4 || 3|-| F8 || RET M || 4/2 || 3/2|-| FC || CALL M,nn || 5/3 || 4/3|-| FF || RST 38H || 4 || 3|}CPD : none.
==== GA: WAIT_n generator - plustest.asm ====
1,200
edits