手把手教你学会 Xilinx PCIE/XDMA 读写DDR系列(三) ——XDMA读写DDR项目工程讲解和下板测试

因最近想通过PCIE把数据从FPGA传到PC,借此机会和大家一起学习XDMA读写DDR

制作不易,记得三连哦,给我动力,持续更新!!!

完整工程文件下载:XDMA读写DDR工程   提取码:4sxh

在前两篇文章的学习中,我们已经成功配置了XDMA读写DDR所需的两个关键IP核,并深入学习了XDMA读写DDR的理论知识。现在是时候趁热打铁,一次性搞定整个XDMA读写DDR工程的构建,并对其功能进行验证了。本章将引导我们逐步完成以下步骤,确保我们的工程顺利实现:

好的,废话不多说,直接来干货!!!!!

一、整体设计全貌

整体设置主要包括四个部分:数据输入部分,读写DDR部分(图中写错了),DDR配置部分,XDMA配置部分。

亮点:同时接出来了用户数据接口,以后可以很方便的接用户数据,并且此接口为AXI4协议接口,同时也留出来PC端用户接口,用于用户通过PC传输指令到FPGA。

实现整体功能为:实现数据流到DDR,然后通过PCIE读出,并从PCIE写数据,然后读DDR的回环测试。

数据流方向:user DATA –>> DDR –> PC –> DDR –> uesr DATA

接下来讲把每个模块单独拎出来,独立进行讲解。

二、模块介绍

(1)数据输入模块

        此模块的功能:为此设计模拟输入数据源,同时也为以后用户外接数据留出接口

        主要通过AXI_data_out模块产生AXI数据,然后通过AXI data fifo对数据进行缓存,然后输出标准的AXI协议的数据。

AXI_data_out具体部分代码:

module AXI_data_OUT (
  input wire clk,
  input wire rst_n,
  output reg valid,
  output reg last,
  input wire fifo_ready,
  output reg [31:0] data
);

  reg [11:0] count;

  always @(posedge clk or posedge rst_n) begin
    if (~rst_n) 
        count <= 0;
    else if (count < 400)
        count <= count + 1;
    else
        begin
            count <= 0;
        end 
    end
  
/* 
因
字
数
限
制
  
部
分
代
码
省
略
*/


endmodule

(2)读写DDR模块

        此模块主要为把用户数据写入DDR,以及读出PC端写入DDR的数据,进行软硬件数据交互,并且通过总线连接到AXI connect IP。

        通过wr_addr模块把数据转化成总线形式,把数据地址和数据通过AXI协议总线连接到AXI Smartconnect IP,同时添加ILA查看读写数据总线状态,方便后期调试数据使用。

        

wr_addr部分具体代码:

module wr_addr
(
    input                       clk,
    input                       rst_n,
    
    input                       i_valid,
    input                       i_last,
    input   [31:0]              i_data,
    output  reg                 fifo_ready,
    
    input                   xdma_valid,
    input                   i_fifo_ready,
    output                  o_valid,
    output                  o_last,
    output  [31:0]          o_data,
    
    
    //AXI总线    
        input wire  m00_axi_init_axi_txn,
		output wire  m00_axi_txn_done,
		output wire  m00_axi_error,
		input wire  m00_axi_aclk,
		input wire  m00_axi_aresetn,
		output wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_awid,
		output wire [C_M00_AXI_ADDR_WIDTH-1 : 0] m00_axi_awaddr,
		output wire [7 : 0] m00_axi_awlen,
		output wire [2 : 0] m00_axi_awsize,
		output wire [1 : 0] m00_axi_awburst,
		output wire  m00_axi_awlock,
		output wire [3 : 0] m00_axi_awcache,
		output wire [2 : 0] m00_axi_awprot,
		output wire [3 : 0] m00_axi_awqos,
		output wire [C_M00_AXI_AWUSER_WIDTH-1 : 0] m00_axi_awuser,
		output wire  m00_axi_awvalid,
		input wire  m00_axi_awready,
		output wire [C_M00_AXI_DATA_WIDTH-1 : 0] m00_axi_wdata,
		output wire [C_M00_AXI_DATA_WIDTH/8-1 : 0] m00_axi_wstrb,
		output wire  m00_axi_wlast,
		output wire [C_M00_AXI_WUSER_WIDTH-1 : 0] m00_axi_wuser,
		output wire  m00_axi_wvalid,
		input wire  m00_axi_wready,
		input wire [C_M00_AXI_ID_WIDTH-1 : 0] m00_axi_bid,
		input wire [1 : 0] m00_axi_bresp,
		input wire [1 : 0] m00_axi_rresp,
		input wire  m00_axi_rlast,
		input wire [C_M00_AXI_RUSER_WIDTH-1 : 0] m00_axi_ruser,
		input wire  m00_axi_rvalid,
		output wire  m00_axi_rready          
);

    wire         aw_ready;
    wire         w_ready;
  
    reg           [31:0]    aw_addr_cnt;

    reg            [1:0]       state, state_next;
    localparam            s0 = 2'b00, s1 = 2'b01, s2 = 2'b10, s3 = 2'b11;
    

/* 
因
字
数
限
制
  
部
分
代
码
省
略
*/
    
   
    assign m00_axi_wdata      = w_data        ;
	assign m00_axi_wvalid     = w_valid       ;
	assign m00_axi_wlast      = w_last        ;
	assign m00_axi_wstrb      = w_strb        ;
	
	assign m00_axi_awaddr     = aw_addr       ;
	assign m00_axi_awlen      = aw_len        ;
	assign m00_axi_awsize     = aw_size       ;
	assign m00_axi_awburst    = aw_burst      ;
	assign m00_axi_awvalid    = aw_valid      ;
	assign aw_ready         = m00_axi_awready ;

	assign b_resp           = m00_axi_bresp   ;
	assign b_valid          = m00_axi_bvalid  ;
	assign m00_axi_bready     = b_ready       ;
	
	
	assign m00_axi_araddr     = ar_addr       ;
    assign m00_axi_arlen      = ar_len        ;
    assign m00_axi_arsize     = ar_size       ;
    assign m00_axi_arburst    = ar_burst      ;
    assign m00_axi_arvalid    = ar_valid      ;
    assign ar_ready         = m00_axi_arready ;
    
    assign r_data           = m00_axi_rdata   ;
    assign r_last           = m00_axi_rlast   ;
    assign r_resp           = m00_axi_rresp   ;
    assign r_valid          = m00_axi_rvalid  ;
    assign m00_axi_rready     = r_ready       ;
  
endmodule

(3)DDR配置模块 和 XDMA配置模块

        这两个模块在前两个章节已经做了具体的介绍,如果需要可以去前两个章节进行详细查看和学习:

DDR配置快速入口:

手把手教你学会 Xilinx PCIE/XDMA 读写DDR系列(一) DDR/MIG配置详细步骤_xlinx pcie xdma 流模式-CSDN博客

XDMA配置快速入口:

手把手教你学会 Xilinx PCIE/XDMA 读写DDR系列(二) ——XDMA详细配置步骤_xdma创建设备流程-CSDN博客

因以前有详细介绍,在这里就不过多介绍了。

三、下板测试

(1)XDMA驱动安装

       1、环境设置

        由于 Xilinx 提供的 XDMA 驱动程序未经过数字认证签名,而是使用测试签名,所以我们还需要在Windows 系统中开启允许加载已进行测试签名的驱动程序,以便启用此驱动程序的安装,否则安装不了XDMA 的驱动。
下面我们介绍如何在 Windows 系统中启用或禁用测试签名代码的使用。按键盘上的 Win+x 快捷键,在弹出的菜单窗口中选择“Windows PowerShell(管理员)(A)” ,以管理员身份运行 PowerShell
在 PowerShell 中输入如下命令以启用测试签名代码的加载:

        在 Windows 系统中启用测试签名代码的加载后, 要使更改生效,必须重新启动计算机。 另外 PCIe 程序下载完成后, 也需要重启电脑(对主机进行热启动),以使电脑能检测到 PCIe 设备,所以现在我们重启安插有开发板的电脑主机。

        2、下载XDMA驱动:

        可以通过官网下载最新版本,也可以 通过直接下载我使用的这个稳定版本

        Windows XDMA驱动下载

        3、安装XDMA驱动

          以 Win10 为例。进入解压缩后的x64\XDMA_Driver\Win10_Release 目录下,鼠标右键点击 XDMA.cer 文件,在弹出的菜单中选择“安装证书(I)”,如下图所示:

然后一路next即可,显示下图表示证书导入成功

        安装完证书后,进入当前目录下的 XDMA_Driver 目录,鼠标右键点击 XDMA.inf 文件,在弹出的菜单中选择“安装(I)”,如下图所示:

在弹出的“Windows 安全中心”界面中选择“始终安装此驱动程序软件(I)”,如下图所示:

弹出操作成功完成窗口, 点击“确定”按钮如下图所示:

(2)下载bit文件测试

通过vivado下载工程编译出的bit文件,然后重启插板卡的主机

1、检测XDMA设备

        完成驱动的安装后,点击设备管理器中的“扫描检测硬件改动” 按钮,会显示出 Xilinx Drivers,如下图所示:

2、测试代码

        进入解压后的驱动文件的bin目录下,里面包含一些使用XDMA驱动程序的基本应用程序如下图所示并执行其中的应用程序的方式是在该文件窗口中:

在打开的Powershell窗口中输入下面命令:

.\xdma_test.exe

        执行结果可以看到, XDMA 使用的是 AXI-MM 接口模式,使用的是双通道的 h2c 和 c2h,在每个 h2c和 c2h 通道上传输 4096 字节的数据并验证数据是匹配的。 从 xdma_test 的检测结果和读写测试中可以知道我们设计的 XDMA Vivado 工程是没有问题的。

3、测试读DDR里面的数据

在打开的Powershell窗口中输入下面命令:

.\xdma_rw.exe c2h_0 read 0x00000000 -b -f datafile4K_rd.bin -l 4096

该命令以二进制的形式创建并打开文件 datafile4k_rd.bin 文件,通过 c2h_0 通道从 DDR 内存地址0x00000000 中读取 4096 字节数据写入到 datafile4k_rd.bin 文件。

测试结果:

如上图用16进制打开之后,就是刚刚在数据输入模块写入的数据,测试结果没问题,说明 此工程从DDR –>PCIE 没问题。

4、测试从PC写数据到DDR

在打开的Powershell窗口中输入下面命令:

.\xdma_rw.exe h2c_0 write 0x00000000 -b -f datafile4K.bin -l 4096

该命令以二进制的形式读取文件 datafile4k.bin 并通过 h2c_0 通道将其前 4096 字节(对于 datafile4k.bin文件而言是整个文件数据) 数据写入到 DDR 内存地址 0x00000000。 执行结果如下图所示:

然后通过ila看DDR的信号:

如上图可以看出,ila上的数据就是从PC写入的3个数据,说明此工程中 PCIE–> DDR也没问题

总结:

这样的话,此工程的读写DDR全部测试完成,并且读写DDR都没有问题,下一次我们可以结合以前写的Aurora的使用,来创建一个通过光纤传输数据到DDR,然后再通过PC读出的一个大工程,这部分后续有时间会继续更新。

如果感觉文章对您有用,麻烦三连支持一下,方便下次用到的时候,就可以快速找到我,非常感谢您的支持!!!

版权声明:本文为博主作者:FPGAmaster创新者原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/w18864443115/article/details/135667746

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2024年5月6日
下一篇 2024年5月6日

相关推荐