Cross-Layer FPGA/STM32 Communication for Radar Control: AERIS-10 Architecture Explained

The AERIS-10 radar platform implements cross-layer FPGA/STM32 communication for radar control over a USB CDC virtual COM port, combining real-time FPGA signal processing with STM32 F746xx power sequencing, register configuration, and hybrid AGC feedback loops.

The AERIS-10 radar system in the open-source NawfalMotii79/PLFM_RADAR repository demonstrates how to tightly couple an STM32 microcontroller with an FPGA for complete radar chain management. This cross-layer FPGA/STM32 communication architecture handles everything from chirp parameter updates to closed-loop gain control. The STM32 orchestrates peripheral initialization while the XC7A50T FPGA executes high-speed DSP, with both domains synchronized through a well-defined binary packet contract.

System Architecture Overview

The AERIS-10 hardware stack is organized into three functional boards that must be initialized in sequence before the radar chain can operate.

Power Sequencing and Clock Distribution

The Power-Management Board sequences power-up and configures all downstream modules through the STM32 MCU, as documented in the repository README. The Frequency-Synthesizer Board then provides phase-aligned clocks via the AD9523-1 clock generator to the FPGA, DAC, ADC, and RF front-ends.

Main Processing Board

The main board hosts the DAC, mixers, phase shifters, and the XC7A50T FPGA that executes the real-time radar DSP chain. It also bridges the STM32 peripheral buses—I²C, SPI, and USB CDC—for runtime configuration and telemetry streaming.

FPGA Real-Time Signal Processing Pipeline

Inside the FPGA, the DSP chain transforms raw RF samples into processed range-Doppler frames.

  1. ADC Capture – The AD9484 ADC samples the analog input at 400 MHz.
  2. Digital Down-Conversion – An NCO mixed with CIC and FIR filters converts the RF signal to baseband and decimates the stream.
  3. Matched Filter and FFT – Pulse compression and range-Doppler processing are applied to the baseband data.
  4. Host Streaming – Processed frames are forwarded over the FT601 USB bridge to the host PC.

STM32 Control and Telemetry Responsibilities

The STM32 F746xx does not merely boot the system; it actively manages the radar state through several runtime tasks.

  • Power sequencing and peripheral initialization – Brings up the FPGA, synthesizer, and RF stages in the correct order.
  • FPGA register configuration – Sends chirp parameters and phase-shifter settings inside a custom binary settings packet over USB CDC.
  • Hybrid AGC loop – Receives instantaneous I-Q power reports from the FPGA and adjusts DAC Vg and PA bias via I²C DACs/ADCs to maintain front-end gain.
  • GPS/IMU integration – Ingests GPS frames over the same USB CDC link and forwards them to the GUI for map-based target visualization.

USB CDC Communication Mechanism

All cross-layer traffic between the host GUI, STM32, and FPGA travels through a USB CDC virtual COM port.

Python GUI and STM32USBInterface

The Python GUI enumerates the device using the STM32USBInterface class located in 9_Firmware/9_3_GUI/v7/hardware.py. This class scans for STM32 devices by vendor and product IDs, then exposes open(), read(), and write() primitives for bidirectional communication.

Cross-Layer Packet Contract

To prevent layout mismatches between the host and firmware, the project defines a strict binary contract in 9_Firmware/tests/cross_layer/contract_parser.py. The unit tests in 9_Firmware/tests/cross_layer/test_cross_layer_contract.py verify field offsets and sizes, confirming that the binary payload sent from the GUI matches the STM32 firmware expectations exactly.

Hybrid AGC Feedback Loop

The Hybrid Automatic Gain Control is a closed-loop system that spans both the FPGA fabric and the STM32 firmware.

  1. The FPGA measures instantaneous I-Q power and raises a data-pending flag when AGC adjustment is required.
  2. The STM32 reads the flag, computes the necessary gain correction, and writes new DAC values over I²C.
  3. The FPGA reads the updated DAC settings on the next chirp cycle, closing the control loop.

This cross-layer feedback is explicitly documented in the README as the "Hybrid Automatic Gain Control (AGC) — cross-layer FPGA/STM32/GUI loop."

Practical Code Examples

Starting the Radar from the Python GUI

from v7.hardware import STM32USBInterface
from v7.processing import RadarSettings

# Enumerate and open the first STM32 CDC device

stm = STM32USBInterface()
devices = stm.list_devices()
stm.open(devices[0])

# Build a radar-settings packet (frequency, chirp, gain, etc.)

settings = RadarSettings()
settings.chirp_rate = 1.2e6      # Hz/µs

settings.tx_power = 0x1F         # Example DAC value

# Send start flag and the settings packet

stm.send_start_flag()
stm.write(settings.to_bytes())

The STM32USBInterface class handles device enumeration and transmission in 9_Firmware/9_3_GUI/v7/hardware.py.

Capturing STM32 Diagnostic UART Output

python 9_Firmware/tools/uart_capture.py --port /dev/ttyUSB0 --baud 115200 \
    --output stm32_diag.log

The uart_capture.py utility auto-detects the STM32 serial port on macOS and writes raw diagnostic data to a log file.

Verifying the Settings Packet Layout

from tests.cross_layer.contract_parser import parse_settings_packet

def test_settings_packet():
    raw = b'\x01\x02\x03\x04' * 8  # mock binary payload

    pkt = parse_settings_packet(raw)
    assert pkt.chirp_rate == 0x0102
    assert pkt.tx_power == 0x0304

This unit test, found in 9_Firmware/tests/cross_layer/test_cross_layer_contract.py, guarantees that the binary layout matches the STM32 firmware definition.

Key Source Files

Component Path Description
Repository Overview README.md High-level project description and system flow
Architecture Diagram docs/architecture.html Block diagram and processing stages
STM32 USB Interface 9_Firmware/9_3_GUI/v7/hardware.py Enumerates and communicates with STM32 over USB CDC
UART Capture Utility 9_Firmware/tools/uart_capture.py Captures diagnostic UART output from the STM32
Cross-Layer Contract Parser 9_Firmware/tests/cross_layer/contract_parser.py Parses binary settings packets for both sides
Cross-Layer Unit Tests 9_Firmware/tests/cross_layer/test_cross_layer_contract.py Verifies packet layout and field offsets
FPGA Testbench 9_Firmware/9_2_FPGA/tb/gen_mf_golden_ref.py End-to-end testbench including STM32 toggle signals
Release Notes docs/release-notes.html Cross-layer firmware updates and bug fixes
GUI Entry Point 9_Firmware/9_3_GUI/v7/GUI_V7_PyQt.py Main application tying FPGA streaming, STM32 config, and visualization

Summary

  • The AERIS-10 platform in NawfalMotii79/PLFM_RADAR uses a USB CDC virtual COM port to link the host GUI, STM32 F746xx, and XC7A50T FPGA.
  • The STM32 manages power sequencing, register configuration, and a hybrid AGC loop that adjusts front-end gain based on FPGA-reported I-Q power.
  • A strict binary packet contract enforced by Python unit tests ensures that settings packets remain synchronized between the GUI and firmware.
  • Real-time processing inside the FPGA includes DDC, matched filtering, and FFT, with results streamed to the host via FT601 USB.

Frequently Asked Questions

How does the AERIS-10 FPGA communicate with the STM32?

The FPGA and STM32 communicate indirectly through shared hardware state and the STM32’s USB CDC interface. The FPGA streams processed data and AGC status flags to the host, while the STM32 writes configuration values—such as DAC Vg and phase-shifter settings—that the FPGA reads on subsequent chirp cycles. Physical I²C and SPI buses on the main board connect the STM32 to the DACs, ADCs, and clock synthesizer that feed the FPGA.

What is the role of the STM32 in the radar control loop?

The STM32 F746xx acts as the system orchestrator. It sequences power at startup, initializes the AD9523-1 clock synthesizer, and transmits chirp parameters to the FPGA. During operation, it closes the hybrid AGC loop by reading FPGA power reports and tuning front-end gain through I²C-connected DACs. It also forwards GPS and IMU data to the host GUI for georeferenced visualization.

Where is the cross-layer packet format defined and tested?

The binary layout for settings packets is declared in 9_Firmware/tests/cross_layer/contract_parser.py and validated by 9_Firmware/tests/cross_layer/test_cross_layer_contract.py. These tests lock field offsets and sizes, ensuring that any change to the GUI packet generator is matched by the STM32 firmware parser.

How is the hybrid AGC loop implemented across FPGA and STM32?

The FPGA measures instantaneous I-Q power and asserts a data-pending flag when gain correction is needed. The STM32 detects this condition via the USB CDC telemetry stream, computes the required adjustment, and writes new bias values to the DACs over I²C. The FPGA samples these updated values on the next chirp, completing the cross-layer feedback loop.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →