zoukankan      html  css  js  c++  java
  • 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:Xilinx14.1ISE_DSISEverilogmti_se10.1b tmodelsim.ini中选中部分复制粘贴到D:modeltech_10.1bmodelsim.ini中

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

    图2 硬件IP

    图3 硬件IP总线地址

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

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

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

    在E:xapp1052dma_performance_demowin32_swwin32_driversource下找到ioctrl.h,复制粘贴到E:pcie_edkEDKworkspaceexamplesrc

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

    D:Xilinx14.1ISE_DSEDKswXilinxProcessorIPLibdriverspcie_v4_01_aexamplesxpcie_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/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 = 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,则需要修改..EDKsimulationehavioral文件夹下的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
        end
    
      initial
        begin
          pcie_sysclk_n = 1'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 = 1'b1;
          forever #(4000)
            EP_pcie_sysclk_p = ~EP_pcie_sysclk_p;   //125 MHz
        end
    
      initial
        begin
          EP_pcie_sysclk_n = 1'b0;
          forever #(4000)
            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_edkEDKsimulation下新建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仿真文件,这样做的目的一是为了激发您学习的动力(花钱买来的东西终究比免费得来的更加珍惜),二是为了赞助我的泡泡鱼团队基金,尊重每一位码农的劳动成果!

    Powered by yuzeren QQ:330853172 Email:yuzeren@mail.ustc.edu.cn
    转载自:http://www.cnblogs.com/yuzeren48/p/3950604.html
  • 相关阅读:
    无重叠区间
    ARC109E 1D Reversi Builder
    IOI2021集训队作业129CF Longest Rivers
    IOI2021集训队作业281CA Balanced Diet
    IOI2021集训队作业227CB Branch Assignment
    IOI2021集训队作业277BK Tours
    IOI2021集训队作业125AA Baggage
    6894. 【2020.11.25提高组模拟】小 S 埋地雷 (loj6611. 摧毁时间线)
    ARC108 题解&总结
    HTML教程
  • 原文地址:https://www.cnblogs.com/chengqi521/p/6684508.html
Copyright © 2011-2022 走看看