大神帮帮忙啊
时间:10-02
整理:3721RD
点击:
我写了一个FPGA串口代码和单片机进行通信,可是数据老是不稳定,会出错不知道是哪里的问题,仿真没有问题。
接收部分代码:module jieshou(clk,rst,rxd,rxdata,rxflag);
input clk;//系统时钟
input rst;//全局复位高电平复位
input rxd;//UART接收信号
output rxflag;
reg rxflag;//接收完一个字节标志位
output [7:0]rxdata;//接受数据
reg rec1;//检测下降沿
reg rec2;
wire rec3;//接收信号下降沿
reg rena;//内部接收使能信号
reg clk_top;//波特率57600时钟
reg [3:0]cout;
reg[9:0]dout;//接收数据寄存器
reg [9:0]cnt_bote;//分频计数器
//reg [9:0]count;
assign rxdata=dout[8:1];//最终数据输出
///////////////////分频模块/////////////////只产生一个时钟的高电平
always @(posedge clk or posedge rst)begin
if(rst)begin
cnt_bote<=10'd0;
clk_top<=1'b0;
end
else if(cnt_bote == 10'd867)begin//57600分频数
clk_top<=1'b1;
cnt_bote<=10'd0;
end
else begin
clk_top<=1'b0;
cnt_bote<=cnt_bote+1'b1;
end
end
/*always @(posedge clk or posedge rst)
begin
if(rst)
count<=10'd0;
else begin
if((~rxd)&&(cout==0)) count<=count+1'b1;
else count<=10'd0;
end
end */
//////////////////////////下降沿检测////////////
always@(posedge clk or posedge rst)begin
if(rst)
begin
rec1 <= 1'b1;
rec2 <= 1'b1;
end
else begin
rec1 <= rxd;
rec2 <= rec1;
end
end
assign rec3 = !rec1 & rec2;
/////////////////内部接收使能信号////////////
always@(posedge clk or posedge rst)begin
if(rst)
rena <= 1'b0;
else if(rec3)//下降沿到来
rena <= 1'b1;
else if(cout == 4'd10)//接受完一个字节接收使能信号复位
rena <= 1'b0;
else
rena <= rena;
end
/////////////////////接收完毕信号/////////////////
always@(posedge clk or posedge rst)begin
if(rst)
rxflag <= 1'b0;
else if(cout == 4'd10)//接受完一个字节,将接收完毕标志位置1两个周期
rxflag <= 1'b1;
else
rxflag <= 1'b0;
end
//////////////////////////////////////接收主程序部分/////////////
always @(posedge clk or posedge rst)
begin
if(rst)
begin //复位信号
dout<=10'dz;
end
else if((rena==1) & (clk_top==1))begin//检测到下降沿到来且波特率时钟为高电平
case(cout)
4'd0: dout[0]<=rxd;//起始位
4'd1: dout[1]<=rxd;//最低位
4'd2: dout[2]<=rxd;
4'd3: dout[3]<=rxd;
4'd4: dout[4]<=rxd;
4'd5: dout[5]<=rxd;
4'd6: dout[6]<=rxd;
4'd7: dout[7]<=rxd;
4'd8: dout[8]<=rxd;//最高位
4'd9: dout[9]<=rxd; //停止位1
4'd10: ;
//rec1<=1'b1;
//rec2<=1'b1;
//dout<=10'dz;
default:;
endcase
end
end
//////////////////接收逻辑计数部分////////////
always @(posedge clk or posedge rst)begin
if(rst)
cout<=4'd0;//计数器清0
else if(rena && clk_top)//接收计数器计数
cout<=cout+4'd1;
else if(!rena)
cout<=4'd0;
else
cout <= cout;
end
endmodule
发送部分代码:module FS_module(clk,rst,txd,txdata,txflag,txbsy,txcom);
input clk,rst,txflag;//系统时钟,全局复位高电平复位,发送启动信号
input [7:0]txdata;//将要发送的数据
output txcom;//发送完毕信号
output txd,txbsy;//UART发送信号,发送忙信号
reg [9:0]txcnt;
reg txd;
reg rena;//发送使能信号
reg txClk;//分频时钟波特率57600
reg txcom;//发送完一个字节
reg [3:0]txstate;
reg txbsy;//发送忙
parameter S0=4'd0;
parameter S1=4'd1;
parameter S2=4'd2;
parameter S3=4'd3;
parameter S4=4'd4;
parameter S5=4'd5;
parameter S6=4'd6;
parameter S7=4'd7;
parameter S8=4'd8;
parameter S9=4'd9;
parameter S10=4'd10;
///////////////////分频模块/////////////////
always @(posedge clk or posedge rst)begin
if(rst)begin
txcnt<=10'd0;//分频计数器
txClk<=1'b0;
end
else if(txcnt==868)begin //57600波特率
txClk<=1'b1;//产生一个周期的高电平
txcnt<=0;
end
else
begin
txClk<=1'b0;
txcnt<=txcnt+1'b1;
end
end
///////////////发送忙信号/////////////////
always@(posedge clk or posedge rst)begin
if(rst)
txbsy <= 1'b0;
else if(txflag)//当发送信号拉高发送忙标志拉高
txbsy <= 1'b1;
else if(txstate == S0 && !rena)//当发送完毕发送忙标志拉低
txbsy <= 1'b0;
else
txbsy <= txbsy;
end
///////////////发送使能信号/////////////
always@(posedge clk or posedge rst)begin
if(rst)
rena <= 1'b0;
else if(txflag)
rena <= 1'b1;
else if(txstate == S1)//起始位发送就复位使能信号
rena <= 1'b0;
else
rena <= rena;
end
////////////////////////////发送数据//////////////////////
always @(posedge clk or posedge rst)begin //
if(rst)begin
txd<=1'b1;//让TXD为高电平
txstate<=S0;//状态机指向
//txbsy<=1'b0;//发送忙清0
txcom<=1'b0;//发送完毕复位
end
else if(txClk)begin
txcom<=1'b0; //发送完毕复位
case (txstate)
S0: begin //初始状态,检测发送标志位
if (rena)begin//发送使能信号
txstate<=S1;
end
else
txstate<=S0;
end
S1:begin //起始位发送
txd<=1'b0;//起始位
txstate<=S2;
end
S2:begin
txd<=txdata[0];//最低位
txstate<=S3;
end
S3:begin
txd<=txdata[1];//2
txstate<=S4;
end
S4:begin
txd<=txdata[2];//3
txstate<=S5;
end
S5:begin
txd<=txdata[3];//4
txstate<=S6;
end
S6:begin
txd<=txdata[4];//5
txstate<=S7;
end
S7:begin
txd<=txdata[5];//6
txstate<=S8;
end
S8:begin
txd<=txdata[6];//7
txstate<=S9;
end
S9:begin
txd<=txdata[7];//最高位
txstate<=S10;
end
S10:begin
txd<=1'b1; //停止位
//txbsy<=1'b0;//发送忙清0等待下次发送
txcom<=1'b1;//发送完一字节数据
txstate<=S0;
end
default :;
endcase
end
end
endmodule
顶层模块代码:module top_tb(
Clk,TXrst,RXD,TXD,RXdata,
//pane_data_out,
pane_cmd_en,
// pane_cmd_ack,pane_rd_ack,
// pane_data_in,pane_addr_in,
// pane_cmd_out,pane_addr_out
);
input Clk;//全局时钟
input TXrst;//全局复位高电平有效
//input [7:0]pane_data_in;
//input [15:0]pane_addr_in;
//input pane_rd_ack;
//input pane_cmd_ack;
reg [7:0] TXdata;//要发送的数据寄存器
output [7:0]RXdata;//接收数据输出
//output [7:0]pane_cmd_out;
//output[15:0]pane_addr_out;
//output[7:0]pane_data_out;
output pane_cmd_en;
input RXD;
output TXD;
reg TXflag;//发送启动信号
reg [3:0] TXstate;//发送状态
wire TXbsy;//发送忙
reg [7:0] pane_cmd_out;
reg [7:0] pane_cmd;
reg [7:0] pane_cmd0;
reg [7:0] pane_cmd1;
reg [7:0] pane_cmd2;
reg [7:0] pane_cmd3;
reg [7:0] pane_data_out;
wire [15:0]pane_addr_out;
reg [7:0] value;
reg pane_cmd_en;
reg pane_cmd_ack;
reg pane_rd_ack;
//reg[7:0] value1;
parameter s0=4'd0;
parameter s1=4'd1;
parameter s2=4'd2;
parameter s3=4'd3;
parameter s4=4'd4;
parameter s5=4'd5;
//这里设置初始值,否则调试会是不定态/////////
reg [7:0] txone = 8'h5a;
reg [7:0] txtwo = 8'h11;
reg [7:0] txthree = 8'h40;
reg [7:0] txfour = 8'h0b;
reg [7:0] txfive = 8'hfc;
reg [7:0] txsix = 8'h00;
reg [7:0] txseven = 8'hc3;
reg[2:0] TXcnt;//发送计数器
wire RXflag;//接收完一字节数据
parameter x0=4'd0;
parameter x1=4'd1;
parameter x2=4'd2;
parameter x3=4'd3;
reg [2:0]RXcnt;//接受计数器
reg [3:0]RXstate;
assign pane_addr_out={pane_cmd,pane_cmd1};
FS_module U1(
.clk(Clk),
.txdata(TXdata),
.txflag(TXflag),
.txd(TXD),
.rst(TXrst),
.txbsy(TXbsy)
);
///////////////////////////////////////////
/////////////////发送主程序////////////////
always @(posedge Clk or posedge TXrst) begin
if(TXrst)begin
TXstate<=s0;//给初值
TXflag<=1'b0;//复位清0
TXcnt<=3'd0;//复位清0
end
else begin
case (TXstate)
s0:begin
if((pane_cmd_ack==1'b1)&&(pane_rd_ack==1'b1))//接收7个字节数据完成,开始发送
begin
TXstate<=s1;
end
else begin
TXstate<=s0;//否则继续等待
end
end
s1:
begin
TXflag<=1'b0;//将发送启动标志位清0
if(TXbsy==1'b0)begin//判断一字节数据是不是发送完成,完成就让计数器加1.
TXcnt<=TXcnt+1'b1;
TXstate<=s2;
end
end
s2:
begin
TXstate<=s3;
case(TXcnt)
3'd1: TXdata<=txone;//需要发送的字节
3'd2: TXdata<=pane_cmd_out;//读写命令
3'd3: TXdata<=pane_cmd;//地址高八位
3'd4: TXdata<=pane_cmd1;//地址低八位
3'd5: TXdata<=pane_data_out;//数据位
3'd6: TXdata<=txsix;//预留位
3'd7: begin
TXdata<=(txone+pane_cmd+pane_cmd1+pane_data_out+txsix+pane_cmd_out);
//TXdata<=value1;//发送校验和
end
default:TXcnt<=3'd1;
endcase
end
s3:
begin
TXflag<=1'b1;
TXstate<=s4;
end
s4:
begin
if(TXcnt == 3'd7)begin//判断发送完七个字节
TXstate<=s5; end
else
TXstate<=s1;
end
s5:
begin
TXcnt<=3'd0;//发送完成计数器清0
TXstate<=s0;//发送完成状态机指向最初状态,等待下次发送
TXflag<=1'b0;//发送启动标志清0
end
default:
begin TXstate<=s0; end
endcase
end
end
/////////////////////调用接收部分///////////////////
//////////////////////////////////////////////////
jieshou U2(
.clk(Clk),
.rst(TXrst),
.rxd(RXD),
.rxdata(RXdata),
.rxflag(RXflag)
);
/////////////接收主程序//////////////////////////
//////////////////两个开始发送标志位/////////////
always @(posedge Clk or posedge TXrst)begin
if(TXrst)begin
pane_cmd_ack<=1'b0;
pane_rd_ack<=1'b0;
end
else if ((RXcnt==3'd7)&&(pane_cmd_en==1'b1)&&(pane_cmd_out==8'h11))//接收完7字节数据,第二字节为11,接收数据正确则让置1
begin
pane_cmd_ack<=1'b1;
pane_rd_ack<=1'b1;
end
else begin
pane_cmd_ack<=1'b0;
pane_rd_ack<=1'b0;end
end
always @(posedge Clk or posedge TXrst)
begin if(TXrst)
pane_cmd_en<=1'b0;
else if(value==pane_cmd3)//接收的前六个字节之和是不是等于第七个字节
begin
pane_cmd_en<=1'b1;//第7个字节等于前面六个字节之和将pane_cmd_en拉高
end
else
pane_cmd_en<=1'b0;//不等则不拉高pane_cmd_en
end
//////////////////////////////接收////
always @(posedge Clk or posedge TXrst)
begin if(TXrst)
begin
// RXflag<=1'b0;
RXstate<=x0;//接收状态机初值
end
else begin
case (RXstate)
x0:begin
RXcnt=3'd0;
RXstate<=x1;
end
x1:begin
if(RXflag==1) begin//接受完1字节数据
RXcnt<=RXcnt+1'b1;
case (RXcnt)
3'd0:
begin
pane_cmd0<=RXdata;//把第一个字节放进去
end
3'd1:
begin
pane_cmd_out<=RXdata;//把第二个字节放进去
end
3'd2:
begin
pane_cmd<=RXdata;//把第三个字节放进去
end
3'd3:
begin
pane_cmd1<=RXdata;//把第四个字节放进去
end
3'd4:
begin
pane_data_out<=RXdata;//把第五个字节放进去
end
3'd5:
begin
pane_cmd2<=RXdata;//把第六个字节放进去
end
3'd6:
begin
pane_cmd3<=RXdata;//把第七个字节放进去
value<=(pane_cmd0+pane_cmd_out+pane_cmd+pane_cmd1+pane_data_out+pane_cmd2);//校验和
end
3'd7:;
default:;
endcase
RXstate<=x2;
end
else
RXstate<=x1;//没有接收完则继续等待接收完成
end
x2:begin
if (RXcnt== 3'd7)begin//判断接收完成且接收正确
RXstate <= x3;end
else begin //如果没有接收完7字节则等待
RXstate <=x1;end
end
x3:begin
RXcnt<=3'd0;
RXstate <=x0;
end
default :RXstate <=x0;
endcase
end
end
endmodule
接收部分代码:module jieshou(clk,rst,rxd,rxdata,rxflag);
input clk;//系统时钟
input rst;//全局复位高电平复位
input rxd;//UART接收信号
output rxflag;
reg rxflag;//接收完一个字节标志位
output [7:0]rxdata;//接受数据
reg rec1;//检测下降沿
reg rec2;
wire rec3;//接收信号下降沿
reg rena;//内部接收使能信号
reg clk_top;//波特率57600时钟
reg [3:0]cout;
reg[9:0]dout;//接收数据寄存器
reg [9:0]cnt_bote;//分频计数器
//reg [9:0]count;
assign rxdata=dout[8:1];//最终数据输出
///////////////////分频模块/////////////////只产生一个时钟的高电平
always @(posedge clk or posedge rst)begin
if(rst)begin
cnt_bote<=10'd0;
clk_top<=1'b0;
end
else if(cnt_bote == 10'd867)begin//57600分频数
clk_top<=1'b1;
cnt_bote<=10'd0;
end
else begin
clk_top<=1'b0;
cnt_bote<=cnt_bote+1'b1;
end
end
/*always @(posedge clk or posedge rst)
begin
if(rst)
count<=10'd0;
else begin
if((~rxd)&&(cout==0)) count<=count+1'b1;
else count<=10'd0;
end
end */
//////////////////////////下降沿检测////////////
always@(posedge clk or posedge rst)begin
if(rst)
begin
rec1 <= 1'b1;
rec2 <= 1'b1;
end
else begin
rec1 <= rxd;
rec2 <= rec1;
end
end
assign rec3 = !rec1 & rec2;
/////////////////内部接收使能信号////////////
always@(posedge clk or posedge rst)begin
if(rst)
rena <= 1'b0;
else if(rec3)//下降沿到来
rena <= 1'b1;
else if(cout == 4'd10)//接受完一个字节接收使能信号复位
rena <= 1'b0;
else
rena <= rena;
end
/////////////////////接收完毕信号/////////////////
always@(posedge clk or posedge rst)begin
if(rst)
rxflag <= 1'b0;
else if(cout == 4'd10)//接受完一个字节,将接收完毕标志位置1两个周期
rxflag <= 1'b1;
else
rxflag <= 1'b0;
end
//////////////////////////////////////接收主程序部分/////////////
always @(posedge clk or posedge rst)
begin
if(rst)
begin //复位信号
dout<=10'dz;
end
else if((rena==1) & (clk_top==1))begin//检测到下降沿到来且波特率时钟为高电平
case(cout)
4'd0: dout[0]<=rxd;//起始位
4'd1: dout[1]<=rxd;//最低位
4'd2: dout[2]<=rxd;
4'd3: dout[3]<=rxd;
4'd4: dout[4]<=rxd;
4'd5: dout[5]<=rxd;
4'd6: dout[6]<=rxd;
4'd7: dout[7]<=rxd;
4'd8: dout[8]<=rxd;//最高位
4'd9: dout[9]<=rxd; //停止位1
4'd10: ;
//rec1<=1'b1;
//rec2<=1'b1;
//dout<=10'dz;
default:;
endcase
end
end
//////////////////接收逻辑计数部分////////////
always @(posedge clk or posedge rst)begin
if(rst)
cout<=4'd0;//计数器清0
else if(rena && clk_top)//接收计数器计数
cout<=cout+4'd1;
else if(!rena)
cout<=4'd0;
else
cout <= cout;
end
endmodule
发送部分代码:module FS_module(clk,rst,txd,txdata,txflag,txbsy,txcom);
input clk,rst,txflag;//系统时钟,全局复位高电平复位,发送启动信号
input [7:0]txdata;//将要发送的数据
output txcom;//发送完毕信号
output txd,txbsy;//UART发送信号,发送忙信号
reg [9:0]txcnt;
reg txd;
reg rena;//发送使能信号
reg txClk;//分频时钟波特率57600
reg txcom;//发送完一个字节
reg [3:0]txstate;
reg txbsy;//发送忙
parameter S0=4'd0;
parameter S1=4'd1;
parameter S2=4'd2;
parameter S3=4'd3;
parameter S4=4'd4;
parameter S5=4'd5;
parameter S6=4'd6;
parameter S7=4'd7;
parameter S8=4'd8;
parameter S9=4'd9;
parameter S10=4'd10;
///////////////////分频模块/////////////////
always @(posedge clk or posedge rst)begin
if(rst)begin
txcnt<=10'd0;//分频计数器
txClk<=1'b0;
end
else if(txcnt==868)begin //57600波特率
txClk<=1'b1;//产生一个周期的高电平
txcnt<=0;
end
else
begin
txClk<=1'b0;
txcnt<=txcnt+1'b1;
end
end
///////////////发送忙信号/////////////////
always@(posedge clk or posedge rst)begin
if(rst)
txbsy <= 1'b0;
else if(txflag)//当发送信号拉高发送忙标志拉高
txbsy <= 1'b1;
else if(txstate == S0 && !rena)//当发送完毕发送忙标志拉低
txbsy <= 1'b0;
else
txbsy <= txbsy;
end
///////////////发送使能信号/////////////
always@(posedge clk or posedge rst)begin
if(rst)
rena <= 1'b0;
else if(txflag)
rena <= 1'b1;
else if(txstate == S1)//起始位发送就复位使能信号
rena <= 1'b0;
else
rena <= rena;
end
////////////////////////////发送数据//////////////////////
always @(posedge clk or posedge rst)begin //
if(rst)begin
txd<=1'b1;//让TXD为高电平
txstate<=S0;//状态机指向
//txbsy<=1'b0;//发送忙清0
txcom<=1'b0;//发送完毕复位
end
else if(txClk)begin
txcom<=1'b0; //发送完毕复位
case (txstate)
S0: begin //初始状态,检测发送标志位
if (rena)begin//发送使能信号
txstate<=S1;
end
else
txstate<=S0;
end
S1:begin //起始位发送
txd<=1'b0;//起始位
txstate<=S2;
end
S2:begin
txd<=txdata[0];//最低位
txstate<=S3;
end
S3:begin
txd<=txdata[1];//2
txstate<=S4;
end
S4:begin
txd<=txdata[2];//3
txstate<=S5;
end
S5:begin
txd<=txdata[3];//4
txstate<=S6;
end
S6:begin
txd<=txdata[4];//5
txstate<=S7;
end
S7:begin
txd<=txdata[5];//6
txstate<=S8;
end
S8:begin
txd<=txdata[6];//7
txstate<=S9;
end
S9:begin
txd<=txdata[7];//最高位
txstate<=S10;
end
S10:begin
txd<=1'b1; //停止位
//txbsy<=1'b0;//发送忙清0等待下次发送
txcom<=1'b1;//发送完一字节数据
txstate<=S0;
end
default :;
endcase
end
end
endmodule
顶层模块代码:module top_tb(
Clk,TXrst,RXD,TXD,RXdata,
//pane_data_out,
pane_cmd_en,
// pane_cmd_ack,pane_rd_ack,
// pane_data_in,pane_addr_in,
// pane_cmd_out,pane_addr_out
);
input Clk;//全局时钟
input TXrst;//全局复位高电平有效
//input [7:0]pane_data_in;
//input [15:0]pane_addr_in;
//input pane_rd_ack;
//input pane_cmd_ack;
reg [7:0] TXdata;//要发送的数据寄存器
output [7:0]RXdata;//接收数据输出
//output [7:0]pane_cmd_out;
//output[15:0]pane_addr_out;
//output[7:0]pane_data_out;
output pane_cmd_en;
input RXD;
output TXD;
reg TXflag;//发送启动信号
reg [3:0] TXstate;//发送状态
wire TXbsy;//发送忙
reg [7:0] pane_cmd_out;
reg [7:0] pane_cmd;
reg [7:0] pane_cmd0;
reg [7:0] pane_cmd1;
reg [7:0] pane_cmd2;
reg [7:0] pane_cmd3;
reg [7:0] pane_data_out;
wire [15:0]pane_addr_out;
reg [7:0] value;
reg pane_cmd_en;
reg pane_cmd_ack;
reg pane_rd_ack;
//reg[7:0] value1;
parameter s0=4'd0;
parameter s1=4'd1;
parameter s2=4'd2;
parameter s3=4'd3;
parameter s4=4'd4;
parameter s5=4'd5;
//这里设置初始值,否则调试会是不定态/////////
reg [7:0] txone = 8'h5a;
reg [7:0] txtwo = 8'h11;
reg [7:0] txthree = 8'h40;
reg [7:0] txfour = 8'h0b;
reg [7:0] txfive = 8'hfc;
reg [7:0] txsix = 8'h00;
reg [7:0] txseven = 8'hc3;
reg[2:0] TXcnt;//发送计数器
wire RXflag;//接收完一字节数据
parameter x0=4'd0;
parameter x1=4'd1;
parameter x2=4'd2;
parameter x3=4'd3;
reg [2:0]RXcnt;//接受计数器
reg [3:0]RXstate;
assign pane_addr_out={pane_cmd,pane_cmd1};
FS_module U1(
.clk(Clk),
.txdata(TXdata),
.txflag(TXflag),
.txd(TXD),
.rst(TXrst),
.txbsy(TXbsy)
);
///////////////////////////////////////////
/////////////////发送主程序////////////////
always @(posedge Clk or posedge TXrst) begin
if(TXrst)begin
TXstate<=s0;//给初值
TXflag<=1'b0;//复位清0
TXcnt<=3'd0;//复位清0
end
else begin
case (TXstate)
s0:begin
if((pane_cmd_ack==1'b1)&&(pane_rd_ack==1'b1))//接收7个字节数据完成,开始发送
begin
TXstate<=s1;
end
else begin
TXstate<=s0;//否则继续等待
end
end
s1:
begin
TXflag<=1'b0;//将发送启动标志位清0
if(TXbsy==1'b0)begin//判断一字节数据是不是发送完成,完成就让计数器加1.
TXcnt<=TXcnt+1'b1;
TXstate<=s2;
end
end
s2:
begin
TXstate<=s3;
case(TXcnt)
3'd1: TXdata<=txone;//需要发送的字节
3'd2: TXdata<=pane_cmd_out;//读写命令
3'd3: TXdata<=pane_cmd;//地址高八位
3'd4: TXdata<=pane_cmd1;//地址低八位
3'd5: TXdata<=pane_data_out;//数据位
3'd6: TXdata<=txsix;//预留位
3'd7: begin
TXdata<=(txone+pane_cmd+pane_cmd1+pane_data_out+txsix+pane_cmd_out);
//TXdata<=value1;//发送校验和
end
default:TXcnt<=3'd1;
endcase
end
s3:
begin
TXflag<=1'b1;
TXstate<=s4;
end
s4:
begin
if(TXcnt == 3'd7)begin//判断发送完七个字节
TXstate<=s5; end
else
TXstate<=s1;
end
s5:
begin
TXcnt<=3'd0;//发送完成计数器清0
TXstate<=s0;//发送完成状态机指向最初状态,等待下次发送
TXflag<=1'b0;//发送启动标志清0
end
default:
begin TXstate<=s0; end
endcase
end
end
/////////////////////调用接收部分///////////////////
//////////////////////////////////////////////////
jieshou U2(
.clk(Clk),
.rst(TXrst),
.rxd(RXD),
.rxdata(RXdata),
.rxflag(RXflag)
);
/////////////接收主程序//////////////////////////
//////////////////两个开始发送标志位/////////////
always @(posedge Clk or posedge TXrst)begin
if(TXrst)begin
pane_cmd_ack<=1'b0;
pane_rd_ack<=1'b0;
end
else if ((RXcnt==3'd7)&&(pane_cmd_en==1'b1)&&(pane_cmd_out==8'h11))//接收完7字节数据,第二字节为11,接收数据正确则让置1
begin
pane_cmd_ack<=1'b1;
pane_rd_ack<=1'b1;
end
else begin
pane_cmd_ack<=1'b0;
pane_rd_ack<=1'b0;end
end
always @(posedge Clk or posedge TXrst)
begin if(TXrst)
pane_cmd_en<=1'b0;
else if(value==pane_cmd3)//接收的前六个字节之和是不是等于第七个字节
begin
pane_cmd_en<=1'b1;//第7个字节等于前面六个字节之和将pane_cmd_en拉高
end
else
pane_cmd_en<=1'b0;//不等则不拉高pane_cmd_en
end
//////////////////////////////接收////
always @(posedge Clk or posedge TXrst)
begin if(TXrst)
begin
// RXflag<=1'b0;
RXstate<=x0;//接收状态机初值
end
else begin
case (RXstate)
x0:begin
RXcnt=3'd0;
RXstate<=x1;
end
x1:begin
if(RXflag==1) begin//接受完1字节数据
RXcnt<=RXcnt+1'b1;
case (RXcnt)
3'd0:
begin
pane_cmd0<=RXdata;//把第一个字节放进去
end
3'd1:
begin
pane_cmd_out<=RXdata;//把第二个字节放进去
end
3'd2:
begin
pane_cmd<=RXdata;//把第三个字节放进去
end
3'd3:
begin
pane_cmd1<=RXdata;//把第四个字节放进去
end
3'd4:
begin
pane_data_out<=RXdata;//把第五个字节放进去
end
3'd5:
begin
pane_cmd2<=RXdata;//把第六个字节放进去
end
3'd6:
begin
pane_cmd3<=RXdata;//把第七个字节放进去
value<=(pane_cmd0+pane_cmd_out+pane_cmd+pane_cmd1+pane_data_out+pane_cmd2);//校验和
end
3'd7:;
default:;
endcase
RXstate<=x2;
end
else
RXstate<=x1;//没有接收完则继续等待接收完成
end
x2:begin
if (RXcnt== 3'd7)begin//判断接收完成且接收正确
RXstate <= x3;end
else begin //如果没有接收完7字节则等待
RXstate <=x1;end
end
x3:begin
RXcnt<=3'd0;
RXstate <=x0;
end
default :RXstate <=x0;
endcase
end
end
endmodule