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

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
    • Parameterization and Generate Hub
    • Top-Level Integration Hub
      • Top-down vs bottom-up integration
      • Port list discipline
      • Parameter propagation across hierarchy
    • Synthesis Intent Hub
    • Style and Static Checks Hub
    • Assertions in RTL Hub
    • Formal Verification Basics Hub
    • Reusable SystemVerilog for RTL
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Top-Level Integration Hub
  1. Topics
  2. RTL Design
  3. Advanced RTL
  4. Top-Level Integration Hub
  5. Port list discipline
On this page

    Part 8 of 9, lesson 5 of 28Part 8 of 9/Advanced/Lesson 5 of 28Advanced

    Port list discipline

    Grouped ports, direction suffixes, named connections, and no debug-only top ports.

    Insert one port into a positional instance and every binding after it shifts, or the tool reports a port-count error. Named connections survive the insert, but a new port can then be left unconnected with no language error.

    After this lesson you can: write a grouped port list with direction suffixes, connect by name, and say when .* is acceptable.

    Group, suffix, and connect by name

    Ports stay grouped by protocol or function instead of random ordering. Clocks and resets lead, then each interface forms one group.

    Suffixes mark direction: _i for in, _o for out. Clocks and resets take _i too, and an active-low signal adds n: clk_i, rst_ni. Reviews then audit direction at a glance.

    stream_stage.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // snippet
    module stream_stage #(
      parameter int W = 16
    ) (
      // clock and reset
      input  logic         clk_i,
      input  logic         rst_ni,
      // upstream port
      input  logic         valid_i,
      input  logic [W-1:0] data_i,
      output logic         ready_o,
      // downstream port
      ...
    );

    Rule

    Form

    Group by interface

    Clock and reset first, then one group per port

    Mark direction

    _i inputs, _o outputs; clocks and resets also take _i, active-low adds n: clk_i, rst_ni

    Connect by name

    .clk_i(clk_i) at every instantiation; .* only where every name already matches

    Keep debug out

    No debug-only wires as permanent top-level ports

    Structs and interfaces belong only where the toolflow supports them through synthesis and lint. Plain grouped ports work everywhere.

    Common mistakes

    Positional connections are sensitive to port order; an insertion can shift bindings or trigger a port-count error. Named connections preserve existing bindings, but a newly added port may remain unconnected without a language error. Enforce missing-port lint diagnostics, such as Verilator's PINMISSING, as failures and connect every required input explicitly; document intentional no-connects separately.

    Likely question: when is .* acceptable? Only when every port name already matches a signal of the same width and intent, as the testbench below proves by comparing both forms cycle by cycle.

    Check yourself A new enable input is added mid-list. Do named connections guarantee every instance is updated?

    No. Named connections keep the existing bindings intact, but the new enable may be left dangling. Positional instances also risk shifted bindings or a port-count error. Require missing-port lint failures and explicitly connect the new input at every instance.

    Check yourself A debug tap is useful this week. Why must it still leave the top level?

    A permanent debug port freezes into the interface contract and every future review pays for it. Probe internally and keep the top-level list to production signals.

    Testbench

    The disciplined stage plus a testbench that proves named and wildcard connections agree. The full code sits below.

    stream_stage.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    module stream_stage #(
      parameter int W = 16
    ) (
      input  logic         clk_i,
      input  logic         rst_ni,
      input  logic         valid_i,
      input  logic [W-1:0] data_i,
      output logic         ready_o,
      output logic         valid_o,
      output logic [W-1:0] data_o,
      input  logic         ready_i
    );
      always_ff @(posedge clk_i or negedge rst_ni) begin
        if (!rst_ni) begin
          valid_o <= 1'b0;
          data_o <= '0;
        end else if (ready_i || !valid_o) begin
          valid_o <= valid_i;
          data_o <= data_i;
        end
      end
      assign ready_o = !valid_o || ready_i;
    endmodule
    
    • Group ports by interface; clocks and resets lead. Use _i and _o, and n for active-low: clk_i, rst_ni.

    • Connect by name, and make missing-port lint diagnostics fatal.

    • Use .* only where every name already matches in width and intent.

    Rule of thumb: keep the port list to production signals; probe internally and do not freeze debug ports into the contract.

    How this was checked

    Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. It compares the named and wildcard connections cycle by cycle. Connection lint is a separate check.

    • Interview: run a mock interview on this topic

    Related topics

    • Top-down vs bottom-up integration

    • Parameter propagation across hierarchy

    Previous

    250 / 350

    Next: Parameter propagation across hierarchy

    Up next

    Up nextParameter propagation across hierarchy

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error