Practice
Hive Scale Sampler
A bee farm weighs every hive to catch swarms early. When a swarm leaves, half the bees go with it, and the hive gets lighter within the hour. The scale under each hive feeds a 12-bit ADC, and the ADC talks SPI.
The old readout board sampled the data line one clock too late, just after the ADC had already shifted it. Every bit landed one place too high, so the logged weight came out doubled. Hive 7 swarmed in June. The chart showed a fat, thriving colony, and nobody opened the lid until the honey was gone.
Your task: build the SPI master that reads one sample from the ADC. Wait in idle until start_i pulses. Then pull cs_n_o low, run sclk_o at 1/4 of the system clock rate, and capture miso_i on each rising sclk_o edge. The ADC sends 2 null bits, then the 12 data bits, highest bit first. Put the reading on sample_o, pulse valid_o for 1 cycle, and go back to idle.
Interface
| Port | Direction | Type | Description |
|---|---|---|---|
clk_i | in | 1 bit | System clock |
rst_i | in | 1 bit | Synchronous reset (active high) |
start_i | in | 1 bit | Request one reading (one-cycle pulse) |
miso_i | in | 1 bit | Serial data from the ADC |
cs_n_o | out | 1 bit | ADC chip select (active low) |
sclk_o | out | 1 bit | Serial clock to the ADC (idles low) |
sample_o | out | 12-bit vector | Last completed reading, held |
valid_o | out | 1 bit | Reading complete (one-cycle pulse) |
Behavior
- When idle,
cs_n_ois high,sclk_ois low, andvalid_ois low - While idle,
start_ihigh at a rising clock edge begins a read:cs_n_ofalls on that same edge - Cycle numbering: cycle 0 is the first full cycle with
cs_n_olow sclk_odivides the system clock by 4: in each group of 4 cycles from cycle 0, it is low for 2 cycles, then high for 2- The first
sclk_orising edge lands at cycle 2; the rest follow every 4 cycles, 14 rising edges in total cs_n_ostays low for cycles 0 through 55: exactly 14sclk_operiods- The ADC updates
miso_iafter eachsclk_ofalling edge; the master capturesmiso_ion eachsclk_orising edge - The first 2 captured bits are null bits, driven 0 by the ADC; the reading does not include them
- The next 12 captured bits are the reading, bit 11 first, bit 0 last
- At cycle 56 the read ends:
cs_n_oreturns high,sclk_ois low,valid_ois high, andsample_opresents the new reading valid_ois high for exactly 1 cycle per readsample_oholds between reads and while a read is in progress; reset clears it to 0start_ipulses whilecs_n_ois low are ignored- A
start_ipulse on the cycle right aftervalid_obegins a new read rst_ihigh at a rising clock edge cancels any read:cs_n_ohigh,sclk_olow,valid_olow,sample_ocleared
What the bench checks
- The testbench models the ADC: it loads a known code when
cs_n_ofalls and shifts it out onsclk_ofalling edges - The testbench checks
cs_n_o,sclk_o, andvalid_oagainst the fixed timeline on every cycle of every read - The testbench compares
sample_oto the loaded code after each read, using codes that expose shifted or reversed bits - The testbench drives
miso_ihigh whenevercs_n_ois high - The testbench pulses
start_iin the middle of one read and checks that no second read starts after it - The testbench pulses
start_ion the last cycle withcs_n_olow and checks that no new read follows - The testbench starts one read on the cycle right after
valid_oand expects a normal read - The testbench asserts
rst_iin the middle of one read and checks the outputs return to idle on the next cycle - The testbench checks
sample_oon every cycle of every read: it must hold the previous reading until the read completes - The testbench checks that
sample_oholds its value between reads
Constraints
TIMING: everything is synchronous to
clk_i; all outputs are registered.
SCOPE: this models the SPI master side of one fixed read: 2 null bits, then 12 data bits at a quarter-rate clock. The scale, the ADC's analog side, and the logging are out of scope.
Do not add ports.
Click Run to execute your code. Output will appear here.