FPGA Signal Processing Chain Architecture for Pulse Compression and CFAR Detection
The AERIS-10 radar implements a deterministic, register-controlled pipeline in its FPGA that converts raw 16-bit I/Q ADC samples into calibrated target detections via range-Doppler processing and constant-false-alarm-rate (CFAR) detection.
This article examines the complete signal processing architecture implemented in the NawfalMotii79/PLFM_RADAR repository, which provides a bit-accurate Python replica of the FPGA signal chain alongside the VHDL hardware implementation. The design emphasizes deterministic latency and host configurability, with every processing stage—from quantization through CFAR detection—exposed via memory-mapped registers defined in the hardware abstraction layer.
Deterministic Processing Pipeline Overview
The FPGA signal chain follows a strictly ordered pipeline defined in software_fpga.py (lines 9–12), processing each chirp through seven distinct stages before outputting a populated RadarFrame. This deterministic flow mirrors the exact RTL implementation in the AERIS-10 firmware.
Quantization Stage
Processing begins with 16-bit signed I/Q samples produced by the ADC-DDC (Analog-to-Digital Converter with Digital Down-Conversion) front end. The hardware expects this specific format, and the reference Python implementation uses quantize_raw_iq() to convert floating-point captures into the fixed-point representation required by the FPGA datapath.
Range FFT and Pulse Compression
The Range FFT stage (run_range_fft) performs pulse compression via fast-Fourier-transform processing on each incoming chirp. The implementation uses pre-computed twiddle factors loaded from fft_twiddle_1024.mem, executing a 1024-point complex FFT that transforms time-domain samples into range-profile bins.
Following the FFT, the Range Bin Decimator (run_range_bin_decimator) reduces the 1024-point spectrum down to 64 range bins, effectively compressing the data volume while preserving target information across the desired unambiguous range.
Clutter Suppression and Doppler Processing
Before extracting velocity information, the chain applies an MTI Canceller (run_mti_canceller) to remove stationary clutter via digital filtering. This two-pulse canceller (or equivalent high-pass filter) eliminates ground returns and stationary objects prior to Doppler analysis.
The Doppler FFT stage (run_doppler_fft) then computes the range-Doppler map using dual 16-point FFTs with Hamming windowing. The twiddle factors for this stage reside in fft_twiddle_16.mem, enabling coherent integration across chirps to resolve target velocity.
DC Notch Filtering
Immediately following Doppler processing, the DC Notch stage (run_dc_notch) zero-writes bins around DC to suppress local oscillator leakage and direct current offsets that manifest as strong returns at zero Doppler.
CFAR Detection Architecture
The final stage implements a Constant-False-Alarm-Rate (CFAR) Detector (run_cfar_ca) that adaptively thresholds the range-Doppler map to maintain consistent detection performance despite varying noise floors. This module is a bit-accurate replica of the VHDL module cfar_ca.v.
Algorithm Implementation
As detailed in golden_reference.py (lines 21–27), the CFAR processor operates on a column-wise basis with the following mathematical operations:
-
Magnitude Computation: The algorithm computes the L1 norm (|I| + |Q|) to generate a 17-bit unsigned magnitude value for each cell under test (CUT), avoiding the resource cost of a full CORDIC-based magnitude calculation.
-
Cell Averaging Strategy: The detector supports three configurable modes controlled by a 2-bit register field (0 = CA, 1 = GO, 2 = SO) mapped via
_CFAR_MODE_MAPinsoftware_fpga.py(lines 62–64):- CA (Cell Averaging): Sums both leading and lagging training cells.
- GO (Greatest Of): Selects the side with the larger average.
- SO (Smallest Of): Selects the side with the smaller average.
-
Threshold Scaling: The noise estimate undergoes multiplication by the Q4.4 alpha factor (α), followed by a 4-bit right shift. The result saturates to 17 bits to prevent overflow while maintaining precision.
-
Binary Detection: The CUT is flagged as a target when its magnitude exceeds the computed adaptive threshold.
Register Configuration Interface
Each processing stage is toggleable and configurable via the FPGA register map defined in radar_protocol.py (lines 85–89). This allows real-time parameter adjustment without re-synthesizing the bitstream.
# Example: Running the full FPGA chain on a captured IQ file
import numpy as np
from 9_Firmware.9_3_GUI.v7.software_fpga import SoftwareFPGA, quantize_raw_iq
# Load a raw complex IQ capture (e.g., from an SDR)
raw_iq = np.load('capture.npy') # shape (chirps, samples), complex64
# Quantize to the 16-bit format used by the FPGA
iq_i, iq_q = quantize_raw_iq(raw_iq)
# Instantiate the software replica and enable CFAR
fpga = SoftwareFPGA()
fpga.set_cfar_enable(True) # turn on CFAR detection
fpga.set_cfar_mode(0) # CA-CFAR (mode code 0)
# Process the chirps – returns a RadarFrame with detections
frame = fpga.process_chirps(iq_i, iq_q, frame_number=1, timestamp=12.34)
print('Detections:', frame.detection_count)
print('CFAR mask shape:', frame.detections.shape)
The SoftwareFPGA class provides register-equivalent methods that mirror the hardware control interface, enabling bit-accurate simulation of the FPGA behavior before hardware deployment.
Real-Time Parameter Adjustment
The architecture supports dynamic reconfiguration of detection parameters through the host interface exposed in software_fpga.py. This capability is essential for adapting to changing clutter environments or target Radar Cross Section (RCS) characteristics.
# Example: Adjusting CFAR parameters on-the-fly
fpga.set_cfar_guard(3) # increase guard cells
fpga.set_cfar_train(12) # increase training cells
fpga.set_cfar_alpha(0x40) # α = 4.0 (Q4.4 format)
# Re-run processing with new parameters
frame2 = fpga.process_chirps(iq_i, iq_q)
print('New detection count:', frame2.detection_count)
The complete processing pipeline—from raw IQ quantization through the final CFAR detection mask—is encapsulated in software_fpga.py (lines 49–57). The resulting RadarFrame object contains the range-Doppler I/Q matrix, magnitude map, detection mask, range profile, and detection count, making it directly consumable by GUI_V7_PyQt.py for visualization and further analytics.
Summary
- The AERIS-10 FPGA implements a deterministic seven-stage signal processing chain: Quantization → Range FFT → Decimation → MTI Canceller → Doppler FFT → DC Notch → CFAR Detector.
- Pulse compression occurs in the 1024-point Range FFT stage, followed by decimation to 64 range bins and Hamming-windowed 16-point Doppler FFT processing.
- The CFAR detector supports CA, GO, and SO variants with configurable training cells, guard cells, and Q4.4 alpha scaling, implementing bit-accurate L1 magnitude detection as defined in
golden_reference.py. - The Python software replica in
software_fpga.pyprovides a cycle-accurate mirror of the VHDL implementation, enabling offline algorithm verification and automated testing via the same register interface used by the hardware GUI.
Frequently Asked Questions
How does the FPGA handle the transition from pulse compression to target detection?
The pipeline transitions seamlessly from the Range FFT (pulse compression) through the MTI canceller and Doppler FFT stages to generate a range-Doppler map. The CFAR detector then processes this map column-wise, applying adaptive thresholding based on local noise estimates derived from configurable training and guard cells. Each stage is controlled via registers defined in radar_protocol.py, allowing the host to enable or disable specific processing elements without interrupting the data flow.
What is the significance of the Q4.4 format in the CFAR alpha parameter?
The Q4.4 format represents a fixed-point number with 4 integer bits and 4 fractional bits, providing a dynamic range of 0.0 to 15.9375 with 1/16 precision. In the CFAR implementation, the alpha scaling factor multiplies the summed training cell magnitudes (the noise estimate) before right-shifting by 4 bits to achieve the desired threshold scaling factor. This approach eliminates floating-point hardware requirements while maintaining sufficient granularity for typical radar detection applications.
Can the processing chain operate without the MTI canceller enabled?
Yes, the MTI canceller is toggleable via FPGA registers. When disabled, the pipeline bypasses the clutter suppression stage and passes raw range-profile data directly to the Doppler FFT. This mode is useful for ground-based surveillance or when analyzing stationary target indication is required, though it increases the false alarm rate in environments with significant stationary clutter returns.
Where is the bit-accurate golden reference for the VHDL modules located?
The reference implementations for all FPGA processing stages, including the cell-averaging CFAR detector with exact L1 magnitude computation and training cell logic, reside in golden_reference.py within the cosimulation testbench directory (9_Firmware/9_2_FPGA/tb/cosim/real_data/). This file serves as the verification standard against which the synthesizable VHDL (cfar_ca.v) and the Python software model (software_fpga.py) are validated.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →