top of page

6.2. What are Localparams?

Localparams are similar to parameters but with one critical difference: they cannot be modified during instantiation. They're used for internal constants derived from parameters or for values that should remain fixed within the module.

Naming Convention

​

  • Use UPPERCASE for consistency with parameters

  • Prefix with module-specific identifier if needed for clarity

  • Group related localparams together

 Verilog

// FSM states

localparam IDLE = 3'b000;

localparam ACTIVE = 3'b001;

localparam DONE = 3'b010;

// Derived calculations

localparam ADDR_WIDTH = $clog2(DEPTH);

localparam MAX_COUNT = (1 << COUNTER_WIDTH) - 1;

// Protocol-specific constants

localparam AXI_BURST_INCR = 2'b01;

localparam AXI_BURST_WRAP = 2'b10;

Localparam Declaration

 Verilog

module fifo_controller #(

    parameter DATA_WIDTH = 8,

    parameter DEPTH = 16

)(

    input clk,

    input rst_n,

    input push,

    input pop,

    output full,

    output empty

);

    // Derived localparam - cannot be overridden

    localparam ADDR_WIDTH = $clog2(DEPTH);

    localparam MAX_COUNT = DEPTH;

    

    // FSM state encoding - should never be changed externally

    localparam IDLE   = 3'b001;

    localparam WRITE  = 3'b010;

    localparam READ   = 3'b100;

    

    // Internal implementation

    reg [ADDR_WIDTH-1:0] write_ptr;

    reg [ADDR_WIDTH-1:0] read_ptr;

    reg [2:0] state;

    

endmodule

Key Characteristics:

​

  • Cannot be overridden during instantiation

  • Perfect for derived values and internal constants

  • Protects critical design parameters from accidental modification

  • Improves code maintainability and safety

​

Use Localparams when:

​

  • Defining constants derived from parameters

  • Declaring FSM states or control values

  • Protecting internal constants from external modification

  • Improving code readability with named constants

6.2.1. Why Localparams Are Essential

6.2.1.1. Design Integrity:

Localparams protect critical internal constants from accidental modification. For example, FSM state encodings should never be overridden externally as it would break the entire state machine logic.

6.2.1.2. Derived Values:

When constants are mathematically derived from parameters, using localparam ensures consistency:

 Verilog

module cache_memory #(

    parameter CACHE_SIZE = 1024,  // in bytes

    parameter LINE_SIZE = 64      // in bytes

)(

    // ports

);

    localparam NUM_LINES = CACHE_SIZE / LINE_SIZE;  // Always consistent

    localparam INDEX_BITS = $clog2(NUM_LINES);

    localparam OFFSET_BITS = $clog2(LINE_SIZE);

    

    // If NUM_LINES was a parameter, someone could set it inconsistently

endmodule

6.2.1.3. Code Readability:

Named constants improve code clarity compared to magic numbers:

 Verilog

// Poor practice

if (status == 3'b101) begin

    // What does 3'b101 mean?

end

// Good practice

localparam ERROR_STATE = 3'b101;

if (status == ERROR_STATE) begin

    // Clear intent

end

Example: Parameterized AXI Interface Width Converter

 Verilog

module axi_width_converter #(

    parameter S_DATA_WIDTH = 32,    // Slave interface width

    parameter M_DATA_WIDTH = 64,    // Master interface width

    parameter ADDR_WIDTH = 32,

    parameter ID_WIDTH = 4

)(

    input wire aclk,

    input wire aresetn,

    // Slave interface

    input wire [ID_WIDTH-1:0] s_awid,

    input wire [ADDR_WIDTH-1:0] s_awaddr,

    input wire [7:0] s_awlen,

    input wire [2:0] s_awsize,

    input wire s_awvalid,

    output wire s_awready,

    input wire [S_DATA_WIDTH-1:0] s_wdata,

    input wire [S_DATA_WIDTH/8-1:0] s_wstrb,

    input wire s_wlast,

    input wire s_wvalid,

    output wire s_wready,

    // Master interface

    output wire [ID_WIDTH-1:0] m_awid,

    output wire [ADDR_WIDTH-1:0] m_awaddr,

    output wire [7:0] m_awlen,

    output wire [2:0] m_awsize,

    output wire m_awvalid,

    input wire m_awready,

    output wire [M_DATA_WIDTH-1:0] m_wdata,

    output wire [M_DATA_WIDTH/8-1:0] m_wstrb,

    output wire m_wlast,

    output wire m_wvalid,

    input wire m_wready

);

    // Localparams for derived values and internal constants

    localparam S_STRB_WIDTH = S_DATA_WIDTH / 8;

    localparam M_STRB_WIDTH = M_DATA_WIDTH / 8;

    localparam RATIO = M_DATA_WIDTH / S_DATA_WIDTH;  // Upsizing ratio

    localparam RATIO_WIDTH = $clog2(RATIO);

    

    // Verify configuration validity at compile time

    localparam CONFIG_VALID = (M_DATA_WIDTH >= S_DATA_WIDTH) && 

                              (M_DATA_WIDTH % S_DATA_WIDTH == 0) &&

                              (RATIO <= 16);

    // State machine states for write data accumulation

    localparam IDLE = 2'b00;

    localparam ACCUMULATE = 2'b01;

    localparam TRANSFER = 2'b10;

    // Internal registers

    reg [1:0] state;

    reg [M_DATA_WIDTH-1:0] data_accumulator;

    reg [M_STRB_WIDTH-1:0] strb_accumulator;

    reg [RATIO_WIDTH-1:0] beat_counter;

    // Implementation would handle data width conversion

endmodule

Example: Memory Controller with Timing Parameters

 Verilog

  // Convert timing parameters from nanoseconds to clock cycles

    // These should be localparams as they're derived from parameters

    localparam tRCD_CYCLES = $rtoi($ceil(tRCD * 1000 / CLOCK_PERIOD_PS));

    localparam tRP_CYCLES = $rtoi($ceil(tRP * 1000 / CLOCK_PERIOD_PS));

    localparam tRAS_CYCLES = $rtoi($ceil(tRAS * 1000 / CLOCK_PERIOD_PS));

    localparam tRC_CYCLES = $rtoi($ceil(tRC * 1000 / CLOCK_PERIOD_PS));

    localparam tRFC_CYCLES = $rtoi($ceil(tRFC * 1000 / CLOCK_PERIOD_PS));

    localparam tWR_CYCLES = $rtoi($ceil(tWR * 1000 / CLOCK_PERIOD_PS));

    localparam tRTP_CYCLES = $rtoi($ceil(tRTP * 1000 / CLOCK_PERIOD_PS));

    // Maximum counter width needed

    localparam COUNTER_WIDTH = $clog2(tRFC_CYCLES + 1);

    // Command encoding

    localparam CMD_NOP = 3'b111;

    localparam CMD_ACTIVE = 3'b011;

    localparam CMD_READ = 3'b101;

    localparam CMD_WRITE = 3'b100;

    localparam CMD_PRECHARGE = 3'b010;

    localparam CMD_REFRESH = 3'b001;

    // Controller states

    localparam ST_IDLE = 4'h0;

    localparam ST_ACTIVATE = 4'h1;

    localparam ST_READ = 4'h2;

    localparam ST_WRITE = 4'h3;

    localparam ST_PRECHARGE = 4'h4;

    localparam ST_REFRESH = 4'h5;

Parameter

Compiler Directives

© Copyright 2025 VLSI Mentor. All Rights Reserved.©

Connect with us

  • Instagram
  • Facebook
  • Twitter
  • LinkedIn
  • YouTube
bottom of page