学习了使用FPGA-UART串口接收数据,做个小结
module uart_byte_rx(
clk,
reset_n,
baud_set,
uart_rx,
data_byte,
rx_done
);
input clk; //时钟输入
input reset_n; //复位信号输入
input [2:0] baud_set; //波特率设置
input uart_rx; //串口输入信号
output reg [7:0]data_byte; //串口接收的1byte数据
output reg rx_done; //1byte数据接收完成标志
parameter CLK_FRQ = 50000000;
localparam BAUD_9600_CNT = CLK_FRQ/9600/16 - 2;
localparam BAUD_19200_CNT = CLK_FRQ/19200/16 - 2;
localparam BAUD_38400_CNT = CLK_FRQ/38400/16 - 2;
localparam BAUD_57600_CNT = CLK_FRQ/57600/16 - 2;
localparam BAUD_115200_CNT = CLK_FRQ/115200/16 - 2;
localparam BAUD_1562500_CNT = CLK_FRQ/1562500/16 - 2;
reg uart_rx_sync1; //同步寄存器
reg uart_rx_sync2; //同步寄存器
reg uart_rx_reg1; //数据寄存器
reg uart_rx_reg2; //数据寄存器
reg [15:0]bps_DR; //分频计数最大值
reg [15:0]div_cnt; //分频计数器
reg bps_clk; //波特率时钟
reg [7:0] bps_cnt; //波特率时钟计数器
reg uart_state;//接收数据状态
wire uart_rx_nedge;
reg [2:0] START_BIT;
reg [2:0] STOP_BIT;
reg [2:0] data_byte_pre [7:0];
//同步串行输入信号,消除亚稳态
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
uart_rx_sync1 <= 1'b0;
uart_rx_sync2 <= 1'b0;
end
else begin
uart_rx_sync1 <= uart_rx;
uart_rx_sync2 <= uart_rx_sync1;
end
//数据寄存器
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
uart_rx_reg1 <= 1'b0;
uart_rx_reg2 <= 1'b0;
end
else begin
uart_rx_reg1 <= uart_rx_sync2;
uart_rx_reg2 <= uart_rx_reg1;
end
//下降沿检测
assign uart_rx_nedge = !uart_rx_reg1 & uart_rx_reg2;
always@(posedge clk or negedge reset_n)
if(!reset_n)
bps_DR <= 16'd324;
else begin
case(baud_set)
0:bps_DR <= BAUD_9600_CNT;
1:bps_DR <= BAUD_19200_CNT;
2:bps_DR <= BAUD_38400_CNT;
3:bps_DR <= BAUD_57600_CNT;
4:bps_DR <= BAUD_115200_CNT;
5:bps_DR <= BAUD_1562500_CNT;
default:bps_DR <= BAUD_9600_CNT;
endcase
end
//counter
always@(posedge clk or negedge reset_n)
if(!reset_n)
div_cnt <= 16'd0;
else if(uart_state)begin
if(div_cnt == bps_DR)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 16'd0;
// bps_clk gen
always@(posedge clk or negedge reset_n)
if(!reset_n)
bps_clk <= 1'b0;
else if(div_cnt == 16'd1)
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
//一个字节数据(START+8BIT+STOP=10位)用16个采样时钟进行计数 16*10=160
//取6 7 8 9 10 11的多次采样数值来确定此次传输数据的高低位,避免电磁干扰产生的错误数据
//bps counter
always@(posedge clk or negedge reset_n)
if(!reset_n)
bps_cnt <= 8'd0;
else if(bps_cnt == 8'd159 | (bps_cnt == 8'd12 && (START_BIT > 2))) //一字节数据计数160次传输完/第一个START信号传输完判断是否为低电平
bps_cnt <= 8'd0;
else if(bps_clk)
bps_cnt <= bps_cnt + 1'b1;
else
bps_cnt <= bps_cnt;
always@(posedge clk or negedge reset_n)
if(!reset_n)
rx_done <= 1'b0;
else if(bps_cnt == 8'd159)
rx_done <= 1'b1;
else
rx_done <= 1'b0;
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
START_BIT <= 3'd0;
data_byte_pre[0] <= 3'd0;
data_byte_pre[1] <= 3'd0;
data_byte_pre[2] <= 3'd0;
data_byte_pre[3] <= 3'd0;
data_byte_pre[4] <= 3'd0;
data_byte_pre[5] <= 3'd0;
data_byte_pre[6] <= 3'd0;
data_byte_pre[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
else if(bps_clk)begin
case(bps_cnt)
0:begin
START_BIT <= 3'd0;
data_byte_pre[0] <= 3'd0;
data_byte_pre[1] <= 3'd0;
data_byte_pre[2] <= 3'd0;
data_byte_pre[3] <= 3'd0;
data_byte_pre[4] <= 3'd0;
data_byte_pre[5] <= 3'd0;
data_byte_pre[6] <= 3'd0;
data_byte_pre[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
6 ,7 ,8 ,9 ,10,11:START_BIT <= START_BIT + uart_rx_sync2;
22,23,24,25,26,27:data_byte_pre[0] <= data_byte_pre[0] + uart_rx_sync2;
38,39,40,41,42,43:data_byte_pre[1] <= data_byte_pre[1] + uart_rx_sync2;
54,55,56,57,58,59:data_byte_pre[2] <= data_byte_pre[2] + uart_rx_sync2;
70,71,72,73,74,75:data_byte_pre[3] <= data_byte_pre[3] + uart_rx_sync2;
86,87,88,89,90,91:data_byte_pre[4] <= data_byte_pre[4] + uart_rx_sync2;
102,103,104,105,106,107:data_byte_pre[5] <= data_byte_pre[5] + uart_rx_sync2;
118,119,120,121,122,123:data_byte_pre[6] <= data_byte_pre[6] + uart_rx_sync2;
134,135,136,137,138,139:data_byte_pre[7] <= data_byte_pre[7] + uart_rx_sync2;
150,151,152,153,154,155:STOP_BIT <= STOP_BIT + uart_rx_sync2;
default:
begin
START_BIT <= START_BIT;
data_byte_pre[0] <= data_byte_pre[0];
data_byte_pre[1] <= data_byte_pre[1];
data_byte_pre[2] <= data_byte_pre[2];
data_byte_pre[3] <= data_byte_pre[3];
data_byte_pre[4] <= data_byte_pre[4];
data_byte_pre[5] <= data_byte_pre[5];
data_byte_pre[6] <= data_byte_pre[6];
data_byte_pre[7] <= data_byte_pre[7];
STOP_BIT <= STOP_BIT;
end
endcase
end
//将读到的data保存到寄存器
always@(posedge clk or negedge reset_n)
if(!reset_n)
data_byte <= 8'd0;
else if(bps_cnt == 8'd159)begin
data_byte[0] <= data_byte_pre[0][2];
data_byte[1] <= data_byte_pre[1][2];
data_byte[2] <= data_byte_pre[2][2];
data_byte[3] <= data_byte_pre[3][2];
data_byte[4] <= data_byte_pre[4][2];
data_byte[5] <= data_byte_pre[5][2];
data_byte[6] <= data_byte_pre[6][2];
data_byte[7] <= data_byte_pre[7][2];
end
always@(posedge clk or negedge reset_n)
if(!reset_n)
uart_state <= 1'b0;
else if(uart_rx_nedge)
uart_state <= 1'b1;
else if(rx_done || (bps_cnt == 8'd12 && (START_BIT > 2)) || (bps_cnt == 8'd155 && (STOP_BIT < 3)))
uart_state <= 1'b0;
else
uart_state <= uart_state;
endmodule