Skip to content
code0.HDL

28Implementation

Define percent literals

Situation and starter reading

Percent stores tenths of a percentage point in a ten-bit field, while a source literal denotes whole percent. The starter implements the Literal#(Percent) interface, but it copies the source integer unchanged and treats the entire representation range as the semantic domain.

Read the code in three passes: the struct establishes storage, fromInteger establishes conversion, and inLiteralRange establishes which typed literals are legal. Finally read show, where Percent sample = 37 supplies the type context. Change only the two method bodies; preserve the struct, instance, and observation module.

Despite the existing field name basisPoints and the runner's output label, this exercise uses ten stored units per percentage point. Standard basis points use one hundred units per percentage point. Preserve the supplied names and runner; implement the exercise's ten-to-one scale, not a basis-point conversion.

Predict before editing

The starter compiles and Run reports a stored value of 37 for 37 percent. That is a unit-conversion error, not a width error. Its range predicate would also accept 101 and 1023 even though neither is a valid whole-percent literal for this domain.

Reason about two contracts separately. Conversion maps a source integer into the stored unit. The range predicate answers whether that source integer belongs to the percentage domain. bsc does not call a user-defined inLiteralRange while compiling literals, so the predicate is a contract that code calls explicitly, not an automatic compile-time check.

The ten-bit field has enough room for 1000 stored units, but its maximum bit pattern must not define the percentage limit.

Required change and observable completion

  • Store ten units for each whole percentage point.
  • Make inLiteralRange return True for the inclusive range 0 through 100 and False for the values just outside either boundary.
  • Keep the explicit Literal#(Percent) instance and ordinary unsized literal syntax.

Run is observably correct when the sample declaration reports a stored value of 370. Completion also requires correct boundary behavior and conversion throughout the domain, not a special case for 37.

Progressive hints

Hint 1: separate the responsibilities

Only one method constructs Percent; only the other returns the Boolean range answer. Do not mix unit conversion into the predicate.

Hint 2: follow the units

fromInteger receives whole percent as an elaboration-time Integer. Apply the ten-to-one scale before converting into the field type.

Hint 3: test both edges

Build the range condition from a lower comparison and an upper comparison. Both documented endpoints belong to the domain; the neighboring integers do not.

Transfer experiment

After the valid implementation runs, add a temporary typed declaration at the upper boundary and predict its stored field. Then move that literal one above the boundary and predict again. The build still succeeds and stores 1010 units, because bsc does not apply your inLiteralRange to the literal. Add a temporary $display that calls inLiteralRange directly with 100 and 101 to see the predicate itself reject the second value. Restore the original mkTop afterward.

Review this concept
Ready
Main.bsv