Skip to content
code0.HDL

23Implementation

Build a generic hold register

Problem

Intended behavior. Hold[T <: Data](gen) is a register for any payload type. On every clock edge where en is high it captures in; on other edges it keeps what it has. out always shows the most recently captured value, so a capture appears on out immediately after the edge that took it. Before the first capture the output is unspecified. PixelHold is the same generator fixed to a three-field Pixel.

Current behavior. The starter connects in straight to out. The output follows the input in every cycle and nothing is held.

Task. Give Hold the register it needs. The body must work for every T: the public run builds both Hold(UInt(8.W)) and PixelHold. Keep the class names, the type parameter, and the ports.

Read the starter

Find where gen is used. It shapes in and out; en is always a Bool. The template itself is never connected to anything. Ask what the body knows about T and what it does not: it cannot name a width or a field, only use what gen describes.

Predict before running

The public run steps the clock after each poke and then prints out. For the UInt test the inputs are 7, 8, 9, 10, 11 with en high only for 7 and 10. Predict the five out values, then the three Pixel rows. Compare with the starter's output, where every row simply repeats its input.

Run and explain

Run your change. In the UInt trace, out may change only on rows where en is true, because each row is printed after its edge. Each Pixel row must hold all three fields together. Explain how one body built an 8-bit register for one instance and a three-field register for the other without naming either type.

Completion check

  • out changes only after an edge where en was high.
  • With en low, out keeps its value for any number of cycles while in changes.
  • All fields of a Bundle payload are captured together.
  • The same body compiles and behaves correctly for UInt and Pixel.

Progressive hints

Hint 1

Holding a value across cycles needs state. Which hardware construct from the sequential circuits chapter stores a value and is updated by :=?

Hint 2

The register's type must be T, and the only description of T you have is gen. A fixed type such as UInt(8.W) fails to compile for the Pixel instance.

Hint 3

Update the register under when(io.en), and drive out from the register, not from the input.

Concept

gen is a Chisel type, a template. Input(gen), Output(gen), and Reg(gen) each make a separate hardware value with that shape. The generic body works on that hardware only through operations every Data supports, such as := and when, so the same code builds an 8-bit register in one instance and a 24-bit Bundle register in another.

Extension experiment

Predict what changes if you write Reg(io.in) instead of using gen. Then predict the elaboration result of new Hold(0.U(8.W)), and in which phase it fails.

Review this concept
Ready

CheerpJ runs Chisel in your browser. A cold Run downloads about 14.5 MB of Java and 47 MB of JARs. Compilation can take a minute. Licenses

Main.scala