`timescale 1ns / 1ns
module uiuart_rx# ( parameter integer BAUD_DIV = 10416 ) ( input clk_i, input uart_rx_rstn_i, input uart_rx_i, output [7:0] uart_rdata_o, output uart_rvalid_o );
localparam BAUD_DIV_SAMP = (BAUD_DIV/8)-1;
wire bps_en ; wire samp_en ; wire bit_cap_done ; wire uarx_rx_done ; wire bit_data ; wire uart_rx_int ;
reg [13:0] baud_div = 14'd0; reg [13:0] samp_cnt = 14'd0; reg [4 :0] uart_rx_i_r = 5'd0; reg [3 :0] bit_cnt=4'd0; reg [3 :0] cap_cnt=4'd0; reg [4 :0] rx_bit_tmp = 5'd0; reg [7 :0] rx_data = 8'd0;
reg bps_start_en_r = 1'b0; reg bit_cap_done_r = 1'b0; reg bps_start_en,start_check_done,start_check_failed;
assign bps_en = (baud_div == (BAUD_DIV - 1'b1)); assign samp_en = (samp_cnt == (BAUD_DIV_SAMP - 1'b1 )); assign bit_cap_done = (cap_cnt == 3'd7); assign uarx_rx_done = (bit_cnt == 9)&&(baud_div == BAUD_DIV >> 1);//received bits finished half the baud rate time earlier
assign bit_data = (rx_bit_tmp < 5'd15) ? 0 : 1; assign uart_rx_int = uart_rx_i_r[4] | uart_rx_i_r[3] | uart_rx_i_r[2] | uart_rx_i_r[1] | uart_rx_i_r[0];
assign uart_rdata_o = rx_data; assign uart_rvalid_o = uarx_rx_done;
//baud rate generator always@(posedge clk_i)begin if(bps_start_en && baud_div < BAUD_DIV) baud_div <= baud_div + 1'b1; else baud_div <= 14'd0; end
//8x oversampling, divider always@(posedge clk_i)begin if(bps_start_en && samp_cnt < BAUD_DIV_SAMP) samp_cnt <= samp_cnt + 1'b1; else samp_cnt <= 14'd0; end
//uart rx bus asynchronous to Synchronous always@(posedge clk_i)begin uart_rx_i_r <= {uart_rx_i_r[3:0],uart_rx_i}; end
//start check always@(posedge clk_i)begin if(uart_rx_rstn_i == 1'b0 || uarx_rx_done || start_check_failed) bps_start_en <= 1'b0; else if((uart_rx_int == 1'b0)&(bps_start_en==1'b0)) bps_start_en <= 1'b1; end
always@(posedge clk_i)begin bps_start_en_r <= bps_start_en; end
always@(posedge clk_i)begin if(uart_rx_rstn_i == 1'b0 || start_check_failed)begin start_check_done <= 1'b0; start_check_failed <= 1'b0; end else if(bps_start_en == 1'b1&&bps_start_en_r == 1'b0) begin start_check_done <= 1'b0; start_check_failed <= 1'b0; end else if((bit_cap_done&&bit_cap_done_r==1'b0)&&(start_check_done == 1'b0))begin start_check_failed <= bit_data ? 1'b1 : 1'b0; start_check_done <= 1'b1; end end
//bits counter always@(posedge clk_i)begin if(uart_rx_rstn_i == 1'b0 || uarx_rx_done || bps_start_en == 1'b0) bit_cnt <= 4'd0; else if(bps_en) bit_cnt <= bit_cnt + 1'b1; end
//sample bits always@(posedge clk_i)begin if(uart_rx_rstn_i == 1'b0 || bps_en == 1'b1 || bps_start_en == 1'b0) begin cap_cnt <= 4'd0; rx_bit_tmp <= 5'd15; end else if(samp_en)begin cap_cnt <= cap_cnt + 1'b1; rx_bit_tmp <= uart_rx_i_r[4] ? rx_bit_tmp + 1'b1 : rx_bit_tmp - 1'b1; end end
always@(posedge clk_i) bit_cap_done_r <= bit_cap_done; //shift rx bit data always@(posedge clk_i)begin if(uart_rx_rstn_i == 1'b0 || bps_start_en == 1'b0) rx_data <= 8'd0; else if(start_check_done&&(bit_cap_done&&bit_cap_done_r==1'b0)&&bit_cnt < 9) rx_data <= {bit_data,rx_data[7:1]}; end
endmodule |