Lesson 15/2560%
MODULE 15 OF 25 18 MIN FPGA FUNDAMENTALS

Clock Distribution Network

Master the FPGA clock network — BUFG, BUFH, BUFR, BUFIO, MMCM, and PLL — and learn how to design robust multi-clock systems with proper CDC handling.

Why Clocks Need Dedicated Networks

A clock signal is the most demanding signal in any synchronous digital system. It must arrive at every flip-flop simultaneously — or as close to simultaneously as possible. The difference in clock arrival time between two flip-flops is called clock skew. Even a few hundred picoseconds of skew between the source and destination registers of a timing path can cause setup or hold violations.

If you were to route a clock through general routing fabric (SL1/SL2/SL6 segments), the clock would experience 3–5 ns of skew across a large FPGA — completely unacceptable at any frequency above a few hundred MHz. Even at 100 MHz (10 ns period), 3–5 ns of skew would consume half the entire timing budget just for clock distribution.

Xilinx FPGAs solve this with a dedicated H-tree clock distribution network — a symmetric, balanced tree of metal wires specifically designed to deliver the clock to all flip-flops with <100 ps of skew across the entire device. This network is separate from general routing fabric and cannot be used for data signals — it is exclusively for clocks. Knowing how to properly use this network is non-negotiable for correct FPGA design.

Clock Skew Impact Every clock in your design must enter through an IBUF (input buffer at the FPGA pin) and then pass through a BUFG or MMCM to reach the dedicated clock network. Routing a clock through LUT outputs or general fabric introduces unpredictable, large skew — setup violations at the destination flip-flops will follow immediately.

Clock Network Hierarchy (7-Series)

Xilinx 7-series FPGAs provide five types of clock buffers, each serving a different scope and purpose:

Buffer Type Scope Drive Capability Use Case
BUFG Global (full chip) All FFs, BRAM, DSP, IO Primary system clocks — highest fanout, symmetric H-tree delivery
BUFH Half chip (one clock region) All FFs in one half-chip region Regional high-fanout signals, saves power vs BUFG for localized clocks
BUFR One clock region FFs + ISERDES/OSERDES in region Regional clocks derived from MMCM for serial interface logic
BUFIO IO bank only ISERDES/OSERDES only Source-synchronous interface clocks — ultra-low skew to IO primitives
BUFMR Multi-region Multiple BUFRs across 2 regions Cascading BUFR across adjacent IO clock regions

BUFG — Global Clock Buffer

The BUFG is the most important clock resource for the majority of designs. Key facts:

  • 7-series devices have 32 BUFG resources per device — this limits how many independent global clocks a design can have
  • BUFG drives a dedicated H-tree with symmetric layout — achieves approximately 50–100 ps skew across the entire chip
  • Must be used for: primary system clocks, DDR memory clocks, MGT (transceiver) reference clocks, any clock driving the entire FPGA
  • A clock signal from an FPGA input pin must pass through IBUF first, then BUFG — the tools insert IBUF automatically for top-level clock ports
  • Cannot be driven directly by LUT outputs without a timing closure violation — the tools will warn about "Clock signal ... not reaching a dedicated clock buffer"
graph LR PIN["FPGA Clock Pin\n(e.g. CLK_P/N)"] IBUF["IBUF or IBUFDS\n(IO Input Buffer)"] BUFG["BUFG\n(Global Clock Buffer)\n32 available per 7-series"] HTREE["H-Tree Clock\nDistribution Network\n<100 ps skew chip-wide"] FF1["FF in CLB\n(left side)"] FF2["FF in CLB\n(right side)"] FF3["FF in BRAM"] FF4["FF in DSP"] PIN --> IBUF --> BUFG --> HTREE HTREE --> FF1 HTREE --> FF2 HTREE --> FF3 HTREE --> FF4

MMCM — Mixed-Mode Clock Manager

The MMCM is Xilinx's advanced clock synthesis and conditioning primitive. It is a phase-locked loop (PLL) with additional features beyond basic frequency multiplication/division:

Capability 7-Series Specification
Input frequency range 10 – 933 MHz
VCO frequency range 600 – 1200 MHz (must be in range)
Output frequency User-defined: F_OUT = F_IN × M / (D × O)
Clock outputs 7 independent outputs (CLKOUT0–CLKOUT6)
Phase adjustment 0–360° in steps of 1/8 VCO period
Duty cycle adjustment 1%–99% on CLKOUT0 only
Spread spectrum clocking Supported (for EMI reduction)
Jitter Device-dependent; typically 50–150 ps RMS

The frequency formula: F_OUT = F_IN × M / (D × O) where M is the feedback multiplier, D is the input divider, and O is the output divider for that specific output. For example, to generate 500 MHz from a 200 MHz input: F_VCO = 200 × 5 / 1 = 1000 MHz (in range), F_OUT = 1000 / 2 = 500 MHz — so M=5, D=1, O=2.

The VCO frequency must stay within 600–1200 MHz for 7-series. If your M/D combination produces a VCO frequency outside this range, the MMCM will not lock. Vivado's Clocking Wizard IP automatically validates this constraint and finds valid M/D/O combinations for your target frequencies.

graph LR CLKIN["CLKIN1\n(e.g. 200 MHz)"] MMCM["MMCM\nM=5, D=1\nVCO=1000 MHz"] CLK0["CLKOUT0\nO=2 → 500 MHz"] CLK1["CLKOUT1\nO=10 → 100 MHz"] CLK2["CLKOUT2\nO=20 → 50 MHz\n+90° phase shift"] BUFG0["BUFG"] BUFG1["BUFG"] BUFG2["BUFG"] DESIGN0["Design Logic\n(500 MHz domain)"] DESIGN1["Design Logic\n(100 MHz domain)"] DESIGN2["IO Interface\n(50 MHz, 90°)"] CLKIN --> MMCM MMCM --> CLK0 --> BUFG0 --> DESIGN0 MMCM --> CLK1 --> BUFG1 --> DESIGN1 MMCM --> CLK2 --> BUFG2 --> DESIGN2

PLL — Phase-Locked Loop

The PLL is a simpler version of the MMCM. Both generate synthesized clocks from a reference, but they differ in feature set:

Use MMCM When...

  • You need phase shifting (0–360°) on output clocks
  • You need fractional frequency division (non-integer M/O)
  • You need spread-spectrum clocking (EMI reduction)
  • You need more than 6 clock outputs
  • You need fine duty-cycle control on CLKOUT0

Use PLL When...

  • You need maximum frequency with minimum jitter
  • You don't need phase shifting or fractional dividers
  • 6 clock outputs are sufficient
  • Power consumption matters and MMCM is overkill
  • The application is a simple frequency multiplier

Clock Domain Crossing (CDC)

Any design with more than one clock domain must carefully handle signals that cross from one domain to another. When a signal generated in clock domain A is sampled by a flip-flop in clock domain B, the signal may not be stable when the B clock edge arrives — this is the metastability problem. A metastable flip-flop may produce an output that is neither a valid 0 nor a valid 1, and may oscillate for an unpredictable time before settling.

The standard solutions:

CDC Scenario Recommended Solution Notes
Single-bit control signal Two-FF synchronizer Gold standard — two FFs in the destination domain, back-to-back
Multi-bit data bus Asynchronous FIFO Use Xilinx FIFO IP with independent read/write clocks
Slow-changing configuration Gray-code encoding + 2FF sync Only adjacent bits change — ensures valid intermediate state
Pulse transfer Pulse synchronizer (toggle FF) Converts pulse to toggle, synchronizes toggle, re-pulses
graph LR subgraph DOMA["Clock Domain A (CLK_A)"] SRC_FF["Source FF\n(data_a)"] end subgraph SYNC["2-FF Synchronizer\n(in CLK_B domain)"] FF1["FF1\n(metastability catcher)"] FF2["FF2\n(stable output)"] FF1 -->|"CLK_B"| FF2 end subgraph DOMB["Clock Domain B (CLK_B)"] DST_FF["Destination Logic\n(data_b — safe to use)"] end SRC_FF -->|"async crossing"| FF1 FF2 --> DST_FF

Vivado includes a dedicated CDC analysis command: report_cdc. Run this after implementation to identify all clock domain crossings in your design. Each crossing is categorized by severity — missing synchronizers appear as "CRITICAL" and will cause functional failures in silicon.

XDC Clock Constraints

Correct XDC timing constraints are essential for the MMCM/PLL setup to be analyzed correctly by Vivado's static timing analysis engine. Without proper constraints, timing analysis either over-constrains or under-constrains your design.

# ─── XDC Clock Constraints Example ───────────────────────────────────────── # Primary input clock: 200 MHz from FPGA pin create_clock -period 5.000 -name clk_200 [get_ports clk_in_p] # MMCM generates 500 MHz (CLKOUT0) and 100 MHz (CLKOUT1) # Vivado usually auto-generates these with Clocking Wizard IP create_generated_clock \ -name clk_500 \ -source [get_pins mmcm_inst/CLKIN1] \ -multiply_by 5 \ -divide_by 2 \ [get_pins mmcm_inst/CLKOUT0] create_generated_clock \ -name clk_100 \ -source [get_pins mmcm_inst/CLKIN1] \ -multiply_by 1 \ -divide_by 2 \ [get_pins mmcm_inst/CLKOUT1] # Tell timing analyzer that clk_500 and clk_100 are asynchronous # (they come from the same MMCM so by default they're treated as related) # For truly independent async clocks: set_clock_groups -asynchronous \ -group [get_clocks clk_200] \ -group [get_clocks clk_ext_async] # False paths on CDC synchronizer inputs (prevents over-tightening) # (Applied by Vivado CDC flow automatically when FIFO IP is used)

Common Clock Mistakes

These are the most common clock-related errors seen in FPGA designs:

Mistake Consequence Correct Approach
Gated clock: clk_g = clk AND en Glitches on the gated clock edge → metastability, incorrect FF behavior Use clock enables: always @(posedge clk) if(en) q <= d;
Clock from LUT output Massive skew through general routing — setup/hold violations everywhere All clocks must come from BUFG, BUFH, or MMCM/PLL output → BUFG
Missing set_clock_groups for async domains Timing analysis reports false failures — impossible to close timing Use set_clock_groups -asynchronous between unrelated clock domains
Exceeding 32 BUFG limit Vivado error: cannot place all BUFG — design fails to route Reuse clocks, use BUFH for regional clocks, reduce clock domain count
Direct combinational paths across CDC Metastability — data corruption in silicon even if simulation passes Always use 2-FF synchronizer, async FIFO, or Xilinx CDC IP
Never Use a Gated Clock in FPGA In ASICs, gated clocks are a power-saving technique. In FPGAs, they are a serious bug. The expression assign clk_gated = clk AND enable; creates glitches whenever enable changes while clk is high — this produces spurious clock edges that corrupt flip-flop state. Instead, use a clock enable signal on the flip-flop itself: always @(posedge clk) if(enable) q <= d; — the flip-flop ignores data when enable is low but always clocks cleanly on the rising clock edge.
Use Clocking Wizard IP — Always Xilinx's Clocking Wizard IP (IP Catalog → FPGA Features and Design → Clocking → Clocking Wizard) automatically calculates valid M/D/O values for your target frequencies, verifies VCO range compliance, estimates output jitter, generates proper XDC constraints, and instantiates MMCM or PLL with all ports correctly connected. There is almost never a reason to manually instantiate MMCM or PLL directly.
Interview Question Q: What is the difference between BUFG and BUFH in Xilinx 7-series?

A: BUFG (Global Clock Buffer) drives the full-chip H-tree clock network, delivering the clock to all flip-flops, BRAM, DSP, and IO primitives across the entire device with <100 ps skew. It consumes more power because it drives the entire chip. BUFH (Half-chip Clock Buffer) drives only one half of the device — one clock region — making it more power-efficient for clocks that only need to reach logic in a specific area. BUFH is typically used for derived clocks from MMCM that feed only a local region of the design, while BUFG is used for the primary system clock that all logic shares.

Knowledge Check

1. How many BUFG (Global Clock Buffer) resources does a Xilinx 7-series FPGA provide?

  • A 8
  • B 16
  • C 32
  • D 64
Correct! Xilinx 7-series FPGAs provide 32 BUFG resources per device. This limits the total number of independent global clocks in a design. Designs that require more than 32 clock domains must use BUFH for regional clocks, share BUFG resources between related domains, or restructure the clock architecture.

2. What does MMCM stand for?

  • A Multi-Mode Clock Multiplexer
  • B Mixed-Mode Clock Manager
  • C Master Module Clock Multiplier
  • D Multi-Channel Clock Monitor
Correct! MMCM stands for Mixed-Mode Clock Manager. It is Xilinx's advanced clock synthesis primitive that combines PLL-based frequency synthesis with additional features including phase adjustment (0–360°), fractional dividers, spread spectrum clocking, and 7 independent output clocks. Use the Clocking Wizard IP to instantiate it automatically.

3. Which clock buffer type is specifically designed for IO source-synchronous interfaces, driving ISERDES and OSERDES primitives only?

  • A BUFG
  • B BUFH
  • C BUFR
  • C BUFIO
Correct! BUFIO (IO Clock Buffer) drives only ISERDES and OSERDES primitives within the same IO bank. It provides ultra-low skew delivery of the source-synchronous interface clock directly to the serializer/deserializer primitives. It cannot drive flip-flops in CLBs — for that, you use BUFR alongside BUFIO in source-synchronous interface designs.

4. Which Vivado Tcl command checks your design for clock domain crossing (CDC) issues and missing synchronizers?

  • A check_timing
  • B report_timing
  • C report_cdc
  • D report_clock_interaction
Correct! report_cdc is Vivado's dedicated clock domain crossing analysis command. It identifies every point in your design where a signal crosses from one clock domain to another, categorizes each crossing by severity (Critical / Warning / Info), and flags missing synchronizers. Run it after implementation to catch CDC bugs before they cause intermittent failures in hardware.

5. The standard two-flip-flop CDC synchronizer uses how many flip-flops in the destination clock domain?

  • A 1
  • B 2
  • C 3
  • D 4
Correct! The standard CDC synchronizer uses 2 flip-flops back-to-back in the destination clock domain. The first FF may go metastable, but has one full destination clock period to resolve before its output is sampled by the second FF. If the first FF's metastability resolves within that period (probability increases with technology speed), the second FF samples a valid value. This reduces MTBF (Mean Time Between Failures) from seconds to millions of years for typical frequencies.

6. Which XDC constraint defines a clock that is derived from (generated by) an MMCM or PLL output?

  • A create_clock
  • B create_generated_clock
  • C set_output_delay
  • D set_clock_groups
Correct! create_generated_clock defines a clock that is derived from a primary source clock through a divider, multiplier, or MMCM/PLL. It tells the timing engine the relationship between the parent clock and the derived clock, enabling correct setup/hold analysis across the design. The Clocking Wizard IP generates these constraints automatically — one of the key reasons to always use it.

7. Why should you never use a gated clock (e.g., assign clk_g = clk AND enable;) in an FPGA design?

  • A It uses too many LUT resources
  • B BUFG cannot buffer a gated clock signal
  • C The AND gate creates glitches on the clock edge when enable changes, corrupting FF state
  • D Gated clocks cannot be analyzed by the static timing tool
Correct! When enable transitions while clk is high, the expression clk AND enable produces a spurious glitch — a short pulse on the gated clock output. Flip-flops sensitive to that glitch will capture incorrect data, causing functional failures that are extremely difficult to debug. The FPGA solution is always to use clock enable inputs on the flip-flops themselves: always @(posedge clk) if(enable) q <= d;

Practical Exercise

Exercise — Configure an MMCM with Clocking Wizard and Write XDC Constraints Open Vivado and create a new IP project. In the IP Catalog, search for "Clocking Wizard" and open it. Configure the MMCM with: Input frequency = 100 MHz, CLKOUT0 = 250 MHz, CLKOUT1 = 50 MHz. Record the M, D, O0, and O1 divider values that the wizard selects. Verify the VCO frequency (100 × M / D) falls within 600–1200 MHz. Note the estimated output jitter for each output.

Then manually write the XDC constraints for this MMCM setup. Create a file clocks.xdc with: (1) a create_clock for the 100 MHz input; (2) a create_generated_clock for the 250 MHz output; (3) a create_generated_clock for the 50 MHz output. Compare your XDC to the one generated automatically by the Clocking Wizard IP — identify any differences and understand why the wizard may add additional constraints you didn't write.

Summary

  • Clocks must use dedicated H-tree networks to achieve <100 ps skew — routing clocks through general fabric introduces 3–5 ns skew and is never acceptable
  • BUFG (32 per 7-series device) drives the full-chip clock network — use for all primary system clocks
  • BUFH drives one half of the chip (one clock region) — power-efficient for regional clocks
  • BUFIO drives ISERDES/OSERDES only — used exclusively for source-synchronous IO interfaces
  • MMCM (Mixed-Mode Clock Manager) provides frequency synthesis, phase adjustment, and 7 output clocks — always instantiate via Clocking Wizard IP
  • PLL is simpler than MMCM — use for minimum-jitter frequency multiplication without phase shift requirements
  • Clock Domain Crossing (CDC) requires synchronizers: 2-FF synchronizer for single bits, async FIFO for data buses
  • Run report_cdc after implementation to identify all CDC crossings and missing synchronizers
  • XDC constraints: create_clock for primary clocks, create_generated_clock for derived clocks, set_clock_groups -asynchronous for unrelated domains
  • Never use gated clocks in FPGA — use clock enables on flip-flops instead