一:前言

这篇博客是我应一位网友之约写的,他想要学习基于FPGA的PCIe DMA控制器设计,但是手上没有合适的Xilinx开发板,而且xapp1052又没有提供仿真代码,让他的学习陷入了困境。所以我想了想,还是用EDK搭建一个微小系统,然后用modelsim来仿真xapp1052的DMA收发控制,这样应该是最全面的理解PCIe_DMA了,希望对大家都有帮助。

二:前期准备

1、Xapp1052 Demo(http://download.csdn.net/download/yuzeren48/7723795)

2、ISE14.1套件

3、基本会使用EDK(主要是Xilinx Platform Studio,XPS 和 Software Development Kit,SDK)

三:操作步骤

1、编译库文件,将D:\Xilinx\14.1\ISE_DS\ISE\verilog\mti_se\10.1b\nt\modelsim.ini中选中部分复制粘贴到D:\modeltech_10.1b\modelsim.ini中

2、打开XPS,新建一个最小系统,使用microblaze和PLB总线,总线上挂载的硬件IP如图2所示,硬件的总线地址如图3所示。

图2 硬件IP

图3 硬件IP总线地址

3、完成硬件系统搭建后,导出到SDK

4、打开SDK后,先新建一个BSP包,步骤请参考《Xilinx FPGA开发实用教程》

然后新建一个空的Xilinx C Project,命名为example。

在E:\xapp1052\dma_performance_demo\win32_sw\win32_driver\source下找到ioctrl.h,复制粘贴到E:\pcie_edk\EDK\workspace\example\src

在src中添加C文件,命名为RC_example.c。再将

D:\Xilinx\14.1\ISE_DS\EDK\sw\XilinxProcessorIPLib\drivers\pcie_v4_01_a\examples\xpcie_rc_enumerate_example.c中的代码复制到RC_example.c中

对RC_example.c做如下修改:

//#define PCIE_CFG_BAR_0_ADDR         0x11110000
#define PCIE_EP_CFG_BAR_0_ADDR 0x0000FFFF // Remote EP BAR0
#define PCIE_RC_CFG_BAR_0_ADDR 0x0000EEEE // RC BAR0

添加:

//-------------------BMD Mrd Test
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCR_OFFSET) = Xil_EndianSwap32(0x00000001); //1. DMA assert reset
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCR_OFFSET) = Xil_EndianSwap32(0x00000000); //
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_ADDR_OFFSET) = PCIE_RC_CFG_BAR_0_ADDR; //2. Read DMA TLP Address Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_SIZE_OFFSET) = Xil_EndianSwap32(0x0000050/); //3. Read DMA TLP Size Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_COUNT_OFFSET) = Xil_EndianSwap32(0x00000100); //4. Read DMA TLP Count Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_PATTERN_OFFSET) = Xil_EndianSwap32(0xA3A2A1A0); //5. Read DMA Data Pattern Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCSR_OFFSET) = Xil_EndianSwap32(0x00010000); //7. MWr start

或者

//-------------------BMD Mrd Test
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCR_OFFSET) = Xil_EndianSwap32(0x00000001); //1. DMA assert reset
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCR_OFFSET) = Xil_EndianSwap32(0x00000000); //
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_ADDR_OFFSET) = PCIE_RC_CFG_BAR_0_ADDR; //2. Read DMA TLP Address Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_SIZE_OFFSET) = Xil_EndianSwap32(0x0000050/); //3. Read DMA TLP Size Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_COUNT_OFFSET) = Xil_EndianSwap32(0x00000100); //4. Read DMA TLP Count Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + READ_PATTERN_OFFSET) = Xil_EndianSwap32(0xA3A2A1A0); //5. Read DMA Data Pattern Register
*(unsigned int*)(XPAR_PLBV46_PCIE_0_IPIFBAR_0 + DCSR_OFFSET) = Xil_EndianSwap32(0x00010000); //7. MWr start

在初始化RC端配置寄存器时,添加代码:

//---------------------------------------------------- Configure RC
//Write Address to PCIe BAR0
HeaderData = PCIE_RC_CFG_BAR_0_ADDR;
XPcie_WriteLocalConfigSpace(XlnxRootComplexPtr, PCIE_CFG_BAR_0_REG, HeaderData);

将RC端pcie_bar0设为0x0000EEEE (有大小端,故实际地址为0xEEEE0000)。

在枚举使需要初始化远端EP,修改代码,使能master enable bit:

ConfigData |= (PCIE_CFG_CMD_BUSM_EN | PCIE_CFG_CMD_MEM_EN | 0x80000000    //master enable bit ); 

修改EP端pcie_bar0为0x0000FFFF(有大小端,故实际地址为0xFFFF0000):

/* Write Address to PCIe BAR0 */
ConfigData = (PCIE_EP_CFG_BAR_0_ADDR | PCIeBusNum | PCIeDevNum | PCIeFunNum);

最后,去掉所有printf函数,打印太慢了,影响仿真。

编译后生成elf文件,打开XPS,设置sim executable:

在Edit中设置preference

然后点击Generate HDL Files,再Launch Simulator

在打开的modelsim脚本栏中输入c;

完成RC编译,再输入s; 开始对RC端仿真。

5、若要仿真整个PCIE DMA,则需要修改..\EDK\simulation\behavioral文件夹下的system_tb.v,在system_tb.v中加入EP端用户逻辑,修改如下:

// START USER CODE (Do not remove this line)

  // User: Put your stimulus here. Code in this
// section will not be overwritten.
initial
begin
pcie_sysclk_p = 'b1;
forever #(fpga_0_clk_1_sys_clk_p_pin_PERIOD)
pcie_sysclk_p = ~pcie_sysclk_p; //100MHz
end initial
begin
pcie_sysclk_n = 'b0;
forever #(fpga_0_clk_1_sys_clk_p_pin_PERIOD)
pcie_sysclk_n = ~pcie_sysclk_n; //100MHz
end reg EP_pcie_sysclk_p;
reg EP_pcie_sysclk_n; initial
begin
EP_pcie_sysclk_p = 'b1;
forever #()
EP_pcie_sysclk_p = ~EP_pcie_sysclk_p; //125 MHz
end initial
begin
EP_pcie_sysclk_n = 'b0;
forever #()
EP_pcie_sysclk_n = ~EP_pcie_sysclk_n; //125 MHz
end wire ep_pci_exp_txp;
wire ep_pci_exp_txn; always@* begin
plbv46_pcie_0_RXP_pin = ep_pci_exp_txp;
plbv46_pcie_0_RXN_pin = ep_pci_exp_txn;
end xilinx_pcie_2_0_ep_v6 # ( .PL_FAST_TRAIN("TRUE") )
EP ( // SYS Inteface
.sys_clk_p(EP_pcie_sysclk_p),
.sys_clk_n(EP_pcie_sysclk_n),
.sys_reset(fpga_0_rst_1_sys_rst_pin), `ifdef ENABLE_LEDS
// Misc signals
.led_0(led_0),
.led_1(led_1),
.led_2(led_2),
`endif // PCI-Express Interface
.pci_exp_txn(ep_pci_exp_txn),
.pci_exp_txp(ep_pci_exp_txp),
.pci_exp_rxn(plbv46_pcie_0_TXN_pin),
.pci_exp_rxp(plbv46_pcie_0_TXP_pin) );
// END USER CODE (Do not remove this line)

为了仿真方便,修改system_tb.v后,在E:\pcie_edk\EDK\simulation下新建bmd_sim文件夹,将behavioral文件夹下的system_tb.v拷贝到bmd_sim文件夹中,编写simulate_mti.do文件,将需要编译的ep端文件(主要包括pcie硬核和xapp1052DMA)写成.f文件。

vlog -work work +incdir+E:/pcie_edk/Coregen/EP_1_7/v6_pcie_v1_7/example_design \
+define+SIMULATION \
+define+PCIE2_0 \
$env(XILINX)/verilog/src/glbl.v \
-f ../bmd_sim/ep_v6.f
vlog -work work ../bmd_sim/system_tb.v

6、打开modelsim,输入以下脚本

cd E:/pcie_edk/EDK/simulation/behavioral

do system_setup.do

c;

do ../bmd_sim/simulate_mti.do

s;

do ../bmd_sim/wave.do

run all

四:仿真结果

这里只贴出DMA写操作的仿真结果

Ep端DMA发送

RC端接收

写入BRAM

五:总结

从搭建系统到最后仿真,工作量还是比较大的。一篇博客很难把每一步都讲得仔仔细细,小编把里面最重要的几个点都给出来了,希望能够帮到有需要的朋友。

对于初学者,可能看了这篇博客觉得不够详细,没法真正理解PCIe DMA的使用,所以小编在最后留下一个支付宝账号【账户:bubble_fish@yeah.net  姓名:俞则人】,10元/份出售以上全部EDK工程文件以及modelsim仿真文件,这样做的目的一是为了激发您学习的动力(花钱买来的东西终究比免费得来的更加珍惜),二是为了赞助我的泡泡鱼团队基金,尊重每一位码农的劳动成果!

PCIE_DMA实例二:xapp1052的EDK仿真的更多相关文章

  1. PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植

    PCIE_DMA实例四:xapp1052在Xilinx 7系列(KC705/VC709)FPGA上的移植 一:前言 这段时间有个朋友加微信请求帮忙调试一块PCIe采集卡.该采集卡使用xilinx xc ...

  2. PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡

    PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡 一:前言 这一年关于PCIE高速采集卡的业务量激增,究其原因,发现百度"xilinx pcie dma",出 ...

  3. C语言库函数大全及应用实例二

    原文:C语言库函数大全及应用实例二                                              [编程资料]C语言库函数大全及应用实例二 函数名: bioskey 功 能 ...

  4. Hibernate实例二

    Hibernate实例二 一.测试openSession方法和getCurrentSession方法 hebernate中可以通过上述两种方法获取session对象以对数据库进行操作,下面的代码以及注 ...

  5. Ajax实例二:取得新内容

    Ajax实例二:取得新内容 通过点击pre和next按钮,从服务器取得最新内容. HTML代码 <div id="slide">图片显示区</div> &l ...

  6. WPF中的多进程(Threading)处理实例(二)

    原文:WPF中的多进程(Threading)处理实例(二) //错误的处理 private void cmdBreakRules_Click(object sender, RoutedEventArg ...

  7. PCIE_DMA实例三:Xilinx 7系列(KC705/VC709)FPGA的EDK仿真

    一:前言 好久没写博客了,前段时间有个朋友加微信请教关于PCIe的一些学习方法.本人也不是专家,只是略知一些皮毛.对于大家反馈的问题未必能一一解答,但一定知无不言.以后我会常来博客园看看,大家可以把问 ...

  8. PCIE_DMA实例一:xapp1052详细使用说明

    一:前言 很多和我一样初学pcie的硬件工程师都会遇到这样一个问题,看了不少pcie相关的资料,还是搞不清这玩意儿到底该怎么用.于是我们打开ISE的core_generator工具,生成了一个pcie ...

  9. express+nodecoffee写passport登录验证实例(二)

    二:实现登录认证 passport官网文档:  http://passportjs.org/guide/ passport验证使用一种被称为“策略”的方式来验证请求,策略支持3种类型的验证:用户名密码 ...

随机推荐

  1. maven 编译打包时,明明类文件没有问题,却提示错误:未结束的字符串字面值,maven-compiler-plugin:2.3.2

    maven错误提示如下: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (de ...

  2. 记录一次mybatis查询返回为空数据库却能查询到数据的经历

    昨晚上测试人员给发了一条测试数据,说是根据这条数据接口返回信息为空.之后根据给的信息去数据库查询了下,明明是有数据的.但是用mybatis就是查询不出来.奇了怪了,自己测试的数据都能查询出来,为何这条 ...

  3. hibernate的延迟加载和抓取策略

    一,延迟加载 1.实体类延迟加载 通过代理机制完成,由javassist类库实现运行时代理,修改实体类的字节码实现了运行时代理     <class lazy="true|false& ...

  4. 使用ServiceBroker自动激活模拟"秒杀"场景

    1.简介 SQL Server Service Broker 是SQL server 里面比较独特的一个功能.它可帮助开发人员构建异步的松散耦合应用程序 ServiceBroker入门文章:http: ...

  5. Oracle EBS 有效银行账户取值

    SELECT ba.bank_account_id, --银行账户key ftv.territory_short_name, --国家 ftv.territory_code, --国家简称 cb.ba ...

  6. Oracle EBS 报表日期格式问题

    1.确保参数日期值集选择:FND_STANDARD_DATE 2.将程序的入口参数选择为 varchar2类型 3.注意输出和游标时参数的截断  to_date(substr(p_DATE_from, ...

  7. 第六章 函数、谓词、CASE表达式 6-1 各种各样的函数

    一.函数的种类 算术函数 字符串函数 日期函数 转换函数 聚合函数   二.算术函数 + - * /   1.ABS——绝对值 ABS(数值) 绝对值 absolute value ,不考虑数值的符号 ...

  8. 连接AWS Ubuntu服务器

    1.在AWS上创建了Ubuntu实例后,在实例里点连接.点使用PuTTY连接,下载PuTTY软件. 2.在所有程序里找到PuTTYgen并打开,点Load选择创建实例时的pem文件,点save pri ...

  9. Python 系统学习梳理_【All】

    Python学习 1. Python学习---Python安装与基础1205 2. Python学习---PyCharm的使用学习 3. Python学习---Python数据类型1206 4. Py ...

  10. Linux 系统调整内核参数

    调整系统内核参数 内核优化:Linux系统(内核 + shell + 应用程序)       针对业务服务应用而进行的系统内核参数调整(主要是/etc/sysctl.conf文件) 1. vim /e ...