In short: Vivado turns your RTL into a bitstream in three big stages — synthesis maps it to FPGA primitives, implementation places and routes those primitives on real silicon, and bitstream generation encodes the result as configuration bits — and each stage rewrites your design in ways that matter for timing, area and debug.
Most engineers meet Vivado as three buttons: Run Synthesis, Run Implementation, Generate Bitstream. Interviewers, however, ask what actually changes between those clicks. If you know that, you can fix timing failures in minutes instead of days. This article walks through the flow as AMD (Xilinx) designed it, and shows what each step does to your code. For the generic picture, see our overview of FPGA design flow stages.
The big picture: three transformations
Your RTL is a behavioural description. The FPGA is a sea of fixed resources: LUT6s, flip-flops, carry chains, DSP48 slices, block RAMs and a programmable routing fabric. The flow is a sequence of refinements that moves from "what the logic does" to "which physical resource does it, where, and over which wire".
Stage 1: Synthesis — from behaviour to primitives
Vivado Synthesis (the default engine, similar in role to Synopsys Synplify or Design Compiler in the ASIC world) parses your RTL, elaborates it, then optimises and technology-maps it onto Xilinx primitives. Typical changes you will see:
- Inference: an array with a synchronous read becomes block RAM (RAMB36); a multiply-accumulate becomes a DSP48E2; a shift register of fixed depth can become an SRL32 inside a LUT.
- Logic mapping: any 6-input Boolean function fits in one LUT6. A wider function is split across LUTs plus F7/F8 muxes, which is why deeply nested
if/elsechains cost levels of logic. - Optimisation: constants propagate, unused registers and unread outputs are deleted, duplicate registers are merged, and FSMs may be re-encoded (for example binary to one-hot) by default.
Key fact: if a signal has no load, synthesis removes it silently. Debug nets disappear unless you mark them (* keep *) or (* mark_debug = "true" *).
Take a state machine written with a 3-bit state register. Synthesis may report "extracted FSM" and rewrite it as 6 one-hot flip-flops, trading area for a shorter next-state path. Our guide to FSM design in FPGA covers when to override this with fsm_encoding.
Synthesis also reads your XDC constraints for clocks, so it can estimate timing, but its wire delays are guesses. A synthesised design that "meets timing" can still fail after routing, because real routing delay is often 50 to 70 percent of the total path delay on a busy device.
Stage 2: Implementation — placement and routing
Implementation takes the netlist and makes it physical. It is itself a sequence of steps, and knowing them is classic interview material:
| Step | What it does | Typical symptom it fixes |
|---|---|---|
| opt_design | Removes redundant logic, retargets constants, sweeps buffers | Wasted LUTs |
| place_design | Assigns every cell to a site (SLICE, DSP, RAMB) | Long wires between related logic |
| phys_opt_design | Replicates high-fanout drivers, moves registers | Negative slack from fanout |
| route_design | Picks real wires and switch boxes for each net | Congestion, unrouted nets |
Placement is timing-driven: cells on critical paths are pulled together, while I/O cells are pinned by your XDC PACKAGE_PIN and IOSTANDARD rules. Routing then connects them, and only now does Vivado know real delays. You will read them in the timing report as WNS (worst negative slack) and TNS (total negative slack). WNS at or above zero means every path met its constraint.
Key fact: a 200 MHz clock gives a 5 ns budget. If a path has 4 LUT levels at about 0.3 ns each plus 2.8 ns of routing, it already uses 4.0 ns and the setup time of the capturing flop leaves almost no margin.
Large clocks need dedicated buffers (BUFG), and clock domain crossings need proper synchronisers; implementation will not fix a CDC bug, it will only report it through report_cdc. Newer devices with several super logic regions add another cost: crossing an SLR boundary costs extra delay, so floorplanning with Pblocks pays off. If you are choosing devices, our comparison of Xilinx vs Intel FPGAs explains how architectures differ.
Animation: a signal travelling through the flow
Stage 3: Bitstream generation
write_bitstream does no logic optimisation. It translates the routed design into configuration frames: each LUT's INIT value, every routing switch setting, IOB options and BRAM contents become bits in a binary file. DRC checks run first, and unconstrained I/O standards or missing pin locations will stop you (or only warn, unless you demote them). The file can be loaded over JTAG, or stored in QSPI flash and read at power-up. Details of encryption, compression and load modes are in FPGA bitstream and configuration.
A bitstream of a mid-range device runs from a few megabytes to tens of megabytes; enabling compression can shrink it noticeably when much of the fabric is unused.
Where the flow goes wrong: practical debugging
- Timing fails only after route: inspect
report_timing_summary, look at logic levels versus net delay, then add pipeline registers or usephys_opt_design -directive AggressiveExplore. - Latches appear: an incomplete
caseorifin a combinational block infers a latch; synthesis warns, so read the log. - Design differs from simulation: uninitialised registers, X-pessimism, or a CDC issue. Run post-synthesis and post-route timing simulation if in doubt.
- Using C instead of RTL: with high-level synthesis, the same flow still runs after the tool generates RTL.
Key fact: save a checkpoint (write_checkpoint) after each stage. Re-running only route_design with new directives takes minutes, while a full rebuild can take hours.
The same ideas, at much larger scale, appear in ASIC tools from Synopsys and Cadence; compare them in our VLSI design flow guide. For hands-on mentoring, the training team at ChipXpert runs FPGA and RTL batches.
Want to practise the full Vivado flow on real projects? Explore the FPGA tracks in CourseTron courses and build your portfolio.
FAQ
What is the difference between synthesis and implementation in Vivado?
Synthesis converts RTL into a netlist of FPGA primitives with estimated timing. Implementation places those primitives on specific sites and routes real wires, producing accurate timing.
Why does my design meet timing after synthesis but fail after routing?
Synthesis uses estimated wire delays. After routing, real net delays, fanout and congestion are known, so paths that looked fine can show negative slack.
Does generating a bitstream change my logic?
No. It only encodes the already routed design as configuration bits after running design rule checks.
What do WNS and TNS mean?
WNS is the worst slack among all paths; TNS is the sum of all negative slacks. You need WNS of zero or more to close timing.