Practice
Cutter Ramp Streamer
The blade head of a vinyl cutter cannot go from parked to cutting speed in one step; it tears the material. So every move starts with a ramp: 8 velocity words, streamed to the servo drive over a valid/ready handshake.
The previous implementation shipped to three customers before the field reports arrived. Ramps had missing steps or the same step twice, and one memorable unit drove the head into the rollers at full speed. The cause: whenever its buffer fills, the drive drops ready_i during the ramp, but the old source counted every word it presented as sent. The handshake rule it skipped is the one every datasheet states: a word transfers only on a cycle where valid_o and ready_i are both high. Until then, the source must hold valid_o high and keep the word rock steady.
Your task: build the source side, with the handshake done right. When the motion planner pulses go_i with a starting velocity on base_i, stream the 8 words base_i, base_i+1, ... base_i+7. Flag the final word with last_o, then go quiet.
Interface
| Port | Direction | Type | Description |
|---|---|---|---|
clk_i | in | 1 bit | Clock |
rst_i | in | 1 bit | Synchronous reset (active high) |
go_i | in | 1 bit | Start pulse from the motion planner |
base_i | in | 8-bit vector | Starting velocity, captured when go_i is taken |
ready_i | in | 1 bit | Drive can accept a word this cycle |
valid_o | out | 1 bit | Word on data_o is valid |
data_o | out | 8-bit vector | Velocity word base_i + k (wraps mod 256) |
last_o | out | 1 bit | High while word 8 of 8 is presented |
Behavior
- Idle:
valid_o = 0andlast_o = 0;data_ois meaningless and unchecked whilevalid_o = 0 go_i = 1sampled at a clock edge while idle starts a burst: from the next cycle,valid_o = 1anddata_o = base_ias captured at that edge- A word transfers at each clock edge where
valid_o = 1andready_i = 1; the next cycle presents the next word,data_o = base_i + kfor word k (wrapping mod 256) - While
valid_o = 1andready_i = 0, every output holds exactly:valid_o,data_o, andlast_omust not change last_o = 1exactly while the eighth word (base_i + 7) is presented, stalled or not- After the eighth word transfers, the block returns to idle from the next cycle; a
go_ion that first idle cycle starts a new burst go_iis ignored whenever a burst is in progress;base_ichanges mid-burst are ignored toorst_i = 1at a clock edge aborts everything: idle from the next cycle
What the bench checks
- The testbench checks
valid_oandlast_oon every cycle anddata_oon every cycle wherevalid_oshould be 1 - A full-rate burst must present eight consecutive values, assert
last_oonly on the eighth, then return to idle - Stalls on the first, middle, and final words must hold outputs steady; the stalled ramp also wraps from
FFto00 - A new
go_ipulse and changes tobase_iduring a burst must not alter that burst - Reset during a stalled burst must abort it immediately and keep the source idle afterward
- A
go_iheld across the final transfer must be ignored there, then start the next burst from the following idle cycle
Constraints
TIMING: everything is synchronous to
clk_i; outputs may only change at clock edges.
SCOPE: this models the source side of the handshake only. The servo drive and its buffer live behind
ready_i, and the blade mechanics are out of scope.
The burst length is fixed at 8 and the word values are base_i + k mod 256, so no memory is involved.
Do not add ports.
Click Run to execute your code. Output will appear here.