Tuesday, November 4, 2025

thumbnail

Parameterized Modules in Verilog

 ðŸ§© What Are Parameterized Modules?


A parameterized module in Verilog is a module that uses parameters to make certain values (like bus width, delay, or size) configurable when you instantiate it.


This helps you reuse the same module for different configurations without rewriting code.


🧠 Why Use Parameters?


✅ To make designs scalable (e.g., same adder for 4-bit, 8-bit, or 16-bit).

✅ To improve code reusability.

✅ To make designs easier to maintain and modify.

✅ To avoid hardcoding constants.


⚙️ Syntax of a Parameterized Module

module module_name #(parameter PARAM_NAME = value) (port_list);

  // Module body

endmodule


Example:

module adder #(parameter N = 4) (

  input  [N-1:0] A, B,

  output [N-1:0] SUM

);

  assign SUM = A + B;

endmodule



Here:


N is a parameter that defines the bit-width.


Default value is 4.


You can change N when you instantiate the module.


🧾 Instantiating a Parameterized Module

Default instantiation (uses N=4)

adder a1 (.A(A), .B(B), .SUM(SUM));


Custom parameter value (override N)

adder #(8) a2 (.A(A), .B(B), .SUM(SUM));  // 8-bit adder



or named parameter style:


adder #(.N(16)) a3 (.A(A), .B(B), .SUM(SUM));  // 16-bit adder


🧰 Multiple Parameters Example

module counter #(parameter WIDTH = 8, parameter MAX = 255) (

  input clk,

  input reset,

  output reg [WIDTH-1:0] count

);

  always @(posedge clk or posedge reset) begin

    if (reset)

      count <= 0;

    else if (count == MAX)

      count <= 0;

    else

      count <= count + 1;

  end

endmodule


Instantiation examples

counter #(4, 9) c1 (clk, reset, count4);       // 4-bit counter up to 9

counter #(.WIDTH(10), .MAX(1023)) c2 (clk, reset, count10); // 10-bit counter


🧮 Example: Parameterized Multiplexer

module mux #(parameter WIDTH = 8) (

  input  [WIDTH-1:0] in0, in1,

  input  sel,

  output [WIDTH-1:0] out

);

  assign out = sel ? in1 : in0;

endmodule


Instantiation:

mux #(16) m1 (.in0(a16), .in1(b16), .sel(sel), .out(y16)); // 16-bit MUX


⚖️ Key Points to Remember

Concept Description

Parameter Constant value that can be changed during instantiation

Default value Used if no override is provided

Override styles Positional (#(value)) or named (#(.NAME(value)))

Compile-time constant Parameters are evaluated at compile time, not runtime

Reusability Makes modules more flexible and portable

🧠 Bonus: Local Parameters


You can also define local parameters inside a module using localparam.

These cannot be overridden from outside — they are fixed constants used internally.


localparam HALF = WIDTH / 2;


🚀 Summary

Feature Parameter Localparam

Can be changed at instantiation ✅ Yes ❌ No

Used for internal constants ⚠️ Sometimes ✅ Commonly

Declared using parameter localparam

✅ Example Summary

module shift_reg #(parameter WIDTH = 8, parameter DEPTH = 4) (

  input clk, reset, shift_en,

  input [WIDTH-1:0] data_in,

  output reg [WIDTH-1:0] data_out

);

  reg [WIDTH-1:0] shift_reg [0:DEPTH-1];


  integer i;

  always @(posedge clk or posedge reset) begin

    if (reset)

      for (i=0; i<DEPTH; i=i+1)

        shift_reg[i] <= 0;

    else if (shift_en) begin

      shift_reg[0] <= data_in;

      for (i=1; i<DEPTH; i=i+1)

        shift_reg[i] <= shift_reg[i-1];

    end

    data_out <= shift_reg[DEPTH-1];

  end

endmodule



This same module can become a 4-bit × 4-stage or 16-bit × 8-stage shift register by changing parameters.

Learn VLSI Training in Hyderabad

Read More

Testbenches in Verilog

Writing a 4-bit Adder in Verilog

First Verilog Code: Hello World

Writing FSMs in Verilog

Visit Our Training Institute in Hyderabad

Get Directions

Subscribe by Email

Follow Updates Articles from This Blog via Email

No Comments

About

Search This Blog

Powered by Blogger.

Blog Archive