FPGA Design Interview Prep

FPGA design interview prep — RTL coding, timing closure, clock domain crossing, pipelining, DSP slices, and BRAM/URAM tradeoffs.

Quick answer

FPGA (Field-Programmable Gate Array) design is the discipline of describing digital hardware at the register-transfer level (Verilog, VHDL, SystemVerilog) and mapping it onto a sea of programmable logic blocks, dedicated hard macros (DSP slices, block RAMs, ultra-RAMs, transceivers), and configurable routing.

FPGA interviews drill into the gap between writing Verilog that simulates and writing Verilog that ships at 400 MHz on the target device.

Editorial review

Written by

CompoundLearn editorial team

Wireless / RF / hardware engineering

Reviewed by

CompoundLearn editorial team

Wireless / RF / hardware engineering

Last reviewed

Built from curated topic maps, editorial validation, and subject-matter review so the page stays aligned with the interview intent and the current content pipeline.

What it is

FPGA (Field-Programmable Gate Array) design is the discipline of describing digital hardware at the register-transfer level (Verilog, VHDL, SystemVerilog) and mapping it onto a sea of programmable logic blocks, dedicated hard macros (DSP slices, block RAMs, ultra-RAMs, transceivers), and configurable routing. The flow runs synthesis (RTL to gate-level netlist), place-and-route (binding to physical resources and resolving routing), and bitstream generation (packing into a programmable file). Across the flow, the designer fights three persistent battles: timing closure (every path meets setup and hold under all PVT corners), area utilization (LUTs, flops, DSPs, and BRAMs all compete for placement), and power (toggling activity, clock-tree fan-out, IO buffer drive strength). Modern FPGA work spans real-time DSP pipelines (FIR/IIR filters, FFTs, beamformers), high-speed serial protocols (PCIe, 10/25/100 GbE, JESD204), software-defined radio front ends, hardware accelerators for ML inference (DPU-style or systolic-array MACs), and increasingly heterogeneous SoC parts that pair FPGA fabric with hardened ARM cores (Zynq UltraScale+, Versal). The languages and tooling are stable; the platform diversity (Xilinx/AMD, Intel/Altera, Lattice, Microchip, Achronix, Efinix) and the SoC integration story are not.

Why interviewers ask

FPGA interviews drill into the gap between writing Verilog that simulates and writing Verilog that ships at 400 MHz on the target device. A candidate who can describe a multiplier-accumulator in code but cannot reason about pipeline depth, retiming, DSP-slice binding, BRAM port width, or CDC handshakes will produce designs that miss timing the moment a customer changes a constraint. Interviewers probe across three axes: language and synthesis literacy (do you know what blocking versus non-blocking assignment means, why latches are a smell, how synthesis infers a particular structure from a coding pattern); architectural reasoning (when do you pipeline, when do you replicate, when do you share, how do you balance area against frequency); and tooling fluency (can you read a timing report, find the worst-case path, and know whether to fix it with retiming or floor-planning). Hardware-aware questions probe the hard-macro layer: which arithmetic should bind to a DSP slice, when does a BRAM port collision force a structural change, how do you handle CDC for a multi-bit bus. Strong candidates connect each technique to a measurable improvement (cycles, area, or fmax) and have an instinct for which one to reach for first.

Common mistakes

The first mistake is treating Verilog like a software language. Loops, conditionals, and assignments do not behave like their C counterparts; they describe hardware. Candidates write nested for loops expecting sequential execution and produce massive combinational fan-out, or assume non-blocking and blocking assignments are interchangeable and create simulation-synthesis mismatches. The second is naive CDC: candidates synchronize a multi-bit bus with two-flop synchronizers per bit, missing that bits will be sampled in different destination cycles and produce torn values; correct designs use gray code, handshakes, or async FIFOs. The third is ignoring the hard macros: candidates write multipliers as a simple a*b expression and assume the synthesizer always binds to a DSP slice, but the LUT-bound variants slip through when operand widths or surrounding logic shapes mismatch the DSP topology, and the design fails timing for unobvious reasons. The fourth is timing-report illiteracy: candidates look at total slack but cannot identify the worst path, distinguish setup from hold, or read the path through a placed-and-routed design. The fifth is over-constraining: setting every clock with create_clock at overly aggressive periods produces a tool that wastes hours optimizing paths the designer never cared about, while loose constraints let real failures slip past synthesis and only surface in silicon when a corner case fires. Strong candidates write minimal correct constraints, then read reports surgically — they treat tools as instruments, not as oracles, and always cross-check the resource report and the worst-case path against expectations.

FPGA vs ASIC vs CPU vs GPU vs DSP — when each wins

DimensionFPGAASICCPUGPUDSP (e.g. C66x, Hexagon)
Time to first siliconDays (hours w/ HLS)Months-yearsN/A (already exists)N/AN/A
Non-recurring engineering (NRE)Low ($0-$10K tools)High ($1M-$100M+)ZeroZeroZero
Per-unit cost (volume 10K)$50-$5000$1-$100$50-$500$200-$5000$5-$200
Power (typical perf/W)Medium-HighHighestLowestLow (perf/W high overall)High
ReconfigurabilityIn-field (partial reconfig possible)None (mask-fixed)SoftwareSoftware (CUDA/HIP)Software (compiler intrinsics)
Best fitReal-time streaming DSP, protocol bridges, prototypingHigh-volume mass-marketGeneral-purpose computeThroughput-parallel computeBlock-mode signal/audio processing

Sample interview questions

  1. In timing closure, a path fails setup after place-and-route but passed in synthesis. What changed, and what is the first fix?
    • A. Routing delay was only estimated at synthesis; after place-and-route the actual net delay pushed the path negative, so pipelining or retiming to cut logic depth is the first move.
    • B. Synthesis already knew final routing, so the failure means the clock constraint was loosened between the two runs and should be tightened again.
    • C. Place-and-route adds hold-fix buffers that consume the setup budget, so removing hold-fix buffers recovers the setup slack on the failing path.
    • D. The path became a false path during routing, so applying a set_false_path exception is the correct way to make it meet timing.

    Option A is correct because synthesis estimates net delay from wire-load models and fanout, but the true routing delay is known only after place-and-route binds logic to physical resources. A path with acceptable logic delay in synthesis can go negative once real routing is added, especially through congested regions. The first structural fix is to reduce combinational logic depth on the path — pipelining adds a register stage, retiming moves existing registers to balance stages — so the worst stage fits the clock period. Option B is incorrect because synthesis does not know final routing; it works from estimates. A post-route failure is expected information, not evidence that the constraint was changed between runs. Option C is incorrect because hold-fix buffers are inserted on hold-critical paths and add delay to fast paths; they do not consume the setup budget of a slow path. Removing them risks hold violations without recovering setup slack. Option D is incorrect because a functional data path that must meet timing is not a false path. Declaring set_false_path on it tells the tool to stop analyzing the path, which hides the violation rather than fixing it — the circuit still fails in silicon.

  2. Why do CDC synchronizers safely cross a single bit but not a multi-bit bus wired one two-flop synchronizer per bit?
    • A. Each bit resolves metastability independently, so the bits can settle on different destination cycles and the receiver latches a torn value absent from the source bus.
    • B. Two-flop synchronizers add too much latency for a wide bus, so the bus arrives after the control logic expects it and the timing budget is missed.
    • C. Per-bit synchronizers consume one flop pair per bit, exceeding the device flop budget, so the synthesis tool drops bits to fit the design.
    • D. Metastability resolves faster on a wide bus because adjacent bits share routing, so the synchronizer depth becomes insufficient and must be increased.

    Option A is correct because a two-flop synchronizer makes a single bit safe by giving metastability time to resolve, but the resolution of each bit is an independent random event. When several bits change on the same source cycle, some may settle on destination cycle N and others on cycle N+1. The receiver then captures a mix of old and new bits — a torn value that was never valid on the source. Safe multi-bit crossings use gray-coded counters (one bit changes per step), req-ack handshakes (data held stable while a single synchronized control bit crosses), or asynchronous FIFOs (gray-coded read and write pointers). Option B is incorrect because synchronizer latency is a small fixed number of cycles and is easily accounted for; the failure here is functional corruption, not a missed latency budget. Option C is incorrect because flop-pair area for a bus is modest, and synthesis does not silently drop bits to fit — it reports utilization and fails loudly if resources are exhausted. Option D is incorrect because metastability resolution time depends on the flop characteristics and the setup-window timing, not on whether neighboring bits share routing; shared routing does not speed resolution.

  3. When does a signed 18x25 multiply belong in a DSP48 slice rather than LUT-based logic on an FPGA?
    • A. When the operand widths fit the slice and the design needs high fmax: the DSP48 has a hardened multiplier and pipeline registers that clock far faster than a LUT multiplier.
    • B. When the multiply feeds combinational logic, because DSP48 slices bypass routing and connect to nearby LUTs without using pipeline registers.
    • C. When the operands are narrow, since DSP48 slices are most efficient on small bit widths and waste area on wide operands.
    • D. When the result is unsigned, because DSP48 slices support unsigned arithmetic while LUT logic must handle the signed cases.

    Option A is correct because a DSP48 slice is a hard macro with a dedicated multiplier, a pre-adder, a post-adder, and pipeline registers. When the operands fit and the slice is pipelined, it closes timing at clock rates a LUT-built multiplier cannot reach, and it frees the general fabric for other logic. Signed multiply-accumulate chains — FIR taps, matrix products, complex multiplies — are the canonical fit. Option B is incorrect because the DSP48 speed advantage comes from using its pipeline registers; running it purely combinationally throws away the timing benefit while still consuming the slice. Option C is incorrect because narrow operands are exactly the case where LUT-based arithmetic stays competitive. Wide operands that match the slice multiplier are where the DSP48 wins. Option D is incorrect because DSP48 slices handle signed arithmetic directly; signedness is not the deciding factor, and assuming the synthesizer will sort it out is how multipliers silently fall back to LUTs and miss timing.

  4. In loop pipelining, an RTL loop has initiation interval II = 3. How does that change throughput versus an II = 1 design?
    • A. A new input can enter every 3 cycles instead of every cycle, so steady-state throughput is one third; II is set by the slowest dependency or shared resource, not by latency.
    • B. Total latency triples, but throughput is unchanged because a pipelined loop accepts one input per cycle once it is full, regardless of II.
    • C. Three inputs enter every cycle, tripling throughput at the cost of three times the resource usage on the loop body.
    • D. II is the number of pipeline stages, so II = 3 means a three-stage pipeline with full one-input-per-cycle throughput once filled.

    Option A is correct because the initiation interval is the number of cycles between successive inputs entering the pipeline. With II = 3, steady-state throughput is one result every three cycles — a third of an II = 1 design. II is usually limited by a recurrence (a loop-carried dependency) or by a shared resource such as a single memory port, not by the pipeline depth. Option B is incorrect because II directly governs throughput; a pipelined loop does not accept one input per cycle when II is greater than 1. Latency and II are separate quantities. Option C is incorrect because II is a spacing between inputs, not a parallelism factor. II = 3 spaces inputs further apart; it does not push three inputs in per cycle. Option D is incorrect because the stage count is the pipeline depth (latency), not the initiation interval. A deep pipeline can still have II = 1, and a shallow one can have II greater than 1 when a dependency forces it.

  5. For a small, wide, shallow register file, why pick distributed LUTRAM over a BRAM block on an FPGA?
    • A. For a few shallow entries a block RAM wastes most of its capacity and adds read latency, while LUT RAM gives asynchronous reads and fine-grained placement next to the logic.
    • B. LUT RAM offers true dual-port write access that block RAM lacks, so any design with concurrent writers needs distributed RAM.
    • C. Block RAM contents cannot be initialized at configuration time, so a register file needing reset values must be built from LUTs.
    • D. LUT RAM has higher total bit capacity per tile than block RAM, so wide register files are denser when built in distributed RAM.

    Option A is correct because a block RAM is a fixed-size hard macro (often 18 or 36 kbit). Mapping a register file of a handful of entries into one leaves most of the block unused and pays the block RAM synchronous-read latency. LUT-based distributed RAM packs into the fabric next to the logic that uses it, supports asynchronous reads, and is efficient when depth is small even if the word is wide. Option B is incorrect because block RAM is the resource with rich port options, including true dual-port; distributed RAM has more limited ports. Concurrent-write needs do not point to LUT RAM. Option C is incorrect because block RAM contents can be initialized in the bitstream at configuration time; initialization is not a reason to avoid block RAM. Option D is incorrect because block RAM has far higher bit density than LUT RAM. Distributed RAM wins on placement and read latency for shallow memories, not on raw capacity.

  6. In HLS, what does the DATAFLOW pragma do, and when does it outperform hand-coded RTL for a streaming design?
    • A. It runs sequential functions as concurrent pipelined stages connected by channels; it wins for large rectangular dataflow graphs where hand-coding the same plumbing is slow and error-prone.
    • B. It unrolls inner loops fully, so it outperforms RTL whenever a design has nested loops with fixed bounds and a regular access pattern.
    • C. It partitions arrays into separate memory banks, so it wins when a design is bottlenecked on block RAM port count rather than logic.
    • D. It forces a single shared pipeline for all functions, so it wins when area is tight and loop-body resources must be reused.

    Option A is correct because the DATAFLOW pragma tells HLS to execute a sequence of functions as concurrent processes connected by FIFOs or ping-pong buffers, so stage N+1 starts consuming while stage N is still producing. It is most valuable for large streaming pipelines with a clean producer-consumer structure, where hand-coding the equivalent stage handshaking and buffering in RTL is tedious and bug-prone. HLS still struggles with bit-level optimization and irregular control logic, so RTL keeps the edge there. Option B is incorrect because full loop unrolling is the UNROLL pragma. DATAFLOW operates at the function and task level, not by unrolling inner loops. Option C is incorrect because array banking is the ARRAY_PARTITION pragma. DATAFLOW connects stages with channels; it does not partition arrays. Option D is incorrect because DATAFLOW creates concurrent stages rather than a single shared pipeline. Resource sharing for tight area is a different directive with a different goal.

  7. On a Zynq SoC, when does AXI4-Stream fit better than AXI4-Lite or AXI4 (full) for PS-to-PL data movement?
    • A. For continuous high-throughput data with no addressing, such as a sample stream: AXI4-Stream drops the address channels and moves one beat per cycle, while Lite suits registers and full AXI suits addressed bursts.
    • B. When the PL must randomly address PS DRAM, because the AXI4-Stream address channels are wider than the AXI4-Lite address channels.
    • C. For low-rate control and status registers, because AXI4-Stream is the simplest protocol and avoids the burst logic that AXI4-Lite carries.
    • D. When cache coherency is required, because the AXI4-Stream protocol is the path routed through the Zynq cache-coherent ports.

    Option A is correct because AXI4-Stream is a point-to-point protocol with only a data channel and handshake — no read or write address channels — so it carries continuous, unaddressed data such as an ADC sample stream or a video line at one beat per cycle. AXI4-Lite is for single-word register access (control and status), and full AXI4 is for addressed, bursting memory-mapped transfers. Matching the protocol to the access pattern is the core decision. Option B is incorrect because AXI4-Stream has no address channels at all; randomly addressing PS DRAM is exactly what memory-mapped full AXI4 is for. Option C is incorrect because low-rate control registers are the AXI4-Lite use case, and AXI4-Lite does not do bursts — the option misstates both protocols. Option D is incorrect because cache coherency on Zynq is a property of which PS interface port is used (the accelerator coherency port or the coherent ports), not a property of the AXI4-Stream protocol itself.

Frequently asked questions

What is timing closure and why is it hard?
Timing closure means the synthesized and placed-and-routed design meets every setup and hold constraint at the target clock frequencies. It is hard because timing slack is a function of logic depth, routing congestion, clock skew, IO timing, and process variation, and these interact in non-linear ways. A path that closes in synthesis may fail after place-and-route if the router cannot find a short connection; a path that closes at typical corner may fail at slow-corner with derated worst-case clock skew. Designers close timing through pipelining (adding registers to break long combinational paths), retiming (moving logic across registers without changing function), floor-planning (placing related logic together to shorten routes), and constraint refinement (tightening or relaxing timing exceptions appropriately).
How do you handle clock domain crossings (CDC)?
A clock domain crossing happens whenever a signal generated in one clock domain is sampled in another. The risk is metastability: if the source data transitions inside the destination flop's setup-hold window, the flop output can hover at an indeterminate level for an unbounded time. Single-bit signals are safely crossed with two- or three-flop synchronizers (the metastability resolves in stages with exponentially decreasing probability of failure). Multi-bit buses cannot be crossed bit-by-bit because individual bits will be sampled across multiple destination cycles, producing torn values. The standard solutions are gray-coded counters (only one bit changes per increment), handshake protocols (req-ack pairs that gate the data), and asynchronous FIFOs (with gray-coded read and write pointers).
What is the difference between RTL synthesis and high-level synthesis (HLS)?
RTL synthesis compiles a register-transfer-level description (Verilog or VHDL) into a gate-level netlist mapped to FPGA primitives (LUTs, flops, DSP slices, BRAMs). The designer explicitly specifies registers and combinational logic and controls cycle-level behavior. HLS compiles an algorithmic description (typically C, C++, or SystemC) and infers an architecture — pipeline stages, resource sharing, memory hierarchy — driven by directives or pragmas. HLS shortens initial development time and is excellent for streaming-DSP and image-processing pipelines where the algorithm has a clean dataflow. RTL gives the tightest control over latency, area, and clock timing and remains the dominant choice for reusable IP blocks, control-heavy logic, and any block where every cycle counts.
When should you use a DSP slice instead of LUT-based arithmetic?
DSP slices (DSP48 in Xilinx, DSP block in Intel/Altera) are hard macros optimized for multiply-accumulate operations. They include a pre-adder, a multiplier (typically 18x27 or 18x18), a post-adder, and pipeline registers, all running at much higher clock frequencies than equivalent LUT-based logic. Use a DSP slice for wider signed multiplications, MAC chains (FIR filter taps, matrix products), or complex multiplies where the operand widths fit and fmax/resource goals justify the hard multiplier. LUT-based arithmetic wins for narrow operands (e.g. 4-bit multipliers), bit-level operations, or bespoke datapaths that do not match the DSP topology. Synthesis tools usually infer DSP slices from straightforward Verilog (`a*b+c`) but check the resource report — fail to bind a multiplier to a DSP slice and you will burn LUTs and miss timing.
What are BRAMs and URAMs and when do you use each?
Block RAMs (BRAMs) are dedicated on-chip memory blocks, typically 18 or 36 kilobits per BRAM in modern FPGAs, with two independent read/write ports and configurable widths. They are the workhorse for buffers, FIFOs, register files, and small lookup tables. UltraRAMs (URAMs, on Xilinx UltraScale+ devices) are larger blocks (288 kilobits each) optimized for deep storage with simpler ports and cascade chaining. Use BRAMs when you need flexible-port memories, dual-port designs, or bandwidth-critical small structures. Use URAMs for deep buffers, large lookup tables, or memory walls where capacity matters more than port flexibility. Distributed RAM (LUT-based) wins for very small (under ~64 entries) lightweight register files or content-addressable structures.
What is the difference between an FPGA and an ASIC?
An FPGA is a reconfigurable device — its logic fabric is programmed by a bitstream and can be re-programmed in the field. An ASIC is fixed at fabrication: the function is committed to silicon masks. The tradeoffs follow from that. FPGAs have near-zero non-recurring engineering cost (you buy the part and the tools) and ship in days, but cost more per unit and run at lower performance-per-watt. ASICs carry large NRE (mask sets, verification, tape-out — often millions of dollars) and take months to years, but at high volume the per-unit cost and the performance-per-watt are hard to beat. The decision rule: FPGA for prototyping, low-to-medium volume, evolving standards, and in-field updates; ASIC for high-volume, mask-stable, cost- and power-critical products. The comparison table above lays the same trade out across FPGA, ASIC, CPU, GPU, and DSP.
Why does timing closure get harder at higher clock frequencies?
Every logic path has a fixed intrinsic delay — the propagation time through LUTs, carry chains, and the routing between them — that does not shrink when you raise the clock. As the clock period shrinks, that fixed delay consumes a larger fraction of the budget, and paths that had comfortable slack go negative. Two effects compound it. First, routing delay is often the larger share of a path on a modern FPGA, and the router has less freedom as frequency rises — it must find short routes, which drives congestion. Second, clock skew and jitter are a fixed overhead that also eats a bigger fraction of a shorter period. Past a device-and-design-specific knee, each additional megahertz forces disproportionately more pipelining, retiming, and floor-planning effort. Sample question oG8iQ1Rv walks through a concrete post-route setup failure and the right first fix.
When does HLS produce better hardware than hand-coded RTL?
High-level synthesis wins when the design is a large, regular dataflow graph — streaming DSP, image and video pipelines, rectangular nested loops with a clean producer-consumer structure — where the architecture is mostly plumbing that HLS pragmas (PIPELINE, DATAFLOW, ARRAY_PARTITION, UNROLL) can generate faster and with fewer bugs than hand-coding the equivalent handshaking and buffering. It also shortens initial development and makes design-space exploration cheap: change a pragma, re-synthesize, compare. HLS still struggles where RTL keeps the edge: bit-level optimization, fine-grained control logic and state machines, asymmetric or irregular pipelines, and any block where every cycle of latency and every LUT counts. The practical pattern is hybrid — HLS for the dataflow-heavy datapath, hand-coded RTL for control and for reusable IP. Sample question tQ7sA9Wa covers the DATAFLOW pragma specifically.
How do FPGA design and RTL design overlap, and where do they diverge?
They share the same source language and core skills — synthesizable Verilog or SystemVerilog, FSM design, pipelining, CDC, timing closure — so an FPGA-design role and an RTL-design role read the same on the first page of the resume. They diverge at the back-end. FPGA design targets a fixed device with vendor-specific resources (LUTs, BRAMs, URAMs, DSP48 slices, hardened transceivers) and uses tools like Vivado, Quartus, or Libero where bitstream generation is the last step. RTL design for ASIC targets a synthesis library, a floorplan, and a tapeout where the same RTL must close timing across PVT corners, pass DRC/LVS, and survive mask costs that make late ECOs extremely expensive. FPGA flows tolerate iteration; ASIC flows punish it. Read /topics/rtl-design-academia-to-industry for the ASIC-side career framing alongside this page.

Related topics

Essential AI-Native Skills for FPGA Design

Modern engineering work increasingly uses AI tools for design and code review, debugging, documentation, test and testbench generation, and workflow automation. The goal is not to let AI replace engineering judgment — it is to move faster while keeping verification discipline.

  • Use AI to explain unfamiliar code, logs, waveforms, datasheets, or test failures.
  • Break large problems into small, reviewable steps you can verify independently.
  • Ask AI for hypotheses, then validate them against tests, measurements, simulations, or lab data.
  • Version-control your analysis scripts, testbenches, and configs — keep changes small and reviewable.
  • Document your assumptions, design tradeoffs, and debugging decisions.
  • Verify AI output before trusting it: run the checks that fit the domain — unit tests, linters, simulations, or bench/lab measurements.
  • Review AI output for correctness, edge cases, and real-world consequences.

Ready to test your FPGA Design readiness?

Start a FPGA Design quiz