Lesson 24/2596%
MODULE 24 OF 25 20 MIN FPGA FUNDAMENTALS

Complete FPGA Architecture Walkthrough

Unify all 23 lessons into one cohesive design example — trace a real signal from IO pin through IBUFDS, clock network, routing fabric, BRAM, DSP48E1 FIR filter, CLB control logic, and output path with CDC crossing.

The Unified Architecture — Putting It All Together

Over the previous 23 lessons, we studied each FPGA building block in isolation: LUTs, flip-flops, carry chains, routing, clock networks, BRAM, DSP slices, IO banks, transceivers, and configuration. Now we bring them all together in one complete design — a 16-tap FIR low-pass filter receiving data from an LVDS ADC interface — and trace every signal from the physical IO pin through every architectural layer to the filtered output.

Device: XC7A200T (Artix-7) — 215,360 LUTs, 269,200 flip-flops, 365 BRAM36, 740 DSP48E1, GTX transceivers in HP banks.

Why This Design? A FIR filter touches almost every FPGA resource: IBUFDS and ISERDES (IO), BUFG and MMCM (clocks), RAMB36E1 (sample history), DSP48E1 (multiply-accumulate), CARRY4 (comparator), CLB Slice M (state machine), clock domain crossing synchronizer, and OBUF (output). It is the ideal vehicle for a unified architectural tour.

Full System Architecture

graph TD PCB[PCB and ADC chip] -->|LVDS differential pair 250 Mbps| IOB[IBUFDS and IDELAY2 and ISERDES\nIO Bank 35 HP 1.8V] PCB -->|LVDS differential clock 250 MHz| CLKIO[IBUFDS for clock] CLKIO --> BUFG[BUFG H-tree network] BUFG --> MMCM[MMCM 100 MHz in 250 MHz out] MMCM -->|250 MHz| CLK250[250 MHz domain clock] MMCM -->|100 MHz| CLK100[100 MHz domain clock] IOB -->|8-bit parallel data| ROUTE1[Routing Fabric\nSL6 segments 1.5 ns] ROUTE1 --> BRAM[RAMB36E1 SDP mode\n512 x 16-bit sample FIFO] BRAM -->|sample history| DSP[8x DSP48E1 cascade\nSymmetric FIR PCOUT chain] DSP -->|48-bit accumulator| CLB[CLB Slice M\nThreshold comparator CARRY4\nState machine FFs] CLB -->|status flag| CDC[2-FF synchronizer\nCDC 250 MHz to 100 MHz] CDC -->|100 MHz domain| OUT[OBUF LVCMOS33\nOutput IO Bank 34 3.3V] CLK250 -->|clock| BRAM CLK250 -->|clock| DSP CLK250 -->|clock| CLB CLK100 -->|clock| CDC CLK100 -->|clock| OUT

Layer-by-Layer Signal Trace

LAYER 1 Package and Die

The ADC output signal enters the FPGA package via a BGA solder ball, travels through the package interposer to the silicon IO pad. The XC7A200T uses a BGA package with IO pads arranged around the die perimeter in banks of 50 pins each. Inside the die, CLB columns run vertically through the center; BRAM and DSP columns flank them; clock spines run horizontally; IO banks frame the perimeter.

LAYER 2 IO Bank Entry — IBUFDS, IDELAY2, ISERDES

The ADC transmits 12-bit data serialized 8:1 at 2 Gbps over an LVDS differential pair at 1.8V into an HP bank. The IBUFDS converts the differential pair to a single-ended signal. An IDELAY2 (programmable 0–511 steps at 78 ps each) compensates for PCB trace length skew. The ISERDES8 deserializes 8:1 — converting 2 Gbps serial to 8-bit parallel at 250 MHz. An IOB flip-flop captures the parallel data on the 250 MHz clock edge before it enters the routing fabric, eliminating the PCB-to-fabric setup time from the critical path.

LAYER 3 Clock Network — IBUFDS, BUFG, MMCM

The ADC also sends a 250 MHz differential LVDS clock. This enters via a second IBUFDS, then immediately into a BUFG — the global clock buffer that drives the H-tree network, delivering the 250 MHz clock to every flip-flop in the design with less than 100 ps skew. An MMCM synthesizes a second 100 MHz output for the slower control domain. The XDC constraints: create_clock -period 4.0 [get_ports adc_clk_p] and create_generated_clock for the MMCM output.

LAYER 4 Routing Fabric — Connection Box and Switch Matrix

The 8-bit parallel data from ISERDES exits the IOB via a Connection Box into the routing fabric. The Vivado router selects SL6 hex segments (6 CLB reach, ~0.5 ns each) to reach the BRAM column approximately 6 CLBs away. The total routing delay from IOB to BRAM write port is approximately 1.5 ns — three SL6 hops. The BRAM column is visible in Vivado's Device view as a dark vertical stripe, placed by the P&R tool to minimize routing distance from the ISERDES.

LAYER 5 Block RAM — RAMB36E1 Sample History FIFO

The FIR filter needs the 16 most recent input samples to compute each output. A RAMB36E1 in SDP (Simple Dual Port) mode, configured as 512x16-bit, stores them as a circular buffer. The write port captures the latest sample on each 250 MHz clock edge; the read port simultaneously outputs all 16 history samples needed by the DSP cascade. The circular buffer write pointer increments each cycle; read addresses are offset by 0 through 15 from the write pointer. Using BRAM here (rather than FFs) saves 16 x 16 = 256 flip-flops, leaving them available for pipeline registers.

LAYER 6 DSP48E1 — Symmetric FIR Filter Core

A 16-tap symmetric FIR filter requires multiplying each sample by a coefficient. Because the filter is symmetric (h[0]=h[15], h[1]=h[14], etc.), we can use the DSP48E1 pre-adder to compute (sample[n-k] + sample[n-(15-k)]) before the multiplier, halving the DSP count from 16 to 8. Eight DSP48E1 primitives cascade via PCOUT to PCIN (dedicated zero-delay cascade wires) accumulating the partial products. The final 48-bit accumulator P output is right-shifted 15 bits (Q15 fixed-point format) to produce the 16-bit filtered output. Each DSP runs all 3 pipeline stages at 741 MHz max — comfortably meeting the 250 MHz target.

LAYER 7 CLB Logic — Comparator and State Machine

A threshold comparator checks if the filter output magnitude exceeds a programmable limit — implemented as a 16-bit signed comparator using a CARRY4 cascade (4 CARRY4 primitives in a column). A small state machine (idle / active / overflow / clear) tracks filter status using FDRE flip-flops in Slice M. The LUT6 cells in the same Slices implement the next-state logic and overflow flag decode. Vivado places these CLBs adjacent to the DSP column to minimize routing delay on the critical accumulator-to-comparator path.

LAYER 8 Clock Domain Crossing — 2-FF Synchronizer

The overflow flag, generated in the 250 MHz domain, must be consumed by a 100 MHz output controller. Crossing clock domains without synchronization causes metastability — the FPGA randomly produces a 0 or 1 with no guaranteed settling time. The fix: a 2-FF synchronizer — two flip-flops in series clocked by 100 MHz, placed in the same Slice column to minimize routing between them. The XDC constraint set_clock_groups -asynchronous -group {clk_250} -group {clk_100} tells Vivado not to time this path, since the synchronizer inherently violates single-cycle timing.

LAYER 9 Output Path — OBUF and IO Bank

The 16-bit filtered result and overflow flag exit through an HR bank (Bank 34, VCCO=3.3V) using LVCMOS33 IO standard with DRIVE=8 and SLEW=SLOW for EMI reduction. The OBUF buffers the fabric signal to the IO pad voltage. IOB output flip-flops are used — Vivado automatically places the last register before OBUF inside the IOB cell, eliminating routing delay on the output setup path. The XDC: set_property IOSTANDARD LVCMOS33 [get_ports {data_out[*]}] and set_output_delay -clock clk_100 -max 2.0 [get_ports {data_out[*]}].

Resource Utilization Summary

Resource Count Architectural Role Lesson
IBUFDS 2 LVDS data + clock entry 19
IDELAY2 1 PCB trace delay calibration 19
ISERDES8 1 8:1 deserializer 19
BUFG 2 250 MHz + 100 MHz H-tree 15
MMCM 1 100 MHz synthesis from 250 MHz 15
RAMB36E1 1 16-sample circular FIFO 16
DSP48E1 8 FIR filter MACC cascade 18
CARRY4 4 16-bit magnitude comparator 13
LUT6 ~52 State machine + decode logic 11
FDRE ~96 Pipeline registers + CDC sync 12
OBUF 17 16-bit data + overflow flag 19

Critical Path Timing Breakdown

Path Segment Delay Resource
FDRE clock-to-Q (DSP input FF) 0.45 ns FDRE in CLB
Routing: CLB to DSP48E1 input 0.55 ns SL2 segment x2
DSP48E1 pre-adder + multiplier + accumulator 2.10 ns DSP48E1 (no pipeline)
PCOUT to PCIN cascade (7 hops) 0.00 ns Dedicated cascade wire
Routing: DSP to CARRY4 0.48 ns SL1 segment
CARRY4 comparator (4 stages) 0.42 ns CARRY4 column
Setup time FDRE 0.12 ns FDRE
Total critical path 4.12 ns WNS = +0.38 ns at 250 MHz (4 ns period)
Timing Closure Strategy for This Design The critical path is the non-pipelined DSP accumulation path. If WNS was negative, the fix would be to add a pipeline register after the DSP accumulator (between the 48-bit P output and the CARRY4 comparator) — adding 1 clock cycle of latency but breaking the 2.1 ns DSP internal delay. With full 3-stage DSP pipelining, this design could run at over 600 MHz.
Interview Question Q: In the FIR filter design described, why does a 16-tap symmetric filter only need 8 DSP48E1 primitives?

A: Because the DSP48E1 pre-adder computes D + A before the multiplier. For a symmetric filter where h[k] = h[N-1-k], we can compute (sample[n-k] + sample[n-(N-1-k)]) x h[k] in one DSP instead of two separate multiply-and-accumulate operations. This halves the DSP count from 16 to 8, which is why the pre-adder exists in the DSP48E1 architecture.
The Big Picture Every element in this walkthrough — IOB, BUFG, MMCM, routing, BRAM, DSP, CLB, CDC, OBUF — appears in virtually every real FPGA design. The names change, the protocols change, the data widths change, but this fundamental pattern of: receive data at IO, buffer clock, route to processing fabric, use hard blocks for compute, manage clock crossings, and drive output — remains constant across every FPGA project.

Knowledge Check

1. Which primitive converts an LVDS differential pair to a single-ended signal inside the FPGA?
  • IBUF
  • IBUFDS
  • BUFG
  • ISERDES
IBUFDS (Input Buffer Differential Signaling) takes the P and N pins of an LVDS pair and converts them to a single-ended signal for the FPGA fabric. IBUF handles single-ended inputs only.
2. In the FIR filter example, why is RAMB36E1 used for sample history instead of flip-flops?
  • BRAM runs at a higher clock frequency than CLB flip-flops
  • BRAM stores 16 x 16-bit samples in one block, saving 256 flip-flops for other use
  • Distributed RAM cannot store more than 64 bits total
  • BRAM supports asynchronous read which FIFOs require
One RAMB36E1 holds 36 Kbits of storage. Sixteen 16-bit samples = 256 bits — far smaller than the BRAM capacity. Using BRAM saves those 256 flip-flops (which occupy valuable CLB resources) for pipeline registers and other logic.
3. How many DSP48E1 primitives does a 16-tap symmetric FIR filter need when using the pre-adder?
  • 16 — one per tap
  • 4 — one per filter quarter
  • 8 — the pre-adder pairs symmetric samples before the multiplier
  • 32 — two DSPs per tap for pre-adder and multiplier
For a symmetric 16-tap filter (h[0]=h[15], h[1]=h[14] ...), we pair samples: (x[n-k] + x[n-(15-k)]) x h[k]. The DSP48E1 pre-adder computes the pair sum before the multiplier, so 8 pairs = 8 DSPs instead of 16.
4. What is the purpose of the 2-FF synchronizer between the 250 MHz and 100 MHz domains?
  • To slow down the signal from 250 MHz to 100 MHz rate
  • To prevent metastability when a signal crosses from the 250 MHz clock domain to the 100 MHz clock domain
  • To double-register data for pipeline depth
  • To buffer the overflow flag so it lasts two extra cycles
When a signal crosses between asynchronous clock domains, a flip-flop may enter metastability — an undefined state where the output is neither 0 nor 1. Two flip-flops in series give the signal two clock cycles to resolve. The MTBF (mean time between failures) from metastability improves exponentially with each FF added.
5. What XDC constraint tells Vivado's timing engine to ignore paths between the 250 MHz and 100 MHz clock domains?
  • set_false_path -from clk_250 -to clk_100
  • set_clock_groups -asynchronous -group {clk_250} -group {clk_100}
  • create_clock -period 4.0 -name clk_250
  • set_multicycle_path 2 -from clk_250 -to clk_100
set_clock_groups -asynchronous tells Vivado that the two clock groups have no timing relationship — paths between them should not be analyzed by the timing engine. This is correct for unrelated clock domains handled by synchronizers. set_false_path would also work but is less precise about the direction of the exemption.

Practical Exercise

Design Exercise — 4-Tap Symmetric FIR Filter Implement a simplified version of this walkthrough in Vivado:

Specification: 4-tap symmetric FIR filter, 12-bit signed input, 12-bit signed output, 100 MHz clock, target XC7A35T.

Coefficients (Q12 format): h[0]=h[3]=256, h[1]=h[2]=2048 (low-pass filter)

Architecture:
- Use 2 DSP48E1 primitives with pre-adder (connect PCOUT of DSP0 to PCIN of DSP1)
- Use 1 RAMB36E1 in SDP mode (64x12-bit) as circular sample buffer
- Add ILA on the output with (* mark_debug = "true" *)

Verification: In simulation, apply a 1 kHz sine wave and a 30 kHz sine wave simultaneously. Verify the 30 kHz component is attenuated at the output while 1 kHz passes through. Then implement, program hardware (if available), and observe output with ILA.

Summary

This walkthrough connected every FPGA architectural layer into a single coherent design. From the LVDS pad through IBUFDS and ISERDES, into the BUFG clock tree, through the routing fabric to BRAM and DSP48E1 cascade, past the CLB comparator and state machine, across a 2-FF CDC boundary, and out through OBUF — every block you studied in isolation has a natural place in a real system. Understanding these interconnections is what separates an FPGA beginner from a professional design engineer.