Pentagon 2.666LE (part 2)

ACNews #77

12xi

Cleaned up extra clocks.
Also set _n for signals with inverse logic.
Read documentation on Quartus.
Configured the requirement Fmax = 65 MHz in TimeQuest Timing Analyzer, optimized (moved do out of the processor), there was a build at 65 MHz, but it was buggy, the best working one was at 63, and that was unstable.
Started making breakpoints and step-by-step execution. They will freeze the processor at T2 (the address is set at the beginning of T1, during T1 it can be checked, and the clock cannot be set on the next clock). It stops, and when trying to continue it crashes.

13xi

Read documentation on Verilog:

  • I don't see how to specify a common settings file for if/ifdef (`include "defs.v" doesn't work in ModelSim)
  • Do module path declarations settings affect synthesis in Quartus?
  • are $timeskew, $fullskew supported in Quartus?

Read the documentation for the memory. /WE should be kept for 7 ns. When writing, data can be kept from 5 ns to the end of /WE, no further (the permissible delay is 0). The memory transfers data to the Z-state by /OE=1 or /WE=0 in 5 ns (so there is a conflict unless you explicitly specify the data delay, and there is none in the project). When reading from the address to valid data, 10 ns.
Removed more clocks (7 out of 46 remained).
Limited the use of i2c_start_condition_n (the pulse is too short). Works unstably.

14xi

Sent data to RAM only in the second half-cycle. 65 MHz, unstable.
Extracted virt_cpu_memwr_n from the processor itself, tied the write to it. Works unstably.
Limited dependencies on i2c_command_strobe and i2c_data_strobe.
Accelerated firmware loading (I2C kicking).
Added display of the number of the loaded ROM page on the border.

15xi

Making i2c synchronous to dvixel_clock. Sometimes the initial bits disappear (0 instead).
In one assembly, bits are occasionally skipped (even with automatic exchange) - although asynchronicity remained only when transmitting from the FPGA.
The ack response from the FPGA interferes. Without it, it loads stably even without additional delays in ARM (but then it freezes, because automatic exchanges do not work without it), but with it, it is completely impossible.
I've compiled a relatively stable version (it doesn't always start) with the only dvixel_clock clock, one build out of 4 is relatively stable.

18xi

Added Alt=Caps Shift+Symbol Shift, like on Sprinter, ZX Evo, and UnrealSpeccy.
Default memory settings and speed when CMOS memory has been erased.
Made data output to memory by shifted_dvixel_clock (shifted by 3.65 ns). In cmos setup, the arrows work like old presses, sometimes it boots with a buggy video controller.
Made reading by shifted_dvixel_clock in the video controller. Didn't help.
Made a record by (ramwrdataenable = '1' and ramwrdataenable_shifted = '1') and returned it as it was. It got better.
Perhaps dvixel_clock and shifted_dvixel_clock are initialized with different numbers when loading from Keil and when turned on.
Remade it to one phase, returned the entry by ramwrdataenable_shifted. The video controller works. But the mouse works only when loading from Keil. NedoOS does not load (hangs on a979 during mount M - it should not get there at all). Another time it hung on 61ba. Another time the ROM did not load even from Keil.
Returned the processor to turn on only after the mouse starts - did not help.
Made run and one step in breakpoints. Works, but at the moment of catching a breakpoint, some points (6, c, e) are unlocked (it happened only once, in another build it was not).
It was impossible to do one step without setting a breakpoint - fixed it. The build is at 68 MHz, stable.
For some reason, you have to press run several times to continue.
Sometimes it stops with the wrong address bus (52, 6c0e), although the PC address is correct (6c0d). 6c0d=halt, in theory nothing else should light up. The stop should always be on M1 T2. Fixed virt_cpu_am1. Fixed it.

19xi

Fixed memory reading, but sometimes it doesn't read (for example, on commands ld (),hl (after inc hl), push bc (after inc (iy+)), dec l (after successful jr z), in a,(c) (after successful jr c)). Fixed promisenomreq. Constant non-reading was fixed, but sometimes it still doesn't read some address.
Shifted shifted_clock by different nanoseconds, didn't help.
Sometimes faulty exchanges via I2C. Sometimes ARM hangs with get_data_flag!=0. If you remove the check for get_data_flag: for some reason send_data_flag turned out to be equal to 2, which led to a hang.
Removed RAM reading - to compare. Partially works, Borsch does not work on 57.
I2C glitches only in the middle of work, where the frequency is low - from the wrong time of setting ack? Tried to make it by the state scl=0 on the 8th bit - exchanges do not work. Made setting ack by the falling edges of scl. ROM is not loaded, but the exchange works. Made it universal - switching the mode on command. 57 once hung in Fatall.
Returned synchronous work with RAM without offset - stable for several builds.
Reads processor data, and not at the specified address. Fixed. 57 stopped working.

20xi

Reading after last_tstate = '1' does not work at all, (promisenomreq = '1' and last_tstate = '0') does not work on 57.
dinst is only used in tstate[2], but other uses of di are in any cycle (although in theory it is di_reg, which latches into tstate[2]). I did the same in 2 - it doesn't work at all. I did reading only in M1 - it didn't help (and the exchange hangs).
Reading only in the first cycle of M1 (request in the last cycle of the command) - didn't help.
Reading only in the last cycle of M1 (request in the 3rd cycle) - doesn't happen (m1_n costs only 2 cycles). Fixed it. Now it doesn't read during a stop (since we are on tstate[2] - the address was known on tstate[1]). Fixed it - now the request can be made in the 2nd cycle of M1. Doesn't work at all and doesn't always help during a stop. You can't stop later - then you won't be able to change the command or move the PC. I did only the 3rd

cycle of M1 or breakpoint_event. It works, but for some reason
sometimes it doesn't read individual bytes even during
breakpoint_event!
Adding disasm from UnrealSpeccy. stdio.h can't be added - no
space. Replaced sprintf with crutches.
Removed string.h, replaced with several small functions - not
enough RAM (504 KB flash, 32 KB RAM). Made a lot of "const" - it
works.
There were problems with incompatibility of char signs, short
width (because of this, addresses were not printed completely).
Writing to disk failed. Fixed - VG93 has higher priority than
the debugger.
Borsch and noise crash when stepping (and Gluk doesn't - because
it's not at 57 MHz? yes, at 28 MHz they are traced normally).
Trying without reading memory when stepping - it still crashes
(no request for reading memory for the processor?).
In theory, it is necessary to make a memory request for the
processor in T2 when starting from a breakpoint, and in the
processor request cycle (while the processor is not active), in
the next cycle (also T2, but already a response cycle) it can
read its data. That is, the processor must wake up when the
response cycle is in progress, otherwise it will read the video
controller data. So, it is necessary to remove breakpoint_event
when the processor request cycle is in progress (in theory, with
the current processor, the request will be issued itself, but
with changes, glitches are possible). So, kill_breakpoint_event
should be ready when the response cycle is in progress
(cpuram_flag = '1'). I tried to make 28 MHz during
breakpoint_event instead (it is not removed during stepping, but
is active during stepping. I need to check the moment of removal
again. Now at this moment the debugger request is not issued,
because the time has passed from one command from ARM to
another). It works.

21xi

How does the I2C frequency affect the primary initialization of
the mouse? before it transmit_cmos_data runs, which waits for
receive.
Moved transmit_cmos_data after mouse initialization - did not
help (hangs on the 1st byte, mouse reset works).
Moved i2c_setup after mouse initialization - helped (although
during mouse initialization i2c exchange does not work anyway!).
Added display of the previous PC.
Added PC change - immediately again it became not always
possible to read at all frequencies (build for 64). And i2c
exchange falls off.
Made blk0_d(7 downto 0) <= ramwrdata(7 downto 0) when
(ramwrdataenable = '1') else (others => 'Z'); etc. - it became
better, but not quite. 57 is unstable.
Made blk0_d(7 downto 0) <= ramwrdata(7 downto 0) when
(ramwrdataenable = '1' and ram_reading = '0') else (others =>
'Z'); etc. - it always reads like this, except for the moment of
writing PC.
PC is not updated immediately. Made manual PC writing more
priority than all other PC writings - did not help. Added a
record to the debugger PC (usually M1 is written there at the
beginning) during PC change - got an unstable build (i2c,
reading). Another seed - same.
Made for half a cycle: blk0_d(7 downto 0) <= ramwrdata(7 downto
0) when (ramwrdataenable = '1' and ramwrdataenable_shifted =
'1') else (others => 'Z'); - it always reads like this.
NGS works, but The Link doesn't work on 28 (shows a picture,
then a black screen). On 3.5 and 7 (it actually switches itself)
it works, but hangs on bars with glitches. After that it's still
poorly reset or doesn't reset at all (due to NGS not being
reset, it remains in the ROM substitution state). In the version
from github too.
Perhaps DMA doesn't have enough time in NGS. This effect uses
the unrolled loop pop hl:ld (hl),d (GSBAR24.H cursor position

2BDD), the unrolled loop pop af;pop hl:ld (hl),a (cursor

position #2EF8) and the unrolled loop pop de;pop hl:ld
(hl),d:dec h:ld (hl),e (cursor position #2FCC).

22xi

With NGS plugged in, it doesn't work at 57 MHz in any version,
starting with p2666_megaturbo.zip.
Made iorq_after_bus_n <= virt_cpu_iorq_n. 57 MHz still doesn't
work.
Removed external memory reading (from ZX-BUS). Tried not to
output mreq to the external bus. Didn't help. Tried not to
output rd, wr, iorq - didn't help. If you don't output csr (/CS
ROM), the processor reads nops. [ROM selection
/csr_out=romaccess_n (from FPGA) -(resistor)-> /bus_rdrom
(replaced by boards) -(resistor)-> /rdrom_in (in FPGA)] It's
surprising that this chain even works at 57 MHz without plugged
in boards. I did (virt_cpu_memrd_n='0' and romaccess_n='0' and
fpga_rdrom_input='1' and cpu_speed(1)='0'), removed the rest of
the protections - it helped. That is, the problem is not in the
short impulse on the rdrom, but in the fact that its own rdrom
simply does not have time to return through the entire board
within a clock cycle. NedoOS does not work at 57 MHz with NGS
(hangs after mounting SD-Card - maybe it accesses NGS?) and
Fatall (it crashes immediately with glitches on the screen).
[ROM page selection rs_out (from FPGA) - (resistor) -> bus_rs
(replaced by plugged devices) - (resistor) -> rs_in (in FPGA)]
made romselect <= fpga_rs_in when portxx77 (3) = '0' else
port7ffd (4) - didn't help (if you remove NGS - it works).
Made slowing down to 28 and even 7 MHz in iocycle - didn't help
(in Fatall too), and it hangs inside NedoOS. Removed the output
of rd, wr, mreq, iorq at 57 MHz. Even without these signals, it
doesn't work with NGS.
Made it not output rd, wr, mreq, iorq, rfsh, halt, busack, m1 at
57 MHz. Fatall started working. NedoOS hung on loading term.com,
another time even earlier, the third time again on loading
term.com, the fourth time it got to clearing the screen. Made it
not output dos at 57 MHz, but restored rfsh, halt, busack. It
got to showing the cursor.
gstest works on 28.
External int and wait were not connected - fixed it (although
wait in TV80 looks suspicious).
You can't stop after the command prefix! Otherwise it will work
on a new command! Fixed it.
The processor immediately goes to the next address or even a
random one - it reads the command that was before the stop. Do

you need to give time to read the command before stepping? (captured in IR in T2 from D). breakpoint_event is calculated in T1. in T2 it is used for cen, at this time the transition to T3 occurs. That is, the processor is frozen on T3. Defreezing occurs at cpuram=1 (RAM reading for Z80). Made T1 by inbreak (although this is a hack, and it will be dangerous when moving calculations to T1 in the future), adjusted the address bus. it became better.

Added writing to memory with a debugger. It works, but in some builds it sometimes writes random numbers similar to command codes (which are not on the screen!).

25xi

KOE says that it does not show on his monitor with my version of the video controller, although from the scanning parameters only the position of the SSI and horizontal blanking by 16 pixels was changed (I checked, inserted the old logic - it assembled 100% the same).

Checked the memory request signals - all sources on the rising edge, except memrd_n_negedge, memwr_n_negedge.

memrd must already be ready in T1, so that there is reading in T2!

Checked that reading from di only in T2 (by posedge).

26xi

Finally made memrd,memwr by posedge, but memrd had to add an extra clock. It still works unstably on 57.

Made iorq,rd,wr by posedge (2 clocks), but rd,wr is only for iorq so far (only memrd,memwr are used for mreq) - it didn't help (and NedoOS doesn't work on 57).

The first half-clock was missing data - I fixed it. It didn't help.

Maybe it's necessary to latch the RAM data unconditionally at a certain moment before the internal latch logic in the processor? But you need to give 10 ns for reading, half a clock is not enough (tested)!

Tried shifting the reading phase. It didn't work through PLL.

Tried through negedge pixel_clock (4.4 ns before the end of the clock) - it reads unstably.

Tried a full write clock - it still reads unstably (especially D0). And some builds don't work.

In the author's version, the reading moment was generally 4.4 ns after the end of the clock (i.e. after the end of OE). But this will not latch the data into T2, and there is also a mux on the way.

Set the time limit "Input delay from pin to internal cells" 4 from blk0_d[*], blk1_d[*] to IR and DI_Reg - Fitter ignored it. I set IR[0], etc. Fitter ignored it. I set blk0_d[0], etc. Fitter ignored it. The documentation hints that this is in picoseconds, I set 4000. Now it says that it should be from 0 to 6, and ignored almost all (but not all!). Or is this the number of intermediate cells? I set 0, but what's the point? It didn't help.

Do I need to insert a 90-degree delayed clock into the processor itself specifically for writing to IR and DI_Reg?

27xi

Delayed writing from RAM to DI_Reg by 90 degrees (this also applies to data from ports!). NedoOS does not work on 57 with NGS (it works without it).

Delayed writing from RAM to IR (current instruction) by 90 degrees. Everything is broken - constantly executes some 3-byte commands. Tried to simplify the IR logic without the delayed clock. Everything is still broken, and the memory in the debugger began to be read unstable. Added a 90-degree delay for the debugger. Reads stably, but the processor is glitchy (sometimes it only has time to display the colour table).

Corrected the choice of the readable chip ram_blk to wasram_blk (since it is already the beginning of T3) - it still glitches.

Made unconditional buffering of RAM data by posedge dvixel_clock, then using in other places (4.4 ns before use) - still buggy.

Removed all RAM restrictions, there were warnings - did not help, video controller began to read unstably.

Returned some restrictions (Fast Output Register, Fast Output Enable Register, Speed ??Optimization Technique) - the debugger and video controller were fixed, the processor was not.

Set 28 MHz initially, removed Fast Output Enable Register (Fitter ignores it) and returned DQS Frequency (why, if it is not DDR?). Does not work at 28 either. Removed override_ram - at 28 it falls into BASIC (stable), sometimes without resetting BASIC (continues to edit the same line after double F12), although the reset buttons work, only all the corresponding options are buggy.

Made databus mux by virt_cpu_memrdresult_n (the cycle immediately after the true T2). memrd and memwr were made by posedge and exactly one cycle before the true T2 (i.e. with cen). All reading is tied to the true T2 (RAM operating time on the processor). Reads FF.

Rewrote promisemreq (rd: before the true T2, wr: before the true T3) - did not help.

Removed IOWait (stretches T1 into iocycle) - did not help.

In ModelSim everything works, although there are short impulses in the signals!

Tried constant 57 MHz (there are no short impulses) - it helped.

Tried constant 28 MHz - reads FF. Does not work in ModelSim either. Found a repeated IR_change, removed it. It worked in ModelSim, it worked in FPGA.

Removed the test, rebuilt with real RAM - at the beginning, ROM executes something, but almost does not write to memory, numbers rarely arrive in the debugger.

Returned reading in the debugger (override_ram) and switching 57/28 MHz by reset. Something is written to the screen, but little.

28xi

Replaced promisetrueT2/3 (taking into account the complex promisecen) with a simpler promiseT2/3 (now one request cycle is not guaranteed, there may be requests in dead cycles) - NedoOS works, but Black Raven does not load on 57 (it loads without NGS). Sometimes it hangs when starting NedoOS after "ZXNetUsb not found".

Replaced write_buf_negedge with write_buf_posedge in the do processor data mux. NedoOS does not boot on 57 (hangs before mounting the SD card or after loading term.com or after clearing the screen) (everything is fine without NGS).

Enabled debugging iorq,rd,wr by posedge (T2+T3) - does not work at all (failure on 0001 ex af,af' (08 d9 c3...) - gets to ffdc). As if the data does not have time to decrypt the command - Quartus does not check when they are from different but related clocks?

It became clear why some old builds worked, and some did not - in some cases, the databus mux managed in 6.3 ns within the RAM cycle (RAM itself = 8-10 ns), but there was also the logic of the latch in the processor. The total should not exceed 17.54 ns. And in the author's versions, databus megamux + latch in the processor managed to do it in 13.1 + 17.54 ns (since 28.5 MHz).

Returned simple memwr, promisemreq, memrd via negedge - works.

Simplified memrd_n_negedge - only in T1 (earlier, T2 was also required, since the input mux of the processor databus was via memrd) - works.

Simplified the databus mux via ideportfound - works.

Simplified portfound (addr_bff7, removed ebl in unnecessary places). Simplified the databus mux via wasrdromaccess_n and removing iord in internal ports (internal ports now have priority) - works, but the least significant bits of the palette are broken (r, g are always at 0 - bright).

Changed the conditions - now data from ZX-BUS always comes by default (internal ports have priority, memory is not intercepted) - databus mux already fits into 6 ns. Changed to 5 ns. JP does not work. Shows the longest m1 and write_buf_posedge, because they are by posedge (only 5 ns remains for logic with them in the databus mux).

Returned write_buf_negedege. JP does not work. rd, wr, etc. Do not have time to form themselves by negedge - they need 7 ns, and there is only (17.54/2)-5.11 = 3.66 ns.

Changed the conditions (RAM was not read). Made wasram_blk by negedge. Fit into 5 ns (portfound is the slowest), but there are still 64 errors in the decoder. Works with buggy lower bits of the palette and does not play AY.

Made 4 ns and portfound by negedge shifted_dvixel_clock (4.4 ns after negedge dvixel_clock, 4.4 ns remains until the new dvixel_clock clock) - does not have time. AY plays, but out of tune.

Made portfound by delayed (posedge dvixel_clock) rd, wr, dos, removed ebl - the same thing, the entry in the debugger is broken.

Made portfound and a latch in the video controller by negedge dvixel_clock - the same thing, the entry in the debugger works.

Made the assembly of port_rd_data partially through and, not mux - now other signals slow down, term.com not found. the entry in the debugger is broken.

Simplified the signal for directing data to ZX-BUS to virt_cpu_wr_n. In the databus mux iorq_rd_set (used in rd?) and memrdresult_n do not keep up. term.com not found.

Made memrdresult_n by negedge dvixel_clock. Simplified to a minimum iorq, mreq, rd, wr - all by negedge. Databus mux almost fits. SD card does not work, floppy drive does not work either, raining on "go sleep". Reading and writing in debugger work.

Feedback do -> IR is visible (do -> virt_cpu_d (in write_buf_negedge) -> fpga_d (in virt_cpu_wr_n=1) -> virt_cpu_d (in virt_cpu_rd_n=0) -> dinst (unconditional) -> IR (conditional latch by lateclk)). Therefore, I rewrote the databus mux using virt_cpu_wr_n. It did not help.

Reading buf_fpga_d instead of fpga_d - it became better, the databus mux fits into 3.835 ns.

Made do in wr (and not in write_buf_negedge) - that was how it used to be. I left 3.65 ns on shifted_dvixel_clock - that was how it used to be. It does not fit in time, the write in the debugger is broken.

Rewrote write (you can also use iorq, no_read as well) to the register via promisewrite. There was a mux in the decoder. To start it from T1 (we are already using dvixel_clock in negedge in T1), I set it in the true last_tstate. Gluk works, but Gluk boot does not start, TR-DOS is buggy. Of the reset buttons only D and keyboard test are working (for some reason on any one keypress). Entering the keyboard test is always - CY is screwed up somewhere (601f: jp c,61d2=TSTKEY).

Found one glitch with promisewrite in push. Made iorq_r via promiseiorq. The glitch with the keyboard test and launch in Gluk boot was fixed, but the 3D engine does not work (even print "a", print 2, list 11 (list works by itself), randomize usr 15616 do not work, although in TR-DOS you can look at LIST), and Fatall shows the cursor in the wrong place.

In tv80_core, I replaced iorq_i with iorq_r for speed. The decoder keeps up, but for the databus mux there is not enough 0.896 ns (for one of the feedback bits, which is not needed). The same glitches. Doctor (on D:), CMOS Setup, C, D, help, tstkey work. Returned complex rd, wr, iorq, mreq - palette is not fixed, but sees SD-card (but does not load NedoOS and does not show Fatall panels). Decoder is in time, but for the databus mux there is not enough 0.886 ns.

Removed feedback - D works as di in processor (it was in TV80). Now everything is in time.

Returned virt_cpu_iord_n = '0' (depends on ZX-BUS!) in the databus mux of the internal ports. There is not enough 1.127 ns for the databus mux. Palette is fixed. NedoOS is not fixed, Fatall too, disk A works.

Instead of virt_cpu_iord_n = '0' I made just virt_cpu_iorq_n = '0' for internal ports. Returned slow write. Palette is damaged again. NedoOS reaches term.com not found.

Added and virt_cpu_rd_n = '0' for internal ports. Enhanced decoding of betadisk ports - overlapped SD-card. Palette OK, NedoOS OK. With NGS plugged in: NedoOS does not boot on 57 and 28, hangs before or after "Drive M mounted".

29xi

promisewrite did not work correctly during index offset reading cycles. Fixed - Fatall and all reset options work, BASIC and NedoOS do not (text mode does not turn on, messages are visible on the graphic). AY and Palette used databus affected with ZX-BUS, fixed it.

Added register output, as well as processor states:
{1'b0,tstate[6:0], IntCycle,NMICycle,Prefix[1:0], IntE_FF2,IntE_FF1,IStatus[1:0]}.

128e did not work: ld (iy+31),2. Figured out the order of machine cycles: 0,0,5,6,2 (1 is skipped - only in this command!). Fixed it. BASIC works. NedoOS does not load with NGS, Fatall does not work. Without NGS it is fine. Removed palette protection by eff7[2], palette glitch in KOT disappeared.

Remove the shifted clock from the processor and from the

processor data latch. Everything works (AY plays normally), but ram writing in the debugger is buggy.

Accelerated the dos_n signal, which is on negedge (wasdos_n is sufficiently delayed in ports) - with NGS plugged in, NedoOS does not load even on 28, Fatall works. Recording to A is broken (sometimes even the directory is buggy).

Rewrote breakpoint_event by negedge. Reading in the debugger is broken - fixed it. Made a record in the debugger in any free cycle during breakpoint_event. F7 immediately stops on T1 or T2. breakpoints always stop on T2. ??recording on a breakpoint does not work again (T2), works when stepping (T1).

Forgot and tstate(1) - added. After stopping in a random place, it steps through the machine cycles of the command. F9 too. At the same time, it increments R. With NGS, NedoOS hangs when loading: at 57 MHz it always reads port 0057, at 28 MHz it always reads port bb.

Added not(virt_cpu_m1_n) - for some reason firstm1_n is formed not only in M1. Removed reading ZX-BUS. Fixed. At 57 MHz, NedoOS does not load with NGS (it always reads port 0057), at 28 it loads. Without NGS it is fine.

Replaced the ZX-BUS direction with write (so that the data was available not only in the strobe, suddenly they do not have time to capture), returned the ZX-BUS databus reading. Did not help, it spins on bb at all frequencies even without NGS.

Made a full decoding of the betadisk ports (intersected with 3b NGS?). Did not help.

Returned the conditions for external ports. Set the scan parameters from the new version of the author's. Did not help.

Inverted write, inserted a new video controller - 57 NedoOS does not boot with NGS (hangs on the SD card ports), without it it works. 28 boots both ways, the NGS test passes.

Now the work with RAM is completely synchronous (from this moment all builds are stable), but ZX-BUS works only at 28 MHz and below!

2xii

Removed ZX-BUS reading from the databus - at 57 NedoOS does not boot with NGS (hangs on the SD card ports).

Removed iorq_after_bus - NedoOS boots at 57.

Returned the data bus without iorq_after_bus - everything boots, gstest passes at 28, but hangs on uploading test tune. Returned complex logic with ZX-BUS priority over RAM reading and rdromaccess instead of wasrdromaccess. Didn't help. Made ZX-BUS priority over everything as it was (only iorq, rd are buffered) - didn't help.

Gluk service incorrectly shows stack (expected e=0 from remote cycle) - fixed.

Added Mode=FastZ80 (shortened processor clocks) depending on megaturbo. Doesn't work (wrong bc after ldir). Removed the clock limit in machine cycles in Mode=1 - Gluk service started with all utilities, but Fatall and NedoOS beep instead of starting (via BASIC) and hang at any speed. Returned complex logic with ZX-BUS priority over RAM reading and rdromaccess instead of wasrdromaccess - did not help. Made ZX-BUS priority over everything as it was (only iorq, rd are buffered) - didn't help.

Returned Mode as a constant in alu and mcode - 50 MHz, didn't help. The order of parameters in # is clearly important, and only default values ??are specified inside the modules. Removed from parameters everywhere, pass them as variables - works, in megaturbo 3168 dhrystones/s.

Added no_read to promisemreq - in megaturbo 3225 dhrystones/s (was 3097, at 28 MHz - 1694).

3xii

Set PC works glitchily, because you need to switch to T1 (to set the reading address). Tried to fix it, at the same time replaced T1 in writing with tlatewrite - assembly at 57, hung on ldir.

Replaced T1 in reading too and set A together with PC - works. Accelerated no_read via reg.

In z80.com the keyboard inside doesn't work (on 28 too. bit 0,c:jr z...), although it works during reset (combinations are polled via in a, ports via keymatrix, and there in r,(c), but it works in other programs), reset 6+8+0 sometimes works, but output (1+3+5), debugger (4+5) and snapshot (1+2+5) work. It just hangs and works on some processors due to the ld a,i glitch, fixed it (replaced it with halt).

The buttons in Cyrus 2 don't work correctly (only space is correct), there the code is from rst 0x38 of 48 BASIC, only instead of ports it reads from keymatrix. This is because system variables are not cleared (works after smb). Fixed it (set system variables to 0xff).

4xii

Accelerated decoding of CB and ld (hl), n in core via registers - gstest works slowly, shows memory reported by boot: 255 pages, reported by 0x20: 0 bytes, hangs on uploading test tune (reads from bb). The second time it works fast, reported by 0x20: 16711679 bytes, hangs on uploading test tune (reads from bb).

Accelerated inc/dec rp to 4 clocks in megaturbo - Fmax=57, in megaturbo 3263 dhrystones/s.

Accelerated all M1 to 4 clocks in megaturbo - on 57 even BASIC does not work, on 28 Borsch glitches. Accelerated only in push and djnz - build at 60, same. Accelerated only in push - build at 59, same. Speeded up only djnz - build at 59, works. Speeded up int, ret cc, rst - build at 57, BASIC doesn't work. Removed rst acceleration - build at 63, Borsch doesn't work and doesn't load, br works. Removed int acceleration - build at 59, works. These commands have one thing in common - they write to the stack (push, int, rst).

Speeded up outi(r) - build at 59, in megaturbo 3267 dhrystones/s, works. Only push, rst, int, nmi remain.

IncDec16Moment_r <= ((tstate[1] && !mcycle[0]) ||
(tstate[3/*2*/] && mcycle[0])) && IncDec_16[2];
//for tstate[4/*3*/] ([2] in next mcycles)

changed to tstate[2] && mcycle[0], as it was before processor optimization, so that 16-bit increments are counted in T3, not in T4 - does not work (spins on ldir). IncDec_16 is not ready in T2 yet! took it into account separately - does not work. Tried to enable 4 cycles on M1 always for speed - assembly on 53, inc hl works as inc bc (decoder does not have time?).

5xii

Returned increments to T4 M1, made a separate DecrementedSP_r, which in T_Res by aDECSP is copied to A. aDECSP and

unconditional DecrementedSP_r are formed in T3 (and in general
always). Doesn't work.
Made calculation of DecrementedSP_r in T3 - doesn't work (in
000a push bc the most significant byte (the first written) was
not written to memory).
Returned durations of these commands. Doesn't work. Returned aSP

  • works. Made again 4 cycles in mode=1, aDECSP uses SP-1 and
    only in mode=1 - works (3276 or 3280 dhrystones/s).
    Returned 3 cycles in other machine cycles in mode=1. megaturbo
    doesn't work (Gluk, D, keyboard test work, but S doesn't erase
    the cursor, nv doesn't move the cursor, dhrystone doesn't work)
  • ldir works as ldi.
    Fixed it like this:
    if (/*I_BC_BT_r*/I_BC || I_BT)
    F[Flag_P] <= #1 IncDecP;

Now 3453 dhrystones/s - equivalent frequency of 58 MHz!

6xii

Added promisecpuram_flag signal (request clock, next -
cpuram_flag) to be able to make a complex arbiter.
With NGS Fatall does not work at 28 (reads port bb), although it
works at 57. Returned a complex databus with external priority,
but without checking iorq, rd on internal ports - did not help,
and gstest still hangs on uploading test tune. Returned a simple
databus - did not help.

9xii

Made data for ZX-BUS from the end of the previous clock. Fatall
at 28 was not cured (reads port bb), although it works at 57.
Snapped ZX-BUS data from the end of clock T2 (the previous clock
was also T3) - did not help, gstest began to correctly show the
memory size.
Returned ZX-BUS operation to 57 MHz - NedoOS started loading at
57 with ZX-BUS, so the fix was not in vain. Fatall hangs both at
28 and at 57.
Added rdrom latch using the same principle (ideally it should be
in the middle of T3, but now it is unrealistic) - everything
broke at 57 with NGS, and gstest did not become better. Instead
of latch, I made (romaccess_n = '1' or fpga_rdrom_input='0') -
Fatall hangs at 57 too.
I made (wasromaccess_n = '1' or fpga_rdrom_input='0') - the
same. May not work if rdrom is only in mreq, rd strobe (ends in
the middle of T3, not at the end)
Judging by the source, gstest operation should not depend on
rdrom. How does uploading test tune differ from other
operations? only sendDat():

    output(datareg, data);
    dataread2 = 128;
    while (dataread2 != 0)
    {
        dataread2 = (input(cmdreg) & 128);
    }

In old firmware, with good performance, zeros were read from bb
(or 01101110 after the new firmware was running) (now 00111110
is read, and 10111110 is held during the upload process).
Previously, everything latched 4.4 ns later than the end of T2.
Otherwise, NGS does not have time to respond? But I always set
3.5 MHz - nothing changed.
Too long iorq? No, everything is as it was.
Is there something wrong with writing to the port? do changes at
the end of T1 (in theory it should be at the beginning or in the
middle), for mreq wr has not yet been issued, but for iorq it
has. Indeed, wr is needed for the full duration of iorq, for
this iorq will have to start from the end of T1. That's how it
is in the source code (in ModelSim the processor stopped
working).
Made dbus_oe by write (in reality fpga_dir is used there: 1 from
fpga, 0 in fpga). Didn't help.
It turned out that the fpga_dir signal was renamed! returned -
now it always gets into the keyboard test (although the keys are
not pressed, and the test itself works adequately).
Removed the ROM substitution. Fatall was not fixed. At 57 it is
set to 0001 xor a (after di), it does not step, it only
increments R. interrupts are disabled (IM 1), while Halt_FF=1
(it is set at Halt (IR[5:0] == 6'b110110 halt) in last_tstate.
but we are not after halt! how can this be? an error in
promisenoread?
I tried a complex databus, only with buffering of sources by
posedge. Fatall crashes at any speed in the same places (that
is, the problem is not in the rdrom, there is protection at 57)

  • the same glitch with a loop. gstest works at any speed.
    In ldi there was an invalid promisenoread - I removed it, as I
    removed it in cpi, ini, outi (it is necessary to do it depending
    on the loop or somehow throw out the last machine cycle). It
    still crashes and loops in the same way.
    I removed no_read (promisenoread only remained in add hl,rp, jr,
    jr cc, adc/sbc hl,rp) - did not help.
    Removed promiseIORQ - did not help.
    Where does Halt_FF come from? can only be on the halt command.
    It is reset by reset or IntCycle or NMICycle.

10xii

Added display of the dos signal.
Removed everything from the external databus except IDE - that's
how Fatall works.
Returned the port data - it still glitches.
Substituted 00 instead of them - it still glitches. Without an
SD card too.
When stepping, it does not do what is written! Fatall enabled
eff7 bit 3 (pg0 in 0000). Removed this feature - Fatall was
fixed.
Returned the full external databus, promisenoread, promiseiorq -
it works (even memory detection in gstest is at 57).
HALT is always on the next command. I reset Halt_FF in inbreak
to avoid hitting the interrupt handler every time. Didn't work.
When we take a step, inbreak is removed until the next command,
so the IR from halt is still processed. I gave breakpoint_event
instead - didn't help. I also reset IntCycle - it helped.
Tried removing the extra machine cycle from ldir - couldn't.

11xii

Added the output of disasm on oldpc.
Tried rdrom at 57 MHz like this: (virt_cpu_memrdresult_n='0' and
wasromaccess_n='0' and fpga_rdrom_input='1') - works at all
frequencies. gstest works, except for the memory size at 57 MHz.
Fatall at startup at 57 MHz (in Fast or Max mode) spins on
reading bb (in Slow mode it's normal), at 28 it's normal, after
switching on the fly to 57 it's normal.
Returned the priority of external ports via fpga_io0..2 - the
same, but the memory in gstest at 57 is shown correctly.
Tried promisecpuram_flag = promisemreq;
//~virt_cpu_wait_counter[0];

  • the ROM firmware is not loaded this way.
    Enhanced decoding of eff7 to exf7 (otherwise it would intersect
    with 77), returned bit 3 eff7 - it works.

ZX-BUS started working at 57 MHz (p2666_arbiter15.zip)!

12xii

Removing delays in 57 MHz mode.
Simplified the conditions for accessing the debugger and VG93
memory. Fatall does not start at 57 - it spins on reading bb,
NedoOS does not boot at 57 - it spins on reading bb.
Changed priorities for setting addresses and data (for other
signals like this): ARM > Z80 > VG93 > debug (video will be
needed between Z80 and VG93). Same. VG93 writes nonsense
(parasitic writes go through the byte, i.e. correct bytes are
stretched: b?o?o?t etc. i.e. the write pulse lasts 2 clock
cycles, write_trz is removed by (vg_tormoz = '1' and
vg93_override_ram = '0'), and vg_require_tormoz is set and
removed by it).
Added a condition for VG93 to write (and read) only in even
clock cycles (it was like that before). It helped.
Moved the arbiter to top. Added a video controller on common
rights (so far it does not allow VG93 and the debugger to work).
Made the video controller capture only valid data (if the
request was not interrupted by higher priority ones): the
address is formed through a clock, then an arbiter clock, then a
reading clock, then half a clock for latching and half a clock
for changing the pixel - a total of 4 clocks 57 MHz (4 pixels of
text, 2 pixels 6912), this is exactly the polling frequency that
should be. Basically, it shows correctly, but: 6912 - a little
raining (black and white), EGA - normal, text - letters and
attributes instead of each other (and at 57 the 2nd symbol
disappears), a little white raining at 57 MHz.

13xii

Rewrote the video controller so that all ATM modes work from one
counter, with one data buffer and one frame multiple of 8.
Doesn't work. Drew clocks on paper - it doesn't work as shown.

16xii

Made the reading start 4 cycles (2 small pixels) earlier -
textmode: normal (only one pixel is missing on the left), EGA:
on the left of the screen instead of pixels with x=0.1 displays
128,129, pixel 128 is visible on the right of the screen. hires:
incorrect attributes in the left column, one pixel is missing on
the left (it's on the right). 6912: one pixel is missing on the
left (it's on the right). At 57, in textmode there is a small
raining with attributes (attribute delay by 2 character spaces),
on EGA and 6912 there is also small raining. The raining is
explainable only with two delays in a row.

20xii

Showed on screen and analyzed the arbiter's cyclogram from the
screen.

23xii

Repeated requests from the processor in adjacent cycles are
visible on 28 constantly, on 57 at least during interrupt
processing, on 3.5 they are not visible.

24xii

In ModelSim, repeated requests for 28 MHz are not received.
promisemreq and memrd, memwr work on negedge, but this should
not spoil.

25xii

Checked on ModelSim at 28 with the halt command (0x76) - all
requests take 1 clock cycle!
Made mreq, memrd, memwr on posedge - at 3.5 (clean), 7 (clean),
57 (with parasitic requests) it works, at 28 (clean) it hangs
(when switching to 57 it continues to work).
Checked on ModelSim at 57 - all requests take 1 clock cycle!
(and the short impulses disappeared)
Took out NGS - everything is the same, but 28 is with parasitic
requests and raining.

26xii

Tried halt (0x76), rst 0x38 (0xff) commands in hardware - no
parasitic requests (28, 57). In ModelSim, does not work.
Made a condition for reading (~write && ~no_read) - still
parasitic requests on 28, 57. Even on the out:jr chain.
Tried the constant jr command (0x18) - parasitic requests on 57
(sometimes on 28). In ModelSim, the command does not work.
setpc_n, inbreak were not set - added, did not help. Added
Mode=1 - did not help. Made the output of D constantly - did not
help.
This does not work in ModelSim (it turns out to be Z-state):

always @* virt_cpu_d[7:0] <= 8'h18;
assign virt_cpu_data[7:0] = virt_cpu_d[7:0];

Only direct substitution of 8'h18 in the processor works.
But there are no parasitic requests anyway.
Apparently, parasitic requests have been cured, and the screen
is an illusion due to half cycles (the period is 24 half cycles,
the halves are visible). I checked with whole cycles - yes. Now
there is no raining.
Moved the 6912 frame by 2 small pixels to the left, the EGA
frame by 1 small pixel to the left - OK (for textmode too),
zeroing the address shifted by 1 small pixel to the left -
didn't help.
Zeroing the address shifted by another 1 small pixel to the
left, removed the request phases from the screen. OK, but
unstable build with Fmax=57.
Simplified the arbiter - OK. At 57 MHz - gstest works (NGS in
slot 3), ZXNetUSB does not (in slot 1). 28 - the opposite (it
happens with NGS, you need to re-enable it). With ZXNetUSB
without NGS, the red light after mount (even at 57) and hangs on
"dhcp resolving" (without a cable only at 28, with a cable at 28
and 57)! Moved ZXNetUSB to slot 3 - didn't help.
With the author's firmware in slot 3 - the same thing, but in
slot 1 (without NGS) - it works, ping passes.
zxwiztst.$C passes the memory test (by ports). SL811H - no
device detected. "send broadcast" hangs on "open socket in UDP
mode" (through memory mapping), similarly "receive packet".
To make the debugger work stable, I added busy signals (at the
time of the request) along the priority chain from the request
signals of previous subscribers - it did not help.
At both frequencies, VG93 writes every second byte extra, reads
well. I made an automatic removal of the VG93 request - it was
fixed, but the debugger is not stable.
Corrected the typo debuf_mreq_busy - the debugger was corrected.
The first character in 16C is duplicated. Fixed.

Now 57 MHz without lags and raining - the equivalent frequency
is 63 MHz (http://alonecoder.nedopc.com/p2666_arbiter41-.zip)!

27xii

Memmap in zxwiztst.$C works when launched from a floppy disk on 3.5 (finds memmap, but sometimes does not find ports), and completely works if the frequency is hard-coded in the firmware to 3.5 MHz or 7 MHz (14 does not work). But wizcfg still crashes.

Tried adding a 15-cycle delay after rdrom during csr - one build is buggy, the other hangs in the test on ZXNetUSB detection (on the ld (0000),a, T1 command). Added !rdromwaiting - does not see memmap on max, fast, slow.

Tried starting rd in the middle of the first T1 - did not help.

28xii

Tried catching rdrom and starting the brake at the end of T1 (to delay T2) - did not help.

Traced wizcfg. Crash in wiznet_read. pgsys (0a) is screwed up.

Made breakpoints for writing to memory (the lower 4 work for both execution and writing, the upper ones only for execution).

Found out that the ini command spoils it (08:50fc - in the ZX Evo version it is 51aa, in the emulator it does not get there, because in wizcfg there is an emulator detection) in w53_rd_udp_loop in the w5300 driver, a very large ix counter is set, it is read from ports 30ab, 31ab (w53_rd_ipraw) (50cd - in evo 517b). What is read is b7,8e (hl=b78e), de=0800, hl-de is subtracted, then added back.

Temporarily made 3.5 MHz in !megaturbo. Didn't help. And because of rdrom stretching, the test doesn't detect memmap or ports.

Removed rdrom stretching. Didn't help, sometimes the test doesn't even see ports.

There could be a parasitic rd in no_read - removed. Stretched iorq and wr for iorq according to the stretched rd. The SD card does not work like that.

Returned rd, wr, iorq to the unstretched state. Did not help with NedoOS. But the test passes with ports and memmap.

As a result, ZXNetUSB does not work fully (it worked correctly only in old firmware) (http://alonecoder.nedopc.com/p2666_megaslow2.zip). If you can fix it, contact me!

Share your thoughts about the article