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
| Port | Direction | Type | Description |
|---|---|---|---|
bclk | in | 1 bit | Bit clock from the codec and the only DUT clock |
rst | in | 1 bit | Synchronous reset (active high) |
ws | in | 1 bit | Word select: low for left, high for right |
sd | in | 1 bit | Serial data from the codec |
left | out | 16-bit vector | Last completed left sample, held |
right | out | 16-bit vector | Last completed right sample, held |
valid | out | 1 bit | Stereo pair complete (one-bclk pulse) |
frame_err | out | 1 bit | Bad word-select boundary (one-bclk pulse) |
Behavior
- The codec changes
wsandsdon fallingbclkedges - The receiver samples all inputs only on rising
bclkedges - 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
wsstarts a new slot but does not carry its first data bit - If a
wschange 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
wschanges - The edge where a
wschange 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
wschange pulsesframe_errfor 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
wslevel 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,
validpulses on the next rising edge leftandrightupdate together on that same edgeleftandrighthold their values between completed pairsvalidandframe_errare low except during their one-bclk pulses- After reset, all outputs are zero and capture waits until the first observed
wschange - 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
rsthigh at a rising edge clears all outputs, capture state, slot timing, and any partial pair
What the bench checks
- The testbench drives
wsandsdat 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
wschange 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_errpulse, 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
wschange
Constraints
everything is synchronous to bclk; inputs are sampled only on rising edges, and all outputs are registered.
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.
Click Run to execute your code. Output will appear here.