101 lines
2.5 KiB
Verilog
101 lines
2.5 KiB
Verilog
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
|