Practice

Codec I2S Receiver

Wrenford Town Hall fitted a new recorder for its council sessions. The audio codec was wired correctly, but every stored word sounded wrong.

On Monday's replay, voices rasped and the mayor appeared in the clerk's channel.

The FPGA read the first data bit when the word select line changed. In I2S, that first bit comes one bit clock later. Each sample lost its top bit and gained a stray bit at the end.

Your task: build the I2S receiver for the recorder. Capture each 16-bit word in its 32-bit slot. Keep left and right words together, and flag any slot with a bad boundary.

Interface

PortDirectionTypeDescription
bclk_iin1 bitBit clock from the codec and the only DUT clock
rst_iin1 bitSynchronous reset (active high)
ws_iin1 bitWord select: low for left, high for right
sd_iin1 bitSerial data from the codec
left_oout16-bit vectorLast completed left sample, held
right_oout16-bit vectorLast completed right sample, held
valid_oout1 bitStereo pair complete (one-bclk pulse)
frame_err_oout1 bitBad word-select boundary (one-bclk pulse)

Behavior

  • The codec changes ws_i and sd_i on falling bclk_i edges
  • The receiver samples all inputs only on rising bclk_i edges
  • Each slot is 32 bits: 16 data bits first, MSB first, followed by 16 padding bits
  • Padding bits may have any value and must be ignored
  • A sampled change on ws_i starts a new slot but does not carry its first data bit
  • If a ws_i change is first sampled at edge k, the word MSB is sampled at edge k+1
  • The remaining 15 data bits are sampled on the next 15 rising edges
  • A legal slot has exactly 32 rising edges between successive first-sampled ws_i changes
  • The edge where a ws_i change is first sampled closes the old slot and carries its last padding bit. The new word's MSB arrives one edge later
  • An early or late ws_i change pulses frame_err_o for exactly one bclk
  • A bad boundary discards any partial stereo pair
  • The bad boundary edge becomes the start of a fresh slot, including the one-bit delay
  • A low ws_i level identifies a left slot, and a high level identifies a right slot
  • A stereo pair requires a clean left word followed by the clean right word from the immediately following slot
  • After the right word's 16th data bit is sampled, valid_o pulses on the next rising edge
  • left_o and right_o update together on that same edge
  • left_o and right_o hold their values between completed pairs
  • valid_o and frame_err_o are low except during their one-bclk pulses
  • After reset, all outputs are zero and capture waits until the first observed ws_i change
  • If capture starts with a right slot, that word is discarded
  • Pairing then begins with the next left slot
  • Samples are signed audio values, but the receiver treats them as raw 16-bit patterns
  • rst_i high at a rising edge clears all outputs, capture state, slot timing, and any partial pair

What the bench checks

  • The testbench drives ws_i and sd_i at falling-edge time and judges every output after each rising edge
  • Its first left word is an alignment discriminator: a capture that reads the MSB at the ws_i change edge itself publishes x4000 instead of x8000
  • It fills the 16 padding bits of every slot with junk that must leave no trace
  • It cuts one slot short and runs another long, expecting the one-bclk frame_err_o pulse, the dropped partial pair, and a re-anchor at the bad edge
  • It starts the stream during a right word and checks that the lone right word never publishes
  • It asserts reset with a left word staged and checks that outputs clear and capture waits for the next ws_i change

Constraints

TIMING: everything is synchronous to bclk_i; inputs are sampled only on rising edges, and all outputs are registered.

SCOPE: this models the digital capture contract on bclk only; there is no system-clock crossing, no volume math, and no analog anything.

Do not add ports.

Loading editor...

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