29Implementation
Latch a PWM duty at the period boundary
Problem
Intended behavior. PwmLatch produces a pulse-width modulated signal
with a period of eight cycles. count runs 0 to 7 and wraps, and pwm is
high while count < level. For level from 0 to 8, level is the number of
high cycles in a period; any larger value also keeps pwm high for all eight cycles.
level must not follow duty directly. It loads duty only at the edge that
ends a period, where count goes from 7 back to 0, so a change of duty in
the middle of a period takes effect from the next period. Reset clears both
count and level.
Current behavior. The starter never updates level, so pwm stays low.
Your task. Replace the TODO line with the update for level. Keep the
ports, count, last, the pwm line, and the public bench.
Read and predict
The public bench records a waveform. It pokes duty to 3, runs four periods
while counting the high cycles of pwm in each, and changes duty to 6 in
the middle of period 3. It prints one PERIOD line per period, then copies the
VCD to dump.vcd, and the lab shows the waveform below the output.
Before running, predict the four PERIOD lines of a correct design. Period 1
needs care: decide what level holds during the first period after reset.
Then run the starter and open the waveform.
Read the waveform
Look for count, last, level, io_duty, and io_pwm. Ports and retained
internal signals appear in the VCD; a Scala val alone does not guarantee that
a separate signal survives optimization. Check three points:
io_dutychanges between rising edges, at the time of the poke, in the middle of period 3.levelmay change only at the rising edge wherecountreturns to 0, the edge that ends the cycle in whichlastis high.- For
levelfrom 1 to 7,io_pwmfalls at the edge wherecountreacheslevel. At 0 it stays low; at 8 or above it stays high for the whole period.
In the starter, level is a flat line at 0. After your fix, compare where it
moves with where io_duty moves.
Completion check
pwmis high for exactlylevelcycles of each period, counted fromcount = 0, for every duty from 0 to 8, and for the whole period above 8.- A duty change at any point inside a period affects only the next period. If
dutychanges several times in one period, only its value on the last cycle counts. - The first period after reset runs with
level0, and a reset clearslevelagain.
Hints
Hint 1
The waveform already shows last, a signal that is high for exactly one cycle
per period. Ask which edge ends that cycle.
Hint 2
Guard the update of level with last. A register assigned inside a when
keeps its value on every other edge.
Concept
A shadow register that loads only at a boundary keeps each period consistent, whatever the input does in between. A waveform shows that property directly: the input moves in the middle of a period, while the register moves only at period boundaries.
Variation
Load level when count === 0.U instead. Predict the four PERIOD lines and
the edges where level changes in the waveform, and explain why the first
cycle of every period now uses the previous duty.