FPGA实验之串口收发整合

FPGA实验之串口收发整合

功能:接收一个8位二进制数,并把它传给上位机。

数据包括1个起始位,8个二进制位,1个奇校验位,1个停止位,共11位。

(1)    建立工程

(2)    编写程序

顶层模块如下:

module UART_TOP(input CLK,RST,RXD,

                                           output TXD);                                                   

UART_send_receive U1(.CLK(CLK),

                                   .RST(RST),

                                   .RXD(RXD),

                                   .call_send(call_send),//CLK:时钟信号; RST:复位信号; RXD:接收数据引脚;

                                   .Send_Data(Send_Data),//Send_Data:数据输入信号;call_send:发送使能信号

                                    .Send_Done(Send_Done),//Send_Done:发送完成输出信号;

                                    .Receive_Done(Receive_Done), //Receive_Done:接收完成信号;

                                    .Receive_error(Receive_error), //接收错误的信号

                                    .TXD(TXD),     //TXD:发送输出

                                    .Receive_data(Receive_data));  //Receive_data:接收完成的数据 

reg call_send,Send_Done,Receive_Done,Receive_error;

reg [7:0] Send_Data,Receive_data;                 

reg [7:0] i;                 

                                         

always @(posedge CLK or negedge RST) // 测试串口收发模块

              if(!RST)

                            begincall_send<=1'b0; end

              else

                            case(i)

                            0:if(Receive_error) begin i<=1'b0; end //如果接收错误,则停留在这一步,继续等待接收

                                          elseif(Receive_Done) begin i<=i+1'b1; end //如果接收完成到达下一步,否则停留在这一步

                                                                      elsei<=8'b0;

                            1:if(Send_Done) begin i<=i+1'b1; call_send<=1'b0;end  // 将发送使能信号置1,将收到的数据发送给串口

                                          elsebegin  call_send<=1'b1;Send_Data<=Receive_data; end

                            2:i<=8'b0;    //返回第一步

                            endcase

endmodule

顶层模块的目的是验证串口收发程序。

模块及端口定义:module UART_TOP(inputCLK,RST,RXD, output TXD);

发送与接收函数的例化:

UART_send_receiveU1(.CLK(CLK),

                                                        .RST(RST),

                                                        .RXD(RXD),

                                                        .call_send(call_send),//CLK:时钟信号; RST:复位信号; RXD:接收数据引脚;

                                                        .Send_Data(Send_Data),//Send_Data:数据输入信号;call_send:发送使能信号

                                                        .Send_Done(Send_Done),//Send_Done:发送完成输出信号;

                                                        .Receive_Done(Receive_Done),

                                                        .Receive_error(Receive_error),

                                                        .TXD(TXD),     //Receive_Done:接收完成信号;TXD:发送输出

                                                        .Receive_data(Receive_data));    //Receive_data:接收完成的数据 

相关寄存器的声明:

regcall_send,Send_Done,Receive_Done,Receive_error;

reg [7:0]Send_Data,Receive_data;                 

reg [7:0] i;   

always测试程序:

always @(posedgeCLK or negedge RST)  // 测试串口收发模块

       if(!RST)

                     begin call_send<=1'b0;end

       else

                     case(i)

                     0: if(Receive_error) begini<=1'b0; end //如果接收错误,则停留在这一步,继续等待接收

                                   elseif(Receive_Done) begin i<=i+1'b1; end //如果接收完成到达下一步,否则停留在这一步

                                                               elsei<=8'b0;

                     1: if(Send_Done) begini<=i+1'b1; call_send<=1'b0;end  // 将发送使能信号置1,将收到的数据发送给串口

                                   elsebegin  call_send<=1'b1;Send_Data<=Receive_data; end

                     2: i<=8'b0;    //返回第一步

                     endcase

endmodule

被顶层模块例化的UART_send_receive模块 :

包括接收部分,发送部分,和检错部分

module UART_send_receive(

               input CLK,RST,RXD,call_send, //CLK:时钟信号; RST:复位信号; RXD:接收数据引脚;

               input [7:0] Send_Data,                             //Send_Data:数据输入信号;call_send:发送使能信号

               output Send_Done,Receive_error,Receive_Done,TXD,            //Send_Done:发送完成输出信号;

               output [7:0]Receive_data        );  //Receive_Done:接收完成信号;TXD:发送输出

                                                                                       //Receive_data:接收完成的数据

                                                                                      //Receive_error:向上层输出的接收错误信号

Parameter参数定义:波特率参数

//-------------------parameter----------------------//

parameter BPS115200=9'd434;//每位数据传输时间为t=1/115200 s,周期T=1/50000000,计数值为t/T=434

//parameter BPS9600=13'd5208; //每位数据传输时间为t=1/9600 s,周期T=1/50000000,计数值为t/T=5208

Reg类型参数定义

//-------------------reg----------------------//

reg [15:0]send_C1,receive_C1; //send_C1:发送计数器; receive_C1:接收计数器;

reg [7:0] send_ii,receive_ii; //send_ii:发送的步骤; receive_ii:接收的步骤

reg txd,send_done,send_odd; //txd:发送寄存器;send_done:reg类型发送完成信号; send_odd:发送的奇校验数据

reg receive_done,Receive_odd,receive_odd; //receive_done:reg类型接收完成信号;receive_odd:接收的奇校验位

reg receive_error; //reg类型的接收错误                                                                                                                                                                          

reg [7:0]receive_data;  //receive_data:接收到的数据;   

UART_send_receive模块中的发送数据的部分

always @(posedge CLK or negedge RST) //发送部分

              if(!RST)

                            begin send_C1<=16'd0; txd<=1'b1;send_ii<=0;send_done<=1'b0; end

              else if(call_send)

                     case(send_ii)

                     0:if(send_C1==BPS115200-2) begin send_C1<=16'd0; send_ii<=send_ii+1'b1;end  //起始位

                       else begin send_C1<=send_C1+1'd1; txd<=1'b0; send_odd<=^~Send_Data; end 

                              //按位同或求奇校验,,,如果按位异或(even_data<=^Send_Data;)求偶校验

                     1,2,3,4,5,6,7,8:

                       if(send_C1==BPS115200-1)begin send_C1<=16'd0; send_ii<=send_ii+1'b1; end //数据位

                       else begin send_C1<=send_C1+1'd1; txd<=Send_Data[send_ii-1]; end

                     9:if(send_C1==BPS115200-1) begin send_C1<=16'd0; send_ii<=send_ii+1'b1;end  //校验位

                        else begin send_C1<=send_C1+1'd1; txd<=send_odd; end

                     10:if(send_C1==BPS115200-1)begin send_C1<=16'd0; send_ii<=send_ii+1'b1; end // 停止位

                          else begin send_C1<=send_C1+1'd1; txd<=1'b1; end

                     11:begin send_done<=1'b1; send_ii<=send_ii+1'b1; end

                     12:begin send_done<=1'b0; send_ii<=1'b0; end

               endcase

UART_send_receive模块中的接收数据的部分

always @(posedge CLK or negedge RST) //接收部分

              if(!RST)

                  begin receive_C1<=16'd0; receive_ii<=1'b0; receive_done<=1'b0;receive_data<=8'b0;end 

              else

                   case(receive_ii)

                   0:if(!RXD) begin receive_ii<=receive_ii+1'b1; end

                  1:if(receive_C1==BPS115200) begin receive_C1<=16'd0;receive_ii<=receive_ii+1'b1; end //起始位,,没做处理,直接忽略

                    elsereceive_C1<=receive_C1+1'b1;

                  2,3,4,5,6,7,8,9:

                    begin

                     if(receive_C1==BPS115200-1)begin receive_C1<=16'd0; receive_ii<=receive_ii+1'b1; end //接收数据位

                      else receive_C1<=receive_C1+1'b1;

                     if(receive_C1==BPS115200>>1)begin receive_data[receive_ii-2]<=RXD; end //采样发生在一帧数据的中间

                    end

              10: begin if(receive_C1==BPS115200-1) begin receive_C1<=16'd0;receive_ii<=receive_ii+1'b1; end //接收校验位

                     elsereceive_C1<=receive_C1+1'b1;

                    if(receive_C1==BPS115200>>1)begin receive_odd<=RXD;  end//receive_odd:从RXD中接收到的校验位

                    Receive_odd<=^~receive_data;  //Receive_odd:是接收到

                    end

               11:if(receive_C1==BPS115200-1)begin receive_C1<=16'd0; receive_ii<=receive_ii+1'b1; end //接收停止位,依然没做处理

                   elsereceive_C1<=receive_C1+1'b1;

                12:beginreceive_done<=1'b1;receive_ii<=receive_ii+1'b1; end   //产生接收完成信号

                13:beginreceive_done<=1'b0;receive_ii<=1'b0; end      //产生接收完成信号

           endcase

UART_send_receive模块中的检错的部分

always @(posedge CLK or negedge RST) //检测是否有接收错误,如果接收错误产生错误信号

              if(!RST)

                 begin receive_error<=1'b0; end 

                    else if(Receive_odd!=receive_odd)  //如果接收的数据的各个位同或与接收到的校验位不同,产生错误信号

                             receive_error=1'b1;

                              else receive_error<=1'b0;

UART_send_receive信号的连接部分

assign TXD = txd;   //TXD输出信号

assign Send_Done = send_done; // 发送完成信号

assign Receive_Done=receive_done; //接收完成信号

assign Receive_data = receive_data; //接收完成的数据

assign Receive_error = receive_error; //接收错误信号

(3)    仿真部分

由于之前的接收和发送都进行了Modelsim仿真,再进行收发结合的时候没有进行Modelsim仿真,直接用串口调试助手和SignalTap结合调试。


FPGA实验之串口收发整合_第1张图片


FPGA实验之串口收发整合_第2张图片

(SignalTap使用并不熟,并且FPGA资源有限(存储深度最多能选8K),所以,SignalTap只能采集到接收的完成,并不能显示发送的完成,需要进一步进行SignalTap的配置优化)。

注:工程下载链接:https://pan.baidu.com/s/1DKTZW1IxOIhC-NPXhsREDQ 密码:s7c5


你可能感兴趣的:(FPGA实验之串口收发整合)