Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations57
  • Combinational Design58
  • Sequential Design61
    • Flip-Flops and Registers
    • Counters and Timers
    • Shift Registers and LFSRs
    • Pipelining
    • Stalls, Bubbles and Hazards
    • Retiming
      • Retiming Mechanism
      • Retiming Decision Guide
      • Handshake-Aware Retiming
      • Practice
      • Sample Q&A
      • Checklist
      • Worked Examples and Waveforms
      • Corner Cases and Stress Tests
      • Integration and Sign-off Notes
  • FSM & Control66
  • Timing & Clocking64
  • Reset & CDC58
  • Memory & Buses94
  • Advanced RTL60
  • Senior & Interview175
  • Glossary and Notation
Loading lesson

‹Retiming
  1. Topics
  2. RTL Design
  3. Sequential Design
  4. Retiming
  5. Retiming Mechanism

Part 3 · Sequential · Intermediate

Retiming Mechanism

How registers move across gates forward and backward, with a simulation of both versions.

On this page

    Why this matters

    Moving a register backward across slow logic splits one long path in two, but it can just move the failure to the output. Budget both boundaries before choosing the move.

    After this lesson you can: retime a register across a gate, size the new register width, and check the move against input and output timing budgets.

    Moving a register across a gate

    Consider the output y = f(g(x)), where g is slow and f is fast. The only register sits after f, so the critical path runs through g and f into the register.

    Two pipelines: the register moves from after f to between g and f.
    Moving the register from after f to between g and f shortens the input path (now only g) and puts f on the output side.

    Moving the register backward across f places it between g and f. The path splits into input → g → register, then register → f → output.

    Moving it the other way is forward retiming. The full code sits under Testbench below.

    The operands a, b and c are 8 bits, so the product a*b needs up to 16 bits and y is 16 bits wide (the largest value is 255 × 255 + 255 = 65280). The product register p_r is 16 bits too; a narrower register would silently truncate the product.

    Both versions have the same latency from inputs to y as seen by a synchronous sampler. The difference is where the delay sits: before, one path of multiply plus add; after, a multiply path into the register and an add path out of it. Settled values agree, but y0 is a register output while y1 is a combinational sum of registers, so clock to output delay and glitches between clocks can differ.

    Budget both boundaries before choosing the move

    Use illustrative maximum delays, not measured cells: latest input arrival 0.4 ns after the upstream launch edge, multiply 2.4 ns, add 0.8 ns, register setup 0.1 ns, clock-to-Q 0.2 ns, and output route 0.2 ns. Target period is 3.0 ns. The system initially requires y at the output port by 1.0 ns after this block's capture edge, reserving the rest of the downstream cycle for external logic/setup. Assume zero skew/uncertainty here; real STA must include them and also check minimum-delay hold paths.

    Budget / cost

    Before: register after add

    After: registers before add

    Input-to-register requirement

    0.4 + 2.4 + 0.8 + 0.1 = 3.7 ns

    0.4 + 2.4 + 0.1 = 2.9 ns (multiply path dominates c)

    Input setup slack at 3.0 ns

    -0.7 ns: fails

    +0.1 ns: passes this model

    Register-to-output arrival

    0.2 + 0.2 = 0.4 ns

    0.2 + 0.8 + 0.2 = 1.2 ns

    Output slack against 1.0 ns required

    +0.6 ns: passes

    -0.2 ns: fails

    Data register bits

    16

    16 product + 8 c = 24 (+8 bits)

    The same budget as bars: before the move the input path is 3.7 ns against a 3.0 ns period; after it the input path fits with 0.1 ns to spare but the output path grows to 1.2 ns against a 1.0 ns requirement

    Each bar is one path drawn to scale, left to right in nanoseconds; the dashed marks above and below it show the limit it must finish before. A bar that runs past its marks has negative slack.

    • Before: the 0.8 ns add sits on the input path, which ends 0.7 ns past the period line. The output path has 0.6 ns to spare.

    • After: the add box moves from the input bar to the output bar. The input path now fits by 0.1 ns, but the output path misses its 1.0 ns requirement by 0.2 ns.

    • The move only shifts work between boundaries. Whether it helps depends on who owns the output budget.

    With the original output budget, reject the move: it merely relocates the failure. If the downstream owner can allow 1.4 ns instead, output slack becomes +0.2 ns and the retimed version meets both modeled boundaries at 3.0 ns, while the original needs at least 3.7 ns for its input path. That is a conditional timing choice with eight extra register bits. Confirm actual constraints, mapped delays, hold closure and reset/initial-state equivalence before accepting it.

    Rules the move must obey

    Rule

    Detail

    A register moved backward across a gate with several inputs is duplicated on each input

    Here c needs its own register rank (c_r).

    A register moved forward across a gate with several inputs requires registers on all inputs

    Otherwise some inputs would be delayed and others not.

    Initial values must be consistent

    A register with a reset value may only move if an equivalent value exists on the other side.

    Registers in different clock domains stay put

    Retiming never crosses a clock boundary.

    Common mistakes

    Common pitfall

    Retiming a register out of a feedback loop changes the loop's cycle count and therefore the function. Tools retime only when the number of registers around every loop is preserved.

    Check yourself After moving the register backward across the adder, why did we need c_r?

    The adder has two inputs. The register moved to the adder's input side must be on both; otherwise c would arrive one cycle earlier than the product and be added to the wrong item.

    Testbench

    Both versions plus the testbench that checks their settled outputs match when sampled after the clock edge. The registers have no reset, so the first two cycles are skipped as unknown startup. Downstream logic must sample y synchronously.

    before_retime.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    module before_retime (
      input  logic       clk, rst_n,
      input  logic [7:0] a, b, c,
      output logic [15:0] y
    );
      // register at the end: path = (a*b) + c all in one cycle
      logic [15:0] r;
      always_ff @(posedge clk) r <= (a * b) + c;   // 8x8 product needs 16 bits; 255*255 + 255 = 65280 still fits
      assign y = r;
    endmodule
    
    module after_retime (
      input  logic       clk, rst_n,
      input  logic [7:0] a, b, c,
      output logic [15:0] y
    );
      // registers moved backward across the adder: multiply | reg | add
      logic [15:0] p_r;             // full 16-bit product (255*255 = 65025)
      logic [7:0]  c_r;
      always_ff @(posedge clk) begin
        p_r <= a * b;               // path 1 = multiply only
        c_r <= c;                   // c must pass through the same register rank
      end
      assign y = p_r + c_r;         // path 2 = add only (after the register)
    endmodule
    

    Remember

    • Moving the register backward across f puts it between g and f and splits the path.

    • The registers around every feedback loop must stay the same in number, or the function changes.

    • The retimed output is a combinational sum of registers, so clock-to-output delay and glitches can differ.

    How this was checked

    The delays are illustrative maximums, not measured cells.

    The 1.4 ns output budget case is a conditional timing choice, not a measured frequency, area or power result.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Decision guide

    Previous

    168 / 694

    Next: Retiming Decision Guide

    Up next

    Up nextRetiming Decision Guide

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Handshake-Aware Retiming
    • Practice
    • Sample Q&A