Skip to content
code0.HDL

24Verification

Size the counter for its limit

Problem

Intended behavior. WrapCounter(cfg) counts 0, 1, ..., cfg.limit on cycles where en is high, then wraps to 0. atLimit is 1 exactly while the count equals the limit. WrapConfig holds the limit and derives the register width from it, so every user of the configuration agrees on that width. CounterBank builds three counters with limits 5, 8, and 16 that share one en.

Observed behavior. The starter compiles and the 5-limit counter behaves, but the other two never reach their limits.

Task. Find the faulty parameter derivation and correct it. Keep the case class, its require, WrapCounter, and CounterBank as they are otherwise.

Run and compare

Run the starter. The public run holds en high and prints the three counts and atLimit flags for eleven cycles. Mark the first cycle at which the 8-limit counter departs from the specification and what it does instead. The 16-limit counter needs more cycles than the run prints to show its symptom; predict what it would do at that point.

Diagnose

Every width in WrapCounter comes from cfg.width. For each of the three limits, compute that width by hand and the largest value a register of that width can hold. Compare the largest value with the value the counter must reach. Ask why limit 5 hides the problem while limits 8 and 16 expose it.

Fix, run, and explain

Correct the derivation and run again. The 8-limit counter must now show 8 with its atLimit flag, then 0 on the next line. The 16-limit counter still cannot reach its limit within eleven cycles, so the public run cannot prove that part of the fix. Explain from your width table why it now works.

Completion check

  • Each counter reaches its own limit, reports atLimit there, and wraps to 0 on the next enabled cycle.
  • Counters hold their values while en is low.
  • Reset returns all three to 0.
  • Derive the width from the configuration rather than choosing a fixed width that happens to fit the three supplied limits.

For additional configurations, keep limit positive and limit + 1 within Scala's Int range. The bank's unchanged 8-bit count outputs must also be able to represent the chosen limits; they are separate from the internal register width.

Progressive hints

Hint 1

The counter must hold limit + 1 distinct values, 0 through limit.

Hint 2

log2Ceil(n) is the number of bits needed to tell n values apart, which means the largest representable value is one less than a power of two. Look at which number is passed in.

Concept

A derived parameter in a case class is computed once and trusted by every module that reads it. An off-by-one there produces a circuit that elaborates cleanly and is wrong only for some configurations: here, limits that are a power of two. The comparison count === cfg.limit.U widens silently, so no width error points at the problem.

Extension experiment

Add a limit of 1 to the bank in your head. Compute the width with the starter's derivation and with yours, and predict what the starter would build for that counter.

Review this concept
Ready

CheerpJ runs Chisel in your browser. A cold Run downloads about 14.5 MB of Java and 47 MB of JARs. Compilation can take a minute. Licenses

Main.scala