Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutRoadmapCareersInternshipsFAQContactPrivacyTerms
Skip to lesson

Course contents

  • RTL Foundations36
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
    • Parameterization and Generate Hub
      • Parameters vs localparams
      • Generate loops and conditionals
      • Avoid defparam overrides
    • Top-Level Integration Hub
    • Synthesis Intent Hub
    • Style and Static Checks Hub
    • Assertions in RTL Hub
    • Formal Verification Basics Hub
    • Reusable SystemVerilog for RTL
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

←Parameterization and Generate Hub
  1. Topics
  2. RTL Design
  3. Advanced RTL
  4. Parameterization and Generate Hub
  5. Avoid defparam overrides
On this page

    Part 8 of 9, lesson 3 of 28Part 8 of 9/Advanced/Lesson 3 of 28Advanced

    Avoid defparam overrides

    Override parameters by name at the instantiation site; defparam is banned.

    A defparam can retarget a parameter deep in the hierarchy from a file far from the instance, so a review of the instantiation never sees it. Positional overrides break the same way when a parameter is inserted.

    After this lesson you can: override parameters by name at the instantiation, pass them down each level, and show that each override took effect.

    Named overrides at the instantiation

    A named override sets parameters where the instance is built. Names keep order irrelevant and review local.

    Pass the same constants down each level of hierarchy. The testbench below wires two identical fifos and one wide fifo from shared localparams.

    Why defparam is banned

    defparam assigns a parameter by hierarchical path, after instantiation. It can retarget deep hierarchy far from the instance site.

    The value hides from the instantiation, so review misses it. This course bans it:

    design.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // snippet
    // Avoid: the value hides far from the instance it changes.
    // defparam u_a.DEPTH = 64;
    
    // Preferred: named override at the instantiation site.
    fifo #(.DEPTH(8), .WIDTH(8)) u_a (
      .clk(clk), .rst_n(rst_n), .wr(wr_a), .rd(rd_a),
      .din(din_a), .dout(dout_a), .full(full_a), .empty(empty_a)
    );

    Common mistakes

    Overriding with positional values, or with a defparam tucked in another file. Both hide intent: a later parameter-list edit silently remaps positional values, and a distant defparam never appears at the instance.

    Likely question: two instances need different depths. How do you show each override worked?

    • Fill each to full: full must assert after exactly DEPTH accepted writes.

    • Log the config: print each depth at time zero from the same constants as the overrides.

    • Compare twins: identical overrides with identical stimulus must produce identical outputs.

    Check yourself u_a has DEPTH 8. After how many writes must full assert, and what evidence checks its data bits?

    After exactly 8 accepted writes. A0..A7 checks only those words: bit 3 never goes high. The additional walking-one and walking-zero round trips drive each configured bit both ways; this is finite digital sensitivity evidence, not proof for all histories or exact resource mapping.

    Check yourself A defparam in another file changes DEPTH. Why is the bug hard to find?

    No instantiation site shows the value. The search must cover the whole hierarchy instead of one line.

    Testbench

    A small parameterizable fifo, two identical instances for equivalence, one wide instance, and a fill-and-drain testbench.

    fifo.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    module fifo #(
      parameter int DEPTH = 16,
      parameter int WIDTH = 8
    ) (
      input  logic             clk,
      input  logic             rst_n,
      input  logic             wr,
      input  logic             rd,
      input  logic [WIDTH-1:0] din,
      output logic [WIDTH-1:0] dout,
      output logic             full,
      output logic             empty
    );
      // Derived widths stay local: only DEPTH and WIDTH are overridable.
      localparam int AW = (DEPTH > 1) ? $clog2(DEPTH) : 1;
      localparam int CW = $clog2(DEPTH + 1);
      logic [WIDTH-1:0] mem [DEPTH];
      logic [AW-1:0] wptr, rptr;
      logic [CW-1:0] count;
    
      assign empty = (count == 0);
      assign full = (count == DEPTH);
      assign dout = mem[rptr];
    
      always_ff @(posedge clk) begin
        if (!rst_n) begin
          wptr <= '0;
          rptr <= '0;
          count <= '0;
        end else begin
          if (wr && !full) begin
            mem[wptr] <= din;
            wptr <= (wptr == (DEPTH - 1)) ? '0 : (wptr + 1'b1);
          end
          if (rd && !empty) begin
            rptr <= (rptr == (DEPTH - 1)) ? '0 : (rptr + 1'b1);
          end
          case ({wr && !full, rd && !empty})
            2'b10:   count <= count + 1'b1;
            2'b01:   count <= count - 1'b1;
            default: count <= count;
          endcase
        end
      end
    endmodule
    
    • Named overrides keep order irrelevant and keep the value at the instance.

    • defparam sets a value by hierarchical path after instantiation, so the instance site hides it. This course bans it.

    • Prove an override with behaviour: fill each instance and check that full rises after exactly DEPTH writes.

    Rule of thumb: if the value is not visible at the instantiation, a reviewer will not find it.

    How this was checked

    Testbench run with Icarus Verilog 13.0 (2026-10-16): prints PASS. The walking-one and walking-zero round trips are finite digital sensitivity checks, not proof for all histories or for exact resource mapping.

    • Interview: run a mock interview on this topic

    Related topics

    • Parameters vs localparams

    • Generate loops and conditionals

    Previous

    248 / 350

    Next: Top-Level Integration Hub

    Up next

    Up nextTop-Level Integration Hub

    Sign in to save progress

    Practice this lessonPrevious lessonReport an error

    See also

    • Parameters vs localparams