How to Create Parameterized Module in Verilog: Syntax and Example
In Verilog, you create a
parameterized module by declaring parameter inside the module header or body, allowing you to customize values like bit widths. You can override these parameters when instantiating the module using the #() syntax to pass different values.Syntax
A parameterized module in Verilog uses the parameter keyword to define constants that can be changed during module instantiation. Parameters are typically declared inside the module header or body. When instantiating, you override parameters using #(value) before the instance name.
- parameter: Defines a constant value inside the module.
- #(): Used to pass new parameter values during instantiation.
- module name: The module identifier.
- instance name: The name of the module instance.
verilog
module my_module #(parameter WIDTH = 8) (input [WIDTH-1:0] in, output [WIDTH-1:0] out); assign out = in; endmodule // Instantiation with default parameter my_module instance1 (.in(data_in), .out(data_out)); // Instantiation with overridden parameter my_module #(16) instance2 (.in(data_in_16), .out(data_out_16));
Example
This example shows a parameterized module adder that adds two inputs of configurable bit width. The parameter WIDTH sets the input and output size. We instantiate it twice: once with the default width 8, and once with width 16.
verilog
module adder #(parameter WIDTH = 8) ( input [WIDTH-1:0] a, input [WIDTH-1:0] b, output [WIDTH-1:0] sum ); assign sum = a + b; endmodule module testbench; reg [7:0] a8 = 8'd15; reg [7:0] b8 = 8'd10; wire [7:0] sum8; reg [15:0] a16 = 16'd1000; reg [15:0] b16 = 16'd2000; wire [15:0] sum16; // Instance with default WIDTH=8 adder adder8 (.a(a8), .b(b8), .sum(sum8)); // Instance with WIDTH=16 adder #(16) adder16 (.a(a16), .b(b16), .sum(sum16)); initial begin #1; $display("8-bit sum: %d + %d = %d", a8, b8, sum8); $display("16-bit sum: %d + %d = %d", a16, b16, sum16); end endmodule
Output
8-bit sum: 15 + 10 = 25
16-bit sum: 1000 + 2000 = 3000
Common Pitfalls
Common mistakes when using parameterized modules include:
- Forgetting to use
#()when overriding parameters during instantiation, which causes the default value to be used. - Using parameters inside the module before they are declared or initialized.
- Confusing
parameterwithlocalparam(localparam cannot be overridden). - Not matching the parameter width with input/output port widths, causing synthesis or simulation errors.
verilog
/* Wrong: overriding parameter without #() */ module wrong #(parameter WIDTH = 8) (input [WIDTH-1:0] in, output [WIDTH-1:0] out); assign out = in; endmodule // Incorrect instantiation - parameter override ignored wrong instance_wrong (.in(data), .out(data_out)); // WIDTH stays 8 /* Correct: use #() to override */ wrong #(16) instance_right (.in(data16), .out(data_out16));
Quick Reference
Remember these tips when working with parameterized modules:
- Declare parameters with
parameterkeyword inside the module. - Override parameters during instantiation using
#(value)syntax. - Use parameters to set widths or constants for flexible modules.
- Do not confuse
parameterwithlocalparam.
Key Takeaways
Use the parameter keyword inside modules to create customizable constants.
Override parameters during instantiation with #(new_value) syntax.
Parameters help make modules flexible for different bit widths or settings.
Always match parameter values with port widths to avoid errors.
localparam cannot be overridden, unlike parameter.