Skip to content
code0.HDL

Design from a requirement

Turn a written requirement into an interface, one register and the action that updates it with the right priority, predict the behaviour with a model, then build and grade a clearable, enableable counter on your own.

In this chapter

  • Read a written requirement into an interface: ports, widths and methods
  • Keep the whole state in one register and express priority as exclusive branches of one action
  • Predict the counter cycle by cycle before writing it, and pick normal, boundary and reset test cases from the requirement
  • Build a selectable operator and a clearable, enableable counter on your own and pass the grader
Concepts in this chapter
  • Rule-based design from a requirement
Prerequisite concepts

1. Read the requirement into an interface

Every earlier chapter started from code. This one starts from a sentence, the way real work does:

A 4-bit counter q. clear returns it to 0. enable advances it by one. When both are asserted in the same cycle, clear wins. With neither, it holds. After 15 it wraps to 0.

The first design step is to sort the sentence into what the outside can observe and what it can command. Observations become value methods; commands become Action methods.

PhraseBSV element
"a 4-bit counter q"Reg#(Bit#(4)), read by a value method
"clear returns it to 0", "enable advances it"commands: Action methods, or one Action taking both as arguments
"clear wins"a priority inside the next-state logic
"holds"no write in that cycle
"wraps to 0"Bit#(4) arithmetic, which is modulo 16

The graded problem declares the interface it grades against: one Action method step(clear, enable) that takes both commands as Bool arguments, and a value method value. Implement that interface, not a different one, because the grader calls the methods the problem names. Separate clear and enable Action methods would also be a valid reading of the sentence; the caution in section 3 says what that choice changes.

2. One register is the whole state

The counter's state is one value, so one register holds it: Reg#(Bit#(4)) q <- mkReg(0);. The reset value is the reset from the fundamentals, applied before cycle 0. The wrap costs nothing: adding 1 to a Bit#(4) holding 15 gives 0 at run time, because arithmetic keeps the operand width. Only a literal 16 is rejected, as types, widths and explicit conversion showed.

Check

q holds 15, enable is 1 and clear is 0. What does q hold after the edge?

3. Priority is exclusive branches in one action

Two commands can arrive in the same cycle, and the register can take only one next value. Write the priority as if and else if inside one action so that exactly one branch writes:

Form

if (first)       r <= valueA;   // the winning command
else if (second) r <= valueB;   // considered only when the first is absent
// neither branch: no write, the register holds

The branch order is the priority. Two unconditional writes to the same register in one rule or method are not "last one wins"; bsc rejects them with compile error G0004, because all statements of an action happen together and a register cannot take two values at once. The missing else is the hold.

Check

q holds 5, and in the same cycle clear is 1 and enable is 1. What does q hold after the edge?

Check

A method body contains q <= 0; followed by q <= q + 1; with no condition on either. What happens?

Your answer

Caution. If an interface had two separate Action methods and a testbench could call both in one cycle, the priority would no longer be decided by a branch inside one body; two callers writing one register is the shadowing situation of rules that share state. With the problem's single step(clear, enable) method, both commands arrive in one call, and the if/else if above is the whole answer.

4. Predict the counter before you build it

Fill in the table with the behaviour the requirement demands. Cycle 0 starts from the reset value q = 0. The two input columns are clear and enable as the counter sees them in that cycle, and the column you fill is q after the edge that ends the cycle.

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
211
301
400
501

This is the browser model of the requirement, not your BSV. When your design is written, the grader runs the same kind of sequence against it with the real toolchain.

5. Choose the test cases from the requirement

A requirement with three behaviours needs more than one happy path. Before you run, list the cases the grader is likely to check and what each should show.

KindCaseExpected
normalenable for a few cycles0, 1, 2, 3 … one step per cycle
holdneither assertedthe same value on consecutive observations
priorityclear and enable together0, regardless of the previous value
boundaryenable at 150 on the next observation
resetafter clear, then enablecounting resumes from 0

The design is finished when every row behaves, not when the sample output looks right. A fixed constant, an unintended write in the hold case, or reversed priority can fail different rows.

6. Apply it: two problems

The first Practice problem, expressions/select-op, is a pure function: a 2-bit sel chooses whether the result is the AND, OR, XOR or NOR of two 4-bit operands. Its shape is the case of selection, case, and the don't-care value, with one arm per value, and its operators are those of Bool, Bit and pure functions; NOR has no operator of its own and is the complement of the OR.

The graded problem, modules-and-interfaces/clear-enable-counter, is the counter of this chapter. Work in this order: read the interface the problem declares, instantiate the register, write the action with the priority from section 3, and make this problem's value method report the register unchanged, as in the first chapter. Run, compare with your table from section 4, then submit for grading. Grading checks the rows of section 5 against your module.

7. The design path

StepChapter it comes from
sort the requirement into observations and commandsA module and its interface; Methods
one register per independent piece of stateRegisters and one rule
next-state logic with explicit priority and a holdSelection, case, and the don't-care value; Guards
width and wrap from the typeTypes, widths and explicit conversion
rules that never compete for one registerRules that share state
test the normal, boundary, priority and reset casesGuards; this chapter

This chapter closes the part of the course that builds a design from first principles. The chapters that follow hold the rules this part deliberately left out: the lexical and package details of a larger source tree, provisos and typeclasses, FIFOs and other library state, and the scheduling attributes that make a priority between rules explicit.

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 BSV problem as your next step.

Sources

Licences and notices for the sources this site follows