module UART_RX ( input i_Clk, input i_ReceiveBit, output o_DataReady, output [7:0] o_DataByte ); parameter CLOCKS_PER_SECOND = 25000000; parameter BAUD_RATE = 115200; localparam integer CLOCKS_PER_BIT = CLOCKS_PER_SECOND / BAUD_RATE; localparam integer HALF_CLOCKS_PER_BIT = (CLOCKS_PER_BIT - 1) / 2; localparam IDLE = 0; localparam VERIFY_START_BIT = 1; localparam READ_DATA_BITS = 2; localparam WAIT_FOR_STOP_BIT = 3; localparam CLEANUP = 4; // golang-style: lowercase is private, uppercase is public reg [$clog2(CLEANUP)-1:0] r_currentState = IDLE; reg r_dataReady = 0; reg [$clog2(CLOCKS_PER_BIT)-1:0] r_clockCount = 0; reg [$clog2(8)-1:0] r_bitIndex = 0; reg [7:0] r_receivedByte = 0; always @(posedge i_Clk) begin case (r_currentState) IDLE: begin r_dataReady <= 0; r_clockCount <= 0; r_bitIndex <= 0; if (i_ReceiveBit == 0) begin r_currentState <= VERIFY_START_BIT; end end // Check the middle of the start bit to make sure it's still low VERIFY_START_BIT: begin if (r_clockCount == HALF_CLOCKS_PER_BIT) begin // still low, let's go if (i_ReceiveBit == 0) begin r_clockCount <= 0; r_currentState <= READ_DATA_BITS; end else begin r_currentState <= IDLE; end end else begin r_clockCount <= r_clockCount + 1; end end // note that we are still in the halfway points of the signal at this // point. we are sampling the very middles. READ_DATA_BITS: begin if (r_clockCount < CLOCKS_PER_BIT - 1) begin r_clockCount <= r_clockCount + 1; end else begin r_clockCount <= 0; r_receivedByte[r_bitIndex] <= i_ReceiveBit; if (r_bitIndex == 7) begin r_bitIndex <= 0; r_currentState <= WAIT_FOR_STOP_BIT; end else begin r_bitIndex <= r_bitIndex + 1; end end end WAIT_FOR_STOP_BIT: begin if (r_clockCount < CLOCKS_PER_BIT - 1) begin r_clockCount <= r_clockCount + 1; end else begin r_dataReady <= 1; r_clockCount <= 0; r_currentState <= CLEANUP; end end CLEANUP: begin r_currentState <= IDLE; r_dataReady <= 0; end default: begin r_currentState <= IDLE; end endcase end assign o_DataByte = r_receivedByte; assign o_DataReady = r_dataReady; endmodule