module UartRx  #(parameter OVERSAMPLING=8)
(
  input clk,                // system clock
  input uart_rxclk,         // uart valid clock (mask for system clock)
  input rx_pin,             // serial input data 
  output o_rx_data_valid,   // rx_data_in are ready to be read 
  output [7:0] rx_data_out  // received data
  ); 

  localparam WAITFORSTART = 0;
  localparam SYNC = 1;
  localparam READING = 2;
  localparam READSTOP = 3;
  localparam CLEARDATAVALID = 4;
  
  reg [3:0] bitcount = 0;
  reg [4:0] clockcount = 0;
  reg [7:0] rx_data = 0;
  reg [2:0] state = WAITFORSTART;
  reg rx_data_valid;

  
  always@(posedge clk) begin
    if (uart_rxclk) begin
      case (state)
        WAITFORSTART: begin
          if (rx_pin == 0) begin
            state <= SYNC;
            clockcount <= 0;
          end
        end
        SYNC: begin
          if (clockcount == OVERSAMPLING/2-1) begin
            state <= READING;
            clockcount <= 0;
            bitcount  <= 0;
          end else begin
            clockcount <= clockcount + 5'd1;
          end  
        end 
        READING: begin
          if (clockcount == OVERSAMPLING-1) begin
            rx_data[bitcount] <= rx_pin;
            clockcount <= 0;
            bitcount <= bitcount + 4'd1;
            if (bitcount == 7) begin
              state <= READSTOP;
            end  
          end else begin
            clockcount <= clockcount + 5'd1;
          end  
        end 
        READSTOP: begin
          if (clockcount == OVERSAMPLING-1) begin
            if (rx_pin == 1) begin 
              rx_data_valid <= 1;
              state <= CLEARDATAVALID;
              clockcount <= 0;
            end else begin
              clockcount <= 0;
              state <= WAITFORSTART;
            end
          end else begin  
            clockcount <= clockcount + 5'd1;
          end
        end 
        CLEARDATAVALID: begin
          rx_data_valid <= 0;
          state <= WAITFORSTART;
        end

        default: begin
          rx_data_valid <= 1;
          state <= CLEARDATAVALID;
        end
      endcase
    end
  end  
  
  assign o_rx_data_valid = rx_data_valid;
  assign rx_data_out = rx_data;
endmodule