mirror of
https://github.com/NawfalMotii79/PLFM_RADAR.git
synced 2026-06-10 23:41:18 +00:00
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:
@@ -643,9 +643,16 @@ wire [17:0] fir_d_in_i, fir_d_in_q;
|
||||
wire cdc_fir_i_overrun;
|
||||
wire cdc_fir_q_overrun;
|
||||
|
||||
cdc_adc_to_processing #(
|
||||
// AUDIT-C11: replaced cdc_adc_to_processing (Gray-CDC anti-pattern: independent
|
||||
// data and toggle synchronizer chains can skew under metastability and let the
|
||||
// destination capture a half-resolved Gray word) with cdc_async_fifo (Cummings
|
||||
// SNUG-2002 design — data sits in dual-clock distRAM; only ±1-incrementing
|
||||
// Gray-coded read/write pointers cross domains). Port shape is preserved so
|
||||
// the swap is local to these two instantiations. Sticky-overrun aggregation
|
||||
// at line ~680 is unchanged.
|
||||
cdc_async_fifo #(
|
||||
.WIDTH(18),
|
||||
.STAGES(3)
|
||||
.DEPTH(16)
|
||||
)CDC_FIR_i(
|
||||
.src_clk(clk_400m),
|
||||
.dst_clk(clk_100m),
|
||||
@@ -658,9 +665,9 @@ cdc_adc_to_processing #(
|
||||
.overrun(cdc_fir_i_overrun)
|
||||
);
|
||||
|
||||
cdc_adc_to_processing #(
|
||||
cdc_async_fifo #(
|
||||
.WIDTH(18),
|
||||
.STAGES(3)
|
||||
.DEPTH(16)
|
||||
)CDC_FIR_q(
|
||||
.src_clk(clk_400m),
|
||||
.dst_clk(clk_100m),
|
||||
|
||||
Reference in New Issue
Block a user