夏老师,您好啊!我自己经过查资料,写了一个关于UART的自发自收的程序。我用串口助手发任何一个数据,他都能接受到。但是连续发两个级以上数据,就收不到,或只是错误的数据。这是什么原因呢?
我自己的程序如下:
接收:module uart_rx(bclk,rst_n,rxdr,rx_ready,rbuf);
input bclk,rst_n,rxdr;
output rx_ready;
output [7:0] rbuf;
reg rx_ready;
reg [7:0] rbuf;
reg[4:0]cnt;
reg[3:0]dcnt;
reg [2:0] state;
parameter [3:0] lframe =8;
parameter [2:0] s_start =3'b000;
parameter [2:0] s_center =3'b001;
parameter [2:0] s_wait =3'b010;
parameter [2:0] s_sample =3'b011;
parameter [2:0] s_stop =3'b100;
always @(posedge bclk)begin
if(!rst_n)begin
rx_ready<=1'b0;
cnt <=5'b00000;
dcnt <=4'b0000;
state <=s_start;
rbuf <=8'b0000_0000;
end
else begin
case(state)
s_start:begin
if(rxdr==1'b0)begin
state <=s_center;
rx_ready<=1'b0;
dcnt <=4'b0;
end
else begin
state <=s_start;
rx_ready<=1'b1;
dcnt <=4'b0;
end
end
s_center:begin
if(rxdr==1'b0)begin
if(cnt==5'b00100)begin
state<=s_wait;
cnt<=5'b00000;
end
else begin
state<=s_center;
cnt<=cnt+1'b1;
end
end
else begin
state<=s_start;
rx_ready<=1'b1;
end
end
s_wait:begin
if(cnt==5'b01111)begin
cnt<=5'b00000;
if(dcnt==lframe)begin
state<=s_stop;
end
else begin
state<=s_sample;
end
end
else begin
cnt<=cnt+1'b1;
state<=s_wait;
end
end
s_sample:begin
rbuf[dcnt]<=rxdr;
dcnt<=dcnt+1'b1;
state<=s_wait;
end
s_stop:begin
rx_ready<=1'b0;
// if(cnt==5'b01111)begin
state<=s_start;
// cnt<=5'b0;
// end
// else begin
// state<=s_stop;
// cnt<=cnt+1'b1;
// end
end
endcase
end
end
endmodule
发送:module uart_tx(bclk,reset,tx_din,tx_cmd,tx_ready,txd);
input bclk; //发送模块的工作时钟
input reset; //发送模块的复位信号,高有效
input tx_cmd; //发送控制信号,高有效
input [7:0] tx_din; //期望发送的字节
output tx_ready; //发送完成指示信号
output txd; //串口发送数据
reg tx_ready;
//定义串口参数
parameter[3:0] lframe=8;
parameter[2:0] s_idle =3'b000;
parameter[2:0] s_start=3'b001;
parameter[2:0] s_wait =3'b010;
parameter[2:0] s_shift=3'b011;
parameter[2:0] s_stop =3'b100;
//parameter[7:0] din=8'b10100101;
//定义所需的中间变量
//发送模块状态机的状态寄存器
reg [2:0]state=s_idle;
reg [3:0]cnt=0;
reg [3:0]dcnt=0;
//reg [7:0]din; //
reg txdt;
assign txd=txdt;
//always@(posedge bclk)begin //
// din<=tx_din; //
//end //
always@(posedge bclk)begin
if(!reset)begin
state <=s_idle;
cnt <=0;
tx_ready<=0;
txdt <=0;
end
else
begin
case(state)
s_idle:begin //空闲状态,检测发送指示信令
tx_ready<=1;
cnt<=0;
txdt<=1'b1;
if(tx_cmd==1'b1)
state<=s_start;
else
state<=s_idle;
end
s_start:begin //发送模块的开始状态
tx_ready<=0;
txdt<=1'b0;
state<=s_wait;
end
s_wait:begin //延时等待状态,使每个有效数据保持16个bclk周期
//从而得到9600的波特率
tx_ready<=0;
if(cnt>=4'b1110)begin
cnt<=0;
if(dcnt==lframe)begin
state<=s_stop;
dcnt<=0;
txdt<=1'b1;
end
else begin
state<=s_shift;
txdt<=txdt;
end
end
else begin
state<=s_wait;
cnt<=cnt+1'b1;
end
end
s_shift:begin //移位状态,每进入一次就将下一个发送比特移动到发送数据端口上
tx_ready<=0;
txdt<=tx_din[dcnt]; //
dcnt<=dcnt+1'b1;
state<=s_wait;
end
s_stop:begin
txdt<=1'b1;
if(cnt>=4'b1110)begin
if(tx_cmd==1'b0)begin
state<=s_idle;
cnt<=0;
tx_ready<=1;
end
else begin
state<=s_stop;
cnt<=cnt;
tx_ready<=1;
end
end
else begin
state<=s_stop;
cnt<=cnt+1'b1;
end
end
endcase
end
end
endmodule |