1. Read the requirement into ports first
This chapter gives no code to run. You write the module yourself, from a requirement like the one the graded problem states:
A 4-bit count
q. At every rising edge: ifclearis 1,qbecomes 0; otherwise, ifenableis 1,qgoes up by one and is 0 after 15; otherwiseqis unchanged.qis 0 after the module's implicit synchronous reset.
Every noun in that text is a port or a register, and every "on an edge where" is a condition on a register's next value. Write the ports before anything else.
| In the text | In the module |
|---|---|
clear, enable are tested | Input(Bool()) each |
q is 4 bits, read from outside | Output(UInt(4.W)) |
q holds a value across cycles, 0 after reset | RegInit(0.U(4.W)), connected to the output |
Give the reset value its width, as the registers chapter said. RegInit(0.U) would be inferred from what is
connected to it, and a counter that only feeds itself settles on 1 bit. The graded problem's starter
already contains the ports, this register, and io.q := q; what it leaves to you is the next value,
the subject of the rest of this chapter.
2. Priority is the order of the chain
The requirement lists three cases and says which wins with the word "otherwise". That order is a
when/.elsewhen chain, and the register holds in the case the chain does not mention. No
.otherwise is needed for a register; the conditional-update chapter explained why a wire would need one and a register
does not.
| Case | Branch | Next value of q |
|---|---|---|
clear is 1 | when (io.clear) | 0 |
clear is 0 and enable is 1 | .elsewhen (io.enable) | q + 1, wrapping |
| both 0 | no branch | q holds |
Check
clear and enable are both 1 at an edge. What is q after the edge?
3. Wrapping is the width, written as +%
q + 1.U on a 4-bit UInt is already 4 bits wide: + keeps the operand width, so 15 + 1 produces
the low four bits of 16, which is 0. Chisel also has +%, the explicitly non-expanding add, which
means the same thing for UInt and says the wrap is intended. +& would produce a 5-bit value, and
the connection to the 4-bit register would truncate it back; the numbers come out the same, but a
reader cannot tell whether the lost bit was wanted. Write q +% 1.U, or q + 1.U as the problem's
hint does; no comparison with 15 is needed, because the maximum is one less than a power of two.
Check
q is 15, clear is 0 and enable is 1. What is q after the edge?
4. clear is a port; reset is the module's implicit signal
clear and reset both make q zero, through different mechanisms, and the problem keeps them apart.
Its text says that q is 0 after the module's implicit synchronous reset, that clear is a
different signal, an ordinary input that zeroes the count at the next edge and must work while
reset is low, and, among the completion checks, that q is 0 at every edge while reset is high
even with enable high. RegInit(0.U(4.W)) is the whole implementation of the reset sentences:
RegInit answers to the implicit reset that the conditional-update chapter described, chiseltest pulses that reset before
the test body, and while it is high the register captures 0 instead of its next value. clear is the
when chain's first branch and nothing else. Do not wire clear into the reset or use withReset;
the grader drives clear as an ordinary input and expects q to follow the chain.
5. Predict the design before you write it
Fill in the table for the counter the requirement describes. Each row is one cycle; clear and
enable are the inputs during that cycle, and you write q after the edge that ends it. The browser
model has the same contract: clear wins, enable counts modulo 16, otherwise hold.
Predict, then compare · counter4
Fill in each cell before comparing. Empty cells count as a mismatch.
| Cycle | clearinputs sampled at the edge | enableinputs sampled at the edge | qafter the edge |
|---|---|---|---|
| 0 | 0 | 1 | |
| 1 | 0 | 1 | |
| 2 | 0 | 1 | |
| 3 | 1 | 1 | |
| 4 | 0 | 1 | |
| 5 | 0 | 0 | |
| 6 | 1 | 0 | |
| 7 | 0 | 1 |
6. A testbench plan from the boundaries
The public testbench of the problem prints a trace; the grader runs hidden tests. Write your own
expectations for the cases that separate a correct design from an almost-correct one before pressing
Run.
| Case | What to check |
|---|---|
| reset only | q reads 0 at the start, before any poke |
| hold | with both inputs 0 for several steps, q does not move |
| count | with enable high for 16 steps, q passes 15 and reads 0 again |
| clear wins | clear and enable high together give 0 at the next edge |
| clear timing | poking clear high changes nothing until a step; q is 0 only after the edge |
Check
q is 7. The testbench pokes clear high and peeks q without stepping. What does it read?
7. Two problems, one method
The graded problem below is the counter of this chapter. Its public run prints q before each
cycle's edge, one line per cycle, so shift your after-edge column down one line when you compare.
The second problem, select-op, is combinational: a 2-bit sel names one of four bitwise operations
on a and b, and y carries that result in the same cycle, with no register. Use the same method:
read the table into ports, build each of the four results as an expression, and select with the
utility from the selection utilities chapter whose selector is one key compared with constants, listing one entry per sel
value and a default of the right type. Parenthesize each operation inside its pair; -> binds before
the bitwise operators. For both, write the expected trace first and compare it with the printed one
line by line.
8. Summary
| Step | Chisel |
|---|---|
| nouns in the requirement | Input, Output, with explicit widths |
| a value that persists | RegInit(v) with a width on v |
| "if … otherwise …" | when/.elsewhen in that order; a register holds without .otherwise |
| "wraps" | +% on the register's width |
| "after reset" | the reset value; a functional clear stays a port |
| before grading | a cycle table and the boundary cases |
The chapters remain the reference for everything this path left out: reset types and withReset in
Sequential Circuits, the selection utilities in
Muxes and Input Selection, and the width rules in
Data Types.