mirror of
https://github.com/NawfalMotii79/PLFM_RADAR.git
synced 2026-06-10 23:41:18 +00:00
fix(fpga): pre-bringup RTL hardening + test-suite hardening
RTL (P0 pre-bringup findings R-1/R-2/R-3/R-5/R-6): - mti_canceller: add use_long_chirp input and waveform-boundary mute so the long->short transition in mode 01 no longer subtracts across heterogeneous waveforms (R-1). Prev buffer is overwritten in-flight at the boundary so the next same-waveform chirp subtracts cleanly. - ad9484_interface_400m: 2FF sync of mmcm_locked into the 400 MHz domain before gating reset_n_gated (R-6). - cic_decimator_4x_enhanced: correct max_fanout narrative (R-3). - ad9484_interface_400m: strip stale pblock comment, note 3.0 ns max_delay instead (R-2). - mti_canceller / doppler_processor: 200T-20km WARNING banners flagging the broken 4096-bin path (R-5). 9-bit BRAM address aliases silently until rewritten. - adc_clk_mmcm.xdc: relax set_max_delay from 2.700 -> 3.000 ns, closes WNS with headroom on 50T build. - radar_receiver_final: wire use_long_chirp into mti_inst. Architecture-bump finalization (2048-pt range FFT, 512 range bins, 32 Doppler bins -> 16384 output cells per frame): - tb/cosim/radar_scene.py: FFT_SIZE 1024 -> 2048, RANGE_BINS 64 -> 512. - tb/gen_mf_golden_ref.py: N 1024 -> 2048. - Regenerate all affected hex goldens (MF cases 1-4, Doppler inputs + py goldens, receiver integration golden_doppler.mem 2048 -> 16384). - tb_radar_receiver_final: widen range_bin_out 6 -> 9 bits, bump GOLDEN_ENTRIES 2048 -> 16384, expand bitmaps/arrays to 512 bins, update all check messages and thresholds. - tb_mti_canceller, tb_fullchain_mti_cfar_realdata: tie/pass use_long_chirp so compile still works after RTL port add. Test-suite hardening (coverage audit findings): - tb_mti_canceller T12: 10 new assertions exercising R-1 waveform- boundary mute across a long/long/short/short/long sequence. Catches a regression that re-enables subtraction across the boundary. - tb_fir_lowpass: replace tautological check(1'b1, ...) on coefficient symmetry with a real hierarchical check coeff[k]===coeff[31-k]; replace always-pass overflow check with a well-driven (not X/Z) assertion on filter_overflow. - tb_matched_filter_processing_chain: replace three always-pass peak- bin placeholders with peak-to-mean-|out| > 2x ratio checks (catches flat/zero output that the old tautologies silently accepted). - tb_cdc_modules M2: replace always-pass narrow-pulse check with a well-defined-output assertion on the synchronizer. - tb_nco_400m: replace always-pass freq-switch check with a swing + no-X assertion across 200 post-switch samples. - tb_system_e2e G12.1: replace check(1, ...) with test_num > 20 so it catches a stalled TB that skipped prior groups. - tb_multiseg_cosim TEST 4: replace always-pass placeholder with a bitmap that asserts segment_request visited all 4 values. - tb_mf_chain_synth and tb_fullchain_mti_cfar_realdata: add DEPRECATED headers plus \$fatal guards (ifndef ALLOW_STALE_*) so they cannot be silently re-enabled in CI with stale 1024-bin goldens against current 2048-pt RTL. Regression: 32 passed, 0 failed. MTI TB grew 30 -> 39 checks; receiver integration grew 17 -> 18 checks with 16384/16384 golden match at tolerance +/- 2 LSB.
This commit is contained in:
@@ -43,6 +43,19 @@
|
||||
|
||||
`include "radar_params.vh"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// !!! 200T 20 km MODE BROKEN — FIX BEFORE 200T BRING-UP !!!
|
||||
// The prev-chirp BRAM buffer is sized to NUM_RANGE_BINS (512) and the
|
||||
// range_bin_in port is 9 bits (`RP_RANGE_BIN_BITS). In 20 km mode the
|
||||
// upstream range_bin_decimator emits `RP_OUTPUT_RANGE_BINS_20KM = 4096
|
||||
// bins per chirp (8 segments × 512 decimated bins), which aliases into
|
||||
// the 9-bit address space and collapses bins 512..4095 onto bins 0..511.
|
||||
// On XC7A50T this is latent (SUPPORT_LONG_RANGE undefined → 3 km only),
|
||||
// but on XC7A200T with SUPPORT_LONG_RANGE the 20 km data path will
|
||||
// silently corrupt every range cell above 3 km.
|
||||
// Fix before 200T bring-up: scale NUM_RANGE_BINS/range_bin width with
|
||||
// `RP_MAX_OUTPUT_BINS, or gate MTI off entirely in 20 km mode.
|
||||
// ----------------------------------------------------------------------------
|
||||
module mti_canceller #(
|
||||
parameter NUM_RANGE_BINS = `RP_NUM_RANGE_BINS, // 512
|
||||
parameter DATA_WIDTH = `RP_DATA_WIDTH // 16
|
||||
@@ -65,6 +78,14 @@ module mti_canceller #(
|
||||
// ========== CONFIGURATION ==========
|
||||
input wire mti_enable, // 1=MTI active, 0=pass-through
|
||||
|
||||
// Current chirp's waveform selector (from radar_mode_controller). Used
|
||||
// to mute MTI output across the long↔short chirp boundary in range
|
||||
// mode 01 (long-range interleave) — without this, the first chirp of
|
||||
// a new waveform subtracts the previous waveform's range profile,
|
||||
// injecting a per-range-bin impulse into slow-time sample 0 of the
|
||||
// new Doppler sub-frame that spreads across all Doppler bins.
|
||||
input wire use_long_chirp,
|
||||
|
||||
// ========== STATUS ==========
|
||||
output reg mti_first_chirp, // 1 during first chirp (output muted)
|
||||
|
||||
@@ -92,20 +113,23 @@ reg signed [DATA_WIDTH-1:0] range_i_d1, range_q_d1;
|
||||
reg range_valid_d1;
|
||||
reg [`RP_RANGE_BIN_BITS-1:0] range_bin_d1;
|
||||
reg mti_enable_d1;
|
||||
reg use_long_chirp_d1;
|
||||
|
||||
always @(posedge clk or negedge reset_n) begin
|
||||
if (!reset_n) begin
|
||||
range_i_d1 <= {DATA_WIDTH{1'b0}};
|
||||
range_q_d1 <= {DATA_WIDTH{1'b0}};
|
||||
range_valid_d1 <= 1'b0;
|
||||
range_bin_d1 <= {`RP_RANGE_BIN_BITS{1'b0}};
|
||||
mti_enable_d1 <= 1'b0;
|
||||
range_i_d1 <= {DATA_WIDTH{1'b0}};
|
||||
range_q_d1 <= {DATA_WIDTH{1'b0}};
|
||||
range_valid_d1 <= 1'b0;
|
||||
range_bin_d1 <= {`RP_RANGE_BIN_BITS{1'b0}};
|
||||
mti_enable_d1 <= 1'b0;
|
||||
use_long_chirp_d1 <= 1'b0;
|
||||
end else begin
|
||||
range_i_d1 <= range_i_in;
|
||||
range_q_d1 <= range_q_in;
|
||||
range_valid_d1 <= range_valid_in;
|
||||
range_bin_d1 <= range_bin_in;
|
||||
mti_enable_d1 <= mti_enable;
|
||||
range_i_d1 <= range_i_in;
|
||||
range_q_d1 <= range_q_in;
|
||||
range_valid_d1 <= range_valid_in;
|
||||
range_bin_d1 <= range_bin_in;
|
||||
mti_enable_d1 <= mti_enable;
|
||||
use_long_chirp_d1 <= use_long_chirp;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -139,6 +163,14 @@ end
|
||||
// Track whether we have valid previous data
|
||||
reg has_previous;
|
||||
|
||||
// Waveform of the chirp whose profile currently lives in prev_i/prev_q.
|
||||
// Latched at end-of-chirp when we mark has_previous=1. Compared against
|
||||
// the incoming chirp's waveform at its first bin (range_bin_d1 == 0) to
|
||||
// detect a long↔short transition and re-mute.
|
||||
reg prev_chirp_was_long;
|
||||
wire waveform_changed = has_previous
|
||||
&& (use_long_chirp_d1 != prev_chirp_was_long);
|
||||
|
||||
// ============================================================================
|
||||
// MTI PROCESSING (operates on d1 pipeline stage + BRAM read data)
|
||||
// ============================================================================
|
||||
@@ -182,6 +214,7 @@ always @(posedge clk or negedge reset_n) begin
|
||||
range_bin_out <= {`RP_RANGE_BIN_BITS{1'b0}};
|
||||
has_previous <= 1'b0;
|
||||
mti_first_chirp <= 1'b1;
|
||||
prev_chirp_was_long <= 1'b0;
|
||||
mti_saturation_count <= 8'd0;
|
||||
end else begin
|
||||
// Count saturated MTI-active samples (F-6.3). Clamp at 0xFF.
|
||||
@@ -206,24 +239,39 @@ always @(posedge clk or negedge reset_n) begin
|
||||
// Reset first-chirp state when MTI is disabled
|
||||
has_previous <= 1'b0;
|
||||
mti_first_chirp <= 1'b1;
|
||||
end else if (!has_previous) begin
|
||||
// First chirp after enable: mute output (no subtraction possible).
|
||||
// Still emit valid=1 with zero data so Doppler processor gets
|
||||
// the expected number of samples per frame.
|
||||
end else if (!has_previous || waveform_changed) begin
|
||||
// No valid previous chirp to subtract from — either the very
|
||||
// first chirp after reset/enable, or the long↔short boundary
|
||||
// in range_mode=01 where the prev buffer holds a different
|
||||
// waveform's profile. Mute output (emit zeros with valid=1
|
||||
// so Doppler still sees the expected chirp count), overwrite
|
||||
// prev_i/prev_q as this chirp streams through the write port,
|
||||
// then re-arm at end-of-chirp with the CURRENT waveform tag.
|
||||
range_i_out <= {DATA_WIDTH{1'b0}};
|
||||
range_q_out <= {DATA_WIDTH{1'b0}};
|
||||
range_valid_out <= 1'b1;
|
||||
mti_first_chirp <= 1'b1;
|
||||
|
||||
// After last range bin of first chirp, mark previous as valid
|
||||
// After last range bin of this chirp, the prev buffer now
|
||||
// holds a full copy of THIS chirp's profile — arm for the
|
||||
// next chirp and remember which waveform was written.
|
||||
if (range_bin_d1 == NUM_RANGE_BINS - 1) begin
|
||||
has_previous <= 1'b1;
|
||||
mti_first_chirp <= 1'b0;
|
||||
has_previous <= 1'b1;
|
||||
mti_first_chirp <= 1'b0;
|
||||
prev_chirp_was_long <= use_long_chirp_d1;
|
||||
end
|
||||
end else begin
|
||||
// Normal MTI: subtract previous from current
|
||||
range_i_out <= diff_i_sat;
|
||||
range_q_out <= diff_q_sat;
|
||||
range_valid_out <= 1'b1;
|
||||
|
||||
// Refresh the waveform tag at end-of-chirp so the compare
|
||||
// on the next chirp stays correct (same-waveform runs are
|
||||
// the common case and the tag must track them).
|
||||
if (range_bin_d1 == NUM_RANGE_BINS - 1) begin
|
||||
prev_chirp_was_long <= use_long_chirp_d1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user