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:
@@ -17,6 +17,35 @@ module neuron_parallel #(
|
||||
output reg done
|
||||
);
|
||||
|
||||
// ============================================================
|
||||
// PARAMETER GUARD
|
||||
//
|
||||
// PARALLEL must evenly divide N_INPUTS. If it does not:
|
||||
//
|
||||
// - GROUPS = N_INPUTS / PARALLEL truncates (integer division),
|
||||
// and the remainder inputs are silently never read by the
|
||||
// accumulator: WRONG result, no error, no warning.
|
||||
//
|
||||
// - If PARALLEL > N_INPUTS, GROUPS = 0 and the controller's
|
||||
// terminal condition (group_index == GROUPS-1) is never
|
||||
// satisfied: the neuron hangs forever (busy stays high,
|
||||
// done is never asserted).
|
||||
//
|
||||
// Both failure modes were confirmed empirically in
|
||||
// sim/parameter_sweep_tb.v (Phase 2 of the roadmap). Rather than
|
||||
// changing the validated datapath, this forces an elaboration-
|
||||
// time failure in BOTH simulation and synthesis by instantiating
|
||||
// a deliberately undefined module when the condition is
|
||||
// violated. When N_INPUTS % PARALLEL == 0 this generate branch
|
||||
// is never elaborated, so valid configurations are unaffected.
|
||||
// ============================================================
|
||||
|
||||
generate
|
||||
if (N_INPUTS % PARALLEL != 0) begin : PARAMETER_ERROR_N_INPUTS_NOT_MULTIPLE_OF_PARALLEL
|
||||
neuron_parallel_requires_N_INPUTS_multiple_of_PARALLEL invalid_parameter_combination();
|
||||
end
|
||||
endgenerate
|
||||
|
||||
localparam GROUPS = N_INPUTS / PARALLEL;
|
||||
localparam GROUP_INDEX_WIDTH =
|
||||
(GROUPS <= 1) ? 1 : $clog2(GROUPS);
|
||||
|
||||
Reference in New Issue
Block a user