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 | in | 1 bit | Clock |
rst | in | 1 bit | Synchronous reset (active high) |
cols | in | 4-bit vector | Column returns, valid one cycle after a row settles |
rows | out | 4-bit vector | Row drive, one-hot active high, registered decode |
key | out | 4-bit vector | Last reported key code, row * 4 + column, registered |
valid | 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 = 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.
colsis sampled only at the rising edge that ends the row's second cycle - Whatever
colsbits 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
validhigh for the following cycle - That same edge loads
keywith the crossing's code, row * 4 + column - A sweep totaling zero crossings, or two or more (real or phantom), produces no pulse and leaves
keyunchanged keyholds its last reported code between pulses (0 after reset); downstream reads it withvalid, 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 = 1at any rising edge abandons the sweep in progress: the count clears,validdrops,keyclears to 0, and scanning restarts at row 0
What the bench checks
- The testbench's matrix is registered:
colsduring any cycle reflects the row drive of the previous cycle - The testbench checks
rows,valid, andkeyon every cycle;keymust 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
everything is synchronous to clk; rows, key and valid change only at clock edges.
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.
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.