Close Menu
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
Instagram LinkedIn WhatsApp Telegram
Instagram LinkedIn WhatsApp Telegram
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
VLSI Web
Verilog

Verilog Modules, Ports and Instantiation: Building a Hierarchy

Raju GorlaBy Raju Gorla21 July 2026Updated:11 October 2026No Comments4 Mins Read
Verilog modules, ports and hierarchy
Share
Facebook Twitter LinkedIn Email Telegram WhatsApp

The short answer: A Verilog module is a block of hardware with a name, a list of ports (input, output, inout) and a body. You build bigger designs by instantiating modules inside other modules and connecting their ports with wires, which creates a hierarchy. Use ANSI-style port declarations, connect ports by name (.port(signal)) rather than by position, and use parameters to make modules reusable.

Every Verilog design is built from modules, from a single flip-flop up to a full SoC. This post covers defining a module, declaring its ports, instantiating it and building a hierarchy. It replaces four older posts on module definitions, port declarations, instantiation and hierarchical design.

  1. Defining a module
  2. Ports
  3. Instantiating modules
  4. Hierarchy and hierarchical names
  5. Generate: many instances at once
  6. How I structure modules

Table of Contents

  • Part 1: Defining a module
  • Part 2: Ports
  • Part 3: Instantiating modules
  • Part 4: Hierarchy and hierarchical names
  • Part 5: Generate: many instances at once
  • Part 6: How I structure modules
  • FAQ
    • What is the difference between a module and an instance?
    • Can an output port be a reg?
    • What happens if I leave an input unconnected?
    • Should I connect ports by name or by position?

Part 1: Defining a module

`default_nettype none

module adder #(
  parameter W = 8                 // width, can be overridden
) (
  input  wire [W-1:0] a,
  input  wire [W-1:0] b,
  output wire [W:0]   sum         // one extra bit for the carry
);
  assign sum = a + b;
endmodule

This is the ANSI style from Verilog-2001: direction, type and width all in the port list. The older style lists port names first and declares them again in the body; you’ll still see it in old code, but there’s no reason to write it today.

Part 2: Ports

Direction Meaning Inside the module
input Driven from outside Always a net (wire)
output Driven from inside wire if assigned with assign, reg if assigned in always
inout Bidirectional A net, usually driven with a tri-state: assign pad = oe ? d : 1’bz;

Bidirectional ports are mostly used at chip I/O pads. Inside a chip, use separate input and output signals; internal tri-states are avoided in modern designs.

Part 3: Instantiating modules

A top module instantiating an adder and a register bank, with ports connected by wires
Instances are connected through their ports.
module top (
  input  wire       clk,
  input  wire [7:0] x, y,
  output wire [8:0] out
);
  wire [8:0] s;

  adder #(.W(8)) u_add (      // parameter override, instance name
    .a   (x),
    .b   (y),
    .sum (s)
  );

  dff_bank #(.W(9)) u_reg (
    .clk (clk),
    .d   (s),
    .q   (out)
  );
endmodule
  • Connect by name (.a(x)), not by position (adder u_add (x, y, s);). Positional connections break silently when someone reorders ports.
  • Give every instance a meaningful name. I use a u_ prefix; it appears in every hierarchical path, waveform and timing report.
  • Unconnected ports: leave an output empty with .carry(). Never leave inputs floating; tie them to a constant.
  • Width mismatches between a port and its signal are only warnings in Verilog. Read them; they’re often real bugs.

Part 4: Hierarchy and hierarchical names

Instantiating modules inside modules creates a tree. Every signal has a hierarchical path, such as top.u_add.sum. Testbenches and waveform viewers use these paths, and so do timing and synthesis reports.

You can read a signal deep in the hierarchy from a testbench with its full path ($display("%h", tb.dut.u_add.sum);). That’s fine for debugging, but don’t use hierarchical references in synthesisable RTL; connect through ports instead.

Part 5: Generate: many instances at once

genvar i;
generate
  for (i = 0; i < 4; i = i + 1) begin : g_lane
    adder #(.W(8)) u_add (
      .a   (a[8*i +: 8]),
      .b   (b[8*i +: 8]),
      .sum (sum[9*i +: 9])
    );
  end
endgenerate

Name the generate block (g_lane) so instances get readable paths like g_lane[2].u_add.

Part 6: How I structure modules

  • One module per file, with the file named after the module.
  • Parameters for anything that might change: widths, depths, counts.
  • Inputs and outputs grouped by interface (clock and reset first, then each bus).
  • Register outputs of a block where possible; it makes timing between blocks much easier.
  • A short comment at the top: what the block does and any assumptions about its inputs.

Practise this on VLSI Forge

I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.

RTL Design problems · Daily challenge

Previous in my Verilog series: Verilog operators. Next: Levels of modelling in Verilog.

FAQ

What is the difference between a module and an instance?

A module is the definition, like a class. An instance is one copy of it placed in a design, with its own name and connections.

Can an output port be a reg?

Yes. Declare it as output reg if you assign it in an always block. In SystemVerilog, use output logic.

What happens if I leave an input unconnected?

It floats at z in simulation and can cause x propagation. Synthesis tools may tie it off, but you should always connect inputs explicitly.

Should I connect ports by name or by position?

By name. It’s self-documenting and doesn’t break when the port order changes.

Digital Circuit Design HDL design Verilog modules
Share. Facebook Twitter LinkedIn Email Telegram WhatsApp
Previous ArticleVerilog Operators Explained with Examples
Next Article Levels of Modelling in Verilog: Switch, Gate, Dataflow and Behavioural
Raju Gorla
  • Website

Related Posts

Verilog

Verilog Coding Guidelines for Clean, Synthesisable RTL

3 August 2026
Verilog

Verilog System Tasks: $display, $monitor, $readmemh and More

2 August 2026
Verilog

parameter vs localparam vs `define in Verilog

1 August 2026
Add A Comment
Leave A Reply Cancel Reply

Topics
  • Digital Circuits
  • Informative
  • Interview Questions
  • Physical Design
  • RTL Design
  • STA
  • System Verilog
  • UVM
  • Verilog
Instagram LinkedIn WhatsApp Telegram
  • About
  • Contact
  • Privacy Policy
  • VLSI Forge
  • Courses
  • Feedback
© 2026 VLSI Web

Type above and press Enter to search. Press Esc to cancel.