# Selectable CPU clock experiment — not integrated

This standalone experiment demonstrates candidate clock generation and reset-time
selection for the **XC3S400-4-PQ208**. It does not add selectable profiles to a
Minimig image. Production clocks, UCF, firmware and published R4 images are
unchanged by these files. A matching host firmware interface, integrated packing,
routed timing and hardware tests are still required.

## Architecture

Keep the existing 28.3751616 MHz and 7.0937904 MHz chipset clocks. Replace the
current CPU DCM with two fixed DCM sources, both fed by the buffered 28 MHz clock:

- `CLKFX_MULTIPLY=17`, `CLKFX_DIVIDE=4`: 120.5944368 MHz.
- `CLKFX_MULTIPLY=30`, `CLKFX_DIVIDE=17`: 50.073814588 MHz.

Plain Spartan-3 has static frequency-ratio attributes and dynamic phase controls;
the Spartan-6 `DCM_CLKGEN` programming mechanism in the AmiCube H20 reference
cannot be transplanted into this device. Reset does not reprogram the ratio.
See [Spartan-3 Libraries Guide, DCM](https://docs.amd.com/api/khub/documents/y69WxdkWPXDQH2SmhT3RFA/content)
and [DS099, DCM frequency synthesis and reset](https://docs.amd.com/api/khub/documents/y7TWBeO97VdEfASgDFNn~Q/content).

The fixed 120 MHz source supplies free-running /2, /3, /4 and /6 dividers.
For /3, a one-cycle registered pulse is ORed with its falling-edge delayed copy,
giving nominally equal high and low times. This avoids depending on the IOB-only
DDR primitive for a clock that must also reach the internal CPU interface and
cache. The IOB implementation of `FDDRRSE` is described in
[DS099, page 11](https://docs.amd.com/api/khub/documents/y7TWBeO97VdEfASgDFNn~Q/content).

| Prototype encoding | Label | Nominal actual MHz | Period, ns |
| --- | --- | ---: | ---: |
| 0 | Normal | 7.093790400 | 140.968360159 |
| 1 | 20 | 20.099072800 | 49.753538880 |
| 2 | 30 | 30.148609200 | 33.169025920 |
| 3 | 40 | 40.198145600 | 24.876769440 |
| 4 | 50 | 50.073814588 | 19.970517689 |
| 5 | 60 | 60.297218400 | 16.584512960 |

These calculated rates assume the existing nominal 4.433619 MHz reference.
Encodings 6 and 7 fall back to 60. This encoding is experimental, not an existing
firmware command or a promise that every attached CPU supports these rates.

### Change sequence

1. A host reset request immediately holds the CPU in reset.
2. Safely switch the final BUFGMUX to the continuously running Normal clock.
3. Wait 32 chipset clocks, then change the unused turbo-source LUT selector.
4. Wait another 32 chipset clocks, safely select the target, and wait for the
   selection to settle.
5. Deliver at least 128 selected CPU clock edges before releasing reset on a
   falling CPU edge.

The two DCMs and all dividers continue running throughout a normal profile change.
The final BUFGMUX select is registered on the falling edge of the currently
selected global clock. It is deliberately not asynchronously reset by a host
reset. Spartan-3 BUFGMUX select still has a setup requirement: missing it can
produce a short pulse. See [UG331, page 54](https://docs.amd.com/api/khub/documents/divgj78jgBZqFZjIjXRfZA/content).

### Integration requirements

- **Feed `reset_request` from an external reset request/epoch.** Do not feed it a
  combined reset containing this controller's `ready` or `cpu_reset_n`; that
  feedback would keep the controller reset forever.
- The profile bus must remain stable until the first 28 MHz edge after the reset
  request releases. A later reset restarts an interrupted selection transaction.
- Changing the requested profile alone has no effect. The legacy boot sequence
  that forces Normal and later enables turbo is a separate integration problem:
  its runtime enable must not be treated as a new frequency-profile request.
  Define that overlay and its safe mux protocol before replacing the old clock
  tree. Preserve the old firmware's selected-60 default and Normal boot behavior.
- Both new CPU DCMs use `STARTUP_WAIT=FALSE`; their fabric reset-release pipeline
  needs startup GWE. Qualify system/CPU reset with clock readiness without the
  feedback above. The existing chipset startup sequence remains separate.
- The physical CPU and internal bridge/cache must share the selected clock.
  Preserve their intended polarity and remeasure forwarded-clock/data/DTACK
  relationships. This prototype's `normal_clk` input is already the desired
  Normal polarity; its isolated wrapper does not encode the board's phase tree.

## Verification performed

The tracked-source entrypoint passed on 2026-09-15. Each full suite exercises all
36 ordered profile pairs, including self-transitions, short asynchronous reset
pulses, request changes without reset, invalid encodings and an interrupted
switch. Five additional real-DCM runs cold-boot profiles 0 through 4; profile 5
boots in the full suite.

| Suite | Modeled global/select delays, ns | Pulse checks | Steady half-period checks | Smallest modeled select setup, ns |
| --- | --- | ---: | ---: | ---: |
| ideal | 0 / 0 | 32,484 | 5,554 | 8.292 |
| routed | 2 / 2 | 32,444 | 5,553 | 4.292 |
| stressed | 2 / 5 | 32,430 | 5,553 | 1.292 |
| real UNISIM DCM | 2 / 2 | 32,445 | 5,564 | 4.292 |

`routed` is the historical test name for **assumed delays**, not a placed-and-routed
netlist. The bench explicitly checks the -4 BUFGMUX 0.60 ns select setup from
[DS099 Table 57](https://docs.amd.com/api/khub/documents/y7TWBeO97VdEfASgDFNn~Q/content);
UNISIM alone does not enforce this requirement. Synthetic 2 ns global plus 6 ns
select delay leaves only 0.292 ns and is correctly rejected.

All five negative controls fail for their intended reason: missing /3 half-cycle
extension; changing the live turbo selector; skipping the Normal settling wait;
releasing reset too early; and violating mux-select setup. Pulse checks require
at least 8.2 ns throughout selection; steady clocks must match the expected
half-period within 30 ps. These checks exclude analogue jitter and actual routing.

Results from the tracked entrypoint:
`build/r5-clock-prototype/sim-20260915T170209Z-1138788/`.
The earlier successful logs at `build/r5-clock-prototype/` remain untouched.

### Isolated synthesis

ISE 14.7 XST succeeds for the target with **33 slices, 42 FF, 58 LUT, two DCMs and
five global buffers**, including two buffered test inputs. The projected complete
clock tree uses four DCMs and seven globals. The R4 core already used 3,550 of
3,584 slices, so the final packing fit is unresolved; isolated slice counts are
not an additive prediction of the complete design.

The report's default **53.114 MHz** estimate is expressed for the 28 MHz input
clock and its inferred derived paths. It is **not** a qualified 120 MHz divider
or 60 MHz CPU timing check. XST does not establish all selected-clock cases here;
no MAP/PAR/TRACE or prototype bitstream was produced.

The original report is `build/r5-clock-prototype/prototype.syr`, SHA-256
`7d8ff29bc757a7ac937f8d34ec3be8dc2e9cbba94d5c5eb81ba9b20a8ceab96b`.
Its synthesized source matches the tracked RTL byte for byte:

| File | SHA-256 |
| --- | --- |
| `profile_clock.v` | `9cfa0f33c9c6b183c89d47f0214c887839499d7b82ffd5b592bcd2bfdf383b71` |
| `prototype_top.v` | `0e9f62961cabef07053ecc2d5764058cd96dc0ab67d36cf60995191eb243c199` |
| `tb_profile_clock.v` | `b394b555b90fe6c6f85376fb23da260204630fa35be6b057e956b3a8fb5a50aa` |

## Still required before integration can be qualified

- Explicitly constrain the 120.594 MHz domain, including the **4.146128 ns**
  positive-to-negative path in /3 generation; independently constrain chipset,
  CPU and 50 MHz sources and analyze each selected clock mode.
- Measure mux-select setup using actual source/global-clock delays, select FF
  clock-to-Q and routing. For the fastest profile the nominal half-cycle is
  8.292256 ns. A falling-edge launch is only adequate if all those delays and
  uncertainty still leave the required setup at the mux input.
- Verify generated-clock pulse widths, clock-mux routing legality, CDC first
  stages, reset recovery/removal and all CPU external timing. Do not false-path
  active CPU/chipset crossings to make the experiment pass.
- Qualify the inherited 28 MHz clock's jitter as an input to both DCMs. The
  proposed frequencies fall inside the DFS LOW frequency limits, but frequency
  legality alone does not establish jitter compliance. See
  [DS099 Tables 60–61](https://docs.amd.com/api/khub/documents/y7TWBeO97VdEfASgDFNn~Q/content).
- Exercise source-lock loss and recovery. The controller holds CPU reset on
  lost lock, but safe recovery from a stopped/irregular selected source is not
  established by the normal-switch suite.
- Test power-on, repeated reset and every profile on the actual 68000, PiStorm
  and TF030 hardware with a matched ARM firmware protocol. This experiment
  establishes no socket-adapter compatibility claim.

## Reproduce

Requires Icarus Verilog and the installed ISE 14.7 UNISIM sources; isolated
synthesis additionally requires ISE and a valid license. From the repository:

```sh
bash experiments/selectable-clock/run_sim.sh
bash experiments/selectable-clock/run_xst.sh
```

Each script creates a fresh timestamped child of ignored
`build/r5-clock-prototype/`. An optional first argument chooses another **new**
output directory. Existing directories and paths within `experiments/` are
rejected. Source files are never generated or changed by the runners.
`ISE_VERILOG_DIR` can select another compatible UNISIM installation. The simulation
entrypoint includes all five negative controls and records input hashes; synthesis
copies its inputs into the new output directory before invoking XST.
