# N-bit counter

## What You Will Learn

Parameterized counters are everywhere. Width comes from `` `RTL_COUNTER_N `` in `define.vh` and parameter `W` on module `counter`—change one define and TB, DUT, and waves stay aligned. You will study enable, synchronous load, and reset priority.

## Learning Objectives

- Read priority among reset, load, and enable in one `always` block.
- Connect `` `include "define.vh" `` to default width 8.
- Predict behavior when `load` and `ena` assert together (reset wins, then load).
- Use parameters to reuse the module at different widths.

## Theory

The counter is a loadable up-counter: on each clock, if not in reset, `load` takes `din`, else if `ena` increments `q`. This if-else-if chain encodes priority—load overrides counting. Parameter `W` defaults to `` `RTL_COUNTER_N `` so synthesis and simulation share one knob.

Headers with `` `define `` are compile-time constants—unlike `parameter`, they cannot be overridden per instance without recompilation, which is often what you want for global datapath width.

## When to use this pattern

Counters timestamp events, generate addresses, and drive baud dividers. Loadable counters implement program interval timers and DMA byte counts.

## Files

| File | Role |
|------|------|
| `rtl/define.vh` | Header / `define`s |
| `tb/tb_counter.v` | Testbench — **`tb_counter`** |
| `rtl/counter.v` | RTL / DUT — **`counter`** |

## Practice Architecture

```mermaid
flowchart TB
  tb[tb_counter] -->|clk rst_n ena load din| dut[counter]
  dut -->|q| tb
```

## What to explore

- Change `` `RTL_COUNTER_N `` to 12 in `define.vh` and re-run sim and synth.
- Waveform: pulse `load` with a nonzero `din` and verify `q` snaps.
- Hold `ena` high for several cycles and watch binary `q`.
- Discuss what happens if `ena` and `load` are both high after reset.
- Compare `parameter W` vs `` `define `` for configurability.

## Summary

The N-bit counter combines parameters, include-file constants, and prioritized clocked updates—patterns you will reuse in timers, PCs, and scoreboards.

# Appendix (Code Review)

This section is an optional deep dive into the example source files. Line numbers refer to the copies in your workspace under `rtl/` and `tb/`.

## rtl/counter.v

**Purpose:** Parameterized loadable up-counter (`counter`).

Lines 8–27 — Module `counter`

```verilog
`include "define.vh"
// N-bit loadable up-counter (N = `RTL_COUNTER_N in define.vh), synchronous active-low reset
module counter #(
  parameter W = `RTL_COUNTER_N
) (
  input wire clk,
  input wire rst_n,
  input wire ena,
  input wire load,
  input wire [W-1:0] din,
  output reg [W-1:0] q
);
  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      q <= 0;
    end else if (load) begin
      q <= din;
    end else if (ena) begin
      q <= q + 1'b1;
    end
  end
endmodule
```

**Code review:** Parameter: `W` defaults to `` `RTL_COUNTER_N `` from `define.vh`. Ports: `clk`, `rst_n`, `ena`, `load`, `din[W-1:0]`, `q[W-1:0]`. Priority: `!rst_n` → clear; else `load` → `din`; else `ena` → increment. Single always: One clocked block—no latch risk.

## tb/tb_counter.v

**Purpose:** Testbench `tb_counter` — elaborates `DUT` and captures waves under `sim/`.

Lines 8–45 — Module `tb_counter`

```verilog
`timescale 1ns/1ps
`include "define.vh"
module tb_counter;
  localparam integer N = `RTL_COUNTER_N;
  reg clk, rst_n, ena, load;
  reg [N-1:0] din, q;

  counter #(.W(N)) u_cnt (
    .clk(clk),
    .rst_n(rst_n),
    .ena(ena),
    .load(load),
    .din(din),
    .q(q)
  );

  initial clk = 0;
  always #5 clk = ~clk;

  initial begin
    $dumpfile("sim/dump.vcd");
    $dumpvars(0, tb_counter);
    rst_n = 0;
    ena = 0;
    load = 0;
    din = 0;
    #30 rst_n = 1;
    load = 1;
    din = ~0;
    @(posedge clk);
    load = 0;
    repeat (5) begin
      ena = 1;
      @(posedge clk);
    end
    ena = 0;
    $display("PASS tb_counter (N=%0d, q=%0h after stimulus)", N, q);
    #100 $finish;
  end
endmodule
```

**Code review:** `tb_counter` instantiates `DUT`. Look for `$dumpfile` / `$dumpvars` in an `initial` block and any loops or `$display` checks that report PASS/FAIL.

---

© 2026 RtlStudio. Licensed under [CC BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/). Commercial use and modifications by third parties are not permitted.

© 2026 RtlStudio. All rights reserved. RTL Studio is proprietary software.