# CPU bus completion and custom-register writes

Run `python3 tests/run_cpu_bus_retirement.py` from the repository. The test uses
Icarus Verilog and the ISE UNISIM models. `ISE_VERILOG` may override the default
`/opt/Xilinx/14.7/ISE_DS/ISE/verilog/src` location.

## What is checked

`tb_cpu_custom_write.v` instantiates the actual CPU bridge, Gary, Agnus arbiter,
and Blitter. It alternates 512 first-word/last-word mask writes, checks the
selected address and data at the chipset capture edge, then checks the actual
Blitter register after its update. It rejects lost, duplicated and wrong-data
writes. The CPU begins each next legal bus cycle without extra idle clocks.
Turbo runs explicitly require AS-high pulses that begin and end between two
chipset capture edges, and verify that those transfers are still distinct.

The integration test also exercises CPU-to-SRAM reads, writes, byte masks,
cache misses/hits and DMA arbitration. The runner covers normal 7 MHz and turbo
60.297 MHz operation, five turbo clock phases, forwarded-clock delay variation,
and additional acknowledgment latency. The custom-register runs disable the
optional ideal input keeper: the CPU must actively hold its write word through
the custom register's capture, rather than rely on charge retention.

CPU transactions follow the MC68000 sequence: DTACK is recognized on a falling
clock; read sampling/write completion occurs one full CPU clock later, followed
by AS/data-strobe release. The model uses a 5 ns DTACK setup reference and 3 ns
clock-to-AS release. It deliberately permits zero additional write-data hold.
The [SEC000 addendum](https://www.nxp.com/docs/en/reference-manual/M68000UMAD.pdf)
and [MC68000 manual](https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf)
provide the protocol and rated-part timing references. These values do not
establish a 60 MHz CPU timing guarantee.

## Focused delay model and limits

The runner creates temporary RTL copies and leaves production files unchanged.
It adds two delays obtained from the R2 routed crossing inventory:

- `_ta_t1` to the first CPU synchronizer: **3.638 ns**.
- `_dtack` back to the chipset `l_dtack` capture: **2.841 ns**.

The same phase sweep also uses the candidate's measured **2.740 ns / 3.138 ns**
pair, retaining the older R2 pair and the zero-delay reference.

Each value includes the reported destination setup threshold, so the delayed
input conservatively determines whether an ideal simulated edge may capture it.
This is a focused sequential timing experiment, **not a full SDF simulation**.
It does not simulate every routed gate, hold violation, metastability, FPGA
clock-tree corner, PCB delay, keeper strength or CPU overclock behavior. A
separate 20 ns first-stage delay exercises additional synchronizer latency; that
value is a functional stress case, not a measured path delay.

The custom-register bench delays sampled strobes by 1 ns before Gary/Agnus so a
clk28 output change cannot race the same derived clk7 capture in RTL delta
cycles. This preserves old-value sampling; it is not a measured full strobe
path. CPU write-data propagation defaults to 6 ns. The SRAM bench retains its
explicit pin/access/return model.

## Failure demonstrated and regression mutations

R2 acknowledges turbo reads at Q3 but uses the acknowledgment's round trip
through the independent CPU clock to retire the chipset request. The return can
miss the next Q0 sampling threshold. A following CPU transaction can then receive
an acknowledgment under the preceding transaction's address/direction. The
[retained R2 trace](../reports/r3/cpu-bus-retirement-r2-trace.txt) shows a write
acknowledged without a write-data capture.

Sampling local completion into `l_as28m` retires that request at Q0 without
waiting for the CPU-domain round trip. Moving turbo writes from Q2 to Q3 then
keeps the CPU word driven through custom-register capture at Q0. Moving write
ACK alone does not fix the transaction-retirement failure.

The runner checks that two temporary mutations reproduce failures:

1. Removing local completion from request retirement causes a stale read or a
   write acknowledgment without Q2 capture under the focused delay model.
2. Restoring early Q2 write acknowledgment causes a custom-register data mismatch
   when the optional input keeper is disabled.

With ideal keepers, the original R2 custom-write sequence passed in both normal
and turbo mode. Normal-mode integration also passed the focused-delay tests.
The user subsequently confirmed that a fresh boot at normal speed does not
corrupt the display; the earlier normal-speed residue followed turbo operation.
That is consistent with a turbo transfer-corruption risk, but these simulations
do not establish which failure caused the observed graphics or game crashes.
