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_i | in | 1 bit | Bit clock from the codec and the only DUT clock |
rst_i | in | 1 bit | Synchronous reset (active high) |
ws_i | in | 1 bit | Word select: low for left, high for right |
sd_i | in | 1 bit | Serial data from the codec |
left_o | out | 16-bit vector | Last completed left sample, held |
right_o | out | 16-bit vector | Last completed right sample, held |
valid_o | out | 1 bit | Stereo pair complete (one-bclk pulse) |
frame_err_o | out | 1 bit | Bad word-select boundary (one-bclk pulse) |
Behavior
- The codec changes
ws_iandsd_ion fallingbclk_iedges - The receiver samples all inputs only on rising
bclk_iedges - 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_istarts a new slot but does not carry its first data bit - If a
ws_ichange 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_ichanges - The edge where a
ws_ichange 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_ichange pulsesframe_err_ofor 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_ilevel 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_opulses on the next rising edge left_oandright_oupdate together on that same edgeleft_oandright_ohold their values between completed pairsvalid_oandframe_err_oare low except during their one-bclk pulses- After reset, all outputs are zero and capture waits until the first observed
ws_ichange - 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_ihigh at a rising edge clears all outputs, capture state, slot timing, and any partial pair
What the bench checks
- The testbench drives
ws_iandsd_iat 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_ichange 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_opulse, 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_ichange
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.
Click Run to execute your code. Output will appear here.