PCIE_DMA實例二:xapp1052的EDK仿真

一:前言app

這篇博客是我應一位網友之約寫的,他想要學習基於FPGA的PCIe DMA控制器設計,可是手上沒有合適的Xilinx開發板,並且xapp1052又沒有提供仿真代碼,讓他的學習陷入了困境。因此我想了想,仍是用EDK搭建一個微小系統,而後用modelsim來仿真xapp1052的DMA收發控制,這樣應該是最全面的理解PCIe_DMA了,但願對你們都有幫助。函數

二:前期準備學習

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

二、ISE14.1套件this

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

三:操做步驟.net

一、編譯庫文件,將D:\Xilinx\14.1\ISE_DS\ISE\verilog\mti_se\10.1b\nt\modelsim.ini中選中部分複製粘貼到D:\modeltech_10.1b\modelsim.ini設計

二、打開XPS,新建一個最小系統,使用microblaze和PLB總線,總線上掛載的硬件IP如圖2所示,硬件的總線地址如圖3所示。3d

圖2 硬件IPcode

圖3 硬件IP總線地址

三、完成硬件系統搭建後,導出到SDK

四、打開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/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端仿真。

五、若要仿真整個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
    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_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

六、打開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仿真文件,這樣作的目的一是爲了激發您學習的動力(花錢買來的東西終究比免費得來的更加珍惜),二是爲了贊助個人泡泡魚團隊基金,尊重每一位碼農的勞動成果!

相關文章
相關標籤/搜索