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:
clear | enable | Next value |
|---|---|---|
True | any | 0 |
False | True | q + 1, wrapping from 15 to 0 |
False | False | q (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
valueis 0 right after reset.step(True, _)makes the nextvalue0 regardless ofenableand 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, leavevalueunchanged.- 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.