Menu
Coddy logo textTech

Parameters

Part of the Fundamentals section of Coddy's Verilog journey — lesson 11 of 90.

You can create many copies of the same module and use them in different places — this is called **multiple instances**. Instead of writing the same code again and again, you write it once and reuse it as many times as you need. Each instance is a separate copy of that hardware on the chip.

But what if you need each copy to be different? For example, one 8-bit counter, one 16-bit counter, and one 32-bit counter. Without parameters, you would need to write three separate modules.

Parameters solve this problem.

A parameter is a constant value that you can set when you create an instance. It lets you configure each copy of the module differently.

Declaring Parameters

module counter #(
  parameter WIDTH = 8
)(
  input clk,
  output reg [WIDTH-1:0] count
);
  always @(posedge clk) count <= count + 1;
endmodule

The #(parameter WIDTH = 8) defines a parameter called WIDTH with a default value of 8.

While declaring parameters, we use the # symbol right after the module name and before the port list. The # tells Verilog that what follows is a list of parameters that configure the module. If your module has no parameters, you simply omit # entirely.

Using Parameters

Parameters can be used anywhere a constant is needed:

reg [WIDTH-1:0] data;        // Vector size
count <= count + 1;           // Works with any width
assign out = data[WIDTH-1];   // MSB position

Overriding Parameters

When you use the module, you can change the parameter value:

// Default width (8 bits)
counter u1 (.clk(clk), .reset(reset), .count(count1));

// Override to 16 bits
counter #(.WIDTH(16)) u2 (.clk(clk), .reset(reset), .count(count2));

Multiple Parameters

You can have multiple parameters:

module fifo #(
  parameter DEPTH = 16,
  parameter WIDTH = 8
)(
  input clk, wr_en, rd_en,
  input [WIDTH-1:0] data_in,
  output [WIDTH-1:0] data_out
);
  reg [WIDTH-1:0] memory [0:DEPTH-1];
endmodule

Localparam

A localparam is similar but cannot be overridden from outside:

module example;
  localparam STATE_IDLE = 2'b00;
  localparam STATE_RUN = 2'b01;
  localparam STATE_STOP = 2'b10;
  // These values are fixed inside this module
endmodule

Use localparam for constants that should not change.

challenge icon

Challenge

Add a parameter called WIDTH with a default value of 4.

What to do:

  1. Add a parameter named WIDTH
  2. Set its default value to 4
  3. The parameter goes inside #( ) after the module name

Cheat sheet

Parameters allow configuring module instances differently without rewriting code.

Declaring Parameters

module counter #(
  parameter WIDTH = 8  // default value
)(
  input clk,
  output reg [WIDTH-1:0] count
);
  always @(posedge clk) count <= count + 1;
endmodule

Overriding Parameters at Instantiation

counter u1 (.clk(clk), .count(count1));          // uses default (8)
counter #(.WIDTH(16)) u2 (.clk(clk), .count(count2)); // overridden to 16

Multiple Parameters

module fifo #(
  parameter DEPTH = 16,
  parameter WIDTH = 8
)( ... );

Localparam (non-overridable constant)

localparam STATE_IDLE = 2'b00;
localparam STATE_RUN  = 2'b01;

Use localparam for internal constants that must not be changed from outside the module.

Try it yourself

module counter #(
  // Add parameter WIDTH here with default 4
  
)(
  input clk,
  input reset,
  output reg [WIDTH-1:0] count
);

endmodule
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Fundamentals