Files
retroDE_ps2/docs/ch318-lpddr-fb-bringup.md
thejayman77 ec82764bef Initial commit: retroDE_ps2 — first-of-its-kind PS2 GS FPGA core (DE25-Nano / Agilex 5)
RTL (GS rasterizer, EE core stub, platform bridge, LPDDR4B path), sim regression
(272 TBs), docs, and tooling. Copyrighted PS2 content (BIOS, game code, GS dumps,
and all dump-derived textures/traces) is excluded via .gitignore and stays local.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 20:10:50 -04:00

62 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ch318 — LPDDR framebuffer write/readback: board bring-up
ONE bitstream. All test controls are **runtime**, via HPS bridge registers — no rebuild
to go disabled → canary → full. Defaults are safe: **arm OFF, canary ON, base 0x80000000**.
The booted core writes nothing to LPDDR until the HPS arms it.
## Runnable script
`docs/hardware/ps2_lpddr_test.sh` (same style as `ps2_status.sh`; bridge base defaults to
`0x40000000`, `busybox devmem`):
```
./ps2_lpddr_test.sh # read-only LPDDR status (safe)
./ps2_lpddr_test.sh --canary # arm canary, verify 32 B vs expected, PASS/FAIL, auto-disarm
./ps2_lpddr_test.sh --full # arm full frame, hash 8 KiB vs expected md5, PASS/FAIL, auto-disarm
./ps2_lpddr_test.sh --disarm # force disarm (LPDDR_CTRL=0x2)
```
The manual register/`dd` reference below is what the script automates.
## Build
QSF (already set): `GS_TILE_PSMCT16FB_DEMO=1` + `GS_LPDDR_FB=1` (plus the usual
`GS_RMW_DEMO`). Build/load the `.rbf` once. That's the only build.
## HPS bridge register map (new in Ch318)
Offsets are relative to the **PS2 HPS-bridge base** — the same base `retrodesd` already
uses to reach `CORE_ID`/`OSD_CTRL`/`INPUT_P1` on this core (the HPS2FPGA bridge window).
32-bit accesses.
| Offset | Name | R/W | Meaning |
|--------|---------------|-----|---------|
| 0x018 | LPDDR_CTRL | RW | bit0 = **arm** (1 = permit AXI writes), bit1 = **canary** (1 = write only the 32-byte top line). Reset = 0x2 (disarmed, canary). |
| 0x01C | LPDDR_FB_BASE | RW | LPDDR byte base address. Reset = 0x8000_0000. |
| 0x02C | LPDDR_STATUS | R | bit0 = idle, bit1 = bresp error seen, bit2 = FIFO overflow seen. |
| 0x030 | LPDDR_BYTES | R | total bytes written. |
| 0x034 | LPDDR_BURSTS | R | total 32-byte bursts issued. |
The framebuffer itself is read from **physical LPDDR 0x8000_0000** (the `f2sdram` AXI
address is the HPS physical address — the qsys slave maps a flat 4 GiB), which is the
`reserved` region from `/proc/iomem` (below Linux System RAM at 0x82000000 — safe).
## Canary test (32-byte write, deterministic)
1. Confirm defaults: read `LPDDR_CTRL` (expect 0x2), `LPDDR_FB_BASE` (expect 0x8000_0000).
2. Baseline: `sudo dd if=/dev/mem bs=1 skip=2147483648 count=32 2>/dev/null | hexdump -C`
3. Arm in canary mode: write `LPDDR_CTRL = 0x3` (arm=1, canary=1).
4. Re-read the 32 bytes (same `dd`). Expect the top scanline (PSMCT16 green = 0x8200):
`00 82 00 82 00 82 00 82 00 82 00 82 00 82 00 82` (×2 lines = 32 bytes).
5. Optional: read `LPDDR_BURSTS` (advancing) + `LPDDR_STATUS` (bit1/bit2 = 0).
PASS = bytes changed baseline → the `00 82` pattern (fabric reached LPDDR at the
expected physical address). Then **disarm: write LPDDR_CTRL = 0x2**.
## Full-frame test (8 KiB)
1. Arm full: write `LPDDR_CTRL = 0x1` (arm=1, canary=0).
2. `sudo dd if=/dev/mem bs=4096 skip=524288 count=2 2>/dev/null | md5sum`
Expect **`3b12baffc00bb6419fa66272c75b2cc7`** (the exact sim image).
3. Confirm `LPDDR_STATUS` bits 1,2 = 0 (no bresp/FIFO errors). Disarm when done (0x2).
## Notes
- `0x80000000` = 2147483648 bytes; `skip=524288` blocks × 4096 = same address.
- Never read/write `0x820000000xBFFFFFFF` (live Linux RAM).
- If a hardened kernel blocks `/dev/mem` to the reserved region, use the same
`devmem`/mmap path the existing runtime uses; if a readback looks stale, it's CPU
caching of that address — read uncached.
- Scanout from LPDDR is Ch319 — start only after this write/readback passes.