I just implemented a simple UART transmitter (10 flops + timing generator), and am looking at the receiver. As a compulsive minimalist, I am offended by the elaborate and enormous 'examples' I've seen. The receiver seems trickier than the transmitter register, but is it really?
I believe that modern devices are likely to have very stable timing, so things like 16x oversampling (or any oversampling) is an overkill. A straightforward shift register with a 1/2-bit start delay should stay in sync for the remaining 8 bits.
So the tricky parts:
* detect 1-0 start bit transition (and ignore other such transitions), which requires two states - idle and busy, and the associated counter for asserting the busy state while shifting;
* set the timing counter to 1/2 the total baud-rate count, to assure sampling mid-bit;
* enable the shift register and busy-state bit and bit counter;
* don't forget to shift out the start bit (count to 8 to 0?)
* upon transition to idle, stop shifting, buffer the data and signal 'data ready'
* if you want to be fancy, check for stop bit and signal 'framing error'
This seems pretty minimal.
Does anyone have experience implementing UARTs for FPGAs?
TLDR: got something working here:
https://tildegit.org/stack/Tangnano9K-UART