Ch443c: per-frame scanout diagnostic + frame-restart latency fix
The Ch443 board A+B diagnostic captured a WARM-UP miss, not a displayed-
frame miss: the line-buffer reader is enabled by video_src_emif
immediately, but the HDMI mux only switches to it at the next vsync, and
the diagnostic (cleared only on !enable) froze that pre-display capture.
scan_y=32/nf=32 was the expected pre-display warm-up, and line_valid is
sticky so it only meant SOME row had loaded, not that row 32 was valid.
Two fixes (all accepted Ch443 timing repairs kept: AW buffer, F_SETTLE +
drain multicycle, tile max-skew, monolithic tex_mem):
1. Per-frame diagnostic: clear diag_valid_q on fs_edge_v as well as
!enable (mirrors underflow_v). Discards the warm-up capture and
records the first miss, if any, AFTER the real frame boundary.
2. Frame-restart latency: in L_R, after the single-beat response is
accepted, if fs_pending || fs_edge_e, abandon the remainder of the
obsolete row -- no beat commit, no next old-row AR, no publish/
increment -- and return to L_IDLE, which restarts at V_SOURCE_START.
Protocol-safe (the accepted AXI transaction is complete); removes up
to a full row of restart latency during vertical blanking, so the
restarted prefetch leads the first displayed row.
New tb_gs_scanout_restart proves: mid-fetch frame-start accepts the
in-flight response, issues NO further old-row AR, restarts at row 32,
loads rows 32/33 before active consumption, and no post-restart
underflow. Regressions green: scanout_lb {,_binomial,_hstretch,
_psm32_256,_fb}, scanout_diag (per-frame), ps2_hps_bridge, and the
complete f52 replay BYTE-IDENTICAL (Z 0/307200, COLOR 0/245760).
Also commits the previously-untracked Ch443 board A+B evidence
(docs/hardware/ch443_board_validation/: verdict, 3-session raw, board
FB, RBF sha). No Quartus/board/push from here.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
SESSION 1
|
||||
0x02C=0x000000F1
|
||||
0x120=0x0000003B
|
||||
0x124=0x02008020
|
||||
SESSION 2
|
||||
0x02C=0x000000F1
|
||||
0x120=0x0000003B
|
||||
0x124=0x02008020
|
||||
SESSION 3
|
||||
0x02C=0x000000F1
|
||||
0x120=0x0000003B
|
||||
0x124=0x02008020
|
||||
DONE
|
||||
@@ -0,0 +1,45 @@
|
||||
# Ch443 board A+B diagnostic — verdict (zsrt139f52, 2026-07-22)
|
||||
|
||||
Image: `retroDE_ps2.ch443.core.rbf` SHA `d15deb42c99212d49715335d460357dc3f2487e14cf49bd60c7ad63ba52b9990`
|
||||
(26.1.0 Build 110 GUI fit of commit 4358bc3; non-canonical diagnostic candidate). Canonical
|
||||
`retroDE_ps2.core.rbf` untouched; Ch441 restored after capture.
|
||||
|
||||
## Fit acceptance (all met)
|
||||
Timing: 0 violated setup/hold paths, EMIF setup +0.177; AWREADY family absent; drain multicycle
|
||||
bound (`Ch443 SDC: texture drain_idx_q -> tex_mem 2-cycle setup / 1-cycle hold (16 src -> 2053 dst)`);
|
||||
monolithic **128-M20K** `tex_mem`; RAM 317/358 (89%), ALM 85%.
|
||||
|
||||
## Board render
|
||||
f52 replay `DONE rc=0`, zero drops, texture CRC `0x13cfe390` == expected, FB **byte-identical to
|
||||
golden** (SHA `d0047677…`, sum32 `0xaad0b94d`). The AW buffer + F_SETTLE 2-cycle drain + monolithic
|
||||
tex_mem are all functionally correct on silicon.
|
||||
|
||||
## A+B diagnostic — 3 independent source-enable sessions, BIT-IDENTICAL each time
|
||||
| reg | raw | decode |
|
||||
|-----|-----|--------|
|
||||
| 0x02C LPDDR_STATUS | `0x000000F1` | idle, scan_cache_valid, **scan_rd_err(bit5)=1**, frame_drained, clear_done |
|
||||
| 0x120 SCAN_DIAG_STATUS | `0x0000003B` | valid=1, **underflow=1**, **read-error-nonzero=0**, cause_base=1, cause_lookahead=1, line_valid=1, vphase=0 |
|
||||
| 0x124 SCAN_DIAG_FIRST | `0x02008020` | **scan_y=32, nf_v=32, nf_s0=32** |
|
||||
|
||||
## VERDICT
|
||||
The `LPDDR_STATUS[5]` `0xF1` symptom is definitively a **line-buffer prefetch UNDERFLOW, NOT an AXI
|
||||
read error** — `0x120` shows underflow=1 with read-error-nonzero=**0**. This resolves the three-way
|
||||
ambiguity Codex flagged: it is cause #1 (starvation-class), not cause #2 (AXI read errors).
|
||||
|
||||
The first failure is pinned to **scan_y = 32 = V_SOURCE_START** (SH3 DISPFB2.DBY=32, the first
|
||||
displayed source row) — exactly the production cold-start row-32 miss predicted. `nf_v = nf_s0 = 32`
|
||||
= `next_fetch` at its frame-start reset value, i.e. the prefetch had not advanced past row 32 when
|
||||
row 32 was first displayed. Both cause bits assert (base + lookahead), consistent with the vertical
|
||||
filter. line_valid=1 confirms the EMIF read path works — this is a first-displayed-row ordering race,
|
||||
not total starvation. Deterministic across 3 independent sessions ⇒ a reproducible STRUCTURAL
|
||||
first-row prefetch boundary, not a random glitch.
|
||||
|
||||
## Caveat (per Codex) + next
|
||||
A single snapshot NARROWS but does not by itself PROVE sustained starvation vs a `next_fetch` CDC-lag
|
||||
at reset (nf_v=32 is exactly the reset value). What is now PROVEN: (a) not an AXI read error; (b) the
|
||||
first miss is the cold-start row-32 boundary; (c) deterministic. Definitive starvation-vs-CDC
|
||||
separation needs the deferred follow-up (gray-code `next_fetch` across the sync, or a 2-cycle
|
||||
compare-agreement, or multi-frame captures). The FB (memory) is byte-perfect; whether this scanout
|
||||
underflow produces visible HDMI top-row corruption needs an actual HDMI capture (not a memory dump).
|
||||
|
||||
Evidence: `ch443_ab_3session_raw.txt`, `sh3_zsrt139f52_ch443_board_fb.mem`, `ch443_rbf.sha256`.
|
||||
@@ -0,0 +1 @@
|
||||
d15deb42c99212d49715335d460357dc3f2487e14cf49bd60c7ad63ba52b9990 docs/hardware/ch443_board_validation/retroDE_ps2.ch443.core.rbf
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user