UART Receiver Data Shifter
UART receivers must robustly sample asynchronous serial data. To avoid data corruption from slight baud rate mismatches between the sender and receiver, the receiver oversamples the incoming stream to find the exact middle of each bit period. This module implements the core shifting and sampling logic for a UART receiver using a standard 16x oversampling approach.
The module receives a serial data line rx and a sample_tick enable signal that pulses 16 times per baud period. When rx drops low, the module interprets this as a potential start bit. It waits 8 sample_tick pulses to sample the middle of the start bit. If rx is still low, it proceeds to sample the next 8 data bits (LSB first), waiting 16 sample_tick pulses between each sample. Finally, it waits 16 ticks to sample the stop bit. If the stop bit is high, the assembled byte is valid. If the stop bit is low, a framing error has occurred.
- Clock edge:
posedge clk - Reset type: Asynchronous, active-low
rst_n - Reset behaviour:
data_outresets to 8'h00;data_validandframe_errreset to 0 - Output rules: All outputs are registered. When the 16th
sample_tickof the stop bit is processed,data_valid(if valid) orframe_err(if invalid) must assert on the next clock edge. They must remain high for exactly one clock cycle.data_outmust update on the same clock edge thatdata_validgoes high.
Worked Trace: Cycle 1: rst_n=0 → state=IDLE, data_valid=0, frame_err=0 Cycle 2: rst_n=1, rx=1, sample_tick=1 → state=IDLE Cycle 3: rx=0, sample_tick=1 → state=START, tick_cnt=0 Cycle 4: rx=0, sample_tick=0 → state=START, tick_cnt=1 (hold) Cycle 5: rx=0, sample_tick=1 → state=START, tick_cnt=1 ... Cycle 17: rx=0, sample_tick=1 → state=START, tick_cnt=7. Middle of start bit sampled; valid. Next state=DATA. Cycle 18: rx=1, sample_tick=1 → state=DATA, tick_cnt=0, bit_idx=0. ... Cycle 150: sample_tick=1 → state=STOP, tick_cnt=15. Stop bit sampled as 1. Cycle 151: sample_tick=0 → state=IDLE, data_valid=1, data_out=assembled_byte (1-cycle pulse) Cycle 152: sample_tick=0 → state=IDLE, data_valid=0
flowchart LR
RESET(( )) -->|reset| IDLE
IDLE((IDLE)) -->|rx=0 & tick| START
START -->|tick & cnt=7 & rx=0| DATA
START -->|tick & cnt=7 & rx=1| IDLE
DATA -->|tick & cnt=15 & bit=7| STOP
DATA -->|tick & cnt=15 & bit<7| DATA
STOP(["STOP ★"]):::out -->|tick & cnt=15 & rx=1| IDLE
STOP -->|tick & cnt=15 & rx=0| IDLE
classDef out fill:#6C5CE7,stroke:#5B4FE8,color:#fff| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered system clock | | rst_n | input | 1 | Asynchronous active-low reset | | rx | input | 1 | Asynchronous serial data line | | sample_tick | input | 1 | Enable pulse that asserts 16 times per baud period | | data_out | output | 8 | Assembled byte; updates when a valid frame is received | | data_valid| output | 1 | Pulses high for exactly 1 clock cycle when a valid byte is received | | frame_err | output | 1 | Pulses high for exactly 1 clock cycle if the stop bit is 0 |
Constraints
- The module must ignore glitches on the start bit; if
rxis high at the 8th tick of the START state, the module must immediately return to IDLE without asserting any errors. - The
data_validandframe_errsignals must never be asserted simultaneously. - The
data_outsignal must hold its value until a new valid frame is completely received. - Data is transmitted LSB first.
sample_tickmay not be asserted every clock cycle; the module must only advance its internal counters whensample_tickis 1.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.