AUDIT-C11: replace Gray-CDC at CIC→FIR with home-grown async FIFO

cdc_adc_to_processing carries multi-bit data across 400→100 MHz via
TWO independent synchronizer chains (data Gray-encoded + a separate
2-bit toggle). Under metastability, the chains can resolve on
different cycles, letting the destination latch a half-resolved Gray
word that decodes to an arbitrary value. Audit C-11. Practical MTBF
is years per event but the design is non-conformant for arbitrary
multi-bit data — Gray code's single-bit-flip protection only holds
for ±1 transitions, not for CIC samples that can change by hundreds
of LSBs.

Replace with cdc_async_fifo, a Cummings SNUG-2002 style #2 async
FIFO. Data does NOT cross domains; it sits in dual-clock distRAM
(write port src_clk, read port dst_clk). Only the read/write
Gray-coded POINTERS cross — and pointers genuinely change ±1 per
increment, so Gray code's protection is correct by construction.
Home-grown rather than XPM_FIFO_ASYNC: vendor-neutral (iverilog can
simulate it directly, no SIM stub), keeps the project's existing
home-grown CDC convention (3 sibling primitives in cdc_modules.v),
and avoids XPM library version skew.

Port shape is preserved (same WIDTH=18, same dst_data/dst_valid/
overrun semantics — 1-cycle pulse per read in steady state) so the
swap is local to two instantiations in ddc_400m.v. Sticky-overrun
aggregation downstream is unchanged.

XDC: project already has blanket set_false_path on
clk_100m ↔ adc_dco_p, which covers both new pointer crossings.
Synchronizer FFs carry ASYNC_REG="TRUE" for placement-aware MTBF.
No XDC change needed.

New TB tb_cdc_async_fifo.v exercises 7 groups (28 checks): reset,
single-sample passthrough, multi-Gray-bit-flip (0x00000 ↔ 0x3FFFF —
audit's recommended coverage point, asserts NO intermediate values
appear at dst_data), matched-rate continuous stream, sustained-burst
overrun, drain-to-empty, and mid-stream reset.

Resource: 8 LUTRAMs per instance × 2 instances = 16 LUTRAMs (~0.05%
of XC7A50T budget).

Verified: full FPGA regression 42/42 PASS (was 41/41; +1 new test,
0 regressions in DDC Chain / Doppler Co-Sim / Full-Chain Real-Data
/ Receiver Integration / System Top / System E2E / MF Co-Sim — all
of which exercise the swap path through the production signal
chain). 0 lint errors.
This commit is contained in:
Jason
2026-04-30 10:47:31 +05:45
parent bf63d64533
commit 58d2e1ba10
4 changed files with 537 additions and 6 deletions
+7 -2
View File
@@ -59,6 +59,7 @@ PROD_RTL=(
nco_400m_enhanced.v
cic_decimator_4x_enhanced.v
cdc_modules.v
cdc_async_fifo.v
fir_lowpass.v
ddc_input_interface.v
chirp_memory_loader_param.v
@@ -99,7 +100,7 @@ RECEIVER_RTL=(
radar_mode_controller.v
tb/ad9484_interface_400m_stub.v
ddc_400m.v nco_400m_enhanced.v cic_decimator_4x_enhanced.v
cdc_modules.v fir_lowpass.v ddc_input_interface.v
cdc_modules.v cdc_async_fifo.v fir_lowpass.v ddc_input_interface.v
chirp_memory_loader_param.v
matched_filter_multi_segment.v matched_filter_processing_chain.v
range_bin_decimator.v doppler_processor.v xfft_16.v fft_engine.v
@@ -585,7 +586,7 @@ echo "--- PHASE 2: Integration Tests ---"
run_test "DDC Chain (NCO→CIC→FIR)" \
tb/tb_ddc_reg.vvp \
tb/tb_ddc_cosim.v ddc_400m.v nco_400m_enhanced.v \
cic_decimator_4x_enhanced.v fir_lowpass.v cdc_modules.v
cic_decimator_4x_enhanced.v fir_lowpass.v cdc_modules.v cdc_async_fifo.v
# Real-data co-simulation: committed golden hex vs RTL (exact match required).
# These catch architecture mismatches (e.g. 32-pt → dual 16-pt Doppler FFT)
@@ -705,6 +706,10 @@ run_test "CDC Modules (3 variants)" \
tb/tb_cdc_reg.vvp \
tb/tb_cdc_modules.v cdc_modules.v
run_test "CDC Async FIFO (AUDIT-C11)" \
tb/tb_cdc_async_fifo_reg.vvp \
tb/tb_cdc_async_fifo.v cdc_async_fifo.v
run_test "Edge Detector" \
tb/tb_edge_reg.vvp \
tb/tb_edge_detector.v edge_detector.v