Practice

Lane Rack Button

Star Lanes is a small bowling alley with pinsetter machines from the 1970s. Each lane has one reset button on the ball return. A press tells the pinsetter to clear the fallen pins and set a fresh rack.

The button is a bare mechanical contact, and its metal leaf bounces on every press. One press reaches the controller as a burst of pulses. The old controller counted each pulse as a new press, so the machine cycled 2 or 3 times and jammed. League nights stalled while staff climbed into the machine to free the pins. Rolling balls shake the contact too, so short rattles arrive with no press behind them.

Your task: build the debouncer that sits between the button and the controller. Pass raw_i through 2 flip-flops first, because the contact is not lined up with clk_i. Then filter it: clean_o may take a new value only after the contact has held that value for 8 samples in a row. Pulse pressed_o high for 1 cycle when clean_o rises. Pulse released_o high for 1 cycle when clean_o falls.

Interface

PortDirectionTypeDescription
clk_iin1 bitSystem clock
rst_iin1 bitSynchronous reset (active high)
raw_iin1 bitRaw contact from the button, bouncy
clean_oout1 bitDebounced button level
pressed_oout1 bitOne-cycle pulse when clean_o rises
released_oout1 bitOne-cycle pulse when clean_o falls

Behavior

  • After reset, clean_o is low: the block treats the button as not pressed
  • The block samples raw_i at every rising edge of clk_i
  • raw_i passes through a 2-flop synchronizer: the filter sees each sample 2 cycles after the edge that took it
  • A qualifying run is an unbroken row of samples with the same value, and that value differs from clean_o
  • When a run reaches 8 samples, clean_o takes the run's value at the 2nd rising edge after the edge with the 8th sample
  • One sample equal to clean_o ends the run; the count starts over at 0
  • A run of 7 or fewer samples never changes clean_o, no matter how many such runs arrive
  • pressed_o is high for exactly the 1 cycle on which clean_o rises, and low at all other times
  • released_o is high for exactly the 1 cycle on which clean_o falls, and low at all other times
  • rst_i high at a rising clock edge forces clean_o, pressed_o, and released_o low from that edge
  • Reset fires no pulse: released_o stays low even when reset drops a high clean_o
  • Reset also clears the synchronizer and the count, so a contact still closed after reset must qualify again with a fresh 8-sample run

What the bench checks

  • The testbench checks clean_o, pressed_o, and released_o on every cycle of every scenario
  • The testbench drives a press as a bounce burst that settles high, and checks the exact edge where clean_o rises
  • The testbench drives a release as a bounce burst that settles low, and checks the exact edge where clean_o falls
  • The testbench drives a long rattle in which no value holds for 8 samples, and checks that no output moves
  • The testbench holds the opposite value for exactly 7 samples, on both sides, and checks clean_o does not move
  • The testbench holds the contact closed for exactly 8 samples, then opens it, and checks the rise and the fall both land on schedule
  • The testbench checks pressed_o and released_o return low exactly 1 cycle after they rise
  • The testbench asserts rst_i mid-rattle while clean_o is high and checks all three outputs drop with no released_o pulse
  • The testbench keeps raw_i high through that reset and checks pressed_o fires on the 10th edge after rst_i goes low
  • The testbench asserts rst_i on the exact edge where clean_o would rise and checks that no rise and no pulse happen

Constraints

TIMING: everything is synchronous to clk_i; all outputs are registered.

SCOPE: this models the debouncer between the bouncy contact and the pinsetter controller. The button's mechanics and the pinsetter machine are out of scope.

SYNCHRONIZER: raw_i must pass through 2 flip-flops before any other logic reads it. The bench's edge counts include this 2-cycle lag, so a skipped stage fails the timing checks.

Do not add ports.

Loading editor...

Click Run to execute your code. Output will appear here.