Fix range_bin_decimator overflow guard priority bug: group completion now takes precedence over overflow guard in ST_PROCESS, ensuring all OUTPUT_BINS outputs are emitted when sufficient input samples exist. Split formal property 5 into 5a (upper bound) and 5b (exact count when start_bin=0), added Cover 4 for overflow guard path, reduced BMC depth to 50.

This commit is contained in:
Jason
2026-03-17 15:40:55 +02:00
parent 37c8925df0
commit 6fc5a10785
4 changed files with 2086 additions and 2062 deletions
@@ -4,9 +4,9 @@ cover
[options] [options]
bmc: mode bmc bmc: mode bmc
bmc: depth 120 bmc: depth 50
cover: mode cover cover: mode cover
cover: depth 120 cover: depth 50
[engines] [engines]
smtbmc z3 smtbmc z3
@@ -180,9 +180,11 @@ module fv_range_bin_decimator (
end end
// ================================================================ // ================================================================
// PROPERTY 5: Exactly OUTPUT_BINS outputs per frame // PROPERTY 5a: Output count never exceeds OUTPUT_BINS
// When state reaches ST_DONE, exactly OUTPUT_BINS valid output // When state reaches ST_DONE, at most OUTPUT_BINS valid output
// pulses must have been emitted. // pulses have been emitted. The overflow guard in ST_PROCESS
// (in_bin_count >= INPUT_BINS-1 ST_DONE) may cause early
// termination when start_bin is large, producing fewer outputs.
// //
// Timing: The last range_valid_out is registered in ST_EMIT and // Timing: The last range_valid_out is registered in ST_EMIT and
// appears high on the same posedge that state transitions to // appears high on the same posedge that state transitions to
@@ -191,10 +193,22 @@ module fv_range_bin_decimator (
// Check when $past(state) == ST_DONE (i.e. the cycle after entry) // Check when $past(state) == ST_DONE (i.e. the cycle after entry)
// so the counter has resolved. At this point state == ST_IDLE, // so the counter has resolved. At this point state == ST_IDLE,
// but the counter's ST_IDLE reset is also an NBA that hasn't // but the counter's ST_IDLE reset is also an NBA that hasn't
// resolved yet, so fv_valid_out_count still reads OUTPUT_BINS. // resolved yet, so fv_valid_out_count still reads its final value.
// ================================================================ // ================================================================
always @(posedge clk) begin always @(posedge clk) begin
if (reset_n && f_past_valid && $past(state) == ST_DONE) if (reset_n && f_past_valid && $past(state) == ST_DONE)
assert(fv_valid_out_count <= OUTPUT_BINS);
end
// ================================================================
// PROPERTY 5b: Exactly OUTPUT_BINS outputs when enough samples
// When start_bin is small enough that INPUT_BINS - start_bin >=
// OUTPUT_BINS * DECIMATION_FACTOR, all outputs are produced.
// With reduced params: 32 - start_bin >= 32, i.e. start_bin == 0.
// ================================================================
always @(posedge clk) begin
if (reset_n && f_past_valid && $past(state) == ST_DONE &&
start_bin == 10'd0)
assert(fv_valid_out_count == OUTPUT_BINS); assert(fv_valid_out_count == OUTPUT_BINS);
end end
@@ -238,6 +252,16 @@ module fv_range_bin_decimator (
cover(state == ST_DONE && decimation_mode == 2'b01); cover(state == ST_DONE && decimation_mode == 2'b01);
end end
// ================================================================
// COVER 4: Overflow guard early termination
// Verify the overflow guard path is reachable: ST_DONE reached
// with fewer than OUTPUT_BINS outputs (start_bin too large).
// ================================================================
always @(posedge clk) begin
if (reset_n && f_past_valid && $past(state) == ST_DONE)
cover(fv_valid_out_count < OUTPUT_BINS);
end
`endif // FORMAL `endif // FORMAL
endmodule endmodule
+8 -8
View File
@@ -236,13 +236,8 @@ always @(posedge clk or negedge reset_n) begin
if (range_valid_in) begin if (range_valid_in) begin
in_bin_count <= in_bin_count + 1; in_bin_count <= in_bin_count + 1;
// Overflow guard: stop if we've consumed all input bins // Mode-specific sample processing always process
// Prevents corruption of downstream Doppler BRAM if matched // the current sample before checking overflow
// filter emits more than INPUT_BINS valid samples
if (in_bin_count >= INPUT_BINS - 1) begin
state <= ST_DONE;
end else begin
// Mode-specific sample processing
case (decimation_mode) case (decimation_mode)
2'b00: begin // Simple decimation 2'b00: begin // Simple decimation
if (group_sample_count == (DECIMATION_FACTOR / 2)) begin if (group_sample_count == (DECIMATION_FACTOR / 2)) begin
@@ -269,10 +264,15 @@ always @(posedge clk or negedge reset_n) begin
// Group complete emit output // Group complete emit output
state <= ST_EMIT; state <= ST_EMIT;
group_sample_count <= 4'd0; group_sample_count <= 4'd0;
end else if (in_bin_count >= INPUT_BINS - 1) begin
// Overflow guard: consumed all input bins but group
// is not yet complete. Stop to prevent corruption of
// downstream Doppler BRAM if matched filter emits
// more than INPUT_BINS valid samples.
state <= ST_DONE;
end else begin end else begin
group_sample_count <= group_sample_count + 1; group_sample_count <= group_sample_count + 1;
end end
end // else (overflow guard)
end end
end end
File diff suppressed because it is too large Load Diff