From 1342ce7b9dc4710dfa3f59c450ebdacf0d7ea183 Mon Sep 17 00:00:00 2001 From: Jason <83615043+JJassonn69@users.noreply.github.com> Date: Mon, 18 May 2026 15:11:31 +0545 Subject: [PATCH] =?UTF-8?q?docs(fpga-xdc):=20PR-AD.b=20=E2=80=94=20close?= =?UTF-8?q?=20H-1/H-2/H-4=20(FT601=20XDC=20documentation=20rot)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit H-1: ft601_rd_n/ft601_oe_n IOB-packing block claimed "constant-1, USB read not implemented" but the driver has had a full RD_OE_ASSERT/READING/DEASSERT read FSM since the host-command path was added. Rewrote the comment to describe the real FSM-driven traffic and explain that -quiet is now for post-synthesis retiming/consolidation cases, not because the registers don't exist. H-2: production XDC (create_generated_clock ft601_clk_fwd + set_output_delay) and FMC dev XDC (set_max_delay -datapath_only) implement two different but deliberate timing strategies for the same FT601 output ports — production forwards ft601_clk_out via ODDR, FMC UMFT601X-B has no return path. Added cross-reference VARIANT STRATEGY blocks in both XDCs explaining the choice and the no-mixing rule. H-4: set_false_path -from ft601_txe -to clk_100m registers was undocumented. Traced both capture paths: ft601_clk_in (write FSM in usb_data_interface.v) and clk_100m (cdc_single_bit in radar_system_top.v driving status_reg[1]). Added comment explaining the async port → clk_100m sync-FF path is what this constraint covers. Comment-only XDC change; regression 46/0/0 unchanged. --- .../constraints/te0713_te0701_umft601x.xdc | 9 ++++++ .../9_2_FPGA/constraints/xc7a200t_fbg484.xdc | 28 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/9_Firmware/9_2_FPGA/constraints/te0713_te0701_umft601x.xdc b/9_Firmware/9_2_FPGA/constraints/te0713_te0701_umft601x.xdc index 8c01d13..bbff874 100644 --- a/9_Firmware/9_2_FPGA/constraints/te0713_te0701_umft601x.xdc +++ b/9_Firmware/9_2_FPGA/constraints/te0713_te0701_umft601x.xdc @@ -233,6 +233,15 @@ set_input_delay -clock [get_clocks ft601_clk_in] -min 1.000 [get_ports {ft601_rx # -------------------------------------------------------------------------- # FT601 output timing — source-synchronous, datapath-only constraints # -------------------------------------------------------------------------- +# VARIANT STRATEGY: this is the FMC-board approach. The production board XDC +# (constraints/xc7a200t_fbg484.xdc, "FT601 output delay relative to ODDR- +# forwarded clock" section) uses a DIFFERENT strategy +# (create_generated_clock ft601_clk_fwd + set_output_delay) because the +# production board DOES forward ft601_clk_out via ODDR back to the FT601. +# Only ONE of these XDCs should be included per build. Do NOT mix or both +# will fight each other (conflicting or over-constrained timing on the same +# ports). +# # The FT601 provides its own 100 MHz clock (D_CLK) and samples data on # the next rising edge of that same clock. The FPGA receives D_CLK through # IBUF→BUFG (~5 ns insertion), but this insertion delay is COMMON to both diff --git a/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc b/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc index 272ff31..cf6fc75 100644 --- a/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc +++ b/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc @@ -568,7 +568,16 @@ set_false_path -hold -from [get_clocks clk_120m_dac] -to [get_clocks dac_clk_fwd # -------------------------------------------------------------------------- # FT601 output delay relative to ODDR-forwarded clock # -------------------------------------------------------------------------- -# ft601_clk_out is now forwarded via ODDR from ft601_clk_in BUFG output. +# VARIANT STRATEGY: this is the PRODUCTION-board approach. The TE0713/TE0701 +# FMC dev variant uses a DIFFERENT strategy (set_max_delay -datapath_only, +# no forwarded clock) because the UMFT601X-B FMC adapter has no return +# path for ft601_clk_out — see constraints/te0713_te0701_umft601x.xdc +# "FT601 output timing" section for the FMC rationale. Only ONE of these +# XDCs should be included per build (set in the Vivado project per board +# variant). Do NOT mix or both will fight each other (conflicting or +# over-constrained timing on the same ports). +# +# ft601_clk_out is forwarded via ODDR from ft601_clk_in BUFG output. # Since both data FFs and clock ODDR are driven by the same BUFG, insertion # delays cancel. Output delay only needs to cover FT601 Tsu/Th + trace skew. # @@ -631,6 +640,13 @@ set_false_path -from [get_clocks clk_120m_dac] -to [get_clocks clk_100m] # clk_100m ↔ ft601_clk_in: USB data interface has CDC synchronizers set_false_path -from [get_clocks clk_100m] -to [get_clocks ft601_clk_in] set_false_path -from [get_clocks ft601_clk_in] -to [get_clocks clk_100m] +# ft601_txe is captured in BOTH the ft601_clk_in domain (write FSM in +# usb_data_interface.v gates on `!ft601_txe`) AND the clk_100m domain +# (cdc_single_bit synchronizer in radar_system_top.v drives status_reg[1] +# for host telemetry). The set_input_delay on ft601_txe (earlier in this +# file, in the FT601 input timing block) covers the ft601_clk_in capture; +# this false_path covers the async port → clk_100m sync-FF path, which is +# an explicit CDC and not source-synchronous to ft601_clk_in. set_false_path -from [get_ports {ft601_txe}] -to [all_registers -clock [get_clocks clk_100m]] # clk_120m_dac ↔ ft601_clk_in: no direct data path expected @@ -711,9 +727,13 @@ set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *oddr_ft601_clk* set_property -quiet IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_data_out_reg*}] set_property -quiet IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_be_reg*}] set_property IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_wr_n_reg*}] -# ft601_rd_n and ft601_oe_n are constant-1 (USB read not implemented) — -# Vivado removes the registers via constant propagation. Use -quiet to -# suppress CRITICAL WARNING [Common 17-55] when the cells don't exist. +# ft601_rd_n and ft601_oe_n are driven by the host-command read FSM +# (RD_OE_ASSERT / RD_READING / RD_DEASSERT in usb_data_interface.v). They +# carry real toggling traffic and are constrained by the set_output_delay +# block above. -quiet stays because Vivado may consolidate the register +# names during synthesis (retiming into the FSM state register), in which +# case the filter returns no objects and the WARNING is benign — timing +# is still met via the set_output_delay constraints. set_property -quiet IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_rd_n_reg*}] set_property -quiet IOB TRUE [get_cells -hierarchical -filter {NAME =~ *usb_inst/ft601_oe_n_reg*}]