`default_nettype none module uart_rx #(parameter CLOCKS_PER_BAUD=16'd868)( input clk, input rst_n, input rx_i, output reg [7:0] data_o, output reg rx_done_o ); localparam clocks_per_half_bit = CLOCKS_PER_BAUD / 2; localparam s_idle = 5'b00001, s_start = 5'b00010, s_rd = 5'b00100, s_stop = 5'b01000, s_done = 5'b10000; reg en_cnt; reg [15:0] cnt; reg [4:0] state; reg [2:0] rx_bits; always @(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 16'd0; else if ((en_cnt == 0) || (cnt == CLOCKS_PER_BAUD)) cnt <= 16'd0; else cnt <= cnt + 1; end // edge detection reg rx_0, rx_1, rx_2, rx_3; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin rx_0 <= 0; rx_1 <= 0; rx_2 <= 0; rx_3 <= 0; end else begin rx_3 <= rx_i; rx_2 <= rx_3; rx_1 <= rx_2; rx_0 <= rx_1; end end wire start_flag; assign start_flag = rx_0 & rx_1 & (~rx_2) &(~rx_3); always @(posedge clk or negedge rst_n) begin if (~rst_n) begin state <= s_idle; en_cnt <= 0; data_o <= 0; rx_bits <= 0; rx_done_o <= 0; end else begin case (state) s_idle: begin rx_bits <= 0; rx_done_o <= 0; if (start_flag) begin en_cnt <= 1; state <= s_start; end else begin en_cnt <= 0; state <= s_idle; end end s_start: begin if (cnt == clocks_per_half_bit) if (rx_i == 0) state <= s_rd; else state <= s_idle; end s_rd: begin if (cnt == clocks_per_half_bit) if (rx_bits == 3'd7) state <= s_stop; else begin data_o[rx_bits] <= rx_i; rx_bits <= rx_bits + 1; state <= s_rd; end end s_stop: begin if (cnt == clocks_per_half_bit) if (rx_i == 1) state <= s_done; else state <= s_idle; end s_done: begin en_cnt <= 0; rx_done_o <= 1; state <= s_idle; end default : begin state <= s_idle; end endcase end end endmodule // Local Variables: // verilog-library-directories:(".." "../rtl" ".") // End: