Verilog Ports

Ports are the interface between a module and the outside world. Understanding port declarations and connections is essential for hierarchical design.

Port Directions

Verilog has three port directions:

Direction Description Use Case
input Signal enters the module Clock, data inputs, control signals
output Signal exits the module Data outputs, status flags
inout Bidirectional signal Buses, I2C data line
Port Declaration Styles
// ANSI-style (Verilog-2001, recommended)
module alu (
    input  wire [7:0]  a,
    input  wire [7:0]  b,
    input  wire [1:0]  op,
    output reg  [7:0]  result,
    output wire        zero
);
    // Module body
endmodule
// Non-ANSI style (legacy Verilog-1995)
module alu (a, b, op, result, zero);
    input  [7:0] a;
    input  [7:0] b;
    input  [1:0] op;
    output [7:0] result;
    output       zero;
    reg [7:0] result;
    // Module body
endmodule

Best Practice

Always use ANSI-style port declarations (Verilog-2001). They're cleaner, less error-prone, and universally supported by modern tools.

Input Ports

Input ports are always of type wire (implicitly or explicitly):

Input Port Examples
module receiver (
    input wire        clk,           // Single-bit input
    input wire        rst_n,         // Active-low reset
    input wire [31:0] data_in,       // 32-bit bus
    input wire [3:0]  byte_enable,   // 4-bit control signal
    input             valid          // 'wire' is implicit
);
    // Inputs can only be read, never assigned
endmodule

Output Ports

Outputs can be wire or reg depending on how they're driven:

Output Port Examples
module transmitter (
    input  wire        clk,
    input  wire        rst_n,
    input  wire [7:0]  data_in,
    output wire [7:0]  combo_out,    // Driven by assign
    output reg  [7:0]  seq_out,      // Driven by always block
    output reg         valid         // Single-bit sequential
);
    // Wire output: use assign
    assign combo_out = data_in ^ 8'hFF;
    // Reg output: use always block
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            seq_out <= 8'd0;
            valid   <= 1'b0;
        end else begin
            seq_out <= data_in;
            valid   <= 1'b1;
        end
    end
endmodule

Bidirectional Ports (inout)

inout ports are used for bidirectional signals like tri-state buses:

Bidirectional Port Example
module bidir_buffer (
    input  wire       clk,
    input  wire       direction,  // 1 = output, 0 = input
    input  wire [7:0] data_out,   // Data to send
    output reg  [7:0] data_in,    // Data received
    inout  wire [7:0] data_bus    // Bidirectional bus
);
    // Drive bus when direction = 1, else high-Z
    assign data_bus = direction ? data_out : 8'bz;
    // Capture incoming data
    always @(posedge clk) begin
        if (!direction)
            data_in <= data_bus;
    end
endmodule

Synthesis Consideration

Bidirectional ports require external tri-state buffers. Only use inout at the top-level chip interface, never for internal module connections.

Common Interview Questions

  1. Can an input port be of type reg?

    No. Inputs must be wire type since they are driven externally.

  2. When should you use inout ports?

    Only for external chip I/O like bidirectional buses (I2C SDA, etc.). Never for internal module connections.

  3. What happens to an unconnected input?

    It becomes high-impedance (Z), which may cause X propagation in simulation.