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.
Full System Architecture
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) |
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.
Knowledge Check
- IBUF
- IBUFDS
- BUFG
- ISERDES
- 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
- 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
- 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
- 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
Practical Exercise
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.