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

  • How to Use This Course
  • Reading Paths
  • Quick Start: Your First Green Build
  • Part 1: How Chips Get Made6
  • Part 2: Your Workstation5
  • Part 3: Specify and Architect3
  • Part 4: The Design Loop6
  • Part 5: The Verification Ladder6
  • Part 6: Automation and Reproducibility5
  • Part 7: Hand-Off to the Back-End3
    • What the Back-End Needs
    • Reading a Constraints File
    • The Release Package
  • Part 8: When Things Go Wrong3
  • Part 9: Project and Next Steps3
  • Reference4
Loading lesson

‹Part 7: Hand-Off to the Back-End
  1. Topics
  2. Start Here: RTL and Verification
  3. Part 7: Hand-Off to the Back-End
  4. What the Back-End Needs

Part 7 · Hand-Off to the Back-End · Working (W)

What the Back-End Needs

RTL is done when another team can build from it. Package the source, the clocks, the resets, the constraints, the issues, and the versions, and check the hygiene list first.

On this page

    Note

    Level: Working (W) · Answers: What does the next team need from your RTL before they can do their job?

    Before this: What Happens After RTL

    Your simulation passes. Lint is clean. The synthesis check is green. Are you done? Not yet. Another team must turn your RTL into silicon, and they cannot ask your testbench questions. Anything you leave unsaid becomes a guess, and a guess in the back-end becomes wrong hardware.

    What does the next team need from your RTL before they can do their job?

    Done means someone else can build it

    Your register-transfer level (RTL) code is finished when the next team can build from it without asking you anything. That team spans several groups, and each one reads your package for a different answer. The package below is the full set: eight items, each with one owner waiting for it.

    • RTL source and a file list in compile order. The code plus the order to read it in, so the build never depends on which file the tool happens to see first.

    • The top module name. One name that says where the design starts. Everything else hangs below it.

    • Every clock, with its intended frequency. Each clock's name and the speed it must run at. An unnamed clock is a guessed clock.

    • Every reset, fully described. Polarity, active level, whether it acts with or without the clock, and how it is released. Resets that differ between blocks must say so.

    • Hierarchy and ownership. Which blocks exist and who owns each one, so questions reach the right person.

    • Timing constraints. What speed each path must meet. The next lesson reads this file line by line.

    • Known issues and waivers. Every open problem plus every waived check. A waiver is written permission to ignore a flagged check, with a reason, an owner, and a revisit date. An unwritten waiver does not exist.

    • Tool versions used. The exact releases that produced the green run, recorded as Pinning Tool Versions describes, so the back-end reproduces your results before trusting them.

    Three questions the back-end will always ask

    Three items on the list deserve one line each, because the back-end raises them on every project. A clock-domain crossing is a signal passing between two clocks, and each one needs handling the back-end must know about. Scan readiness means your flip-flops can join the test chains manufacturing uses to find broken chips, so nothing in your RTL may block that insertion. Power intent names which blocks switch off or retain state, so the power team plans for it from the start.

    One package, five teams

    The figure below draws the package as one box on the left and its five readers on the right. Follow each arrow: the same eight items answer different questions for synthesis, physical design, timing sign-off, manufacturing test, and power.

    One hand-off package on the left sends its eight items to five teams on the right: synthesis, physical design, timing sign-off, manufacturing test, and power.

    Check the project against the hygiene list

    Before the package leaves, the RTL must pass a hygiene list: the habits that keep the back-end from tripping on your code. The project's counter is shown below, and each check after it names what the back-end would flag:

    mini_controller.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    `timescale 1ns/1ps
    // Counts accepted events, 4 bits, wraps 15 -> 0.
    // Priority: reset > clear > count > hold. Reset is synchronous, active low.
    module mini_controller (
        input  logic       clk,
        input  logic       rst_n,
        input  logic       event_valid,
        input  logic       clear_count,
        output logic [3:0] count
    );
        always_ff @(posedge clk) begin
            if (!rst_n)
                count <= 4'd0;
            else if (clear_count)
                count <= 4'd0;
            else if (event_valid)
                count <= count + 4'd1;
        end
    endmodule

    This listing is the design the checks below judge: one clock, one reset, and a priority chain the tools can build directly.

    • One clock. The design has a single clock input, clk. The constraints file gives its intended period as 10 ns, an illustrative value chosen for teaching, and the package must state it so nobody guesses.

    • One reset, fully stated. The reset rst_n is synchronous and active low: the if (!rst_n) branch sits inside the clocked block, so deassertion takes effect on a rising edge like any other synchronous input.

    • No inferred latches. The priority chain covers reset, then clear, then count, then hold inside a clocked block, so every path assigns the count or keeps it by design. Nothing holds a value by accident.

    • No delays or initial blocks in the RTL. The source contains no timing controls and no initial blocks: everything in it describes hardware, and nothing in it runs only in simulation.

    • Lint is clean. The Verilator lint step passes with no warnings on this file, measured on macOS with Verilator 5.048:

    Synthesis is clean. The Yosys check reports zero problems on this file, measured on macOS with Yosys 0.69+post. You have already read both clean outputs in full: lint in Lint with Verilator and the synthesis check in First Synthesis Check. The hand-off only needs the verdict, so repeat both runs and tick them off the checklist:

    Check

    Command

    Hand-off passes when

    Lint

    make lint

    no warnings and exit status 0

    Synthesis check

    make synth

    the check reports 0 problems and exit status 0

    Simulation

    make sim

    exactly one PASS: line and exit status 0

    Everything

    make all

    all three above, in one command

    Predict first How many clocks does this design have, and where is that written down?

    One clock, clk. It is written in three places that must agree: the port list in the RTL, the constraints file with its intended period, and the hand-off package. If any one of the three is missing, the back-end guesses, and a guessed clock builds the wrong hardware.

    Break it on purpose: widen one constant

    Change a 4-bit increment to add an 8-bit constant instead, and lint fails the build at once with two width warnings and a nonzero exit, measured on macOS with Verilator 5.048:

    Diagram
    # captured terminal output
    $ verilator --lint-only -Wall --top-module w widthdemo/w.sv
    %Warning-WIDTHEXPAND: widthdemo/w.sv:2:45: Operator ADD expects 8 bits on the LHS, but LHS's VARREF 'count' generates 4 bits.
                                             : ... note: In instance 'w'
        2 |     always_ff @(posedge clk) count <= count + 8'd1;
          |                                             ^
                          ... For warning description see https://verilator.org/warn/WIDTHEXPAND?v=5.048
                          ... Use "/* verilator lint_off WIDTHEXPAND */" and lint_on around source to disable this message.
    %Warning-WIDTHTRUNC: widthdemo/w.sv:2:36: Operator ASSIGNDLY expects 4 bits on the Assign RHS, but Assign RHS's ADD generates 8 bits.
                                            : ... note: In instance 'w'
        2 |     always_ff @(posedge clk) count <= count + 8'd1;
          |                                    ^~
                         ... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=5.048
                         ... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message.
    %Error: Exiting due to 2 warning(s)
    [exit status 1]

    Read the warning literally: the addition expects 8 bits on one side while the target holds 4, and the assignment then truncates back to 4. The project avoids this by sizing every constant to its target, as the 4'd1 in the counter shows. The fix is the same everywhere: size the constant to the signal, or waive the warning in writing with a reason instead of ignoring it.

    Three handoffs that come back to hurt you

    • Handing over RTL with unstated clocks. A clock named only in conversation arrives at the back-end as a guess about frequency, and every timing answer built on it is wrong. Name each clock and its intended frequency in the package.

    • Resets that differ between blocks without saying so. One block's synchronous active-low reset is another block's asynchronous active-high reset until the package says otherwise. State every reset's polarity, timing, and release, or unify them first.

    • Leaving waivers unwritten. A waived warning with no note rots: the next tool version flags it again, the next engineer re-litigates it, and nobody remembers why it was safe. Write the reason, the owner, and the revisit date, or fix the code.

    Rule: hand over everything the next team needs to build without asking you a question.

    Try it: review this module

    The short module below compiles. Read it as the back-end would: two hygiene problems hide in fourteen lines, and both would sail through simulation. Name them before reading the answer:

    needs_review.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // A small enabled register. Read it before trusting it.
    module needs_review (
        input  logic clk,
        input  logic en,
        input  logic d,
        output logic q
    );
        initial q = 1'b0;
        always_comb begin
            if (en)
                q = d;
        end
    endmodule
    Check yourself What two problems does the module above hide, and what is the fix?

    First, the combinational block assigns q only when en is high, so the tools infer a latch: q holds its value by accident instead of by design. Second, the initial block sets q once at time zero in simulation and synthesizes to nothing, so the design has no real reset. The fix gives the module a synchronous active-low reset input, moves the state into a clocked block with a reset branch, and gives the combinational logic a default assignment so no path holds by accident.

    Check yourself The back-end asks for your clocks and resets. What do you send for the counter?

    One clock, clk, with its intended period from the constraints file, which is an illustrative 10 ns. One reset, rst_n, synchronous and active low, released synchronously on a rising edge. Both appear in the RTL, the constraints, and the package, all three agreeing.

    Check yourself A lint warning fires on legacy code everyone agrees is safe. Waive it or fix it?

    Waive it in writing or fix the code, never ignore it silently. A written waiver names the check, the reason it is safe, the owner, and the revisit date. If the fix is cheaper than the paperwork, fix the code and keep the lint clean.

    Interview

    Asked: "What do you hand to the physical design team along with your RTL?"

    Weak answer: The Verilog files.

    Strong answer: The RTL source with a file list in compile order, the top module name, every clock with its intended frequency, every reset with its polarity, timing and release, the timing constraints, the known issues with written waivers, and the tool versions behind the green run. I also flag the clock-domain crossings, scan needs, and power intent so each back-end team finds its answer without asking me.

    Follow-ups: (1) Your design has two clocks. What extra line does each crossing need in the package? (2) A waiver has no owner and no date. Is it a waiver?

    Key takeaways

    • Done means the next team can build without asking you.

    • Write down every clock, every reset, and every waiver.

    • Check hygiene first: one clock, stated resets, no latches, lint and synthesis clean.

    Keep going

    Next: Lesson 7.2, Reading a Constraints File. The package names timing constraints as one of its items. The next lesson teaches you to read that file.

    Related topics

    • Physical design course

    • Static timing analysis course

    • DFT course

    • Low-power course

    • RTL: Coding Lint

    Previous

    35 / 47

    Next: Reading a Constraints File

    Up next

    Up nextReading a Constraints File

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • The Release Package