module ser_rx(clk,rst,rx,rx_done,rx_state,outdata);
input clk;
input rst;
input rx;
output reg[7:0]outdata;
output reg rx_done;
output reg rx_state;
reg[15:0] baud = 16'd324;
//9600=324, 19200=162, 38400=80, 57600=53, 115200=26.
//设置波特率:
//对每一bit进行16次采样,分为【5+6+5】,将中间六次作为稳定期
//并将其累加,所得结果可能为:000,001,010,011,100,101,110
//我们认定在采样期间出现3次以上为1,那么就认定此bit为1.
//即:中间六次采样累加的结果的最高位为1,就认定此bit为1.
//9600bit/s -》 1bit=104167ns -》104167/20ns(50Mhz)=5208个时钟 -》5208/16(次采样)=325个时钟
//对系统时钟计数从0~324 正好为325次
//同步
reg sync1,sync2;
always@(posedge clk or negedge rst)
if(!rst)
begin
sync1 <= 1'b0;
sync2 <= 1'b0;
end
else
begin
sync1 <= rx;
sync2 <= sync1;
end
//产生符合时间标准的采样flag
reg[15:0] cnt;
reg flag;
always@(posedge clk or negedge rst)
if(!rst)
cnt <= 16'b0;
else if(rx_state)begin
if(cnt == baud)
cnt <= 16'd0;
else
cnt <= cnt + 16'd1;
end
else
cnt <= 16'd0;
always@(posedge clk or negedge rst)
if(!rst)
flag <= 1'b0;
else if(cnt == 16'd1)
flag <= 1'b1;
else
flag <= 1'b0;
//串口数据为10bit 10*16=160,所以一组数据需要160个采样flag
reg [8:0] cnt_for_flag;
always@(posedge clk or negedge rst)
if(!rst)
cnt_for_flag <= 8'd0;
else if(cnt_for_flag == 8'd159 || (cnt_for_flag == 8'd12 && accum_START_BIT > 2'd2 ))
//计满 或 出现起始位出错[当计数到12时(这时对起始位的采样累加已经完成)但是采到1的次数大于2(but起始位为低电平)]将计数器清零!
cnt_for_flag <= 8'd0;
else if(flag)
cnt_for_flag <= cnt_for_flag + 1'd1;
else
cnt_for_flag <= cnt_for_flag;
//多路器,数据端为下面这三个寄存器,选择端为cnt_for_flag的特定计数值,当处于特定计数值的时候下面这三个某个寄存器会与sync2进行累加
reg [2:0]accum_START_BIT;
reg [2:0]accum_STOP_BIT;
reg [2:0]accum_data[7:0]; //累加寄存器(深度为8bit,宽度为3bit)
always@(posedge clk or negedge rst)
if(!rst) begin
accum_START_BIT <= 3'd0;
accum_data[0] <= 3'd0;
accum_data[1] <= 3'd0;
accum_data[2] <= 3'd0;
accum_data[3] <= 3'd0;
accum_data[4] <= 3'd0;
accum_data[5] <= 3'd0;
accum_data[6] <= 3'd0;
accum_data[7] <= 3'd0;
accum_STOP_BIT <= 3'd0;
end
else if(flag)
case(cnt_for_flag)
0:begin
accum_START_BIT <= 3'd0;
accum_data[0] <= 3'd0;
accum_data[1] <= 3'd0;
accum_data[2] <= 3'd0;
accum_data[3] <= 3'd0;
accum_data[4] <= 3'd0;
accum_data[5] <= 3'd0;
accum_data[6] <= 3'd0;
accum_data[7] <= 3'd0;
accum_STOP_BIT <= 3'd0;
end
6,7,8,9,10,11:accum_START_BIT <= accum_START_BIT + sync2;
22,23,24,25,26,27:accum_data[0] <= accum_data[0] + sync2;
38,39,40,41,42,43:accum_data[1] <= accum_data[1] + sync2;
54,55,56,57,58,59:accum_data[2] <= accum_data[2] + sync2;
70,71,72,73,74,75:accum_data[3] <= accum_data[3] + sync2;
86,87,88,89,90,91:accum_data[4] <= accum_data[4] + sync2;
102,103,104,105,106,107:accum_data[5] <= accum_data[5] + sync2;
118,119,120,121,122,123:accum_data[6] <= accum_data[6] + sync2;
134,135,136,137,138,139:accum_data[7] <= accum_data[7] + sync2;
150,151,152,153,154,155:accum_STOP_BIT <= accum_STOP_BIT + sync2;
default:
begin
accum_START_BIT <= accum_START_BIT;
accum_data[0] <= accum_data[0];
accum_data[1] <= accum_data[1];
accum_data[2] <= accum_data[2];
accum_data[3] <= accum_data[3];
accum_data[4] <= accum_data[4];
accum_data[5] <= accum_data[5];
accum_data[6] <= accum_data[6];
accum_data[7] <= accum_data[7];
accum_STOP_BIT <= accum_STOP_BIT;
end
endcase
//取累加结果的最高位,作为最终结果
always@(posedge clk or negedge rst)
if(!rst)
outdata <= 8'd0;
else if(cnt_for_flag == 8'd159)
begin
outdata[0] <= accum_data[0][2];
outdata[1] <= accum_data[1][2];
outdata[2] <= accum_data[2][2];
outdata[3] <= accum_data[3][2];
outdata[4] <= accum_data[4][2];
outdata[5] <= accum_data[5][2];
outdata[6] <= accum_data[6][2];
outdata[7] <= accum_data[7][2];
end
//一次接收完成标志“rx_done”
always@(posedge clk or negedge rst)
if(!rst)
rx_done <= 1'd0;
else if(cnt_for_flag == 8'd159)
rx_done <= 1'd1;
else
rx_done <= 1'd0;
//下降沿检测:用于检测从空闲到检测起始位那个下降沿
wire f_edge;
reg data1,data2;
always@(posedge clk or negedge rst)
if(!rst)
begin
data1 <= 1'b0;
data2 <= 1'b0;
end
else
begin
data1 <= sync2;
data2 <= data1;
end
assign f_edge = !data1 && data2;
//输出工作状态:rx_state,从空闲到起始位的下降沿开始 至 一次数据接收完成
always@(posedge clk or negedge rst)
if(!rst)
rx_state <= 1'b0;
else if(f_edge)
rx_state <= 1'b1;
else if(rx_done || (cnt_for_flag == 8'd12 && (accum_START_BIT > 2)))
rx_state <= 1'b0;
else
rx_state <= rx_state;
endmodule
【verilog】UART 串口接收(FPGA)
于 2021-02-23 15:29:47 首次发布