Tutorials

Learn More

Modules and Ports in Verilog

Modules

A Module is a basic building design block in Verilog and it can be an element that implements necessary functionality. It can also be a collection of lower-level design blocks. As a part of defining a module, it has a module name, port interface, and parameters (optional). The port interface i.e. inputs and outputs is used to connect the high-level module with the lower one and hides internal implementation. 

Declaration

The module is declared using a keyword ‘module’ with an optional port list and followed by its implementation. In the end, it is enclosed with the keyword ‘endmodule’.

module <module_name> (<port_list>);
  ...
  <implementation>
  ...
endmodule

A module consists of variable declaration, dataflow statements, behavioral blocks, instantiation of lower hierarchical modules, tasks, and functions. All of these are optional depending on the requirement statements or blocks that can be used, but module, endmodule, and module name are mandatory. It is not allowed to have nested modules; instead, it allows instantiating sub-module to have the module connections.

// This is illegal to write
module dut_1;
  ...
  module dut_2;
  ...
  endmodule
endmodule

Ports

An interface to communicate with other modules or a testbench environment is called a port. In simple words, the input/ output pins of digital design are known as ports. This interface is termed a port interface or port list. Since the port list is available for connection, internal design implementation can be hidden from other modules or an environment.

Verilog keywords used for port declaration are as follows:

Port Type

Keywords used

Description

Input port

input

To receive signal values from another module

Output port

output

To send signal values to another module

Bidirectional port

inout

To send or receive signal values to another module.

Verilog ports

Ports in Verilog

Example:

module mod(input a, b, output y);
...
endmodule

Note: 

  1. Ports are of wire data type by default.
  2. If output ports hold their value, then they must be declared as reg data type.
  3. The input and inout ports can not be reg as they can not store values. Input ports pass signals from externally connected signals.

Connection rules in Verilog port

While writing a module, the designer needs to make sure what type of signals have to be connected to the module’s inputs and outputs and follow the below rules.

For understanding port connecting rules, consider the current design module as an internal world and outside of the module to be an external world.

Port type

External world

Internal world

Description

input

reg or net

net

In an internal world, the input port must be of the net type and it can be connected to reg or net type variable in an external world.

output

net

reg or net

In an internal world, the output port can be of reg or net type and it must be connected to the net type variable in an external world.

inout

net

net

In an internal world, the inout port must be of the net type and it must be connected to the net type variable in an external world.

Module instantiation

While designing complex digital circuits, usually it is split into various modules that connect to have a top-level block. Thus, Verilog supports a hierarchical design methodology. When a module is instantiated, a unique object is created and it has a unique name. Similarly, a top-level design can also be instantiated while creating a testbench.

module dut_1(<port_list>);
  ...
endmodule

module dut_2(<port_list>);
  ...
endmodule

module dut_3(<port_list>);
  dut_2 d2(...);
  ...
endmodule

// Top level module
module dut_top(<port_list>);
  dut_1 d1(...);
  dut_3 d3(...);
endmodule

 Following the hierarchical approach, a particular signal can be reached out following hierarchy and each identifier is separated using a dot.

// Hierarchical connections
dut_top.d3.d2.<signal>  // To track a signal in dut_2 module.

A mechanism for connecting the port to the external signals

When a module is instantiated in the top-level hierarchy or top-level design in a testbench, any one of the following methods can be used.

Method A: Connecting a port list in an ordered manner

An ordered manner connection is feasible when a port list has minimum signals as the user has to follow the same order in which design level signals are declared.

Design declaration:

module mux_2_1(
  input sel,
  input i0, i1,
  output y);

Design instantiation in testbench:

module mux_tb;
  reg in0, in1, select;
  wire out;
  
  mux_2_1 mux(select, in0, in1, out);
        ...
endmodule

Observe that the port list in design mux_2_1 and its instantiation in testbench mux_tb follow the same order.

module mux_2_1(input sel, input i0, i1, output y); // At design 
mux_2_1 mux(select, in0, in1, out); // At testbench

Note: It is not mandatory to use different names at the design and testbench level.

module mux_2_1(input sel, input i0, i1, output y); // At design 
mux_2_1 mux(sel, i0, i1, y); // At testbench

Method B: Connecting a port list by name

For complex designs having more ports, remembering and writing in the same order while instantiating the design is error-prone. In this method, the order of port list connection does not matter based on the port name, the connection is established.

For an above example,

module mux_2_1(input sel, input i0, i1, output y); // At design 
mux_2_1 mux(.i0(in0), .sel(select), .y(out), .i1(in1)); // At testbench