| // Oversampling UART receiver. | 
 | module UART_RX( | 
 |     input rst, clk, baud_edge, rx, | 
 |     output [7:0] data, | 
 |     output data_ready, framing_error | 
 | ); | 
 |     parameter OVERSAMPLE = 8; | 
 |     localparam FIND_EDGE = 3'd1, START = 3'd2, DATA = 3'd3, END = 3'd4; | 
 |  | 
 |     reg prev_rx; | 
 |     reg [7:0] data_reg; | 
 |     reg [2:0] data_counter; | 
 |     reg [2:0] state = 0; | 
 |     reg [$clog2(OVERSAMPLE+OVERSAMPLE/2)-1:0] over_sample_counter = 0; | 
 |  | 
 |     reg data_ready_reg = 0; | 
 |     reg framing_error_reg = 0; | 
 |  | 
 |     assign data = data_reg; | 
 |     assign data_ready = data_ready_reg; | 
 |     assign framing_error = framing_error_reg; | 
 |  | 
 |     always @(posedge clk) begin | 
 |         if(rst) begin | 
 |             data_reg <= 0; | 
 |             prev_rx <= 0; | 
 |             data_ready_reg <= 0; | 
 |             state <= FIND_EDGE; | 
 |             data_counter <= 0; | 
 |             over_sample_counter <= 0; | 
 |         end else if(baud_edge) begin | 
 |             case(state) | 
 |                 FIND_EDGE: begin | 
 |                     prev_rx <= rx; | 
 |  | 
 |                     if(prev_rx & !rx) begin | 
 |                         state <= START; | 
 |                         prev_rx <= 0; | 
 |                         over_sample_counter <= 0; | 
 |                     end | 
 |                 end | 
 |                 START: begin | 
 |                     // Align sample edge in the middle of the pulses. | 
 |                     if(over_sample_counter == OVERSAMPLE/2-1) begin | 
 |                         over_sample_counter <= 0; | 
 |                         data_counter <= 0; | 
 |                         state <= DATA; | 
 |                     end else begin | 
 |                         over_sample_counter <= over_sample_counter + 1; | 
 |                     end | 
 |                 end | 
 |                 DATA: begin | 
 |                     if(over_sample_counter == OVERSAMPLE-1) begin | 
 |                         over_sample_counter <= 0; | 
 |                         data_reg[data_counter] <= rx; | 
 |                         if(data_counter == 7) begin | 
 |                             state <= END; | 
 |                             data_counter <= 0; | 
 |                         end else begin | 
 |                             data_counter <= data_counter + 1; | 
 |                         end | 
 |                     end else begin | 
 |                         over_sample_counter <= over_sample_counter + 1; | 
 |                     end | 
 |                 end | 
 |                 END: begin | 
 |                     if(over_sample_counter == OVERSAMPLE-1) begin | 
 |                         if(rx) begin | 
 |                             data_ready_reg <= 1; | 
 |                         end else begin | 
 |                             framing_error_reg <= 1; | 
 |                         end | 
 |                         state <= FIND_EDGE; | 
 |                     end else begin | 
 |                         over_sample_counter <= over_sample_counter + 1; | 
 |                     end | 
 |  | 
 |                 end | 
 |                 default: begin | 
 |                     data_ready_reg <= 0; | 
 |                     state <= FIND_EDGE; | 
 |                 end | 
 |             endcase | 
 |         end else begin | 
 |             data_ready_reg <= 0; | 
 |             framing_error_reg <= 0; | 
 |         end | 
 |     end | 
 | endmodule |