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

  • Start Here6
  • SystemVerilog Language Foundations28
    • SystemVerilog Data Types
    • Arrays: Packed, Dynamic, Queues & Associative
    • Procedural Code & Scheduling
    • Operators, Expressions & Width Rules
    • Packages, Typedefs & Compilation
    • Interfaces, Modports & Clocking Blocks
      • Interface Basics
      • Modports
      • Clocking Blocks
      • Interface BFM
  • Object-Oriented SystemVerilog for Verification30
  • Constraint Randomization — Interview-Critical Deep Dive36
  • SystemVerilog Assertions — Interview-Critical Deep Dive40
  • Functional Coverage in SystemVerilog22
  • Testbench Architecture in SystemVerilog23
  • Advanced Language & Integration25
  • Senior & Interview Preparation21
  • Principal-Level Verification28
Loading lesson

‹Interfaces, Modports & Clocking Blocks
  1. Topics
  2. SystemVerilog
  3. SystemVerilog Language Foundations
  4. Interfaces, Modports & Clocking Blocks
  5. Modports

Part 1 · Language Foundations · Intermediate

Modports

Mirror-image direction views for DUT and testbench, and what modports cannot check.

On this page

    Why this matters

    A DUT drove a signal that only the testbench should drive, and the two fought every cycle. A modport turns that mistake into a compile error.

    After this lesson you can: write mirror-image modports for each side of a bus, choose a view in a port, and say what a modport does not check.

    Direction is relative

    A raw interface has no notion of direction: req is just a variable, and both the DUT and the testbench could legally drive it. Direction is the essence of a protocol, so each side needs its own view.

    A modport (“module port”) declares a named directional view of the signals. The same physical net appears as input in one modport and output in another, because direction is always relative to the component looking at the bus.

    Modports add no hardware and no new nets. They are compile-time lenses that let the compiler reject a module driving a signal its view declares as input.

    The next section's listing starts with an interface that declares two opposite views of the same four signals: dut and tb.

    Choose the view in the port

    A module selects its view by qualifying the port type: bus_if.dut. The port-declaration style is preferred, because the module then documents and enforces its own role.

    Once a view is in force, a procedural drive of an input-view signal is a compile error. The wrong-direction bug fails before simulation starts instead of surfacing as a runtime fight.

    The listing declares the interface with both views, a DUT and a driver that each choose their view in the port, and a top that checks one request. Its drives are still raw signals; the clocking lesson upgrades them.

    bus_if.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
    26
    interface bus_if (input logic clk);
      logic        req, gnt;
      logic [31:0] addr;
      logic [63:0] rdata;
    
      // the SAME nets, two opposite views:
      modport dut (
        input  req, addr,      // DUT receives requests
        output gnt, rdata,     // DUT produces grant + read data
        input  clk
      );
      modport tb (
        output req, addr,      // testbench produces requests
        input  gnt, rdata,     // testbench samples responses
        input  clk
      );
    endinterface
    
    // view chosen in the port declaration (preferred)
    module dut (bus_if.dut bus);
      always_ff @(posedge bus.clk) begin
        bus.gnt   <= bus.req;              // OK: gnt is output in the dut view
        bus.rdata <= {32'h0, bus.addr};    // OK: rdata is output too
        // bus.req <= 1'b0;                // COMPILE ERROR: req is input here
      end
    endmodule
    
    Terminal
    PASS: the dut view granted the tb view's request and returned rdata 000000a5

    The commented drive above is the whole check in one line. Uncommented, it is the next block: a deliberately broken illustration.

    Predict first dut_bad below drives bus.req through the dut view, where req is an input. When is the mistake caught: at compile time, while simulating, or never?

    At compile time. The view says req is an input, so the compiler refuses the drive before any simulation starts.

    dut_bad.sv
    1
    2
    3
    4
    5
    // bad-example: req is an input in the dut view, so this drive is illegal
    module dut_bad (bus_if.dut bus);
      always_ff @(posedge bus.clk)
        bus.req <= 1'b0;             // illegal drive through an input view
    endmodule

    Compiled together with the interface above, the build stops here:

    Terminal
    %Error: bad_drive.sv:21:9: Attempt to drive input-only modport: 'req'
                             : ... note: In instance 'dut_bad'
    %Error: Exiting due to 1 error(s)

    Lenses, not locks

    Modports restrict access through the modport only. Code holding the whole interface, or a hierarchical reference such as tb_top.bus.req, bypasses the view entirely.

    Enforcement strength varies across tools for continuous assignments and virtual-interface handles. Treat modports as documentation plus best-effort checking, never as a boundary.

    Modports create no drivers and resolve no contention. Two output views of one logic variable remain a multiple-driver problem.

    A modport can also export a clocking block (modport tb (clocking cb)) or a method (import task read). Both appear in the following lessons.

    Common pitfall

    A modport that lists every signal with a permissive direction compiles everywhere and checks nothing. Keep the DUT and testbench views tight mirrors of each other.

    Interview

    “Can a module bypass its modport?” Yes, through the unqualified interface or a hierarchical reference. The modport checks the lens, not the nets.

    Check yourself The DUT and testbench views of req disagree. Is that a bug?

    No. Direction is relative to the viewer: output in tb, input in dut, one net underneath.

    Check yourself A block reaches tb_top.bus.req directly instead of through its modport. Does the modport stop it?

    No. The modport checks only access through itself. Hierarchical references bypass it.

    Remember

    • A modport is a direction view; it adds no signals and no hardware.

    • Driving an input of your view is a compile error.

    • Hierarchical references and the plain interface bypass the view.

    Rule of thumb: each module declares the view it needs, and no more.

    How this was checked

    Run with Verilator 5.048 (--binary --timing) on 2026-10-18; every bench printed the PASS line shown, with no warnings. Icarus 13 cannot run these benches: it rejects interface ports.

    The error shown is Verilator 5.048's for the bad drive, recorded on 2026-10-18.

    Related topics

    • Next: Clocking Blocks

    Previous

    32 / 259

    Next: Clocking Blocks

    Up next

    Up nextClocking Blocks

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Interface BFM