///////////////////////////////////////////////////////////
// uart_rx.v
// Receive only 8-bit UART with fixed baud rate
//
//    - o_valid   - Raised when data has been received and
//                  placed on o_data
//
//    - o_data    - This is used as counter when shifting
//                  in data by shifting a single bit
//
///////////////////////////////////////////////////////////

`timescale 1ns/1ps

module uart_rx(
   input    wire           i_clk,
	input    wire		      i_nrst,
   output   reg   [7:0]    o_data,
   input    wire           i_rx,
	output   reg            o_valid,
   input    wire           i_accept
);

    parameter  SAMPLE      = 1,  
               SM_IDLE     = 2'b00,
               SM_RX_START = 2'b01,
               SM_RX       = 2'b11,
               SM_WAIT     = 2'b10,
               START_BIT   = 8'h80;

   reg [1:0]                   state;
   reg [$clog2(SAMPLE)-1:0]    count;

   assign   full_sample =  (count == SAMPLE        );
   assign   half_sample =  (count == (SAMPLE >> 1) );
   
   always@(posedge i_clk or negedge i_nrst) begin
      if(!i_nrst) begin
         state    <= SM_IDLE;	
         count    <= 'b0; 
         o_data   <= 8'h0;
         o_valid  <= 1'b0;
      end else begin
         count <= count + 'b1;
         case(state)
            SM_IDLE:       begin
                              if(i_accept) begin
                                 o_valid  <= 1'b0;
                              end
                              if(!i_rx) begin
                                 state    <= SM_RX_START;
                                 count    <= 'b0;
                                 o_data   <= START_BIT;
                                 o_valid  <= 1'b0;
                              end
                           end
            SM_RX_START:   if(half_sample) begin
                              state       <= SM_RX;
                              count       <= 'b0;
                           end
            SM_RX:         if(full_sample) begin
                              o_data      <= {i_rx,o_data[7:1]}; 
                              count       <= 'b0;
                              if(o_data[0]) begin
                                 state    <= SM_WAIT;
                                 o_valid  <= 1'b1;
                              end
                           end
            SM_WAIT:       begin
                              if(full_sample) begin
                                 state    <= SM_IDLE;
                                 count    <= 'b0;
                              end
                              if(i_accept) begin
                                 o_valid  <= 1'b0;
                              end
                           end
         endcase
      end
   end
endmodule