diff --git a/9_Firmware/9_2_FPGA/doppler_processor.v b/9_Firmware/9_2_FPGA/doppler_processor.v index 1fdceb4..9d3fcff 100644 --- a/9_Firmware/9_2_FPGA/doppler_processor.v +++ b/9_Firmware/9_2_FPGA/doppler_processor.v @@ -22,8 +22,12 @@ // to make NUM_SUBFRAMES=2; the FSM generalises cleanly. doppler_bin still // reports 6 bits there with the high bit always zero. // -// Staggered-PRF ambiguity resolution downstream picks the matching Doppler -// bin from the SHORT vs MEDIUM vs LONG sub-frame to resolve velocity. +// Staggered-PRF ambiguity resolution is host-side (see v7/processing.py +// unfold_velocity_crt under PR-Q). Three distinct PRIs in production — +// SHORT 175 µs, MEDIUM 161 µs, LONG 167 µs — give the host enough info +// to run 3-PRI Chinese-Remainder unfolding on Doppler aliases beyond the +// per-sub-frame ±~41 m/s unambiguous range. doppler_bin's high two bits +// carry the sub_frame ID so the host can group detections by source. // // WINDOW: // 16-point Dolph-Chebyshev, 60 dB equiripple sidelobes (PR-M). diff --git a/9_Firmware/9_2_FPGA/radar_params.vh b/9_Firmware/9_2_FPGA/radar_params.vh index 21832a7..c4638d9 100644 --- a/9_Firmware/9_2_FPGA/radar_params.vh +++ b/9_Firmware/9_2_FPGA/radar_params.vh @@ -214,8 +214,15 @@ // Reset defaults for host-configurable timing registers. // Match radar_mode_controller.v parameters and main.cpp STM32 defaults. // -// 3-LADDER (3 km build): SHORT 1 µs, MEDIUM 5 µs, LONG 30 µs. Same listen -// budget across waveforms (~175 µs PRI) keeps Doppler resolution uniform. +// 3-LADDER (3 km build): SHORT 1 µs, MEDIUM 5 µs, LONG 30 µs. +// PRI ladder is intentionally STAGGERED across waveforms — SHORT 175 µs, +// MEDIUM 161 µs, LONG 167 µs (PR-Q). Three coprime PRIs let the host run +// 3-PRI Chinese-Remainder unfolding on Doppler aliases (see C-5 in the +// 2026-04-29 audit). In 3 km mode LONG is blind (4500 m blind zone) so +// SHORT-vs-MEDIUM (Δ=14 µs / 8 %) is the operative pair; in 20 km mode +// MEDIUM-vs-LONG (Δ=6 µs / 4 %) carries the long-range slice that has +// SNR for both. Picking listen cycles to differ by ≥5 % keeps the alias +// resolver robust against the 5.1 m/s/bin Doppler quantization. // LONG kept on 50T as legal-but-unused so 200T spin-up doesn't need a // second wave through the codebase. @@ -228,9 +235,9 @@ // 3-ladder defaults — added in PR-A, consumed by chirp_scheduler in PR-D. `define RP_DEF_SHORT_CHIRP_CYCLES_V2 100 // 1 µs at 100 MHz (was 0.5 µs) -`define RP_DEF_SHORT_LISTEN_CYCLES_V2 17400 // PRI 175 µs - chirp - guard slack +`define RP_DEF_SHORT_LISTEN_CYCLES_V2 17400 // SHORT PRI 175 µs (chirp 1 + listen 174) `define RP_DEF_MEDIUM_CHIRP_CYCLES 500 // 5 µs at 100 MHz -`define RP_DEF_MEDIUM_LISTEN_CYCLES 17000 // PRI 175 µs - chirp - guard slack +`define RP_DEF_MEDIUM_LISTEN_CYCLES 15600 // MEDIUM PRI 161 µs (chirp 5 + listen 156, PR-Q stagger) // LONG defaults reuse RP_DEF_LONG_CHIRP_CYCLES / RP_DEF_LONG_LISTEN_CYCLES `define RP_DEF_CHIRPS_PER_SUBFRAME 16 // 16 per sub-frame, 3 sub-frames = 48 frame `define RP_DEF_SUBFRAME_ENABLE 3'b111 // SHORT|MEDIUM|LONG all on by default diff --git a/9_Firmware/9_2_FPGA/radar_system_top.v b/9_Firmware/9_2_FPGA/radar_system_top.v index 720ea67..a850fea 100644 --- a/9_Firmware/9_2_FPGA/radar_system_top.v +++ b/9_Firmware/9_2_FPGA/radar_system_top.v @@ -270,15 +270,17 @@ reg [15:0] host_guard_cycles; // Opcode 0x12 (default 17540) reg [15:0] host_short_chirp_cycles; // Opcode 0x13 (default 100, V2) reg [15:0] host_short_listen_cycles; // Opcode 0x14 (default 17400, V2) reg [15:0] host_medium_chirp_cycles; // Opcode 0x17 (default 500, PR-G G2) -reg [15:0] host_medium_listen_cycles; // Opcode 0x18 (default 17000, PR-G G2) +reg [15:0] host_medium_listen_cycles; // Opcode 0x18 (default 15600, PR-Q staggered PRI) reg [5:0] host_chirps_per_elev; // Opcode 0x15 (default 32) reg host_status_request; // Opcode 0xFF (self-clearing pulse) // Fix 4: Doppler/chirps mismatch protection // DOPPLER_FRAME_CHIRPS is the fixed chirp count expected by the staggered-PRI -// Doppler path (16 long + 16 short). If host sets chirps_per_elev to a -// different value, Doppler accumulation is corrupted. Clamp at command decode -// and flag the mismatch so the host knows. +// Doppler path: 48 chirps split as 16 SHORT (175 µs PRI) + 16 MEDIUM (161 µs +// PRI, PR-Q) + 16 LONG (167 µs PRI). Three distinct coprime PRIs let the +// host run 3-PRI CRT to unfold Doppler aliases (C-5 / PR-Q). If host sets +// chirps_per_elev to a different value, Doppler accumulation is corrupted. +// Clamp at command decode and flag the mismatch so the host knows. localparam DOPPLER_FRAME_CHIRPS = `RP_CHIRPS_PER_FRAME; // 48 (PR-F); was 32 reg chirps_mismatch_error; // Set if host tried to set chirps != FFT size diff --git a/9_Firmware/9_2_FPGA/tb/tb_radar_receiver_final.v b/9_Firmware/9_2_FPGA/tb/tb_radar_receiver_final.v index ee32115..942b406 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_radar_receiver_final.v +++ b/9_Firmware/9_2_FPGA/tb/tb_radar_receiver_final.v @@ -196,8 +196,10 @@ radar_receiver_final dut ( // ============================================================================ // SIM TIMING — driven via host_* inputs above (chirp-v2 PR-D). // chirp_scheduler is host-input driven; no defparam overrides needed. -// Real values: LONG_CHIRP=3000, LONG_LISTEN=13700, GUARD=17540, -// SHORT_CHIRP=100 (V2), SHORT_LISTEN=17400 (~31040 per chirp). +// Real values: LONG_CHIRP=3000, LONG_LISTEN=13700, +// MEDIUM_CHIRP=500, MEDIUM_LISTEN=15600 (PR-Q stagger), +// SHORT_CHIRP=100, SHORT_LISTEN=17400 (V2), +// GUARD=17540. // The host_* assignments above feed the same compressed timing the legacy // defparams used. // ============================================================================