uisrc 发表于 2023-12-29 11:31:12

2-3-12 基于FPGA的串口程序收发环路设计

软件版本:VIVADO2021.1操作系统:WIN10 64bit硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!1 概述前面两课,我们完成了我们发送程序的测试,成功给我们的PC主机发送了我们"HELLO FPGA"的信息,我们主机显示接收成功。但是我们串口接收的程序仅仅是通过我们模拟仿真,虽然仿真结果达到了期望,但是不能直接上板测试难免差强人意。所以我们不妨将我们串口UART接收程序以及发送程序连接起来,做到能将PC端通过USB发送过来的数据接收,然后将接收到的数据再通过发送程序返回给我们的PC机。实验目的:1:实现UART串口收发环路的设计2:实现主程序中调用串口接收信息并且发送接收到的信息3:完成仿真验证4:编译并且固化程序到FPGA验证2 UART收发环路在完成以下实验前,请确保已经完成了"UART串口发送实验"和"UART串口接收实验"2.1 系统框图上位机通过串口发送数据到FPGA开发板的UART数据接收模块,数据接收模块接收数据后,通过UART数据发送模块把数据发回到串口芯片,之后数据在串口调试助手上打印,实现环路测试。对于发送控制器中的uart_busy信号,不需要使用,因为这里uart发送模块是被动发送。2.2 顶层模块调用UART收发驱动源码顶层模块只需要调用uart的首发模块驱动接口。并且设置uart_rdata和uart_wdata互联,uart_wreq和uart_rvalid互联。
/*********************uart_top UART串口环路测试*********************1.uiuart_rx接收驱动,用于接收串口数据,当O_uart_rvalid代表uiuart_rx接收驱动接收到了总线的有效数据2.uiuart_tx发送驱动,用于发送数据,当I_uart_wreq为高电平,请求发送数据环路测试中,用O_uart_rvalid = I_uart_wreq,使用接收的数据再转发出去I_uart_wdata = O_uart_wdata *********************************************************************/
`timescale 1ns / 1ns //仿真时钟刻度和精度
module uart_top(inputI_sysclk,//系统时钟输入inputI_uart_rx,//uart rx接收信号output O_uart_tx //uart tx发送信号);
localparam SYSCLKHZ = 50_000_000;//系统输入时钟
reg rstn_cnt = 0;//上电后延迟复位wire uart_rstn_i;//内部复位信号wire uart_wreq,uart_rvalid;wire uart_wdata,uart_rdata;
assign uart_wreq= uart_rvalid;//用uart rx接收数据有效的uart_rvalid信号,控制uart发送模块的发送请求assign uart_wdata = uart_rdata; //接收的数据给发送模块发送assign uart_rstn_i = rstn_cnt;//延迟复位设计,用计数器的高bit控制复位
//同步计数器实现复位always @(posedge I_sysclk)begin    if(rstn_cnt == 1'b0)      rstn_cnt <= rstn_cnt + 1'b1;    else      rstn_cnt <= rstn_cnt;end
//例化uart 发送模块uiuart_tx#(.BAUD_DIV(SYSCLKHZ/115200-1)    )uart_tx_u(.I_clk(I_sysclk),//系统时钟输入.I_uart_rstn(uart_rstn_i), //系统复位.I_uart_wreq(uart_wreq), //uart发送驱动的写请求信号,高电平有效.I_uart_wdata(uart_wdata), //uart发送驱动的写数据.O_uart_wbusy(),//uart 发送驱动的忙标志.O_uart_tx(O_uart_tx)//uart 串行数据发送);
//例化uart 接收uiuart_rx#(.BAUD_DIV(SYSCLKHZ/115200-1))uiuart_rx_u(.I_clk(I_sysclk), //系统时钟输入.I_uart_rstn(uart_rstn_i),//系统复位.I_uart_rx(I_uart_rx), //uart 串行数据接收.O_uart_rdata(uart_rdata), //uart 接收数据.O_uart_rvalid(uart_rvalid)//uart 接收数据有效,当O_uart_rvalid =1'b1 O_uart_rdata输出的数据有效);
endmodule


3 FPGA工程fpga工程的创建过程不再重复,如有不清楚的请看前面实验(以下FPGA型号,以实际的为准)米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹01_rtl:放用户编写的rtl代码02_sim:仿真文件或者工程03_ip:放使用到的ip文件04_pin:放fpga的pin脚约束文件或者时序约束文件05_boot:放编译好的bit或者bin文件(一般为空)06_doc:放本一些相关文档(一般为空)4 RTL仿真4.1 准备工作仿真测试文件源码如下:
module uart_top_tb();
localparam      BPS          = 'd115200   ;             //波特率localparam      CLK_FRE    = 'd50_000_000   ;   //系统频率localparam      CLK_TIME   ='d500_000_000 /CLK_FRE;//计算系统时钟周期,以ns为单位localparam      BIT_TIME   = 'd500_000_000/ BPS ; //计算出传输每个bit所需要的时间以ns为单位localparam      NUM_BYTES= 3;            //需要发送的BYTES
reg               I_sysclk;         //系统时钟reg               bsp_clk ;   //波特率时钟reg               O_uart_tx;      //uart 数据发送,该信号接入到,FPGA的uart 接收wire             I_uart_rx;      //uart 数据接收,该信号接入到,FPGA的uart 发送reg uart_send_data; //需要发送的数据reg              uart_send_data_r; //寄存每次需要发送的BYTE
integer i,j;
//例化顶层模块uart_top uart_top_inst(.I_sysclk(I_sysclk),.I_uart_rx(O_uart_tx),.O_uart_tx(I_uart_rx));

//仿真初始化initial begin//初始化REG寄存器I_sysclk =0;bsp_clk= 0;O_uart_tx= 1;i=0;j=0;uart_send_data   =0;uart_send_data_r =0;
#20000;//延迟20000ns,等待uart测试代码中的复位延迟uart_send_data[(0*8) +: 8] = 8'b1001_0101;//初始化需要发送的第1个BYTEuart_send_data[(1*8) +: 8] = 8'b0000_0101;//初始化需要发送的第2个BYTEuart_send_data[(2*8) +: 8] = 8'b1000_0100;//初始化需要发送的第3个BYTE
//uart tx 发送数据for(i=0; i<NUM_BYTES;i=i+1)begin      uart_send_data_r = uart_send_data[(i*8) +: 8];//寄存需要发送的数据到寄存器      $display("uart_send_data : 0x%h",uart_send_data_r);//打印准备发送的数据
      @(posedge bsp_clk);//发送起始位1bit      O_uart_tx = 1'b0;
      for(j=0;j<8;j=j+1)begin//发送数据8bits      @(posedge bsp_clk);//发送      O_uart_tx = uart_send_data_r;      end
       @(posedge bsp_clk);//发送停止位1bit       O_uart_tx = 1'b1;
end       @(posedge bsp_clk);       #200 $finish;            end
always #(CLK_TIME/2) I_sysclk = ~I_sysclk;    //产生主时钟always #(BIT_TIME/2) bsp_clk= ~bsp_clk;       //产生波特率时钟

endmodule


仿真文件第产生测试波形10010101、00000101和10000100给串口接收模块。4.2 RTL功能仿真为保证数据接收和发送的正确性,分别对串口接收模块和串口发送模块进行了仿真。其对应的仿真测试文件,参见工程文件夹里面的源文件。接收端仿真如下所示,预先接收到低电平,之后再接收8位有效信号,接收寄存器得到8bit数据分别为10010101、00000101、10000100。串口回路仿真,必须注意,保持和接收发送文件中设置的波特率一致。发送模块相对简单,以下是RTL功能仿真,可以看到我们的发送模块把测试文件中模拟发送的数据,从接收模块接收后正确发送出去了。
5 下载演示下载程序前,先确保FPGA工程已经编译。5.1 硬件连接(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)请确保下载器和开发板已经正确连接,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)5.2 运行结果
页: [1]
查看完整版本: 2-3-12 基于FPGA的串口程序收发环路设计