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 pulses. Then pull cs_n low, run sclk at 1/4 of the system clock rate, and capture miso on each rising sclk edge. The ADC sends 2 null bits, then the 12 data bits, highest bit first. Put the reading on sample, pulse valid for 1 cycle, and go back to idle.

Interface

PortDirectionTypeDescription
clkin1 bitSystem clock
rstin1 bitSynchronous reset (active high)
startin1 bitRequest one reading (one-cycle pulse)
misoin1 bitSerial data from the ADC
cs_nout1 bitADC chip select (active low)
sclkout1 bitSerial clock to the ADC (idles low)
sampleout12-bit vectorLast completed reading, held
validout1 bitReading complete (one-cycle pulse)

Behavior

  • When idle, cs_n is high, sclk is low, and valid is low
  • While idle, start high at a rising clock edge begins a read: cs_n falls on that same edge
  • Cycle numbering: cycle 0 is the first full cycle with cs_n low
  • sclk divides 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 rising edge lands at cycle 2; the rest follow every 4 cycles, 14 rising edges in total
  • cs_n stays low for cycles 0 through 55: exactly 14 sclk periods
  • The ADC updates miso after each sclk falling edge; the master captures miso on each sclk rising 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 returns high, sclk is low, valid is high, and sample presents the new reading
  • valid is high for exactly 1 cycle per read
  • sample holds between reads and while a read is in progress; reset clears it to 0
  • start pulses while cs_n is low are ignored
  • A start pulse on the cycle right after valid begins a new read
  • rst high at a rising clock edge cancels any read: cs_n high, sclk low, valid low, sample cleared

What the bench checks

  • The testbench models the ADC: it loads a known code when cs_n falls and shifts it out on sclk falling edges
  • The testbench checks cs_n, sclk, and valid against the fixed timeline on every cycle of every read
  • The testbench compares sample to the loaded code after each read, using codes that expose shifted or reversed bits
  • The testbench drives miso high whenever cs_n is high
  • The testbench pulses start in the middle of one read and checks that no second read starts after it
  • The testbench pulses start on the last cycle with cs_n low and checks that no new read follows
  • The testbench starts one read on the cycle right after valid and expects a normal read
  • The testbench asserts rst in the middle of one read and checks the outputs return to idle on the next cycle
  • The testbench checks sample on every cycle of every read: it must hold the previous reading until the read completes
  • The testbench checks that sample holds its value between reads

Constraints

TIMING

everything is synchronous to clk; 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.

Loading editor...

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