Practice
Storage Gate Scan
The entry gate at the BoxBarn self-storage yard reads a 16-key pad wired as a 4-by-4 matrix: 4 row wires, 4 column wires, a key at each crossing. A pressed key connects its row to its column. The scanner finds keys by driving one row at a time and reading which columns answer.
It is the cheapest pad on the market, and that brings two problems. First, the pad connects through 15 m of ribbon cable. After the scanner drives a new row, the column lines need a full cycle to settle before they mean anything. Second, the pad has no diodes behind the keys. When 3 pressed keys form an L shape in the matrix, current sneaks around the corner. A 4th crossing appears: a phantom key that no finger is on.
The old scanner card ignored both problems. It sampled the columns in the same cycle it moved the row, so it read the previous row's echo. And it trusted phantoms: a customer in winter gloves once pressed 3 keys at once, and a digit nobody entered went into the gate code. Entering 3 wrong codes locks the account until morning.
Your task: build the replacement. Scan on the fixed schedule below, count every crossing a sweep sees, and report a key only when the total is exactly 1. A phantom is electrically identical to a real key, so a sweep that sees more than one crossing reports nothing.
Interface
| Port | Direction | Type | Description |
|---|---|---|---|
clk_i | in | 1 bit | Clock |
rst_i | in | 1 bit | Synchronous reset (active high) |
cols_i | in | 4-bit vector | Column returns, valid one cycle after a row settles |
rows_o | out | 4-bit vector | Row drive, one-hot active high, registered decode |
key_o | out | 4-bit vector | Last reported key code, row * 4 + column, registered |
valid_o | out | 1 bit | One-cycle pulse: the finished sweep saw exactly one key |
Behavior
- After a reset edge the scan starts at row 0:
rows_o = 0001for two cycles, then0010for two, then0100, then1000, then back to row 0 - The sweep is 8 cycles long and repeats forever
- For each row, the first cycle is settle time.
cols_iis sampled only at the rising edge that ends the row's second cycle - Whatever
cols_ibits are high at that sample count as crossings on that row - Crossings accumulate across the sweep's four samples
- At the edge that ends the sweep (the same edge as row 3's sample), a total of exactly one crossing sets
valid_ohigh for the following cycle - That same edge loads
key_owith the crossing's code, row * 4 + column - A sweep totaling zero crossings, or two or more (real or phantom), produces no pulse and leaves
key_ounchanged key_oholds its last reported code between pulses (0 after reset); downstream reads it withvalid_o, but the hold is part of the contract- A key held down reports once per sweep, every sweep
- Three pressed keys forming an L produce a fourth phantom crossing in the matrix model, exactly as the diode-less pad does. Such sweeps see four crossings and must report nothing
rst_i = 1at any rising edge abandons the sweep in progress: the count clears,valid_odrops,key_oclears to 0, and scanning restarts at row 0
What the bench checks
- The testbench's matrix is registered:
cols_iduring any cycle reflects the row drive of the previous cycle - The testbench checks
rows_o,valid_o, andkey_oon every cycle;key_omust hold its last reported code between pulses - The testbench drives empty sweeps, single keys held across sweeps (including both corner keys), two keys sharing a row, and two sharing a column
- It also drives the L-shaped phantom trio, a key pressed after its row already went by in the current sweep, and a reset mid-sweep
Constraints
TIMING: everything is synchronous to
clk_i;rows_o,key_oandvalid_ochange only at clock edges.
SCOPE: this models the scanner against a matrix model with settle delay and diode-less phantoms. The gate lock, the entry codes, and the cable's true analog behavior are out of scope.
SCAN SCHEDULE: the two-cycle row dwell and the sample-on-the-second-edge rule are load-bearing. The matrix model answers late, exactly like the real ribbon cable.
Do not add ports. Do not try to identify which of several keys is real: at the electrical level the phantom is real. That is why multi-key sweeps report nothing.
Click Run to execute your code. Output will appear here.