Project: UART Transmitter
A complete serial transmitter: an FSM, a baud-rate counter and a shift register, checked by a receiver model in the testbench.
UART is the simplest serial protocol and a classic first hardware project: the line idles high, each byte is sent as a start bit (0), eight data bits least significant first, and a stop bit (1), each bit lasting a fixed time set by the baud rate. The transmitter combines everything so far: an FSM, a counter and a shift register.
The design
IDLE: hold tx high; on start, capture data into shreg and go to START.
START: drive tx low for one bit time.
DATA: drive bit bit_idx of shreg, eight times.
STOP: drive tx high for one bit time, then return to IDLE and drop busy.
clk_cnt counts clocks within a bit; bit_done marks the last clock of each bit.
Taking it further
tx <= shreg[7 - bit_idx]; // MSB first tx <= shreg[bit_idx]; // LSB first
UART sends the least significant bit first. Sending MSB first produces characters that are bit-reversed at the receiver.
With a 100 MHz clock, what CLKS_PER_BIT gives 9600 baud?
100,000,000 / 9600 = 10416.67, so 10417 (an error of about 0.003%, far inside UART's tolerance of a few percent).
How long does one 8N1 frame take at 115200 baud?
10 bits (start + 8 data + stop) / 115200 = about 86.8 µs.