Achieve full timing closure on xc7a100tcsg324-1 at 400 MHz (0 violations)

Complete FPGA timing closure across all clock domains after 9 iterative
Vivado builds. WNS improved from -48.325ns to +0.018ns (107,886 endpoints).

RTL fixes for 400 MHz timing:
- NCO: 6-stage pipeline with DSP48E1 phase accumulator, registered LUT
  index (Fix D splits address decode from ROM read), distributed RAM
- CIC: explicit DSP48E1 PCOUT->PCIN cascade for 5 integrator stages,
  CREG=1 on integrator_0 to eliminate fabric->DSP setup violation
- DDC: 400 MHz reset synchronizer (async-assert/sync-deassert),
  active-high reset register for DSP48E1 RST ports, posedge output stage
- FIR: 5-stage binary adder tree pipeline (7-cycle latency)
- FFT: 5-cycle butterfly pipeline with registered twiddle index,
  XPM_MEMORY_TDPRAM for data storage
- XDC: CDC false paths, async reset false paths, CIC comb multicycle paths

Final Build 9 timing (all MET):
  adc_dco_p (400 MHz): WNS = +0.278ns
  clk_100m  (100 MHz): WNS = +0.018ns
  clk_120m_dac (120 MHz): WNS = +0.992ns
  ft601_clk_in (100 MHz): WNS = +5.229ns
  Cross-domain (adc_dco_p->clk_100m): WNS = +7.105ns
This commit is contained in:
Jason
2026-03-16 15:02:35 +02:00
parent 692b6a3bfa
commit 00fbab6c9d
7 changed files with 1150 additions and 410 deletions
+6 -6
View File
@@ -259,16 +259,16 @@ module tb_nco_400m;
#1;
sin_before_gate = sin_out;
// Deassert phase_valid with 4-stage pipeline, dds_ready has 5-cycle latency
// Deassert phase_valid with 6-stage pipeline, dds_ready has 7-cycle latency
phase_valid = 0;
repeat (6) @(posedge clk_400m); #1;
repeat (8) @(posedge clk_400m); #1;
check(dds_ready === 1'b0, "dds_ready deasserts when phase_valid=0");
repeat (10) @(posedge clk_400m);
// Re-enable wait for pipeline to refill (5 cycles)
// Re-enable wait for pipeline to refill (7 cycles)
phase_valid = 1;
repeat (6) @(posedge clk_400m); #1;
repeat (8) @(posedge clk_400m); #1;
check(dds_ready === 1'b1, "dds_ready re-asserts when phase_valid=1");
//
@@ -285,8 +285,8 @@ module tb_nco_400m;
frequency_tuning_word = FTW_10MHZ;
phase_valid = 1;
// Skip pipeline warmup (4-stage pipeline + 1 for dds_ready)
repeat (5) @(posedge clk_400m);
// Skip pipeline warmup (6-stage pipeline + 1 for dds_ready)
repeat (7) @(posedge clk_400m);
mag_sq_min = 32'hFFFFFFFF;
mag_sq_max = 32'h00000000;