07Implementation
A counter with clear and enable
1. Required behaviour
clear_enable_counter is a 4-bit counter driven by the rising edge. The state q is observable as
an output, and the functional inputs clear and enable are sampled at the edge. With q[n] the
state just before an edge and q[n+1] the state after it:
| Priority | Inputs sampled at the edge | q[n+1] |
|---|---|---|
| 1 | clear = 1 | 0, whatever enable is |
| 2 | clear = 0, enable = 1 | (q[n] + 1) mod 16; after 15 comes 0 |
| 3 | clear = 0, enable = 0 | q[n], unchanged |
clear is this design's synchronous functional input. There is no separate reset port, and at the
start of simulation q is undefined (x). The initialisation sequence is part of the public
contract: the testbench holds clear = 1 for the first two edges, after which q starts from 0.
Hidden grading starts the same way.
No finished code is given: the starter's always block only keeps q as it is. Keep the ports and
the public testbench below the marker; design the inside of the block.
Note. The BSV track's intro-counter problem has a different contract, stopping at 5. This counter never stops; it wraps every 16.
2. Reading the public testbench
Inputs change on the falling edge, so each rising edge samples settled values. The print runs #1
after the rising edge, so each line's q is the value that edge produced, q[n+1]: the same view as
the AFTER lines of the counter-trace example in the Testbench chapter.
| cycle | event |
|---|---|
| 0, 1 | clear = 1: initialisation |
| 2 | clear = 0, enable = 1: counting starts |
| 6 | enable = 0: hold |
| 8 | enable = 1: counting resumes |
| 10 | clear = 1: back to 0 |
| 11 | clear = 0: counting resumes |
Before editing, write q for cycles 0 to 13. The falling edge before the cycle 6 rising edge
sets enable = 0, so the cycle 6 line already shows the held value.
3. Completion conditions
- After initialisation, with
enable = 1the count runs 0, 1, …, 15, 0, 1 and never reaches 16. - With
enable = 0the value does not change, however many cycles pass. - With
clear = 1the next edge makesq0 whateverenableis, andqstays 0 whileclearstays 1. Whencleardrops, counting restarts from 0. - The rules hold for repeated clears and for a clear in the middle of counting.
4. Hints, in order
Hint 1
Listing the three cases as if, else if, else turns the priority order directly into code: the
first condition wins.
Hint 2
q is 4 bits wide, so adding 1 to 15 gives 0 by itself; no comparison is needed. Register updates use
the nonblocking assignment <=.
Hint 3
The hold case can be q <= q; or simply absent: a register not assigned in a clocked block keeps
its value. That is unlike the latch a combinational block infers.
5. Further experiment
After passing, build two variations. Write down what has to change before changing it.
- A 3-bit or 5-bit counter: which port widths and which wrap point change?
- A counter that stops at 12 and restarts only through
clear: one more hold condition is needed.
Check variations with the public testbench only, and restore the original contract before submitting.