blob: 1500c11734fe97bb79c9e796d42b9765f859f0f0 [file] [log] [blame] [edit]
// Oversampling UART receiver.
module UART_RX(
input rst, clk, baud_edge, rx,
output [7:0] data,
output data_ready, framing_error
);
parameter OVERSAMPLE = 8;
localparam FIND_EDGE = 3'd1, START = 3'd2, DATA = 3'd3, END = 3'd4;
reg prev_rx;
reg [7:0] data_reg;
reg [2:0] data_counter;
reg [2:0] state = 0;
reg [$clog2(OVERSAMPLE+OVERSAMPLE/2)-1:0] over_sample_counter = 0;
reg data_ready_reg = 0;
reg framing_error_reg = 0;
assign data = data_reg;
assign data_ready = data_ready_reg;
assign framing_error = framing_error_reg;
always @(posedge clk) begin
if(rst) begin
data_reg <= 0;
prev_rx <= 0;
data_ready_reg <= 0;
state <= FIND_EDGE;
data_counter <= 0;
over_sample_counter <= 0;
end else if(baud_edge) begin
case(state)
FIND_EDGE: begin
prev_rx <= rx;
if(prev_rx & !rx) begin
state <= START;
prev_rx <= 0;
over_sample_counter <= 0;
end
end
START: begin
// Align sample edge in the middle of the pulses.
if(over_sample_counter == OVERSAMPLE/2-1) begin
over_sample_counter <= 0;
data_counter <= 0;
state <= DATA;
end else begin
over_sample_counter <= over_sample_counter + 1;
end
end
DATA: begin
if(over_sample_counter == OVERSAMPLE-1) begin
over_sample_counter <= 0;
data_reg[data_counter] <= rx;
if(data_counter == 7) begin
state <= END;
data_counter <= 0;
end else begin
data_counter <= data_counter + 1;
end
end else begin
over_sample_counter <= over_sample_counter + 1;
end
end
END: begin
if(over_sample_counter == OVERSAMPLE-1) begin
if(rx) begin
data_ready_reg <= 1;
end else begin
framing_error_reg <= 1;
end
state <= FIND_EDGE;
end else begin
over_sample_counter <= over_sample_counter + 1;
end
end
default: begin
data_ready_reg <= 0;
state <= FIND_EDGE;
end
endcase
end else begin
data_ready_reg <= 0;
framing_error_reg <= 0;
end
end
endmodule