# CPU interface timing investigation

The first hardware test of commit `5016887` booted at 7 MHz and showed a red
screen at 60 MHz. The previous core also failed at 60 MHz on that board.
This points the investigation toward a shared CPU interface limitation; it
does not establish which transfer failed. The target remains 60.2972184 MHz.

## What the routed design shows

These measurements use copies of `build/release-60mhz-03/Minimig1.ncd` and
`build/baseline-final-constraints/Minimig1.ncd`. The temporary 1000 ns
constraints expose paths for measurement; their passing status does **not**
establish external CPU timing closure. The FPGA output load model also does
not replace measurements of the assembled board.

| Maximum FPGA path, ns | Original baseline | Release 5016887 |
| --- | ---: | ---: |
| Cache/tag RAM clock to CPU data pad | 23.660 | 21.120 |
| Cache/tag RAM clock to DTACK pad | 14.365 | 14.990 |
| Chipset input latch to CPU data pad | 15.583 | 13.246 |
| Turbo acknowledgment FF to DTACK pad | 7.991 | 6.376 |
| CPU data pad to cache write port, including setup | 4.897 | 8.498 |
| CPU address pad to cache ports, including setup | 10.439 | 12.555 |

The last row includes write control paths. The release's direct data-RAM
read-address path reaches 9.131 ns. Cache clear selection adds logic to the
write inputs; this explains part of the increased cache input delay.

The longest tag-to-data and tag-to-DTACK paths share their tag comparator.
The data path then takes 6.130 ns longer. The data output buffer alone
contributes 7.006 ns with the existing SLOW/4 mA setting; DTACK's FAST/12 mA
buffer contributes 1.642 ns. These numbers identify useful optimization
targets but do not prove that the CPU sampled invalid data.

## The external clock is delayed

Maximum-corner SDF from NETGEN places the release's CPU clock pad 5.433 ns
after the BUFG output, versus 1.015 ns for the cache tag RAM clock. The
external CPU edge therefore follows the internal cache edge by 4.418 ns.
The baseline difference is 4.206 ns. The separate minimum-delay SDF models
give 1.459 ns and 1.390 ns respectively. Do not combine the two SDF corners
as if they were simultaneous measured delays.

For the release's registered turbo acknowledgment, the maximum-corner
same-model interval before the next external CPU falling edge is:

```
8.292256 + 5.433 - 1.033 - 6.376 = 6.316256 ns
half cycle   clock pad   FF clock   FF-to-DTACK
```

This excludes PCB skew, actual loading, clock jitter and CPU behavior at
60 MHz. It is an illustrative timing budget, not guaranteed setup margin.
It also shows why a simulation using identical internal and external
clock edges misses a material part of the interface.

## Protocol and part references

The [M68000 user manual, section 5.1](https://www.nxp.com/docs/en/reference-manual/MC68000UM.pdf)
describes DTACK recognition at a falling clock edge and read-data sampling
one full processor cycle later. The CPU negates its strobes after that
data-sampling edge. A fast acknowledgment does not require data to have
arrived at exactly the same instant.

The [MC68SEC000 addendum, sections 6 and 7](https://www.nxp.com/docs/en/reference-manual/M68000UMAD.pdf)
specifies 10, 16 and 20 MHz grades. Its listed data and asynchronous-input
setup requirements are 5 ns; the 20 MHz write-data hold requirement is
10 ns after strobe negation. These provide useful reference values and
simulation sweeps. They do not specify the part's behavior at 60 MHz.

## R2 interface changes

The R2 candidate replaces the direct cache-hit acknowledgment with a
staged lookup, a held 16-bit return word, and a registered acknowledgment.
An initial warmup edge allows CPU address propagation before the lookup;
the tag comparison gets a full CPU period. The following positive edge
acknowledges the held result. The decision and word remain fixed until AS
ends, and pending lookup suppresses an overlapping chipset request.

Simply sampling the old `cache_hit` at the next positive edge is not a
timing fix: the release's existing tag comparison path already takes about
11.5 ns before the final DTACK output logic, exceeding the 8.292 ns half
cycle. The staged implementation avoids that half-cycle path.

UCF constraints TS21 and TS22 now budget held-data/selector FF-to-pad at
16 ns and turbo acknowledgment FF-to-pad at 6 ns. TS23 preserves the old
20 ns byte-strobe input budget to the new lookup-register boundary. Empty
direct RAM/strobe-to-DTACK constraints were removed. These are FPGA routing
budgets. The forwarded clock and output paths must be measured again after
routing; meeting these constraints alone does not qualify the board at
60 MHz.

The staged decision has an explicitly guarded slow-only timing exception:
`memory_config[3:2]`, `scanline[1]`/cache bypass, and `turbo` to
`CPU1/cache_lookup_hit`. In settled slow mode, `turbo=0` forces eligibility
and the decision to zero. Mode changes require AS high, which asynchronously
clears the decision. The audit script verifies those assumptions against
the build snapshot before adding this exception. Independently clocked
turbo-mode analysis and the crossing inventory retain those paths.
CPU-clocked RAM/lookup paths remain timed in both modes. A regression
toggles bypass and configuration during slow transfers; a separate guard
test verifies that changing any proof assumption removes the exception.

## Final R2-04 routed measurements

`r2-60mhz-04` passes the main, component, slow-mode and focused external
TRACE checks. The focused report has zero timing errors and zero warnings.
The final turbo synchronizer has a location constraint near DTACK; it
keeps the 6 ns output limit without relaxing synchronizer or refill timing.

| FPGA path | Maximum delay |
| --- | ---: |
| Held data and selector registers to CPU data, 48 paths | 15.535 ns |
| Registered turbo/cache acknowledgment to DTACK, 2 paths | 5.744 ns |
| Byte strobes to lookup decision, 2 paths | 5.469 ns |
| Uncached input latch to CPU data, 16 paths | 13.443 ns |
| SRAM data pads to input latch, 16 paths | 11.109 ns |
| CPU address pads to data-cache read ports, 22 paths | 8.450 ns |

The latter three are explicit inventories with loose reporting limits;
passing those limits does not qualify the external memory or CPU. The
8.450 ns address path is below the 9.131 ns path used to motivate the extra
lookup warmup edge. The two uncached paths must be considered alongside
SRAM access time, clock phase and the Q3 acknowledgment sequence.

With the implementation PCF supplied, routed SDF reports 4.540–5.433 ns
from the CPU BUFG output to the clock pad and 0.862–1.014 ns to either
acknowledgment FF clock. Using the earliest forwarded clock, latest local
clock and latest acknowledgment gives **6.074 ns** before the next CPU
falling edge for bus acknowledgment and **6.154 ns** for cache acknowledgment.
After a 5 ns rated-speed CPU setup reference and an additional 0.5 ns
engineering allowance, only **0.574 ns / 0.654 ns** remains for unmodeled
skew and loading. These are narrow model-based budgets, not a guarantee
that an overclocked CPU meets timing on the assembled board.

The held cache data has a much larger modeled interval: at least
**21.160 ns** before the earliest protocol data-sampling edge, or 15.660 ns
after the same setup/engineering reserves. It remains fixed until AS ends.
The calculation assumes the implemented falling-edge word capture,
following rising-edge acknowledgment, and the CPU's subsequent full-cycle
delay from acknowledgment recognition to data sampling.

Reproduce the read-only audit with:

```sh
scripts/audit_external_timing.sh build/r2-60mhz-04 build/r2-external-audit-04
```

The output directory must be new. Portable measurements and focused
excerpts are in `reports/r2/external-timing-summary.json` and
`reports/r2/external-timing-focused.txt`; the slow exceptions are recorded
in `reports/r2/slow-mode-exceptions.txt`. Raw R1 investigation files remain
in `build/cpu-io-redscreen-audit/`. Original release implementation files
and bitstreams were not modified by these audits.
