test: certify mem_arbiter priority order (C.4)

Priority B>C>A>D confirmed correct with distinguishable per-port data
(not just "someone got served" but "the right requester got its own
data back") across 4 contention scenarios. D-alone case confirms low
priority does not mean never granted.

Found and fixed a real race in the test harness itself: blocking
assignments withdrew loser requests in the same clock edge meant to
grant the winner, racing the DUT's own synchronous block -- dut.owner
never left SEL_NONE, every wait() blocked forever. Fixed by switching
request-signal drives to non-blocking assignments throughout.

Documented (not filed as a bug) that D can starve indefinitely under
sustained continuous B contention -- standard behavior for a
fixed-priority arbiter with no aging, and explicitly outside the
header's own stated operating assumption (B/C temporally disjoint in
normal operation). Flagged the header's "never starves or corrupts
A/B/C" wording as ambiguous about whether it promises D's own
progress.

Full regression: 40/40 real tests 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-04 14:41:44 +02:00
co-authored by Claude Sonnet 5
parent 3dd75e9e0d
commit b528901510
21 changed files with 285 additions and 17 deletions
+5
View File
@@ -142,3 +142,8 @@ perché siano difetti.
precedente), e uno stub di memoria comportamentale che ignorava le byte-lane
`mem_lb_n`/`mem_ub_n` durante la scrittura. Entrambi difetti della testbench, non
dell'RTL — vedi `docs/validation/03-memoria.md` §3.1.
- **C.4 (`mem_arbiter` mai concedeva nulla nella mia prima testbench)**: assegnazioni
bloccanti per ritirare le richieste dei "perdenti" nello stesso fronte di clock che
doveva concedere la richiesta — race reale con il blocco sincrono del DUT. Diagnosticato
con `dut.owner` mai uscito da `SEL_NONE`. Corretto passando ad assegnazioni non bloccanti.
Vedi `docs/validation/04-arbiter.md` §4.1.