`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 21:56:42 10/11/2022
// Design Name:
// Module Name: uart_rx
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_rx(
input clk, //clock input
input rst_n, //asynchronous reset input, low active
input [2:0] baud_set,
output reg finish_receive, //完成接收
input rs232_rx_pin,
output reg [7:0] now_rx_data
);
reg [2:0] r_data[7:0];//二维数组:8个3位r_data(最大是7) 对输入IO口信号多次采样,防止有偶尔的干扰造成的错误读数。
reg [2:0] sta_bit; //起始位
reg [2:0] stp_bit; //停止位
reg rx232_rx0;
reg rx232_rx1;
reg start_receive;
reg [8:0] max_count_1_bit_div16;
wire start_rx_negedge;
//波特率查找表 50M时钟的1个计数是20ns //5207=9600、2603=19200、1301=38400、867=57600、433=115200
///*波特率设置,其中除以16的原因是将一个位周期划分成16段,来综合判断高低电平,防止只判断一两次会出现有掉电和升电的误判*/
//讲1个bit的时间段分成16份,则0,1,2,3,4认为是开头不进行采样,5,6,7,8,9,10,11是中间段进行采样,12,13,14,15,16是末尾段不进行采样。
//则1个采样点对应的最大计数脉冲个数是如下:
always@(*)
begin
case(baud_set)
3’d0: max_count_1_bit_div16 = (50_000_000/9600/16 - 1);
3’d1: max_count_1_bit_div16 = (50_000_000/19200/16 - 1);
3’d2: max_count_1_bit_div16 = (50_000_000/38400/16 - 1);
3’d3: max_count_1_bit_div16 = (50_000_000/57600/16 - 1);
3’d4: max_count_1_bit_div16 = (50_000_000/115200/16 - 1);
default: max_count_1_bit_div16 = (50_000_000/9600/16 - 1);
endcase
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rx232_rx0 <= 1’b0;
rx232_rx1 <= 1’b0;
end
else
begin
rx232_rx0 <= rs232_rx_pin;
rx232_rx1 <= rx232_rx0;
end
end
assign start_rx_negedge = ((~rx232_rx0 ) & (rx232_rx1));//提取下降沿。2022年10月11日22:04:43
//设置启动接收标志。
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
start_receive <= 1’b0;
else if(start_rx_negedge)
start_receive <= 1’b1;
else if(finish_receive) //完成接收
start_receive <= 1’b0;
else if(sta_bit >= 4) //每个bit位会采样7次,即是在如下位置采样5,6,7,8,9,10,11是中间段进行采样
start_receive <= 1’b0;
else
start_receive <= start_receive;
end
/--------------1/16个位时间循环---------------/
reg [8:0] cnt_of_one_bit_div16;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt_of_one_bit_div16<=0;
else if(start_receive) //在工作情况下,判断div_cnt是否有1/16个位时间。到达则清零,否则递增
begin
if(cnt_of_one_bit_div16 < max_count_1_bit_div16)
cnt_of_one_bit_div16 <= cnt_of_one_bit_div16 + 1'b1;
else
cnt_of_one_bit_div16 <= 0;
end
else
cnt_of_one_bit_div16<=0;
end
wire middle_count_of_one_bit_div16;
assign middle_count_of_one_bit_div16 = (cnt_of_one_bit_div16 == max_count_1_bit_div16/2);//一位周期分成16段,取每一段的中间时刻值来作为依据
//1个起始位+8个数据位+1个停止位,一共10个bit位。1个bit位分成16段,则10个bit位分成160段。
reg [7:0]bps_cnt;//160个bps_clk_16x需要8位数据来存储(一位有16个,总共有十位)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
bps_cnt<=0;
else if(start_receive)
if(middle_count_of_one_bit_div16 == 1’b1)//16个分段中的中间。
begin
if(bps_cnt<159)
bps_cnt<=bps_cnt+1’b1;
else
bps_cnt<=0;
end
else
bps_cnt<=bps_cnt;
else
bps_cnt<=0;
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sta_bit<=0;
stp_bit<=0;
r_data[0]<=0;//多位宽只能一个一个来,不能r_data[2:0][7:0]
r_data[1]<=0;
r_data[2]<=0;
r_data[3]<=0;
r_data[4]<=0;
r_data[5]<=0;
r_data[6]<=0;
r_data[7]<=0;
end
else if(middle_count_of_one_bit_div16 ==1'b1)
begin
case(bps_cnt)
1:begin
sta_bit<=0;
stp_bit<=0;
r_data[0]<=0;//多位宽只能一个一个来,不能r_data[2:0][7:0]
r_data[1]<=0;
r_data[2]<=0;
r_data[3]<=0;
r_data[4]<=0;
r_data[5]<=0;
r_data[6]<=0;
r_data[7]<=0;
end
5, 6, 7, 8, 9, 10,11 : sta_bit <=sta_bit + rs232_rx_pin;//起始位判断
21,22,23,24,25,26,27 : r_data[0]<=r_data[0] + rs232_rx_pin;//分成16次,但是只取该16次中的中间其次来判断,下同。
37,38,39,40,41,42,43 : r_data[1]<=r_data[1] + rs232_rx_pin;
53,54,55,56,57,58,59 : r_data[2]<=r_data[2] + rs232_rx_pin;
69,70,71,72,73,74,75 : r_data[3]<=r_data[3] + rs232_rx_pin;
85,86,87,88,89,90,91 : r_data[4]<=r_data[4] + rs232_rx_pin;
101,102,103,104,105,106,107 : r_data[5]<=r_data[5] + rs232_rx_pin;
117,118,119,120,121,122,123 : r_data[6]<=r_data[6] + rs232_rx_pin;
133,134,135,136,137,138,139 : r_data[7]<=r_data[7] + rs232_rx_pin;
149,150,151,152,153,154,155 : stp_bit <=stp_bit + rs232_rx_pin;//结束位
default : ;
endcase
end
end
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
now_rx_data <= 8'b0000_0000;
else if(bps_cnt==159)//到159取数即可。
begin
now_rx_data[0] <= (r_data[0]>4)? 1'b1 :1'b0;
now_rx_data[1] <= (r_data[1]>4)? 1'b1 :1'b0;
now_rx_data[2] <= (r_data[2]>4)? 1'b1 :1'b0;
now_rx_data[3] <= (r_data[3]>4)? 1'b1 :1'b0;
now_rx_data[4] <= (r_data[4]>4)? 1'b1 :1'b0;
now_rx_data[5] <= (r_data[5]>4)? 1'b1 :1'b0;
now_rx_data[6] <= (r_data[6]>4)? 1'b1 :1'b0;
now_rx_data[7] <= (r_data[7]>4)? 1'b1 :1'b0;
end
else
now_rx_data <= now_rx_data ;
end
//finish_receive
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
finish_receive <= 1’b0;
else if(bps_cnt==159)//到159取数即可。
finish_receive <= 1’b1;
else if(start_rx_negedge)
finish_receive <= 1’b0;
else
finish_receive <= finish_receive ;
end
endmodule