Hardware Engineering · FPGAs

Partial Reconfiguration: Static and Dynamic Partitions

How a region of an FPGA is redefined while the rest keeps running, what the boundary between static and dynamic logic requires, and why the decoupler is not optional.

The bitstream described in the fabric overview defines the entire device state, and loading it is normally a whole-device operation performed at power-up. Partial reconfiguration breaks the bitstream into a static portion, which is loaded once, and one or more reconfigurable partitions, whose frames are rewritten at runtime while the static logic continues to run. What makes this hard is not the loading — it is the boundary.

Frames, regions, and what can be redone

The device’s configuration memory is addressed by frame, and each frame covers a fixed set of resources at one row and column. A reconfigurable partition is therefore not an arbitrary set of cells but a set of rectangular regions aligned to the configuration memory’s frame structure. The tooling calls these reconfigurable partitions, and it enforces that every implementation of a partition occupies exactly the same region, down to the frame boundaries. That requirement is the reason placement for partial reconfiguration is constrained first and synthesized second.

Because the region is fixed, its resources are fixed. Every implementation of a partition must fit in the number of slices, memory blocks, and arithmetic blocks in the region, and every implementation’s timing must be valid at the positions those resources occupy. A partition whose variants differ in resource use leaves some resources idle in the implementations that need less; that is the cost of a fixed region, and it is the main reason a dynamic region is sized generously.

The boundary between the static design and each partition is a physical boundary in the fabric. Signals crossing it are routed through dedicated routes at the region’s perimeter, and the number of such routes is finite. In practice the number of signals crossing the boundary, not the number of logic cells inside, is the sizing constraint that bites first.

Why a decoupler is mandatory

The static design drives signals into the partition and receives signals from it. While the partition is being reconfigured, its contents are undefined: the configuration memory is being rewritten frame by frame, and the logic and routing in the region pass through states that correspond to no valid design. Outputs from the region into the static design can therefore carry arbitrary values during reconfiguration, and a static state machine that acts on them can enter an unreachable state or drive a bus that other logic is also driving.

The remedy is a decoupling block at the boundary. On the static side, every signal entering the region is gated to a safe value, typically zero, and every signal leaving the region is ignored or forced to a constant, while the region is being reconfigured. The gates are controlled by a signal that is asserted before reconfiguration starts and de-asserted only after the new bitstream has loaded and the region has been reset.

-- Static-side boundary logic: hold the partition's inputs at a defined
-- level while its configuration is being replaced.
process (clk_static)
begin
  if rising_edge(clk_static) then
    if pr_reset = '1' then
      part_in <= (others => '0');
      part_valid <= '0';
    else
      part_in <= core_in;
      part_valid <= core_out_valid;
    end if;
  end if;
end process;

The decoupler is also a timing structure. Its registers are in the static design, so the paths through them are analysed in the static implementation. The paths that cross the boundary into the region are constrained within each partition’s own implementation, and the tooling requires the boundary’s timing to match across variants, which is why the boundary signals are typically registered on both sides.

The build sequence

A partial reconfiguration build is a set of related builds rather than one. The static design is synthesized and implemented once, with the partitions treated as black boxes whose interfaces are known. Each partition variant is synthesized separately and implemented into the shared region, with the surrounding design represented by the fixed boundary. The tool then assembles a full bitstream for each combination of variants, and produces partial bitstreams for each variant that can be loaded into a running device.

The constraint that ties these builds together is the region definition: every variant’s implementation must place its cells in the same region and route its boundary signals to the same boundary pins. A change to the boundary’s signal list therefore invalidates every variant, and a change inside one variant does not affect the others. That independence is the point of the technique, and it is also its fragility: a variant that fails timing fails alone, but a change to the static design’s boundary requires rebuilding all of them.

Timing closure is done per variant against the static design’s boundary, with the paths inside the region analysed at the positions the region provides. A variant that met timing in a standalone build can fail in the shared region if its logic is placed differently, because placement inside a fixed region is more constrained than placement in an unconstrained build. The arithmetic is the same as any other timing analysis, described in static timing analysis, but the placement freedom that would normally fix a failing path is not available.

Runtime control

Loading a partial bitstream requires either an internal configuration access port driven by logic inside the device, or an external processor writing the bitstream through the configuration interface. The internal port is a primitive that presents a simple write interface to the configuration memory; logic connected to it can read a bitstream from external memory and stream it into the port. The vendor provides a controller that wraps this, handles the frame addressing, and reports status.

Two timing facts constrain the operation. The reconfiguration takes time proportional to the number of frames in the region, and the device’s logic in the static region continues to run throughout, but the region itself is unavailable for that duration. A design that switches variants to amortize area must therefore accept a gap of the reconfiguration time between tasks, and that gap is often much larger than the work the variant performs. This is the economic question of partial reconfiguration: it pays when the region is large and the tasks are long, and it does not pay when the tasks are short relative to the load time.

A second fact is that the device’s configuration logic is a shared resource. Reading the configuration memory for verification or for scrubbing competes with the reconfiguration port, and some devices serialize both through the same interface. A design that depends on continuous scrubbing for single-event-upset tolerance must account for the time the scrubber holds the interface.

What partial reconfiguration is not

It is not a way to fit more logic than the device holds. The static region and the largest variant must both fit simultaneously, and the sum of all variants is irrelevant because they are never resident together. A design with four variants of a large block saves the area of three of them, not the area of all four.

It is not free of global constraints. Clocks, resets, and any signal that must be common across the design live in the static region, and every variant must use the same clock structure at the boundary. A variant that wishes to use a different clock rate must either derive it inside the region from the static clock or accept that the boundary is clocked by the static clock.

And it is not portable in the way a whole-device bitstream is portable within a family. Partial bitstreams are tied to the exact device and to the exact static design they were built against, so a change to the static design requires regenerating every partial bitstream. The versioning problem is real: a system that ships partial bitstreams must ship them together with the static bitstream they match, and a mismatch produces a device that runs a variant against a boundary it was not built for, with failures that surface as corrupt data rather than as a configuration error.

Where the technique is well matched is the case of a large, slow-changing resource: a signal-processing chain whose filter coefficients change between operating modes, a cryptographic engine that switches algorithms, a test instrument that presents different measurement engines over time. In each, the region is a fixed interface with interchangeable contents, the variants are developed independently, and the reconfiguration happens at a rate that is slow relative to the region’s work. That is the shape the mechanism was designed for, and designs outside it tend to pay the boundary cost without collecting the benefit.

References

  1. Vivado Design Suite User Guide: Dynamic Function eXchange (UG909) — Xilinx / AMD
  2. Partial Reconfiguration of Virtex FPGAs in ISE 12 (XAPP1099) — Xilinx
  3. IEEE 1532: In-System Configuration of Programmable Devices — IEEE