diff --git a/top/x400/constraints/timing/x410.xdc b/top/x400/constraints/timing/x410.xdc index 454e821..d1830e1 100644 --- a/top/x400/constraints/timing/x410.xdc +++ b/top/x400/constraints/timing/x410.xdc @@ -90,18 +90,17 @@ set_false_path -from [get_pins -hierarchical -filter {NAME =~ */rfdc/clock_gates # SYSREF is generated by the LMK04832 clocking chip (SPLL), which also produces # the PLL reference clock (PRC) used to generate data clocks with a MMCM. Both # SYSREF and PLL reference clock are directly fed into the RFSoC. -# SYSREF is captured by the FPGA fabric in the PRC clock domain (MMCM's PRC -# output) with a double synchronizer and then transfered to the RFDC clock -# domain. Both SYSREF versions (PRC and RFDC) are used by downstream logic for -# sync. purposes. -# SYSREF is a continuous signal running at PRC freq. / 25, and it is -# intentionally shifted in the LMK chip to align it closer to the -# PRC's falling edge. -# The added delay follows the formula: -# SYSREF LMK delay = 22 * sample clock period -# The highest sampling frequency supported in MPM (3.072 GHz) is used for -# timing constraints. Therefore, SYSREF LMK's delay = 22 * (1 / 3.072e9). -set sysref_lmk_delay 7.161 +# The LMK04832 is configured to output all clocks synchronized to the +# rising edge of SYSREF. SYSREF is first captured by the FPGA fabric in the +# PRC clock domain (MMCM's PRC output) on the falling edge to meet setup and +# hold times. Afterwards it is captured with a double synchronizer and then +# transferred to the RFDC clock domain. Both SYSREF versions (PRC and RFDC) +# are used by downstream logic for sync purposes. +# The highest PRC frequency supported in MPM (64 MHz) is used for +# timing constraints. +# Set SYSREF LMK Delay to 0 ns as we assume rising edge alignment from the +# LMK04832 chip. +set sysref_lmk_delay 0 # # These are the signals' lengths and corresponding delays (assuming 170 ps/in): # - SYSREF --> 5794 mils (5.794 inches) = 0.985 ns diff --git a/top/x400/constraints/timing/x440.xdc b/top/x400/constraints/timing/x440.xdc index 84ba13e..3893070 100644 --- a/top/x400/constraints/timing/x440.xdc +++ b/top/x400/constraints/timing/x440.xdc @@ -76,15 +76,17 @@ set_false_path -from [get_pins -hierarchical -filter {NAME =~ */rfdc/clock_gates # SYSREF is generated by the LMK04832 clocking chip (SPLL), which also produces # the PLL reference clock (PRC) used to generate data clocks with a MMCM. Both # SYSREF and PLL reference clock are directly fed into the RFSoC. -# SYSREF is captured by the FPGA fabric in the PRC clock domain (MMCM's PRC -# output) with a double synchronizer and then transfered to the RFDC clock -# domain. Both SYSREF versions (PRC and RFDC) are used by downstream logic for -# sync. purposes. -# SYSREF is a continuous signal intentionally shifted in the LMK chip to align -# it closer to the PRC's falling edge. +# The LMK04832 is configured to output all clocks synchronized to the +# rising edge of SYSREF. SYSREF is first captured by the FPGA fabric in the +# PRC clock domain (MMCM's PRC output) on the falling edge to meet setup and +# hold times. Afterwards it is captured with a double synchronizer and then +# transferred to the RFDC clock domain. Both SYSREF versions (PRC and RFDC) +# are used by downstream logic for sync purposes. # The highest PRC frequency supported in MPM (64 MHz) is used for -# timing constraints. Therefore, SYSREF LMK's delay = (1/64e6)/2. -set sysref_lmk_delay 7.8125 +# timing constraints. +# Set SYSREF LMK Delay to 0 ns as we assume rising edge alignment from the +# LMK04832 chip. +set sysref_lmk_delay 0 # # These are the signals' lengths and corresponding delays (assuming 170 ps/in): # - SYSREF --> 5794 mils (5.794 inches) = 0.985 ns diff --git a/top/x400/rf/common/capture_sysref.v b/top/x400/rf/common/capture_sysref.v index 1fea5ab..3fdedd5 100644 --- a/top/x400/rf/common/capture_sysref.v +++ b/top/x400/rf/common/capture_sysref.v @@ -32,15 +32,32 @@ module capture_sysref ( output wire sysref_out_rclk // RFDC output (Domain: rfdc_clk). ); - (* ASYNC_REG = "TRUE" *) reg sysref_pclk_ms = 1'b0; - reg sysref_pclk = 1'b0; - reg sysref_rclk = 1'b0; + (* ASYNC_REG = "TRUE" *) reg sysref_neg_pclk_ms = 1'b0; + (* ASYNC_REG = "TRUE" *) reg sysref_pos_pclk_ms = 1'b0; + reg sysref_pclk = 1'b0; + reg sysref_rclk = 1'b0; - // Capture SYSREF synchronously with the pll_ref_clk, but double-sync it just - // in case static timing isn't met so as not to destroy downstream logic. + // The following waveform illustrates the capture process of SYSREF. + // + // PRC ___/-----\_____/-----\_____/-----\_____/---- + // SYSREF ___/---------------------------------------- + // falling edge FF MS ---------|R|-------------------------------- + // rising edge FF MS ---------------|R|-------------------------- + // rising edge FF ---------------------------|R|-------------- + // + // Capture SYSREF synchronously with the pll_ref_clk, but at the falling edge. + // This is done to ensure that SYSREF is captured well after its initial + // rising edge to ensure a stable signal. + // But to be on the safe side when combining this FPGA code with older + // LMK04832 MPM configuration (before June 2024), the signal is considered + // metastable and requires additional double synchronization. + always @ (negedge pll_ref_clk) begin + sysref_neg_pclk_ms <= sysref_in; + end + always @ (posedge pll_ref_clk) begin - sysref_pclk_ms <= sysref_in; - sysref_pclk <= sysref_pclk_ms; + sysref_pos_pclk_ms <= sysref_neg_pclk_ms; + sysref_pclk <= sysref_pos_pclk_ms; end assign sysref_out_pclk = sysref_pclk;