module serial_rx #(
		parameter CLK_PER_BIT = 50,
		parameter CTR_SIZE = 6
	)(
		input clk,
		input rst,
		input rx,
		output [7:0] data,
		output new_data
	);
	
	localparam STATE_SIZE = 2;
	localparam IDLE = 2'd0,
			WAIT_HALF = 2'd1,
			WAIT_FULL = 2'd2,
			WAIT_HIGH = 2'd3;
	
	reg [CTR_SIZE-1:0] ctr_d, ctr_q;
	reg [2:0] bit_ctr_d, bit_ctr_q;
	reg [7:0] data_d, data_q;
	reg new_data_d, new_data_q;
	reg [STATE_SIZE-1:0] state_d, state_q = IDLE;
	reg rx_d, rx_q;
	
	assign new_data = new_data_q;
	assign data = data_q;
	
	always @(*) begin
		rx_d = rx;
		state_d = state_q;
		ctr_d = ctr_q;
		bit_ctr_d = bit_ctr_q;
		data_d = data_q;
		new_data_d = 1'b0;
		
		case (state_q)
			IDLE: begin
				bit_ctr_d = 3'b0;
				ctr_d = 1'b0;
				if (rx_q == 1'b0) begin
					state_d = WAIT_HALF;
				end
			end
			WAIT_HALF: begin
				ctr_d = ctr_q + 1'b1;
				if (ctr_q == (CLK_PER_BIT >> 1)) begin
					ctr_d = 1'b0;
					state_d = WAIT_FULL;
				end
			end
			WAIT_FULL: begin
				ctr_d = ctr_q + 1'b1;
				if (ctr_q == CLK_PER_BIT - 1) begin
					data_d = {rx_q, data_q[7:1]};
					bit_ctr_d = bit_ctr_q + 1'b1;
					ctr_d = 1'b0;
					if (bit_ctr_q == 3'd7) begin
						state_d = WAIT_HIGH;
						new_data_d = 1'b1;
					end
				end
			end
			WAIT_HIGH: begin
				if (rx_q == 1'b1) begin
					state_d = IDLE;
				end
			end
			default: begin
				state_d = IDLE;
			end
		endcase
		
	end
	
	always @(posedge clk) begin
		if (rst) begin
			ctr_q <= 1'b0;
			bit_ctr_q <= 3'b0;
			new_data_q <= 1'b0;
			state_q <= IDLE;
		end else begin
			ctr_q <= ctr_d;
			bit_ctr_q <= bit_ctr_d;
			new_data_q <= new_data_d;
			state_q <= state_d;
		end
		
		rx_q <= rx_d;
		data_q <= data_d;
	end
	
endmodule