Skip to content
code0.HDL

Design from a requirement

Turn a written requirement into ports, a register with a reset value, a when chain whose order is the priority, and a wrapping add, keep the functional clear apart from the implicit reset, and check the design against a cycle table before grading.

In this chapter

  • Read a written requirement into ports, widths and a register with a reset value
  • Express priority as the order of a when chain and wrapping as the width, written with +%
  • Keep a functional clear port apart from the module's implicit reset
  • Check the design against a cycle table, plan the tests from its boundaries, and pass the grader
Concepts in this chapter
  • A parameterisable design from a requirement
Prerequisite concepts

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: if clear is 1, q becomes 0; otherwise, if enable is 1, q goes up by one and is 0 after 15; otherwise q is unchanged. q is 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 textIn the module
clear, enable are testedInput(Bool()) each
q is 4 bits, read from outsideOutput(UInt(4.W))
q holds a value across cycles, 0 after resetRegInit(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.

CaseBranchNext value of q
clear is 1when (io.clear)0
clear is 0 and enable is 1.elsewhen (io.enable)q + 1, wrapping
both 0no branchq holds

Check

clear and enable are both 1 at an edge. What is q after the edge?

Your answer

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.

State table
Cycleclearinputs sampled at the edgeenableinputs sampled at the edgeqafter the edge
001
101
201
311
401
500
610
701

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.

CaseWhat to check
reset onlyq reads 0 at the start, before any poke
holdwith both inputs 0 for several steps, q does not move
countwith enable high for 16 steps, q passes 15 and reads 0 again
clear winsclear and enable high together give 0 at the next edge
clear timingpoking 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

StepChisel
nouns in the requirementInput, Output, with explicit widths
a value that persistsRegInit(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 gradinga 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.

Checkpoint

Submit the Practice problem for grading

Grading runs on the server against hidden tests; the result is recorded in this browser only.

Practice

Use this concept in a short Chisel problem as your next step.