module uart_byte_rx(
clk ,//50MHz时钟
rst_n ,//复位
baud_set ,//波特率设置
rs232_rx ,//rs232数据接收
data_byte ,//并行数据输出
rx_done //单个字节接收完标志
);
//参数定义s
parameter DATA_W = 8;
parameter BAUS_W = 3;
parameter DABS_W = 3;
parameter BAUV_W = 13;
parameter CNTB_W = 8;
parameter RDAB_W = 3;
parameter RDAB_N = 8;
//输入信号定义
input clk ;
input rst_n ;
input [BAUS_W-1:0] baud_set ;
input rs232_rx ;
//输出信号定义
output[DATA_W-1:0] data_byte ;
output rx_done ;
//输出信号定义
reg [DATA_W-1:0] data_byte ;
wire rx_done ;
//中间信号定义
reg uart_state ;//串口接收状态
reg [DABS_W-1:0] data_byt_syn;
wire nedge ;
reg [BAUV_W-1:0] baud_div ;//波特率分频值
reg [BAUV_W-1:0] cnt_div ;//分频计数器
wire add_cnt_div ;
wire end_cnt_div ;
reg [CNTB_W-1:0] cnt_byt ;
wire add_cnt_byt ;
wire end_cnt_byt ;
reg [RDAB_W-1:0] start_bit ;
reg [RDAB_W-1:0] stop_bit ;
reg [RDAB_W-1:0] r_data_byte[RDAB_N-1:0];//RDAB_N寄存器,每个寄存器位宽为RDAB_W
//接入两个D触发器,对异步数据进行同步化处理
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
data_byt_syn <= 0;
end
else begin
data_byt_syn <= {data_byt_syn[1:0],rs232_rx};
end
end
assign nedge = (data_byt_syn[2:1] == 2‘b10);
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
uart_state <= 0;
end
else if(nedge) begin
uart_state <= 1;//检测到起始位0
end
else if(end_cnt_byt)begin
uart_state <= 0;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
baud_div <= 0;
end
else begin
//取16个采样点
case (baud_set)
0 : baud_div <= 13‘d5208;//600bps/16
1 : baud_div <= 13‘d2604;//1200bps/16
2 : baud_div <= 13‘d1302;//2400bps/16
3 : baud_div <= 13‘d651 ;//4800bps/16
4 : baud_div <= 13‘d325 ;//9600bps/16
5 : baud_div <= 13‘d163 ;//19200bps/16
6 : baud_div <= 13‘d81 ;//38400bps/16
7 : baud_div <= 13‘d54 ;//57600bps/16
default:
baud_div <= 0;
endcase
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_div <= 0;
end
else if(add_cnt_div)begin
if(end_cnt_div)
cnt_div <= 0;
else
cnt_div <= cnt_div + 1‘b1;
end
end
assign add_cnt_div = (uart_state == 1);
assign end_cnt_div = add_cnt_div && cnt_div == baud_div-1 ;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_byt <= 0;
end
else if(add_cnt_byt)begin
if(end_cnt_byt)
cnt_byt <= 0;
else
cnt_byt <= cnt_byt + 1‘b1;
end
end
assign add_cnt_byt = (end_cnt_div == 1);
assign end_cnt_byt = (add_cnt_byt && cnt_byt == 160-1) || (start_bit > 2);//10个比特,每个比特采样16个点
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
start_bit <= 0;
r_data_byte[0] <= 0;
r_data_byte[1] <= 0;
r_data_byte[2] <= 0;
r_data_byte[3] <= 0;
r_data_byte[4] <= 0;
r_data_byte[5] <= 0;
r_data_byte[6] <= 0;
r_data_byte[7] <= 0;
stop_bit <= 0;
end
else if(uart_state) begin
case (cnt_byt)
//在16个点中,取样中间6个点
5,6,7,8,9,10 : start_bit <= start_bit + rs232_rx;
21,22,23,24,25,26 : r_data_byte[0] <= r_data_byte[0] + rs232_rx;
37,38,39,40,41,42 : r_data_byte[1] <= r_data_byte[1] + rs232_rx;
53,54,55,56,57,58 : r_data_byte[2] <= r_data_byte[2] + rs232_rx;
69,70,71,72,73,74 : r_data_byte[3] <= r_data_byte[3] + rs232_rx;
85,86,87,88,89,90 : r_data_byte[4] <= r_data_byte[4] + rs232_rx;
101,102,103,104,105,106 : r_data_byte[5] <= r_data_byte[5] + rs232_rx;
117,118,119,120,121,122 : r_data_byte[6] <= r_data_byte[6] + rs232_rx;
133,134,135,136,137,138 : r_data_byte[7] <= r_data_byte[7] + rs232_rx;
149,150,151,152,153,154 : stop_bit <= stop_bit + rs232_rx;
default: begin
start_bit <= start_bit;
r_data_byte[0] <= r_data_byte[0];
r_data_byte[1] <= r_data_byte[1];
r_data_byte[2] <= r_data_byte[2];
r_data_byte[3] <= r_data_byte[3];
r_data_byte[4] <= r_data_byte[4];
r_data_byte[5] <= r_data_byte[5];
r_data_byte[6] <= r_data_byte[6];
r_data_byte[7] <= r_data_byte[7];
stop_bit <= stop_bit;
end
endcase
end
else begin
start_bit <= 0;
r_data_byte[0] <= 0;
r_data_byte[1] <= 0;
r_data_byte[2] <= 0;
r_data_byte[3] <= 0;
r_data_byte[4] <= 0;
r_data_byte[5] <= 0;
r_data_byte[6] <= 0;
r_data_byte[7] <= 0;
stop_bit <= 0;
end
end
always@(posedge clk or negedge rst_n)begin
if(rst_n==1‘b0)begin
data_byte <= 0;
end
else if(end_cnt_byt)begin
//取r_data_byte的最高位,当r_data_byte[n]中取样‘1‘的个数大于或等于4时,该比特位为1,否则为0
data_byte[0] <= r_data_byte[0][2];
data_byte[1] <= r_data_byte[1][2];
data_byte[2] <= r_data_byte[2][2];
data_byte[3] <= r_data_byte[3][2];
data_byte[4] <= r_data_byte[4][2];
data_byte[5] <= r_data_byte[5][2];
data_byte[6] <= r_data_byte[6][2];
data_byte[7] <= r_data_byte[7][2];
end
end
assign rx_done = (add_cnt_byt && cnt_byt == 160 - 1);
endmodule