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 Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
    • STA Foundations
    • Setup, Hold and Slack
    • Skew and Variation
    • Timing Exceptions
    • Clock Gating
    • RTL for Timing
      • Practice
      • Fanout
      • Patterns
      • RTL Hooks
      • Checklist
      • Cutting Logic Depth: a Timing-Closure Story
      • Mini Project: Close Timing on a FIR Filter
    • Clock Architecture
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹RTL for Timing
  1. Topics
  2. RTL Design
  3. Timing & Clocking
  4. RTL for Timing
  5. RTL Hooks

Part 5 · Timing & Clocking · Intermediate

RTL Hooks

Parameters, generate branches and attributes that change timing structure without rewriting logic.

On this page

    Why this matters

    A pipeline depth fixed in the code means a rewrite when timing slips. A parameter, a generate switch or a keep attribute makes the change a configuration edit plus a test run.

    After this lesson you can: add a timing hook to a design, such as a pipeline depth, a fast or small variant, a replication count or a preserve attribute, and keep the testbench latency-aware.

    Hooks for timing closure

    A hook is a place in the RTL designed to be changed later: a parameter for pipeline depth, a switch between two implementations, or an attribute that tells the tool what to preserve. Timing closure then becomes a configuration change plus a test run.

    Common hooks

    Seven hooks cover depth, implementation choice, preservation and tool limits. The table names each form and its use.

    Hook

    Form

    Used for

    Pipeline depth

    parameter int STAGES

    Add or remove register ranks on a long path

    Implementation choice

    parameter bit FAST = 0, selected with a generate if

    Plain adder or prefix adder

    Output register

    parameter bit REG_OUT = 1

    Registered outputs at block boundaries

    Replication count

    parameter int COPIES

    Fanout control

    Preserve

    (* keep *) / (* keep_hierarchy *) (tool specific)

    Stop merging of duplicated registers or logic

    Fanout limit

    A tool attribute such as max_fanout, or a constraint

    Ask the flow to buffer or duplicate

    Don't touch

    dont_touch style constraints

    Protect hand-built structures such as clock gates

    Attribute names are tool specific. keep and keep_hierarchy are Yosys spellings; other tools use syn_keep, dont_touch, max_fanout, KEEP.

    Put the attributes in one wrapper or a single macro per tool, so a switch of flow changes one file.

    Tip

    A pipeline stage hook needs a latency-aware testbench. A scoreboard that takes latency from the same parameter keeps simulation and design in step.

    Common pitfall

    A parameterised pipeline depth only works if every consumer of the result is latency-aware: valid bits, control signals and side data must be delayed by the same number of stages. Put the data and its valid bit in the same hook so they cannot diverge.

    Check yourself Why is STAGES = 0 implemented as a wire in a generate branch instead of a register with a zero-length chain?

    A zero-length array is illegal, and a one-register chain would add a cycle of latency. The generate branch removes the registers entirely, which is exactly what 0 stages means.

    Testbench

    Legal parameters are STAGES >= 0 and W >= 1. STAGES counts register ranks. With input A stable before acceptance edge E0 and observation after NBA, stage 1 shows A after E0, stage 2 after E1, and stage 4 after E3: STAGES-1 elapsed periods to visibility for registered cases. A downstream flop consumes A at E1/E2/E4 respectively. Stage 0 is combinational, with no accepting edge or storage. This hook has no valid, reset or backpressure; the consumer owns fill masking and transaction alignment.

    Input A sampled at E0

    Post-NBA visibility

    Earliest downstream edge

    STAGES=0

    Combinational before E0

    E0 if setup is met

    STAGES=1

    E0

    E1

    STAGES=2

    E1

    E2

    STAGES=4

    E3

    E4

    Each slot is one clock cycle, sampled just after its rising edge. Token 1 is driven in slot 0, so the edge that starts slot 1 is its accepting edge E0.

    • out0 is a wire: it shows each token in the same slot as in.

    • out1 shows token 1 in slot 1, straight after E0. out2 shows it in slot 2 (after E1).

    • out4 shows token 1 in slot 4, after E3, and token 5 in slot 8: four cycles of latency, one per rank.

    • Every lane carries the same sequence 1 to 5; only the delay differs, which is why a consumer must take its latency from the same parameter.

    The finite checker below drives on falling edges, observes after NBA, checks only filled ranks, and drains four edges.

    opt_pipe.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // An optional pipeline stage count, chosen at instantiation. STAGES = 0 is a plain wire.
    module opt_pipe #(parameter int STAGES = 1, parameter int W = 16) (
      input  logic         clk,
      input  logic [W-1:0] in,
      output logic [W-1:0] out
    );
      if (STAGES < 0 || W < 1) begin : g_invalid
        initial $fatal(1, "Require STAGES >= 0 and W >= 1");
      end else if (STAGES == 0) begin : g_wire
        assign out = in;
      end else begin : g_pipe
        logic [W-1:0] r [STAGES];
        always_ff @(posedge clk) begin
          r[0] <= in;
          for (int i = 1; i < STAGES; i++) r[i] <= r[i-1];
        end
        assign out = r[STAGES-1];
      end
    endmodule
    

    Remember

    • Hooks cover depth, implementation choice, output registers, replication, preserve, fanout limits and don't-touch.

    • Valid bits, control and side data must be delayed by the same number of stages as the data, so put them in the same hook.

    • Attribute names are tool specific. Put them in one wrapper or macro per tool.

    Rule of thumb: let the scoreboard take its latency from the same parameter as the design.

    How this was checked

    Latency bench, run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It drives on falling edges, observes after NBA, checks only filled ranks and drains four edges. It checks latency in an ideal model, not a timing result.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Checklist

    Previous

    144 / 350

    Next: Checklist

    Up next

    Up nextChecklist

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Practice
    • Fanout
    • Cutting Logic Depth: a Timing-Closure Story
    clkin123450out0123450out10123450out20123450out4012345
    Simulation of opt_pipe with STAGES = 0, 1, 2 and 4 on one input carrying tokens 1 to 5