Prev Problem
Next Problem

31. Parameterized LED Blinker

module led_blinker #(
  parameter integer COUNTER_WIDTH = 2,
  parameter integer TOGGLE_EVERY  = 3
)(
  input  wire clk,
  input  wire rst,
  output reg  led
);
  reg [COUNTER_WIDTH-1:0] cnt;

  always @(posedge clk) begin
    if (rst) begin
      led <= 1'b0;
      cnt <= {COUNTER_WIDTH{1'b0}};
    end else begin
      if (cnt == TOGGLE_EVERY-1) begin
        led <= ~led;
        cnt <= {COUNTER_WIDTH{1'b0}};
      end else begin
        cnt <= cnt + {{(COUNTER_WIDTH-1){1'b0}},1'b1};
      end
    end
  end
endmodule

💡 Remember

  • Parameters are compile-time constants. Override per instance: led_blinker #(.TOGGLE_EVERY(100), .COUNTER_WIDTH(7)) u0 (...);
  • Pick COUNTER_WIDTH large enough so 2^COUNTER_WIDTH ≥ TOGGLE_EVERY.
  • Separating what changes (TOGGLE_EVERY) from how stored (COUNTER_WIDTH) makes the module reusable across boards/clocks with no RTL edits.
  • A smaller TOGGLE_EVERY is perfect for short simulations; a larger value gives a slower real-hardware blink without changing the code.
  • The concatenation {{(COUNTER_WIDTH-1){1'b0}}, 1'b1} builds a constant that is exactly the same width as cnt and is definitely unsigned. No implicit extension, no truncation.