|
| 1 | +# VCU118 SDRAM bring-up |
| 2 | + |
| 3 | +FPGA test bitstream for the `fmc_sdram` mezzanine plugged into VCU118 |
| 4 | +**J2** (FMC HPC1, LPC functional subset). Brings up the dual |
| 5 | +`MT48LC16M16A2P` SDRAM (organized x32, 64 MB) at 50 MHz CL=2 and runs a |
| 6 | +multi-pattern built-in self test across the SDRAM, then verifies the |
| 7 | +data and counts mismatches. |
| 8 | + |
| 9 | +Current bring-up status (50 MHz, 1 Mword sweep, 4 patterns, |
| 10 | +`T_WR_CYC = 3`): **0 / 4,194,304 read errors**. |
| 11 | + |
| 12 | +## Files |
| 13 | + |
| 14 | +- `top.v` — top-level: clocking, reset sync, controller wiring, IOBUFs, |
| 15 | + ODDR clock forwarding, BIST instantiation, LED status, ILA probes. |
| 16 | +- `sdram_ctrl.v` — minimal SDRAM controller (BL=1, CL=2, x32, single |
| 17 | + outstanding request). Honours datasheet tCK-spec constraints, notably |
| 18 | + `tRDL = 2 tCK` (last-data-in to PRECHARGE). |
| 19 | +- `sdram_bist.v` — sweep-write / sweep-read BIST cycling 4 patterns |
| 20 | + (`addr XOR {a,~a}`, `AAAA5555 XOR addr`, `5555AAAA XOR addr`, `~base`), |
| 21 | + with per-pattern and total error counters and first-error capture. |
| 22 | +- `top.fl` — Verilog filelist consumed by `build.tcl`. |
| 23 | +- `top.xdc` — pin / IO standards: 250 MHz diff clock, on-board |
| 24 | + LEDs/buttons/switches, full SDRAM x32 on J2. |
| 25 | +- `build.tcl` — Vivado batch flow with `batch_insert_ila`. MMCM is |
| 26 | + generated for 50 MHz; debug hub is told the matching clock frequency. |
| 27 | +- `load.tcl` — program `top.bit` over the VCU118 USB-JTAG. |
| 28 | +- `ila_capture.tcl` — main ILA capture script with selectable trigger |
| 29 | + modes (`done` / `mismatch` / `pattern N` / `alive`). |
| 30 | +- `ila_capture_r0.tcl`, `ila_capture_w0.tcl`, `ila_capture_w.tcl` — |
| 31 | + targeted capture scripts that trigger on the first read at addr 0, the |
| 32 | + first write at addr 0 in pattern 0, and the first write at addr 0xB9 |
| 33 | + in pattern 3 respectively. Useful for diagnosing specific transactions. |
| 34 | +- `ila_dump.tcl` — connect, program and dump every probe name without |
| 35 | + arming. Quick sanity check for the dbg_hub. |
| 36 | + |
| 37 | +## Build |
| 38 | + |
| 39 | +```bash |
| 40 | +source /opt/Xilinx/Vivado/2021.1/.settings64-Vivado.sh |
| 41 | +vivado -mode batch -source build.tcl 2>&1 | tee vivado_build.log |
| 42 | +grep -i "error\|critical warning" vivado_build.log |
| 43 | +``` |
| 44 | + |
| 45 | +## Load + run BIST |
| 46 | + |
| 47 | +```bash |
| 48 | +vivado -mode batch -source ila_capture.tcl |
| 49 | +``` |
| 50 | + |
| 51 | +This programs the device, arms the ILA on `dbg_bist_state == 6 (S_DONE)`, |
| 52 | +waits for the BIST to complete its full 4-pattern × 1 Mword sweep |
| 53 | +(~ 22 s on first iteration including the auto-start delay), and writes |
| 54 | +the captured buffer to `ila_capture.csv`. |
| 55 | + |
| 56 | +## Run / observe (on-board) |
| 57 | + |
| 58 | +LED layout after the bitstream loads: |
| 59 | + |
| 60 | +| LED | Meaning | |
| 61 | +| ---- | --------------------------------------------- | |
| 62 | +| `7` | error_count_total != 0 (red flag) | |
| 63 | +| `6` | bist_done | |
| 64 | +| `5` | bist_busy | |
| 65 | +| `4` | mmcm_locked | |
| 66 | +| `3:0`| heartbeat / pattern_idx+phase / err_count nibble | |
| 67 | + |
| 68 | +`btn[0]` (BTNU) restarts the BIST. `sw[0]` selects loop mode (1 = auto |
| 69 | +restart after one full pass; the default reads HIGH on VCU118 so the |
| 70 | +BIST cycles forever). |
| 71 | + |
| 72 | +## ILA probes |
| 73 | + |
| 74 | +`debug_nets.ltx` is generated next to `top.bit`. Useful trigger conditions: |
| 75 | + |
| 76 | +- `dbg_bist_state == 6` — BIST finished all 4 patterns |
| 77 | +- `dbg_bist_state == 5` — between patterns (NEXT_PAT) |
| 78 | +- `dbg_bist_state == 4` — read in progress (proves BIST is alive) |
| 79 | +- `dbg_mismatch == 1` — first failing read |
| 80 | +- `dbg_pattern == N` — capture during a specific pattern |
| 81 | +- `dbg_ctrl_state == 0xa` (S_AREF) — verify refresh is firing |
| 82 | + |
| 83 | +The ILA core captures 32 k samples per arm on the 50 MHz logic clock. |
| 84 | + |
| 85 | +## Bring-up history (notable bugs found) |
| 86 | + |
| 87 | +1. **CPU_RESET polarity** — VCU118 `cpu_reset` (pin L19) is active-HIGH |
| 88 | + with a pulldown, not active-low. Wired `cpu_reset` then inverted in |
| 89 | + RTL to drive MMCM's active-low `resetn`. |
| 90 | +2. **Debug hub clock not configured** — `dbg_hub` needs an explicit |
| 91 | + `C_CLK_INPUT_FREQ_HZ` matching the ILA capture clock, otherwise HW |
| 92 | + Manager reports "debug hub core was not detected". |
| 93 | +3. **CL_CYC** — at 50 MHz CL=2, FPGA must sample DQ four FPGA clocks |
| 94 | + after issuing READ (= 1 cmd-register cycle + CL=2 SDRAM cycles + |
| 95 | + round-trip propagation through the level shifter). |
| 96 | +4. **BIST ready/valid handshake** — the master must hold `req_valid` |
| 97 | + until it observes `req_valid && req_ready` in the SAME cycle. |
| 98 | + Otherwise a refresh that fires between asserting valid and the slave |
| 99 | + latching the request eats the request and the BIST hangs. |
| 100 | +5. **tRDL violation** — `T_WR_CYC` must be ≥ 2 because the datasheet |
| 101 | + specifies `tRDL = 2 tCK`. This is a cycle count, not a nanosecond |
| 102 | + count, so it holds at any clock frequency. |
| 103 | +6. **PCB DQM-DIR rework** — on this mezzanine the DQM signals are |
| 104 | + routed through bidirectional SN74AVCH2T45 level shifters whose DIR |
| 105 | + pins are tied to `SDRAM_DQ_DIR`. During READ the level shifters flip |
| 106 | + to B→A, leaving the SDRAM-side DQM input floating (illegal for a |
| 107 | + CMOS input). The PCB has been reworked to tie both DIR pins (U13.5 |
| 108 | + and U14.5) to VADJ so the DQM lanes are always FPGA→SDRAM. |
0 commit comments