fix: guard neuron_parallel against invalid N_INPUTS/PARALLEL combos

Both Phase 2 findings (docs/FPGA-NeuralNetwork-Engine.md) shared one
root cause: GROUPS = N_INPUTS / PARALLEL is integer division. When
N_INPUTS is not an exact multiple of PARALLEL, the remainder inputs
were silently dropped from the accumulation (wrong result, no
error); when PARALLEL > N_INPUTS, GROUPS = 0 and the controller's
terminal condition was never met, hanging the neuron forever.

Added a single elaboration-time guard to rtl/neuron_parallel.v: a
`generate` block instantiates a deliberately undefined module when
N_INPUTS % PARALLEL != 0, forcing a hard failure in both simulation
and synthesis instead of a silent wrong answer or a deadlock. Valid
configurations are unaffected (the branch is never elaborated). The
validated datapath (mac8/mac_unit/accumulation/ReLU/saturation) is
untouched -- this is authorized as a scoped exception to the
"core is fixed, do not touch" project policy, for this guard only.

- sim/neuron_parallel_guard_negative_nonmultiple_tb.v and
  sim/neuron_parallel_guard_negative_degenerate_tb.v: negative tests
  that must fail to elaborate; verified both fail with the expected
  "Unknown module type" error.
- sim/parameter_sweep_tb.v: rewritten to valid-configs-only (the
  three configs that used to demonstrate truncation/hang no longer
  compile, by design); added PARALLEL=2 and PARALLEL=4 configs,
  the two best-performing values from
  docs/FPGA-Neural-Datapatch-Benchmark.md.
- Full regression re-run after the RTL change: all existing
  testbenches still pass unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WQV3vS9TXaGDJ5cRfnfidt
This commit is contained in:
2026-09-02 14:41:49 +02:00
co-authored by Claude Sonnet 5
parent 9b9859a104
commit 1a6f0ba2ef
14 changed files with 45001 additions and 62768 deletions
@@ -0,0 +1,41 @@
`timescale 1ns/1ps
// ================================================================
// NEGATIVE TEST - intentionally invalid parameter combination.
//
// This file must FAIL TO COMPILE/ELABORATE. That failure is the
// test: it proves the PARAMETER_ERROR_N_INPUTS_NOT_MULTIPLE_OF_PARALLEL
// guard in rtl/neuron_parallel.v rejects configurations where
// N_INPUTS is not an exact multiple of PARALLEL (Phase 2 finding:
// N_INPUTS=30, PARALLEL=8 used to silently drop the last 6 inputs
// instead of erroring).
//
// Verify with:
// iverilog -g2012 -o /tmp/out rtl/*.v \
// sim/neuron_parallel_guard_negative_nonmultiple_tb.v
//
// Expected: nonzero exit status and
// "error: Unknown module type:
// neuron_parallel_requires_N_INPUTS_multiple_of_PARALLEL"
// ================================================================
module tb;
neuron_parallel #(
.DATA_WIDTH(8),
.N_INPUTS(30),
.PARALLEL(8),
.ACC_WIDTH(32)
) u_invalid (
.clk(1'b0),
.rst(1'b0),
.start(1'b0),
.x_bus(240'b0),
.w_bus(240'b0),
.bias(8'sd0),
.y(),
.busy(),
.done()
);
endmodule