博观而约取,厚积而薄发。这篇文章主要讲述PCIE_DMA实例二:xapp1052的EDK仿真相关的知识,希望能为你提供帮助。
一:前言
这篇博客是我应一位网友之约写的,他想要学习基于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_ADDR0x11110000 #define PCIE_EP_CFG_BAR_0_ADDR0x0000FFFF// Remote EP BAR0 #define PCIE_RC_CFG_BAR_0_ADDR0x0000EEEE// 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/4); //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/4); //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 = https://www.songbingjia.com/android/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 = https://www.songbingjia.com/android/(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 = 1\'b1; forever #(fpga_0_clk_1_sys_clk_p_pin_PERIOD) pcie_sysclk_p = ~pcie_sysclk_p; //100MHz endinitial begin pcie_sysclk_n = 1\'b0; forever #(fpga_0_clk_1_sys_clk_p_pin_PERIOD) pcie_sysclk_n = ~pcie_sysclk_n; //100MHz endreg EP_pcie_sysclk_p; reg EP_pcie_sysclk_n; initial begin EP_pcie_sysclk_p = 1\'b1; forever #(4000) EP_pcie_sysclk_p = ~EP_pcie_sysclk_p; //125 MHz endinitial begin EP_pcie_sysclk_n = 1\'b0; forever #(4000) EP_pcie_sysclk_n = ~EP_pcie_sysclk_n; //125 MHz endwire 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; endxilinx_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仿真)】
Powered by yuzeren QQ:330853172 Email:yuzeren@mail.ustc.edu.cn 转载自:http://www.cnblogs.com/yuzeren48/p/3950604.html
推荐阅读
- Cannot read lifecycle mapping metadata for artifact org.apache.maven.plugins问题的解决
- AndroidStudio升级后出现Refresh gradle project和connection timed out的原因和解决方法
- 10款最佳人工智能软件(最新人工智能软件评测)
- 数据挖掘 Vs 机器学习 Vs 人工智能 Vs 深度学习(它们有什么区别())
- 机器学习的类型有哪些(监督学习与无监督学习)
- C++ 与 Java比较(C++ 与 Java 之间的30大差异(附示例))
- Javascript 与 Python比较 – 它们的主要区别是什么()
- TypeScript 与 JavaScript比较 – 它们的主要区别是什么()
- Java 与 JavaScript比较(重要的区别是什么())