// UART RX with fractional clock divider. // Baud rate = frequency of `clk` / (DIV_NUM / DIV_DEN) // // Author: nand2mario, Feb 2025 module uart_rx #( parameter DIV_NUM = 25, parameter DIV_DEN = 1 )( input clk, input resetn, input rx, output reg [7:0] data, output reg valid ); reg [1:0] state; reg [$clog2(DIV_NUM)-1:0] cnt, cnt_next; reg [2:0] bit_index; reg [7:0] rx_data; always @(posedge clk) begin if (!resetn) begin state <= 0; valid <= 0; data <= 0; end else begin reg cnt_overflow; cnt_next = cnt + DIV_DEN; cnt_overflow = cnt_next >= DIV_NUM; if (state != 0) cnt <= cnt_overflow ? cnt_next - DIV_NUM : cnt_next; valid <= 0; case (state) 0: begin // Idle if (!rx) begin state <= 1; cnt <= 0; bit_index <= 0; rx_data <= 0; end end 1: begin // Start bit, wait half a bit time if (cnt_next >= DIV_NUM/2) begin state <= 2; cnt <= 0; end end 2: begin // Data bits if (cnt_overflow) begin rx_data[bit_index] <= rx; if (bit_index == 7) state <= 3; else bit_index <= bit_index + 1; end end 3: begin // Stop bit if (cnt_overflow) begin valid <= 1; data <= rx_data; state <= 0; end end endcase end end endmodule