fix: neural_director_packed.v SV literal for synth; exonerate it from a testbench race (EXP-0073)

Replaced three uses of the SystemVerilog '0 self-sizing literal with
explicit-width zero-fill so the file synthesizes under Vivado's
synth_design (which has no -sv equivalent in this flow), needed while
adding this module to the real in-context P&R project.

Re-running its isolated regression after that edit surfaced 3/8
failures. Root-caused via git stash (reproduces on the untouched
committed file, not caused by this edit) and a DUT-internal $display:
tb_neural_director_packed.v's own submit_job task drove DUT inputs
with blocking assignment across two separate @(posedge clk) waits,
racing the DUT's own always block under Icarus and causing a spurious
duplicate enqueue. Fixed by switching to nonblocking assignment
(race-free by construction). neural_director_packed.v itself was
correct all along - 8/8 tests pass after the testbench fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
2026-09-19 13:37:25 +02:00
co-authored by Claude Sonnet 5
parent 562cf91f1e
commit 6caea54b8e
3 changed files with 105 additions and 7 deletions
+24 -4
View File
@@ -113,18 +113,38 @@ module tb;
integer errors, tests;
// Drives DUT inputs with NONBLOCKING assignment (<=), not blocking
// (=). Root-caused this session: the previous blocking-assignment
// version raced neural_director_packed.v's own posedge-triggered
// always block -- Icarus does not consistently order "testbench
// process resumes from @(posedge clk) and executes a blocking
// write" against "DUT's always @(posedge clk) block reads that
// same signal" when both wake on the SAME edge, and the ordering
// was observed to differ between the SET edge and the CLEAR edge
// within the same task call (confirmed via a DUT-internal $display
// showing job_in_valid sampled as 1 on TWO consecutive edges from
// a single submit_job call, both times with the FIRST job's stale
// x_base -- a spurious duplicate enqueue, not a Director bug: the
// committed neural_director_packed.v was re-verified bit-identical
// via the same test with this fix applied). Nonblocking assignment
// removes the race entirely: NBA updates land strictly after the
// Active region where the DUT's own always block runs, so the DUT
// always samples the OLD value at the driving edge and the NEW
// value only from the NEXT edge onward -- deterministic by the
// language, not by scheduler luck.
task automatic submit_job(
input [ADDR_WIDTH-1:0] xb, input [ADDR_WIDTH-1:0] wb,
input [15:0] nt, input [ADDR_WIDTH-1:0] resaddr, input [15:0] nid
);
begin
@(posedge clk);
job_in_x_base = xb; job_in_w_base = wb; job_in_n_tiles = nt;
job_in_result_addr = resaddr; job_in_node_id = nid;
job_in_valid = 1'b1;
job_in_x_base <= xb; job_in_w_base <= wb; job_in_n_tiles <= nt;
job_in_result_addr <= resaddr; job_in_node_id <= nid;
job_in_valid <= 1'b1;
@(posedge clk);
while (!job_in_ready) @(posedge clk);
job_in_valid <= 1'b0;
@(posedge clk);
job_in_valid = 1'b0;
end
endtask