uart rx 接收(rx)模块
第一部分 接收模块
第二部分 数码管显示
第三部分 顶层调用
//uart 接收模块
// 宏定义 校验位
`define NONE 0
`define ODD 1
`define EVEN 2
`define SPACE 3
`define MARK 4
//宏定义停止位
`define STOP_ONE 0
`define STOP_ONEHALF 1
`define STOP_TWO 2
module uart_rx2
#(
parameter CLK =50_000_000, //时钟
parameter BAUD =9600, //波特率
parameter DATABITS = 8, //数据位
parameter PARITY = `NONE , //校验情况
parameter STOPBITS =`STOP_ONE //停止位数量
)
(
input wire clk,
input wire rst,
input wire rx,
output reg done, //接收完成,输出信号
output reg err, // 错误输出
output reg [DATABITS -1:0] data //数据位个数
);
//*****************************************************************
reg [31:0 ] cnt;
reg [2:0] rx_r;
reg flag; //定义检测开始时,信号拉起
reg sampling; //采样信号
wire enable; // 边沿检测信号
reg [3:0] num; //数据位个数变量
reg [2:0] cstate; // 状态变量
reg databit; //检测到第一位数据
localparam cnt_max=CLK /BAUD ; //接收数据的时钟周期
localparam fsm_idel =0;
localparam fsm_start =1;
localparam fsm_data =2;
localparam fsm_parity =3;
localparam fsm_stop =4;
//******************************************************************
// 边沿检测,寄存两拍
always@(posedge clk or posedge rst) begin
if(rst)
rx_r<=0;
else begin
rx_r[1:0]<={rx_r[0] , rx };
rx_r[2:1]<={rx_r[1] , rx_r[0]};
end
end
assign enable=(rx_r[2:1]== 2'b10) ? 1 :0;
//拉起信号
always@(posedge clk or posedge rst) begin
if(rst)
flag<=0;
else if(sampling && cstate==fsm_stop)
flag<=0;
else if(enable)
flag<=1;
else
flag<=flag;
end
//取值信号
always@(posedge clk or posedge rst) begin
if(rst)
sampling<=0;
else if(cnt==cnt_max>>1)
sampling<=1;
else
sampling<=0;
end
//计数器
always@(posedge clk or posedge rst) begin
if(rst)
cnt<=0;
else if(flag==0 || cnt==cnt_max-1)
cnt<=0;
else if(flag)
cnt<=cnt+1;
end
//状态的输出,转移和判断
always@(posedge clk or posedge rst) begin
if(rst) begin
cstate<=fsm_idel;
err<=0;
done<=0;
end
else
case(cstate)
fsm_idel : begin
err<=0;
done<=0;
if (flag)
cstate<=fsm_start;
else
cstate<=fsm_idel;
end
fsm_start : begin
if (sampling) begin
databit=rx;
if(databit)
cstate<=fsm_idel;
else
cstate<=fsm_data;
end
else
cstate<=fsm_start;
end
fsm_data : begin
if (sampling && num<=DATABITS -1)
begin
data[num]<=rx;
num<=num+1;
end
else if (num==DATABITS ) begin
cstate<=ifparity ? fsm_parity : fsm_stop;
num<=0;
end
else
cstate<=fsm_data;
end
fsm_parity : begin
if(sampling) begin
cstate<=fsm_stop;
if(parity_value==rx)
err<=0;
else
err<=1;
end
else
cstate<=fsm_parity;
end
fsm_stop : begin
if(sampling ) begin
done<=1;
if(rx)
cstate<=fsm_idel;
else
err<=1;
end
else
cstate<=fsm_stop;
end
default : cstate<=fsm_idel;
endcase
end
reg parity_value; //检验位的值
reg ifparity; //有无校验位
always@(*) begin
if(rst)
parity_value=0;
else
case(PARITY )
`NONE :begin parity_value=0 ; ifparity=0; end
`ODD :begin parity_value=~(^data);ifparity=1 ; end
`EVEN :begin parity_value=^data; ifparity=1; end
`SPACE :begin parity_value=0;ifparity=1; end
`MARK :begin parity_value=1;ifparity=1; end
default :begin parity_value=0;ifparity=1; end
endcase
end
endmodule