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

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • Logic Synthesis Glossary
  • Logic Synthesis Cheatsheet
  • Synthesis Foundations14
  • Logic Optimisation and Mapping20
  • Constraints and Timing15
  • Sequential, FSM and Memory19
    • Flops, Resets and Enables
    • FSM Synthesis
    • Memory and Macro Inference
    • Retiming and Pipelining
      • What Retiming Moves
      • Latency, Throughput and Register Count
      • Reset, Initial State and Equivalence
      • Pipelining a Long Path by Hand
      • A Retiming Model and the Tool Flow
  • Datapath Synthesis14
  • Area, Power and Test14
  • Verification, ECO and Handoff15
  • Flows and Debugging15
  • Interview and Judgment11
Loading lesson

←Retiming and Pipelining
  1. Topics
  2. Logic Synthesis
  3. Sequential, FSM and Memory
  4. Retiming and Pipelining
  5. What Retiming Moves
On this page

    Part 4 of 9, lesson 15 of 19Part 4 of 9/Sequential, FSM and Memory/Lesson 15 of 19Intermediate

    What Retiming Moves

    How forward and backward retiming move registers across gates, with a tool-recorded move.

    A slow stage with idle neighbours looks like a mapping failure, but no new logic is needed: the register between them is simply in the wrong place. One recorded move makes the mechanism concrete.

    After this lesson you can: predict the flop count of a forward or backward move across a gate, and read the move off a pair of netlists.

    The question

    Two input registers feed one AND gate and an output register follows it: three flops where two would do. Can the input pair slide forward across the gate and merge into one, without changing what the circuit computes? This lesson answers with a real run: a flop-merging (min-area) forward move across an AND gate, with the flop count, the area, and the delay all read back from the tool's own reports. The delay-balancing version of the story waits for the Leiserson-Saxe model further down.

    One script, two jobs

    The design below holds two input registers and one output register around a single AND gate. The script first proves a hand-retimed copy equivalent, then maps the original twice: once with the flop-passing flag that invites retiming, once without it. Every count on this page comes from the stat and ABC reports the script writes.

    Predict first ABC is invited to retime with a 1000 ps target, loose beside a path of about a hundred picoseconds. The two input flops sit on both inputs of the AND, so a min-area forward move is legal. Do both input flops survive the run?

    No. A forward move across a 2-input gate replaces the two input flops with one flop on the gate output, so the run should hold 2 flops where the generic netlist holds 3 flops: the pair merges into one, in series with the existing output flop. Path register counts stay at 2 either way.

    yosys
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    read_verilog <<EOV
    module areademo(input clk, input a, b, output y);
      reg ra, rb, ry;
      always @(posedge clk) begin ra <= a; rb <= b; ry <= ra & rb; end
      assign y = ry;
    endmodule
    module areademo_rt(input clk, input a, b, output y);
      reg q1, q2;
      always @(posedge clk) begin q1 <= a & b; q2 <= q1; end
      assign y = q2;
    endmodule
    EOV
    hierarchy -check
    proc
    opt
    design -save rtl
    miter -equiv areademo areademo_rt miter
    hierarchy -check -top miter
    flatten
    tee -o equiv_rt.txt sat -seq 6 -prove trigger 0 -verify -set-init-zero
    design -load rtl
    hierarchy -check -top areademo
    synth -top areademo -flatten
    tee -o stat_gen.txt stat -liberty course.lib
    select -assert-count 3 t:$_DFF_P_
    write_json net_generic.json
    design -save generic
    tee -o abc_dff.txt abc -liberty course.lib -constr typical.constr -D 1000 -dff
    tee -o stat_dff.txt stat -liberty course.lib
    select -assert-count 2 t:$_DFF_P_
    write_json net_dff.json
    check
    design -load generic
    tee -o abc_plain.txt abc -liberty course.lib -constr typical.constr -D 1000
    tee -o stat_plain.txt stat -liberty course.lib
    select -assert-count 3 t:$_DFF_P_
    log PASS: forward retiming mapped with and without dff and pair proved over 6 cycles

    What the flagged run recorded

    The generic netlist holds 3 flops around one AND gate. Without the flag, the plain mapping reports 1 mapped gate at area 3 and 133.96 ps and keeps all 3 flops: that is the before. With the flop-passing flag, ABC reports 3 mapped gates at area 7 and 122.37 ps, and the netlist keeps 2 flops: the two input flops became a single flop on the AND output, in series with the output flop the design already had. Every input-to-output path still crosses 2 flops, so latency is unchanged. Note what this move does not do: the whole AND ends up ahead of both flops, so no delay is shared between stages. The gain is one fewer flop, not a balanced split. The separate sequential check proves the hand-retimed copy equivalent over all 6 compared steps, starting from the zeroed state.

    Before: one AND gate with 3 flops around it, two on the inputs and one on the output. Flops are highlighted.
    After: the AND output feeds 2 flops in series at area 7 and 122.37 ps. The output buffers carry the 50 fF load.

    Forward and backward moves

    Leiserson and Saxe showed that retiming is just repositioning: give every logic vertex a delay and every edge a register count, and a legal move shifts an integer lag across a vertex so that no path changes its total count. The smallest achievable period is then bounded by the slowest cycle average of delay over registers, and every move in the table below is one lag shift that preserves all path sums.

    Read the recorded pair with that lens. Before the move, the path from input a to the output crosses ra and then ry: two registers with the AND between the first and the second. After the move it crosses the merged flop and then the output flop: still two, with the AND now ahead of both. Nothing was added and nothing removed; the AND simply changed which side of the register boundary it sits on. That is the whole visual vocabulary of the two netlists above: find the gate, find which side its flops sit on, and count each path again.

    Move

    Across

    Register count

    Forward

    A 2-input gate: two input registers become one output register, as the run above records (3 to 2)

    Falls by one.

    Backward

    A 2-input gate: one output register becomes two input registers

    Rises by one.

    Forward

    A 2-way fanout stem: one register becomes one per branch, recorded in the next lesson

    Rises by one.

    Backward

    A 2-way fanout stem: one register per branch merges into one, recorded in the next lesson

    Falls by one.

    The same move as stage bars

    The program below is a model, not a tool run: it recomputes a classroom 6, 2 and 4 ns block split with plain arithmetic and asserts every figure it prints. The two timing bars that follow draw the model's own numbers, one per retimed stage, so read them as the shape of the idea rather than a measurement.

    example.py
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    import sys
    
    A = 6.0
    B = 2.0
    C = 4.0
    
    def stage_max(stages):
        m = stages[0]
        for s in stages[1:]:
            if s > m:
                m = s
        return m
    
    before = [A + B, C]
    after = [A, B + C]
    p_before = stage_max(before)
    p_after = stage_max(after)
    
    regs_before = len(before) - 1
    regs_after = len(after) - 1
    
    problems = []
    if p_before != 8.0:
        problems.append("before period")
    if p_after != 6.0:
        problems.append("after period")
    if regs_before != 1:
        problems.append("before path registers are 1, got %s" % regs_before)
    if regs_after != 1:
        problems.append("after path registers are 1, got %s" % regs_after)
    if regs_after != regs_before:
        problems.append("path count changed")
    if min(before) != 4.0 or min(after) != 6.0:
        problems.append("stage split")
    
    if not problems:
        print("PASS: model period 8.0 ns before and 6.0 ns after, path registers 1 to 1")
        sys.exit(0)
    print("FAIL: " + ", ".join(problems))
    sys.exit(1)
    Model before the move: stage 1 holds blocks A and B for an 8 ns arrival against an 8 ns requirement. Stage 2 (block C alone, 4 ns) is not drawn.
    Model after the move: stage 2 holds blocks B and C for a 6 ns arrival against a 6 ns requirement. Stage 1 (block A alone, 6 ns) matches it exactly.

    Break it: drop the -dff flag

    The second mapping in the same script is the changed variant: identical library, target and load, but no flop-passing flag. It reports 1 mapped gate at area 3 and keeps 3 flops: in this ABC script, mapping alone never moves a register at any target. The move belongs to the retiming step, not the mapper, and without the flag that step never sees the flops.

    Common mistakes

    Moving a register across a gate with side fanout changes every branch at once. Recount each branch, or one path keeps the old timing while another changes. The next lesson counts exactly such a fanout case.

    Which direction adds registers, and what stays fixed?

    • Weak answer: retiming adds registers wherever the path is slow, and latency drops with the period.

    • Strong answer: backward moves across gates and forward moves across fanout add registers; forward moves across gates remove them. Every input-to-output path keeps its count, so latency is fixed: here 2 flops per path before and after, while the total falls from 3 to 2 and the reported delay is 122.37 ps.

    • Follow-up: the two input flops have different reset values. Can the forward move still happen? Only if the tool can justify one shared value for the merged flop; otherwise it refuses, which is exactly the reset lesson that follows.

    Check yourself The flagged run keeps 2 flops where the generic netlist keeps 3. Which flops merged, and why is the path count still 2?

    The two input flops ra and rb merged into the single flop on the AND output. Each path crossed ra or rb plus ry before (2), and crosses the merged flop plus the output flop after (2).

    Check yourself The plain mapping keeps all 3 flops at area 3 while the retimed one reports area 7. What does the gap prove about where the move happened?

    It proves the move happened in the retiming step the flag enables, not in mapping: same library, target and load, yet only the flagged run changes the count.

    • Forward across a 2-input gate turns two input flops into one output flop; backward does the reverse.

    • Every input-to-output path keeps its register count, so latency is fixed while the split moves.

    • The flag enables the retiming step; without it the mapper never moves a flop.

    Rule of thumb: recount every path after a move, not just the total: the total may fall while each path keeps its count.

    How this was checked

    Flop counts, ABC areas and delays, netlist pictures, and the 6-step equivalence result on this page come from one Yosys 0.70 run of the script shown, recorded by the course checker (scripts/tools/run-rtl-testbenches.mjs with COURSE=synth): synth maps the demo, ABC maps it with and without the flop-passing flag against the teaching library course.lib with typical.constr (BUF driver, 0.05 pF load), and sat proves the hand-retimed copy. The stage-bar figures are drawn from the stdlib-only Python model on the page, labelled so; the library is fictional, so absolute areas and delays are teaching units.

    • Interview: run a mock interview on this topic

    Related topics

    • Latency, throughput and register count

    • Flops, resets and enables

    Previous

    66 / 139

    Next: Latency, Throughput and Register Count

    Up next

    Up nextLatency, Throughput and Register Count

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Reset, Initial State and Equivalence
    • Pipelining a Long Path by Hand
    • A Retiming Model and the Tool Flow