fix(fpga): move IBUF+BUFIO+BUFR into 50T wrapper (same scope as pad)
The previous attempt put BUFIO inside u_core/gen_ft_bufr, but the pad (ft_clkout) and its inferred IBUF live at the top wrapper level. Vivado shape-packs IBUF↔BUFIO into the same IOB tile, and it couldn't do that across the wrapper→u_core hierarchy boundary — producing CRITICAL WARNING [12-1411] "Illegal to place BUFIO on TIEOFF site" and WNS=-5.737 (worse than the CLOCK_DEDICATED_ROUTE=FALSE baseline). Fix: instantiate IBUF+BUFIO+BUFR explicitly in radar_system_top_50t.v and pass the BUFR output into u_core.ft601_clk_in. radar_system_top.v now does a pass-through wire assign for USB_MODE=1 (no BUFG) so the clock net doesn't get double-buffered.
This commit is contained in:
@@ -329,22 +329,14 @@ BUFG bufg_120m (
|
|||||||
|
|
||||||
// USB clock buffering:
|
// USB clock buffering:
|
||||||
// USB_MODE=0 (200T/FT601): pin is MRCC (D17) → BUFG, global clock network.
|
// USB_MODE=0 (200T/FT601): pin is MRCC (D17) → BUFG, global clock network.
|
||||||
// USB_MODE=1 (50T/FT2232H): pin is SRCC (C4, non-MRCC) → BUFIO + BUFR for
|
// USB_MODE=1 (50T/FT2232H): pin is SRCC (C4, non-MRCC). The wrapper
|
||||||
// regional dedicated routing. SRCC can drive BUFIO/BUFR but not BUFG
|
// radar_system_top_50t.v instantiates IBUF+BUFIO+BUFR on the pin
|
||||||
// directly (the "poor placement IO→BUFG" CLOCK_DEDICATED_ROUTE=FALSE
|
// and passes the already-buffered clock into ft601_clk_in. We only
|
||||||
// override was burning ~5 ns in fabric routing on the ft_clkout path).
|
// pass it through here — inserting a BUFG would create a second
|
||||||
// All ft_clkout-domain logic (FT2232H FSM, FIFO flops, toggle CDCs) is
|
// buffer on an already-clock-network net and break the BUFIO/BUFR
|
||||||
// contained in bank 35 / one clock region, so regional distribution
|
// shape packing. See UG472 §3 BUFIO/BUFR.
|
||||||
// is sufficient. See UG472 §3 BUFIO/BUFR.
|
generate if (USB_MODE == 1) begin : gen_ft_passthru
|
||||||
generate if (USB_MODE == 1) begin : gen_ft_bufr
|
assign ft601_clk_buf = ft601_clk_in;
|
||||||
wire ft_clk_bufio;
|
|
||||||
BUFIO bufio_ft (.I(ft601_clk_in), .O(ft_clk_bufio));
|
|
||||||
BUFR #(.BUFR_DIVIDE("BYPASS"), .SIM_DEVICE("7SERIES")) bufr_ft (
|
|
||||||
.I(ft_clk_bufio),
|
|
||||||
.O(ft601_clk_buf),
|
|
||||||
.CE(1'b1),
|
|
||||||
.CLR(1'b0)
|
|
||||||
);
|
|
||||||
end else begin : gen_ft_bufg
|
end else begin : gen_ft_bufg
|
||||||
BUFG bufg_ft601 (.I(ft601_clk_in), .O(ft601_clk_buf));
|
BUFG bufg_ft601 (.I(ft601_clk_in), .O(ft601_clk_buf));
|
||||||
end endgenerate
|
end endgenerate
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ module radar_system_top_50t (
|
|||||||
input wire stm32_mixers_enable,
|
input wire stm32_mixers_enable,
|
||||||
|
|
||||||
// ===== FT2232H USB 2.0 Interface (Bank 35: 3.3V) =====
|
// ===== FT2232H USB 2.0 Interface (Bank 35: 3.3V) =====
|
||||||
input wire ft_clkout, // 60 MHz from FT2232H CLKOUT (MRCC pin C4)
|
input wire ft_clkout, // 60 MHz from FT2232H CLKOUT (SRCC pin C4 — not MRCC)
|
||||||
inout wire [7:0] ft_data, // 8-bit bidirectional data bus
|
inout wire [7:0] ft_data, // 8-bit bidirectional data bus
|
||||||
input wire ft_rxf_n, // RX FIFO not empty (active low)
|
input wire ft_rxf_n, // RX FIFO not empty (active low)
|
||||||
input wire ft_txe_n, // TX FIFO not full (active low)
|
input wire ft_txe_n, // TX FIFO not full (active low)
|
||||||
@@ -86,6 +86,25 @@ module radar_system_top_50t (
|
|||||||
output wire gpio_dig7 // DIG_7 (H12→PD15): reserved
|
output wire gpio_dig7 // DIG_7 (H12→PD15): reserved
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ===== FT2232H clock buffering — IBUF → BUFIO → BUFR =====
|
||||||
|
// C4 is SRCC (IS_CLK_CAPABLE=1, IS_MASTER=0). SRCC cannot drive BUFG
|
||||||
|
// with dedicated routing, but can drive BUFIO → BUFR regionally. All
|
||||||
|
// ft_clkout-domain logic fits in Bank 35's clock region. All three
|
||||||
|
// primitives must live in the same hierarchical scope so Vivado can
|
||||||
|
// shape-pack IBUF↔BUFIO correctly — that's why this lives here in the
|
||||||
|
// wrapper and not inside u_core.
|
||||||
|
wire ft_clkout_ibuf;
|
||||||
|
wire ft_clkout_bufio;
|
||||||
|
wire ft_clkout_bufr;
|
||||||
|
IBUF ibuf_ft (.I(ft_clkout), .O(ft_clkout_ibuf));
|
||||||
|
BUFIO bufio_ft (.I(ft_clkout_ibuf), .O(ft_clkout_bufio));
|
||||||
|
BUFR #(.BUFR_DIVIDE("BYPASS"), .SIM_DEVICE("7SERIES")) bufr_ft (
|
||||||
|
.I(ft_clkout_bufio),
|
||||||
|
.O(ft_clkout_bufr),
|
||||||
|
.CE(1'b1),
|
||||||
|
.CLR(1'b0)
|
||||||
|
);
|
||||||
|
|
||||||
// ===== Tie-off wires for unconstrained FT601 inputs (inactive with USB_MODE=1) =====
|
// ===== Tie-off wires for unconstrained FT601 inputs (inactive with USB_MODE=1) =====
|
||||||
wire ft601_txe_tied = 1'b0;
|
wire ft601_txe_tied = 1'b0;
|
||||||
wire ft601_rxf_tied = 1'b0;
|
wire ft601_rxf_tied = 1'b0;
|
||||||
@@ -123,7 +142,7 @@ module radar_system_top_50t (
|
|||||||
// ----- Clocks & Reset -----
|
// ----- Clocks & Reset -----
|
||||||
.clk_100m (clk_100m),
|
.clk_100m (clk_100m),
|
||||||
.clk_120m_dac (clk_120m_dac),
|
.clk_120m_dac (clk_120m_dac),
|
||||||
.ft601_clk_in (ft_clkout), // FT2232H 60 MHz CLKOUT → shared USB clock port
|
.ft601_clk_in (ft_clkout_bufr), // Pre-buffered via IBUF+BUFIO+BUFR above (SRCC fix)
|
||||||
.reset_n (reset_n),
|
.reset_n (reset_n),
|
||||||
|
|
||||||
// ----- DAC -----
|
// ----- DAC -----
|
||||||
|
|||||||
Reference in New Issue
Block a user