G1.5 (FSM trim): doppler section emits NUM_RANGE_BINS*NUM_DOPPLER_BINS
cells (49152 B) and detect emits packed valid bytes (6144 B), matching
the 9-byte header advertisement. Replaces flat counters with nested
range x doppler indices in usb_data_interface_ft2232h.v. Saves ~18.4 kB
per frame on the wire.
G2 (runtime MEDIUM ladder): adds opcodes 0x17/0x18 for medium chirp/
listen cycles with RP_DEF_MEDIUM_* defaults. Plumbed through
radar_system_top -> radar_receiver_final -> chirp_scheduler. SHORT/LONG
were already runtime-tunable; MEDIUM was hardcoded.
TBs: tb_usb_protocol_v2 adds TEST 4 (full-frame egress byte count =
56330) and TEST 5 (MEDIUM opcode round-trip) - 27/27 PASS.
tb_ft2232h_frame_drop updated for new section sizes - 10/10 PASS.
Full regression: 37/41 with 4 pre-existing failures (T-2..T-5,
tracked in PR-Tests-1 / PR-I). Stash test confirmed pre-PR-G HEAD has
identical failures - PR-G introduces zero new test regressions.
Bumps RP_CHIRPS_PER_FRAME 32 -> 48 (= 3 sub-frames × 16 chirps), widens
doppler_bin from 5 to 6 bits ({sub_frame[1:0], bin[3:0]}), and replaces the
1-bit detect_flag rail with a 2-bit detect_class (NONE / CANDIDATE /
CONFIRMED) sourced from a soft+confirm CFAR threshold pair.
doppler_processor:
Generalised the 2-subframe FSM to NUM_SUBFRAMES = CHIRPS_PER_FRAME /
CHIRPS_PER_SUBFRAME (=3 in production, =2 when TBs override). S_OUTPUT
walks current_sub_frame 0..NUM_SUBFRAMES-1 then advances range_bin;
the chirp_base * CHIRPS_PER_SUBFRAME formula replaces the if/else split.
write_chirp_index, read_doppler_index, sub_frame, current_sub_frame all
widened to 6/2 bits accordingly. doppler_bin packing {current_sub_frame[1:0],
fft_sample_counter[3:0]} naturally yields 6 bits.
cfar_ca:
Adds cfg_alpha_soft input + r_alpha_soft register (default
RP_DEF_CFAR_ALPHA_SOFT = 0x18 ≈ 1.5 in Q4.4 → Pfa_soft ≈ 1e-5). ST_CFAR_MUL
computes both noise_product (alpha) and noise_product_soft (alpha_soft) in
parallel DSPs; ST_CFAR_CMP emits detect_class = CONFIRMED when cur > thr,
CANDIDATE when cur > thr_soft (and not CONFIRMED), NONE otherwise.
detect_flag is preserved as (class != NONE) for backward compat.
Address packing now pads doppler axis to next power-of-2 (DOPPLER_PAD =
1 << ceil(log2(NUM_DOPPLER))) so {range, doppler} packs contiguously
for both NUM_DOPPLER=32 (legacy TB) and NUM_DOPPLER=48 (production).
Mag-BRAM grows from ~16 to ~30 RAMB18 on 50T (acceptable on the budget).
usb_data_interface_ft2232h:
doppler_bin_in widened to 6 bits. FRAME_CELLS pads to next power of two
(32K) so {range, doppler[5:0]} concatenation lands cleanly. Address regs
bumped: mag_wr/rd_addr 14→15, detect_byte_addr 11→12, detect_clear bit-
counter 14→15. Detect-bit BRAM grows 2K→4K bytes. Wire-protocol byte
counts auto-scale with FRAME_CELLS / DOPPLER_MAG_SECTION_BYTES; PR-G
bumps the bulk-frame protocol version so the host parser knows.
Other:
- radar_params.vh: RP_CHIRPS_PER_FRAME 32→48, RP_NUM_DOPPLER_BINS 32→48,
RP_DOPPLER_MEM_ADDR_W 14→15 (50T) / 17→18 (200T), RP_CFAR_MAG_ADDR_W
likewise. Other macros (RP_DOPPLER_BIN_WIDTH=6, RP_DETECT_CLASS_WIDTH=2,
RP_DEF_CFAR_ALPHA_SOFT=0x18, RP_NUM_SUBFRAMES=3) were already in place
from PR-A.
- radar_system_top: rx_doppler_bin / dbg_doppler_bin widened. Adds
host_cfar_alpha_soft register (default RP_DEF_CFAR_ALPHA_SOFT). USB
opcode mapping deferred to PR-G.
- radar_system_top_50t: dbg_doppler_bin_nc width.
- radar_receiver_final: doppler_bin port width.
Test summary:
- tb_chirp_controller_v2: 43/43 PASS
- tb_chirp_contract: 10/10 PASS
- tb_cfar_ca: 24/0 PASS
- tb_mti_canceller: 43/43 PASS
- tb_rxb_fullchain: peak 24033 ~80x (parity with PR-D/E)
- tb_doppler_realdata: 2056/2056 PASS (had been broken pre-PR-F due
to missing RANGE_BINS=64 override; this PR fixes
the parameter override along with the widening)
- tb_system_e2e: 33/49 PASS — identical to PR-E baseline; the
one new fail vs PR-D (G2.2) carries over.
- tb_radar_receiver_final: still finishing in background (~10 min).
Establishes the macro vocabulary for the SHORT/MEDIUM/LONG waveform ladder,
3-subframe Doppler layout, track-mode dwell, and 2-class CFAR detection.
PR-A is purely additive — no module references the new macros yet.
Subsequent PRs (B–H) progressively replace the old chirp logic; this one
puts the names in place so each follow-on PR is mechanical.
Added:
- Waveform identity: RP_WAVE_{SHORT,MEDIUM,LONG,RESERVED} (2-bit selector)
- Sub-frame layout: RP_NUM_SUBFRAMES=3, RP_DOPPLER_BIN_WIDTH=6,
RP_SUBFRAME_ID_WIDTH=2
- Track mode: RP_DOPPLER_FFT_SIZE_TRACK=64, RP_MODE_TRACK=2'b11,
RP_DEF_TRACK_CHIRP_COUNT=64, RP_DEF_TRACK_WATCHDOG_FRAMES=5
- Detection class: RP_DETECT_{NONE,CANDIDATE,CONFIRMED,RSVD}
- 3-ladder timing defaults (V2 suffix to coexist with legacy in this PR):
SHORT 100 cyc (1 µs), MEDIUM 500 cyc (5 µs), LONG 3000 cyc (30 µs)
- Soft-CFAR alpha default: RP_DEF_CFAR_ALPHA_SOFT=0x18 (1.5 Q4.4,
Pfa_soft ≈ 10⁻⁵; confirm Pfa ≈ 10⁻⁶ at α=3.0)
- host_subframe_enable default: RP_DEF_SUBFRAME_ENABLE=3'b111
Marked LEGACY (deleted in the noted PR):
- RP_CHIRPS_PER_FRAME=32, RP_NUM_DOPPLER_BINS=32 (PR-F)
- RP_DEF_SHORT_CHIRP_CYCLES=50 (PR-E switches to 100)
- RP_DEF_CHIRPS_PER_ELEV=32 (PR-F)
Verified: iverilog preprocess clean. Sweep across 9_2_FPGA confirms no
module references the new macros yet — the PR is fully isolated.
Revert tag pre-chirp-v2 placed at 4f898ae for the chirp-v2 series.