Skip to content
code0.HDL

16Implementation

Counter with clear and enable

Problem

mkClearEnableCounter keeps a 4-bit state q and reports it through value. The caller drives it through one Action method, step(clear, enable), at most once per cycle. The arguments decide the value seen on the next cycle:

clearenableNext value
Trueany0
FalseTrueq + 1, wrapping from 15 to 0
FalseFalseq (hold)

A cycle in which step is not called also holds q. The register starts at 0 through mkReg(0). That is the module reset, which the environment applies once at start-up; clear is a functional input the caller may raise at any time, and it has to work without a reset.

The earlier Count with one rule exercise built a counter that counts on its own and stops at five. This counter has a different contract: it counts only when told to, never stops on its own, and wraps.

Edit only the two TODO bodies inside mkClearEnableCounter. Keep the interface, the register declaration, and mkTop unchanged.

Read and predict

mkTop prints value and then calls step once per cycle for ten cycles. Read the clear and enable expressions in drive and fill in a table of the ten printed values before running. The starter returns ? from value and never writes q, so predict that every line shows the same arbitrary number; run once to confirm.

Implementation path

value returns the register. step writes the register at most once: decide clear first, then enable, and write nothing in the remaining case. <= schedules the write, so the current cycle still prints the old state and the next cycle shows the new one. The repaired design should show 0 on the cycle after a clear, one more per enabled cycle, and an unchanged value wherever neither argument is set.

Completion contract

  • value is 0 right after reset.
  • step(True, _) makes the next value 0 regardless of enable and of the current state, including in the middle of a count.
  • step(False, True) increments by exactly one, and 15 is followed by 0.
  • step(False, False), and a cycle without any call, leave value unchanged.
  • Counting restarts from 0 after a clear.
  • The interface and the Bit#(4) width are unchanged.

Progressive hints

Hint 1

Two of the three table rows write the register and one does not. An if inside an Action method may leave its remaining branch empty; no write means the register keeps its value.

Hint 2

Order the conditions so that clear is tested before enable. Testing enable first lets a clear raised in the same cycle be ignored.

Hint 3

4-bit arithmetic already wraps: adding one to 4'd15 gives 4'd0. A comparison against 15 is not needed, and one that stops the count breaks the contract.

Transfer experiment

Change q and value to Bit#(3) together and rerun the public driver to check clear priority and holding. This driver clears the count before it reaches 7, so it does not demonstrate wraparound. In scratch code, apply eight consecutive step(False, True) calls from state 0 and predict the state after each call. The count should wrap after 7 instead of 15 with no change to step. Restore Bit#(4) before submitting.

Review this concept
Ready
Main.bsv