Skip to content

RustyNES v2.8.4 — "Tether" (the MiSTer core's SDRAM build, made trustworthy)

Choose a tag to compare

@github-actions github-actions released this 26 Sep 14:45
b2d5da8

RustyNES v2.8.4 — "Tether"

The fifth and last release of the v2.8.x line that ADR 0041 put before the SuperStation One core (v3.0.0). v3.0.0 ships two bitstreams: the on-die one, with the whole cartridge in the FPGA's block RAM, and a secondary off-die one that keeps the cartridge in SDRAM. This release makes the off-die path defensible, and in doing so found that it would not have worked on hardware at all. Every SDRAM row of the RTL audit has a verdict and evidence in its ledger.

For emulator users: nothing changes. Everything here is the MiSTer core. No hardware has run any bitstream; that is v2.9.2's subject.

Every off-die read would have been wrong on hardware

The co-simulation tests the SDRAM controller against a model of the memory written from its datasheet. That model delivered read data one clock later than the datasheet says the part does, and the controller had been written to match it. Controller and model agreed, so every test passed, and on a real board every read from SDRAM would have been sampled after the memory had already let go of the bus.

No simulation could have caught that. The timing analysis did, once this release gave the SDRAM pins timing constraints for the first time: the read data failed its timing by 11 ns. The datasheet's own read waveform then named the clock edge. The model now follows the datasheet, the controller samples one clock earlier (so reads are also a clock faster), and the constraints say which edge captures the data. Against the old controller, the corrected model read 0x0000 at every address.

Two more things the model could not see

  • The power-up sequence. The memory ignores a command issued on the clock where its clock-enable rises, and the controller's first command was exactly that one. It now waits a clock.
  • Reads at CAS latency 3. The controller masked read data while waiting for it. At the latency the shipped clock uses the mask happened to lift in time; at latency 3 every read returned zero.

In both cases the model changed first, and was shown to fail against the unfixed controller.

Two races in the arbiter

  • A request arriving mid-service changed which byte the previous one got. The byte select is now latched when the request is granted. The new test read 0xa1 where it had written 0xb2 before the fix.
  • A write on the cycle the arbiter said "not busy" could be dropped. Not reachable from today's cartridge path, which writes at most once every four memory clocks; fixed because nothing enforces that spacing.

Timing, and the seed

The SDRAM pins now carry constraints from the documented memory part, the Alliance AS4C32M16SB. They are provisional: they assume zero board delay, and the SuperStation One's memory part and trace delays are read at v2.9.2.

Off-die, worst of four corners Setup Hold
SDRAM read data +0.439 ns +12.822 ns
SDRAM outputs +4.137 ns +0.606 ns
console clock to SDRAM clock +2.022 ns +0.158 ns
whole design +0.270 ns +0.081 ns

The read-data margin is thin, and the board's trace delays come straight out of it, so the SDRAM clock phase is a v2.9.2 question. The console-to-SDRAM crossing the audit flagged (R-5.2) is not a defect: both clocks come from one PLL and the crossing is timed at every corner.

At the close of the v2.8.x line both builds were swept across five fitter seeds, and every seed closes in both. The pin moves from 4 to 5, the best on-die seed under both of the project's criteria; the off-die build pays for it with less setup margin (+0.270 ns against +0.389 at seed 4), and still closes.

Building the off-die bitstream

It used to mean editing a line of the RTL. Now scripts/build-offdie.sh builds it and OFFDIE=1 scripts/seed-sweep.sh sweeps it, both without changing any tracked file. The first version relied on a Quartus option to leave its project file alone; the compile wrote to the file anyway, and only the script's own check caught it. An off-die bitstream holds the console in reset when no SDRAM is detected, and bring-up now runs MemTest before it.

The test harness

  • The ladder really does run from a clean checkout now. v2.8.3 said it did; it did not. The first gate checks each golden against the ROM it came from, and 19 of those ROMs are built by later rungs, so a clean checkout failed. The gate now builds every generator's output itself.
  • Two ROMs long recorded as unreproducible are accounted for. One is simply a generator program nothing had built under its name. The other really is hand-made, and its only copy was a gitignored file; it is now committed.

Verification

Check Result
Co-simulation ladder, on-die, one run from a clean checkout 165 passed, 0 failed, 1 expected failure, nothing skipped
Co-simulation ladder, off-die (USE_SDRAM=1), same 166 passed, 0 failed, 1 expected failure, nothing skipped
SDRAM latency on the running console, off-die worst CHR fetch 20 cycles against a floor of 31
SDRAM read fix, red first the corrected model read 0x0000 at every address against the old controller
Quartus 17.0.2, seed 5, on-die worst setup +0.414 ns, hold +0.078 ns; 22,216 ALMs, 468 RAM blocks, 33 DSP
Quartus 17.0.2, seed 5, off-die worst setup +0.270 ns, hold +0.081 ns; 23,154 ALMs, 84 RAM blocks, 33 DSP
Seed sweep, both builds seeds 1-5, every seed closes in both
emulator unchanged; its gates run in CI

The ladders ran at the sibling's 0f53373, which differs from the release only in a build script the ladder does not use.

Next: v2.9.0, the re-audit of all four scopes against the fixed tree.

Install

  • Download the pre-built binaries for Linux, macOS, and Windows below.
  • The MiSTer core bitstreams are attached below: RustyNES_MiSTer-v2.8.4.rbf (on-die) and RustyNES_MiSTer-v2.8.4-offdie.rbf (cartridge in SDRAM; its name is provisional until v3.0.0). Neither has run on hardware.
  • The WebAssembly build is live at doublegate.github.io/RustyNES.
  • The RetroArch core is in RetroArch's Online Updater on the platforms the libretro buildbot publishes to.
  • The audit ledger is docs/audits/rtl-disposition.md, and the plan to-dos/plans/v2.8.4-tether-plan.md.
  • Licensed under GPL-3.0-or-later.