fix: ERR-0026 SDRAM tMRD datasheet-unit mismatch at 64MHz

Real Alliance Memory AS4C4M16SA-6TIN datasheet (Rev 5.0, Table 17)
specifies tMRD as a fixed 2-tCK cycle count, not an ns value.
sdram_controller.v modeled it via ns_to_cycles(12), which rounded to
2 cycles by coincidence at every previously-tested frequency
(100/133/166MHz) but rounds to only 1 cycle at the real 64MHz board
target -- an under-provisioned one-time init sequence. Fixed by
hardcoding T_MRD=2, matching how CAS_LATENCY is already modeled.

Verified zero regression: full 9-config legacy sweep + a new
dedicated 64MHz config (461/461 PASS each), N=2/N=4 D-Stress
(identical cycle counts), board-level smoke test (11/11 PASS).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
This commit is contained in:
2026-09-06 18:27:36 +02:00
co-authored by Claude Sonnet 5
parent d6376e8f2a
commit 8890b0abc2
3 changed files with 80 additions and 1 deletions
+21
View File
@@ -2140,3 +2140,24 @@ and the new host-arb arbitration layer) -- this was deliberately not
attempted before now, since running the real toolchain against RTL attempted before now, since running the real toolchain against RTL
known to compute wrong answers would not have been a meaningful known to compute wrong answers would not have been a meaningful
result. That reason no longer applies. result. That reason no longer applies.
DEC-0038
DATE: 2026-09-06
DECISION:
The SDRAM datasheet-parameter audit (PRE-PCB VERIFICATION FREEZE,
section 8) is CLOSED. Every timing parameter in hardware/v2/nms/rtl/
sdram_controller.v was cross-checked against the real Alliance Memory
AS4C4M16SA-6TIN datasheet (Rev 5.0, Table 17) at the real 64MHz target
frequency, not merely re-cited from a previous, uncross-checked
baseline. This found and closed ERR-0026 (T_MRD unit mismatch -- see
errors.log), the only genuine discrepancy found. tRCD, tRP, tRAS,
tWR, tMRD, tREFI are all now confirmed correct at 64MHz with zero
regression to the existing bit-exact regression suite. See
hardware/v2/docs/PRE_PCB_VERIFICATION.md for the full parameter-by-
parameter table (DATASHEET PARAMETER -> REQUIRED VALUE -> RTL VALUE ->
STATUS).
This REVISES CHIP_READINESS.md/OPEN_ITEMS.md's own prior "SDRAM
datasheet-parameter cross-check: OPEN (sim-level only)" status to
CLOSED.
+44
View File
@@ -1244,3 +1244,47 @@ STATUS: ERR-0025 (Parts A and B) fully RESOLVED. The physical SPI host
interface is now verified correct end-to-end (SPI -> dependency_ interface is now verified correct end-to-end (SPI -> dependency_
manager -> compute -> SDRAM -> result) under both tight and realistic- manager -> compute -> SDRAM -> result) under both tight and realistic-
gap job pacing, with zero regression to the STEP19 baseline. gap job pacing, with zero regression to the STEP19 baseline.
ERR-0026 -- T_MRD datasheet-unit mismatch (SDRAM init sequence, 64MHz)
DATE: 2026-09-06
FOUND DURING: PRE-PCB VERIFICATION FREEZE, section-8 SDRAM datasheet-
level audit (real Alliance Memory AS4C4M16SA-6TIN datasheet, Rev 5.0,
Oct 2018, Table 17 "Electrical Characteristics/AC Operating
Conditions", -6 speed grade).
ROOT CAUSE: hardware/v2/nms/rtl/sdram_controller.v modeled tMRD (LOAD
MODE REGISTER -> any command spacing) as `ns_to_cycles(12)`, i.e. as
if it were a nanosecond-based timing spec like tRCD/tRP. The real
datasheet specifies tMRD as a FIXED CYCLE COUNT, "2 tCK", independent
of clock frequency -- the same category of spec as CAS_LATENCY, which
this same file already correctly models as a fixed value two lines
below. `ns_to_cycles(12)` rounds to exactly 2 cycles at every
frequency this design had previously been tested at (100/133/166MHz),
so the wrong unit model was silently masked by coincidence. At the
real V2 board's own 64MHz operating point it rounds to only 1 cycle --
one cycle short of the real, fixed 2-tCK minimum -- a genuine,
datasheet-violating under-provisioning of the one-time SDRAM power-up/
mode-register-set sequence. Confirmed NOT a bug in tRCD/tRP (correctly
ns-based, correctly use ns_to_cycles()), tRAS (satisfied by construction:
the fixed tRCD+CAS_LATENCY+BURST_LEN dispatch sequence is always >=6
cycles, 93.75ns >= the real 42ns minimum at 64MHz), or tWR (folded in
conservatively via T_RP+1, giving 3 cycles >= the real 2-tCK minimum).
FIX: hardcoded `localparam T_MRD = 2;` (matching how CAS_LATENCY is
already modeled), replacing `localparam T_MRD = ns_to_cycles(12);`.
Only affects the one-time SDRAM init sequence, not per-transaction
timing.
VERIFICATION (all via Verilator, the trusted tool per DEC-0004):
- tb_sdram_controller.v: full 9-config legacy sweep (100/133/166MHz
x BURST_LEN 1/4/8), 461/461 PASS each config, zero regression.
- tb_sdram_controller.v: NEW dedicated 64MHz/BURST_LEN=4 config (the
real board target, not covered by the legacy sweep) -- 461/461
PASS, confirming the fix is correct at the frequency where the
bug actually manifested.
- tb_nms_dstress_sdram_unified.v N=2: 49788 cycles, 256/256
bit-exact -- IDENTICAL to pre-fix (expected: T_MRD only affects
one-time init, not steady-state per-transaction timing).
- tb_nms_dstress_sdram_unified.v N=4: 49771 cycles, 256/256
bit-exact -- IDENTICAL to pre-fix.
- tb_fpga_neural_v2_top_smoke.v: 11/11 PASS, unaffected.
STATUS: RESOLVED. Files changed: hardware/v2/nms/rtl/sdram_
controller.v (single localparam, plus explanatory comment).
+15 -1
View File
@@ -99,7 +99,21 @@ module sdram_controller #(
// (tRCD + CAS_LATENCY + BURST_LEN data cycles, always >= 3+3+1=7 // (tRCD + CAS_LATENCY + BURST_LEN data cycles, always >= 3+3+1=7
// even at the narrowest BURST_LEN=1) already comfortably exceeds // even at the narrowest BURST_LEN=1) already comfortably exceeds
// it by construction before auto-precharge can begin internally. // it by construction before auto-precharge can begin internally.
localparam T_MRD = ns_to_cycles(12); // LOAD MODE REGISTER -> any command // tMRD is specified by the real AS4C4M16SA-6TIN datasheet (Table 17)
// as a FIXED CYCLE COUNT ("2 tCK"), not a nanosecond value -- unlike
// tRCD/tRP, which genuinely are ns-based and correctly belong behind
// ns_to_cycles(). A previous draft modeled tMRD as ns_to_cycles(12),
// an assumed-equivalent ns figure that happened to round up to
// exactly 2 cycles at every frequency this design had been tested at
// (100/133/166MHz), silently masking the wrong unit model. At the
// real V2 board's own 64MHz operating point, ns_to_cycles(12) rounds
// to only 1 cycle -- one cycle short of the real, fixed 2-tCK
// minimum -- found via this step's own fresh datasheet-level audit
// (real Alliance Memory AS4C4M16SA-6TIN datasheet Rev.5.0, Table 17).
// Fixed by hardcoding the real, frequency-independent requirement
// directly, matching how CAS_LATENCY (also a real fixed-cycle spec)
// is already modeled two lines below.
localparam T_MRD = 2; // LOAD MODE REGISTER -> any command (tMRD = 2 tCK, fixed)
localparam T_INIT_US= 200; // power-up wait, real datasheet value localparam T_INIT_US= 200; // power-up wait, real datasheet value
localparam T_INIT = T_INIT_US * CLK_FREQ_MHZ; localparam T_INIT = T_INIT_US * CLK_FREQ_MHZ;
localparam CAS_LATENCY = 3; // fixed for this part/speed grade localparam CAS_LATENCY = 3; // fixed for this part/speed grade