Gap 7 MMCM jitter cleaner + CIC comb CREG pipeline + XDC clock-name fix

MMCM (Gap 7):
- Add adc_clk_mmcm.v: MMCME2_ADV wrapper (VCO=800MHz, CLKOUT0=400MHz)
- Modify ad9484_interface_400m.v: replace BUFG with MMCM path, gate reset on mmcm_locked
- Add adc_clk_mmcm.xdc: CDC false paths for clk_mmcm_out0 <-> clk_100m

XDC Fix (Build 19 WNS=-0.011 root cause):
- Remove conflicting create_generated_clock -name clk_400m_mmcm
- Replace all clk_400m_mmcm references with Vivado auto-generated clk_mmcm_out0
- CDC false paths now correctly apply to actual timing paths

CIC CREG Pipeline (Build 18 critical path fix):
- Explicit DSP48E1 for comb[0] with CREG=1/AREG=1/BREG=1/PREG=1
- Absorbs integrator_sampled_comb fabric FDRE into DSP48 C-port register
- Eliminates 0.643ns fabric->DSP routing delay (Build 18 tightest path)
- +1 cycle comb latency via data_valid_comb_0_out pipeline
- Move shared register declarations above ifndef SIMULATION (iverilog fix)
- Update golden data for +1 cycle CIC pipeline shift

Build scripts: build19_mmcm.tcl, build20_mmcm_creg.tcl
Regression: 18/18 FPGA pass, 20/20 MCU pass
Build 20 launched on remote Vivado (pending results)
This commit is contained in:
Jason
2026-03-19 22:59:46 +02:00
parent f3bbf77ca1
commit c6103b37de
10 changed files with 9038 additions and 7438 deletions
+17 -6
View File
@@ -62,9 +62,16 @@ BUFIO bufio_dco (
.O(adc_dco_bufio)
);
BUFG bufg_dco (
.I(adc_dco),
.O(adc_dco_buffered)
// MMCME2 jitter-cleaning wrapper replaces the direct BUFG.
// The PLL feedback loop attenuates input jitter from ~50 ps to ~20-30 ps,
// reducing clock uncertainty and improving WNS on the 400 MHz CIC path.
wire mmcm_locked;
adc_clk_mmcm mmcm_inst (
.clk_in (adc_dco), // 400 MHz from IBUFDS output
.reset_n (reset_n),
.clk_400m_out (adc_dco_buffered), // Jitter-cleaned 400 MHz on BUFG
.mmcm_locked (mmcm_locked)
);
assign adc_dco_bufg = adc_dco_buffered;
@@ -117,12 +124,16 @@ reg dco_phase;
// is asynchronous and safe the FFs enter reset instantly. De-assertion
// (going high) must be synchronised to adc_dco_buffered to avoid
// metastability. This is the classic "async assert, sync de-assert" pattern.
//
// mmcm_locked gates de-assertion: the 400 MHz domain stays in reset until
// the MMCM PLL has locked and the jitter-cleaned clock is stable.
(* ASYNC_REG = "TRUE" *) reg [1:0] reset_sync_400m;
wire reset_n_400m;
wire reset_n_gated = reset_n & mmcm_locked;
always @(posedge adc_dco_buffered or negedge reset_n) begin
if (!reset_n)
reset_sync_400m <= 2'b00; // async assert
always @(posedge adc_dco_buffered or negedge reset_n_gated) begin
if (!reset_n_gated)
reset_sync_400m <= 2'b00; // async assert (or MMCM not locked)
else
reset_sync_400m <= {reset_sync_400m[0], 1'b1}; // sync de-assert
end