Skip to content

rtl: 68k bus arbitration (BR/BG/BGACK) for Zorro II DMA#87

Open
codewiz wants to merge 1 commit into
captain-amygdala:mainfrom
codewiz:z2-dma
Open

rtl: 68k bus arbitration (BR/BG/BGACK) for Zorro II DMA#87
codewiz wants to merge 1 commit into
captain-amygdala:mainfrom
codewiz:z2-dma

Conversation

@codewiz
Copy link
Copy Markdown

@codewiz codewiz commented May 15, 2026

Summary

Implements the standard 68000 BR / BG / BGACK bus-arbitration handshake in the CPLD. The stock RTL declares those pins as ports but never samples them, so Zorro II bus-master devices (e.g. the A590 SCSI controller) can't take the bus for DMA.

Changes in rtl/pistorm.v:

  • 3-state arbitration FSM (IDLE → GRANTING → RELEASED → IDLE), two-flop synchronizers on BR_n / BGACK_n
  • Tri-state hand-off: M68K_FC, M68K_AS_n, M68K_UDS_n, M68K_LDS_n, M68K_RW are now inout, gated by a bus_owned flag so the PiStorm cleanly releases the bus when the requester asserts BGACK
  • CPU FSM stays parked at S1 while the arbiter is not in IDLE (matches a real 68k: no new cycles between BG-out and BGACK-in)
  • One existing reg declaration moved earlier so iverilog accepts the file

Changes in rtl/pistorm.qsf:

  • Internal weak pullups on M68K_BR_n / M68K_BGACK_n — the long CPLD-to-CPU-socket trace was picking up DMA noise on the A500 and false-triggering the arbiter, which caused intermittent lockups during heavy disk activity even on fast-RAM accesses

Changes in rtl/pistorm.sdc:

  • set_false_path -from entries for the new async inputs

New rtl/pistorm_tb.v:

  • Icarus Verilog testbench, eight scenarios: normal cycle, BR while idle, queued op during release, BR mid-cycle, BR pulsed (sync filter), BGACK delayed, two grants back-to-back, BR + queued op race
  • Two continuous protocol assertions

Resources: ~86 / 570 LEs on EPM570T100C5 (15 %), 88 / 240 LEs on EPM240T100C5 (37 %).

Test plan

Tested on PiStorm Classic (EPM240) + Amiga A500 + A590 sidecar:

  • devtest scsi.device 0 -i 8192 -l 1000 -m zorro — A590 fast RAM via DMA
  • devtest scsi.device 0 -i 8192 -l 1000 -m chip — chip RAM via DMA (Agnus arbitration)
  • devtest scsi.device 0 -i 8192 -l 1000 — no -m, regression check
  • Destructive read/write modes — devtest compares read-back data, so the bus is verified correct both with and without DMA
  • Simulation: iverilog -g2012 -o pistorm_tb pistorm_tb.v pistorm.v && vvp pistorm_tb — all 8 scenarios pass

Draft because I want to do one more hardware run with the latest build to confirm no regressions before marking ready for review.

🤖 Generated with Claude Code

The stock RTL declares M68K_BR_n and M68K_BGACK_n as input ports but
never samples them, and ties M68K_BG_n high — so the CPLD ignores
bus-master requests from Zorro II devices like the A590 SCSI controller
during DMA. This patch implements the standard 68000 BR/BG/BGACK
handshake:

  - Two-flop synchronizers on M68K_BR_n and M68K_BGACK_n
  - A 3-state arbitration FSM (IDLE -> GRANTING -> RELEASED -> IDLE)
    sharing the c200m clock domain with the existing CPU FSM
  - Tri-state hand-off: M68K_FC, M68K_AS_n, M68K_UDS_n, M68K_LDS_n,
    M68K_RW are now inout, driven through a bus_owned flag so the
    PiStorm cleanly releases the bus when BGACK is asserted by the
    requester
  - The CPU FSM stays parked at S1 while the arbiter is not in IDLE,
    matching the real 68k's behavior (no new cycles are started
    between BG-out and BGACK-in)
  - Internal weak pullups on BR_n / BGACK_n to backstop the
    motherboard's external pullups; the long CPLD-to-CPU-socket trace
    picks up DMA noise otherwise, which previously caused intermittent
    lockups on fast-RAM accesses during heavy disk activity
  - set_false_path entries in the SDC for the new async inputs
  - rtl/pistorm_tb.v: an Icarus Verilog testbench covering eight
    scenarios — normal cycle, BR while idle, queued op during release,
    BR asserted mid-cycle, BR pulsed (sync filter), BGACK delayed,
    two grants back-to-back, BR + queued op race

Also moves the `ipl` reg declaration earlier in pistorm.v so open
source simulators (iverilog) accept declaration-before-use; Quartus
was lenient about this but iverilog is not.

Tested on PiStorm Classic (EPM240) + Amiga A500 + A590 sidecar:
  devtest scsi.device 0 -i 8192 -l 1000 -m zorro   (A590 fast RAM via DMA)
  devtest scsi.device 0 -i 8192 -l 1000 -m chip    (chip RAM via DMA)
  devtest scsi.device 0 -i 8192 -l 1000            (no -m, works as before)
  Destructive read/write modes also pass — devtest compares read-back
  data, so the bus is verified correct both with and without DMA.

Resources: ~86 / 570 LEs on EPM570T100C5 (15 %), 88 / 240 LEs on
EPM240T100C5 (37 %).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 15, 2026

I totally vibe coded this since I know calmost nothing about Verilog. Sorry if this isn't not the correct approach.

What I can say is that I have flashed the EPM240 variant on my PiStorm Classic and tested it with my A590 as described above by Claude. DMA works reliably with it:
EPM240_dma_v3_nohold.svf.gz

This svf is untested, since I don't have an EPM570-based PiStorm:
EPM570_dma_v3.svf.gz

@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 15, 2026

I also have a GVP Impact HC+8 controller which I can hook up to my A500 with a Zorro adapter.

From past testing, I know that this combo requires the "longer_hold" firmware in order to fix data corruption issues when accessing onboard Fast RAM. I have attempted to recreate this patch since the sources are lost, but it's out of scope for this PR.

Lightly tested patch available on demand.

@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 16, 2026

I tested the GVP Impact HC+8, and it's also behaving very well.

All I/O tests with DMA to chipram and GVP onboard ram are passing:

devtest ominiscsi.device 0 -iii 65536 -l 100 -m chip
devtest ominiscsi.device 0 -iii 65536 -l 100 -m chip -d
devtest ominiscsi.device 0 -iii 65536 -l 100 -m zorro
devtest ominiscsi.device 0 -iii 65536 -l 100 -m zorro -d

@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 16, 2026

AmigaTestKit crashed (yes, crashed!) once during a long-running memory test on the GVP onboard RAM :-(

However, I have already experienced RAM issues on this GVP card when 4 SIMMs are installed. My DMA changes are unlikely to affect the stability of CPU bus cycles (except for slight timing differences).

This happened with a single c7m delay cycle in S6, but I think my GVP requires 2 delay cycles (as done by the longer_hold firmware). I will test more and report back.

@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 16, 2026

UPDATE: this was a bad idea, do not use these variants. See PR #89 instead.

I built a few more variants of the bus arbitration firmware with extra changes to holds AS, address and data lines for the specified number of 7MHz clock semi-cycles:

EPM240_0hold.svf.gz
EPM240_2hold.svf.gz
EPM240_3hold.svf.gz

The 0hold variant should match the stock firmware timings.

The 2hold variant works on my A500 and makes access to the GVP onboard RAM 100% reliable, but I still see occasional compare errors in devtest's integrity tests when using GVP onboard RAM (-m zorro). I think this matches the former "long_hold" firmware.

The 3hold variant is my attempt to approximate the "longer_hold" firmware: since 2 full 7MHz cycles would throw the m68k bus access beyond the 4-clock cycle expected by Agnus, I thought that maybe 3 half cycles would fit. However, IT MAKES MY A500 RESET LOOP. I'm sharing it in the hope someone can figure out what's wrong with it.

These are entirely untested, since I don't have a PiStorm with an EPM570:
EPM570_0hold.svf.gz
EPM570_2hold.svf.gz
EPM570_3hold.svf.gz

I will open a followup PR after some more testing and cleaning up things a bit. Meanwhile, this is the raw diff corresponding to the above builds. Comments welcome.

diff --git a/rtl/pistorm.v b/rtl/pistorm.v
index d0c1b8c..abdba94 100644
--- a/rtl/pistorm.v
+++ b/rtl/pistorm.v
@@ -2,6 +2,17 @@
  * Copyright 2020 Claude Schwarz
  * Copyright 2020 Niklas Ekström - rewrite in Verilog
  */
+
+// Extra bus-access hold: HOLD_CLOCKS half-c7m steps added in S6 to every
+// 68k cycle, holding AS / address / data longer before deassert. Meant to
+// help Zorro II cards that mishandle the PiStorm's very short bus cycles
+// (e.g. GVP RAM). Default 0 = stock, so scripts that don't set it (e.g.
+// the Windows make.bat) keep working.
+//   0 = stock   2 = +1 c7m   3 = +1.5 c7m
+`ifndef HOLD_CLOCKS
+`define HOLD_CLOCKS 0
+`endif
+
 module pistorm(
     output reg      PI_TXN_IN_PROGRESS, // GPIO0
     output reg      PI_IPL_ZERO,        // GPIO1
@@ -186,6 +197,11 @@ module pistorm(
 
   reg [2:0] state = 3'd0;
   reg [2:0] PI_TXN_IN_PROGRESS_delay;
+  // Bus-access hold depth, in half-c7m steps. At HOLD_N==0 the S6 compare
+  // folds to a constant and synthesis prunes s6_hold_cnt, so 0 == the
+  // original counter-free logic.
+  localparam HOLD_N = `HOLD_CLOCKS;
+  reg [2:0] s6_hold_cnt = 3'd0;   // half-c7m hold counter — see S6
 
   // -------- Bus arbitration (BR/BG/BGACK) --------
   // Two-flop synchronizers for async inputs from the other master.
@@ -330,10 +346,18 @@ module pistorm(
         end
       end
        
-      3'd6: begin // S6
-        if (c7m_falling) begin
-          M68K_VMA_n <= 1'b1;
-          state <= 3'd7;
+      3'd6: begin // S6 — bus-access hold (HOLD_CLOCKS half-c7m steps).
+        // Stock exits on the first c7m edge; each extra step holds AS /
+        // address / data one more half c7m (~70 ns) before S7 deasserts.
+        // Counting both c7m edges gives the half-c7m resolution.
+        if (c7m_rising || c7m_falling) begin
+          if (HOLD_N == 0 || s6_hold_cnt == HOLD_N) begin
+            s6_hold_cnt <= 3'd0;
+            M68K_VMA_n <= 1'b1;
+            state <= 3'd7;
+          end else begin
+            s6_hold_cnt <= s6_hold_cnt + 3'd1;
+          end
         end
       end
        

@codewiz
Copy link
Copy Markdown
Author

codewiz commented May 20, 2026

Timing analysis of the two svf variants (EPM240 and EPM570) built from this PR:
zdma-timing-reports.tar.gz

@codewiz codewiz marked this pull request as ready for review May 24, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant