fix: use authoritative tx frame signal for frame sync, consistent ad9523 error path

FPGA-001: The previous fix derived frame boundaries from chirp_counter==0,
but that counter comes from plfm_chirp_controller_enhanced which overflows
to N (not wrapping at chirps_per_elev). This caused frame pulses only on
6-bit rollover (every 64 chirps) instead of every N chirps. Now wires the
CDC-synchronized tx_new_chirp_frame_sync signal from the transmitter into
radar_receiver_final, giving correct per-frame timing for any N.

STM32-004: Changed ad9523_init() failure path from Error_Handler() to
return -1, matching the pattern used by ad9523_setup() and ad9523_status()
in the same function. Both halt the system, but return -1 keeps IRQs
enabled for diagnostic output.
This commit is contained in:
Jason
2026-04-16 00:33:27 +05:45
parent 8187771ab0
commit db4e73577e
4 changed files with 38 additions and 24 deletions
+17 -22
View File
@@ -11,8 +11,10 @@ module radar_receiver_final (
input wire adc_dco_n, // Data Clock Output N (400MHz LVDS)
output wire adc_pwdn,
// Chirp counter from transmitter (for frame sync and matched filter)
// Chirp counter from transmitter (for matched filter indexing)
input wire [5:0] chirp_counter,
// Frame-start pulse from transmitter (CDC-synchronized, 1 clk_100m cycle)
input wire tx_frame_start,
output wire [31:0] doppler_output,
output wire doppler_valid,
@@ -392,30 +394,31 @@ mti_canceller #(
.mti_first_chirp(mti_first_chirp)
);
// ========== FRAME SYNC USING chirp_counter ==========
reg [5:0] chirp_counter_prev;
// ========== FRAME SYNC FROM TRANSMITTER ==========
// [FPGA-001 FIXED] Use the authoritative new_chirp_frame signal from the
// transmitter (via plfm_chirp_controller_enhanced), CDC-synchronized to
// clk_100m in radar_system_top. Previous code tried to derive frame
// boundaries from chirp_counter == 0, but that counter comes from the
// transmitter path (plfm_chirp_controller_enhanced) which does NOT wrap
// at chirps_per_elev it overflows to N and only wraps at 6-bit rollover
// (64). This caused frame pulses at half the expected rate for N=32.
reg tx_frame_start_prev;
reg new_frame_pulse;
always @(posedge clk or negedge reset_n) begin
if (!reset_n) begin
chirp_counter_prev <= 6'd0;
tx_frame_start_prev <= 1'b0;
new_frame_pulse <= 1'b0;
end else begin
// Default: no pulse
new_frame_pulse <= 1'b0;
// [FPGA-001 FIXED] Detect frame boundary when chirp_counter wraps to 0.
// The chirp_counter (driven by radar_mode_controller) counts 0..N-1
// and wraps back to 0 at the start of each new frame. Previous code
// also checked (== host_chirps_per_elev) and (== 2*host_chirps_per_elev)
// which were unreachable dead conditions for any N, since the counter
// never reaches N. Now works correctly for any chirps_per_elev value.
if (chirp_counter != chirp_counter_prev && chirp_counter == 6'd0) begin
// Edge detect: tx_frame_start is a toggle-CDC derived pulse that
// may be 1 clock wide. Capture rising edge for clean 1-cycle pulse.
if (tx_frame_start && !tx_frame_start_prev) begin
new_frame_pulse <= 1'b1;
end
// Store previous value
chirp_counter_prev <= chirp_counter;
tx_frame_start_prev <= tx_frame_start;
end
end
@@ -481,14 +484,6 @@ always @(posedge clk or negedge reset_n) begin
`endif
chirps_in_current_frame <= 0;
end
// Monitor chirp counter pattern
if (chirp_counter != chirp_counter_prev) begin
`ifdef SIMULATION
$display("[TOP] chirp_counter: %0d ? %0d",
chirp_counter_prev, chirp_counter);
`endif
end
end
end
+2
View File
@@ -505,6 +505,8 @@ radar_receiver_final rx_inst (
// Chirp counter from transmitter (CDC-synchronized from 120 MHz domain)
.chirp_counter(tx_current_chirp_sync),
// Frame-start pulse from transmitter (CDC-synchronized togglepulse)
.tx_frame_start(tx_new_chirp_frame_sync),
// ADC Physical Interface
.adc_d_p(adc_d_p),
@@ -96,15 +96,31 @@ end
reg [5:0] chirp_counter;
reg mc_new_chirp_prev;
// Frame-start pulse: mirrors the real transmitter's new_chirp_frame signal.
// In the real system this fires on IDLELONG_CHIRP transitions in the chirp
// controller. Here we derive it from the mode controller's chirp_count
// wrapping back to 0 (which wraps correctly at cfg_chirps_per_elev).
reg tx_frame_start;
reg [5:0] rmc_chirp_prev;
always @(posedge clk_100m or negedge reset_n) begin
if (!reset_n) begin
chirp_counter <= 6'd0;
mc_new_chirp_prev <= 1'b0;
tx_frame_start <= 1'b0;
rmc_chirp_prev <= 6'd0;
end else begin
mc_new_chirp_prev <= dut.mc_new_chirp;
if (dut.mc_new_chirp != mc_new_chirp_prev) begin
chirp_counter <= chirp_counter + 1;
end
// Detect when the internal mode controller's chirp_count wraps to 0
tx_frame_start <= 1'b0;
if (dut.rmc_chirp_count == 6'd0 && rmc_chirp_prev != 6'd0) begin
tx_frame_start <= 1'b1;
end
rmc_chirp_prev <= dut.rmc_chirp_count;
end
end
@@ -128,6 +144,7 @@ radar_receiver_final dut (
.adc_pwdn(),
.chirp_counter(chirp_counter),
.tx_frame_start(tx_frame_start),
.doppler_output(doppler_output),
.doppler_valid(doppler_valid),