Xilinx PCIe IP核示例工程代码分析与仿真

PCIe学习笔记系列:

  1. PCIe基础知识及Xilinx相关IP核介绍
    概念了解:简单学习PCIe的数据链路与拓扑结构,另外看看有什么相关的IP核。
  2. 【PG054】7 Series Integrated Block for PCI Express IP核的学习
    基础学习:关于Pcie IP核的数据手册,学习PCIe相关的IP核的配置参数及其对应的含义。
  3. Xilinx PCIe IP核示例工程代码分析与仿真
    基础学习:关于PCIe IP核的仿真,学习PCIe的配置流程以及应用过程。
  4. Xilinx XDMA 例程代码分析与仿真结果
    应用学习:关于Xilinx PCIe DMA IP核的仿真,学习 PCIe DMA 的配置过程以及具体的数据传输流程。
  5. XDMA linux平台调试过程记录
    应用学习:关于XDMA的实际调试过程,可在此基础上定制自己的需求。

【PG054】7 Series Integrated Block for PCI Express IP核的学习中学习了7 Series Integrated Block for PCI Express IP核的一些基础知识,下面通过仿真进一步理解。

1 工程建立

只进行仿真设计,随便配置成Endpoint器件就行。

1 page1:Basic

在这里插入图片描述

2 page2: IDs

在这里插入图片描述

3 page3: BARs

在这里插入图片描述

4 page4: Core Capabilities

在这里插入图片描述

5 page5: Interrupts

在这里插入图片描述

设置好IP核之后,右击IP核打开示例工程:

在这里插入图片描述

示例工程的文件结构:

 xilinx_pcie_2_1_ep_7x
 |
 |--pcie_7x_0_support
 |  |--pcie_7x_0_pipe_clock                                      
 |  |--pcie_7x_0 (Core Top level module Generated by Vivado in synth directory)
 |     |--pcie_7x_v3_3_4_top (Static Top level file) 
 |        |--pcie_7x_v3_3_4_core_top
 |           |
 |           |--pcie_7x_0_pcie_top
 |           |  |
 |           |  |--pcie_7x_0_axi_basic_top
 |           |  |  |
 |           |  |  |--pcie_7x_0_axi_basic_rx
 |           |  |  |  |
 |           |  |  |  |--pcie_7x_0_axi_basic_rx_pipeline
 |           |  |  |  |--pcie_7x_0_axi_basic_rx_null_gen
 |           |  |  |
 |           |  |  |--pcie_7x_0_axi_basic_tx
 |           |  |     |
 |           |  |     |--pcie_7x_0_axi_basic_tx_pipeline
 |           |  |     |--pcie_7x_0_axi_basic_tx_thrtl_ctl
 |           |  |
 |           |  |--pcie_7x_0_pcie_7x
 |           |  |  |
 |           |  |  |--pcie_7x_0_pcie_bram_top_7x
 |           |  |  |  |
 |           |  |  |  |--pcie_7x_0_pcie_brams_7x (an instance each for Rx & Tx)
 |           |  |  |     |
 |           |  |  |     |--pcie_7x_0_pcie_bram_7x
 |           |  |  |
 |           |  |  |--PCIE_2_1 (Integrated Block Instance)
 |           |  |
 |           |  |--pcie_7x_0_pcie_pipe_pipeline
 |           |     |
 |           |     |--pcie_7x_0_pcie_pipe_misc
 |           |     |--pcie_7x_0_pcie_pipe_lane (per lane)
 |           |
 |           |--pcie_7x_0_gt_top
 |              |
 |              |--pcie_7x_0_gt_rx_valid_filter
 |              |
 |              |--pcie_7x_0_pipe_wrapper
 |              |  |
 |              |  |--pcie_7x_0_pipe_reset
 |              |  |--pcie_7x_0_qpll_reset
 |              |  |--pcie_7x_0_pipe_user
 |              |  |--pcie_7x_0_pipe_rate
 |              |  |--pcie_7x_0_pipe_sync
 |              |  |--pcie_7x_0_pipe_drp
 |              |  |--pcie_7x_0_pipe_eq
 |              |  |  |--pcie_7x_0_rxeq_scan
 |              |  |  |
 |              |  |--pcie_7x_0_gt_common
 |              |  |  |--pcie_7x_0_qpll_drp
 |              |  |  |--pcie_7x_0_qpll_wrapper
 |              |  |
 |              |  |--pcie_7x_0_gt_wrapper
 |
 |--pcie_app_7x (PIO design, in example_design directory)
    |
    |--PIO
       |
       |--PIO_EP
       |  |
       |  |--PIO_EP_MEM_ACCESS
       |  |  |
       |  |  |--EP_MEM
       |  |     |
       |  |     |--RAMB36
       |  |
       |  |--PIO_RX_ENGINE
       |  |--PIO_TX_ENGINE
       |
       |--PIO_TO_CTRL

2 工程仿真

2.1 代码分析

再回顾一下示例程序的结构:

在这里插入图片描述

首先打开testbench中的文件pci_exp_usrapp_tx.v, 层次路径为:board/RP/tx_usrapp, 重点关注一个initial块:

在这里插入图片描述

  • 308行:这里指定了测试任务的名称为pio_writeReadBack_test0
  • 324行:这里通过调用TSK_USR_DATA_SETUP_SEQ任务对DATA_STORE进行初始化。
  • 332行:这里通过文件包含命令``include "tests.vh"添加了有关测试任务的具体内容。注意verilog的文件包含与c有区别,verilog是直接把tests.vh中的内容直接搬过来,打开tests.vh可以看到只有一句代码:\include “sample_tests1.vh”, sample_tests1.vh中的就是具体的每个测试任务的内容了:

在这里插入图片描述

其中,名为pio_writeReadBack_test0的测试任务的具体内容为:

else if(testname == "pio_writeReadBack_test0")
begin

    // This test performs a 32 bit write to a 32 bit Memory space and performs a read back

    board.RP.tx_usrapp.TSK_SIMULATION_TIMEOUT(10050);

    board.RP.tx_usrapp.TSK_SYSTEM_INITIALIZATION;

    board.RP.tx_usrapp.TSK_BAR_INIT;

//--------------------------------------------------------------------------
// Event : Testing BARs
//--------------------------------------------------------------------------

        for (board.RP.tx_usrapp.ii = 0; board.RP.tx_usrapp.ii <= 6; board.RP.tx_usrapp.ii =
            board.RP.tx_usrapp.ii + 1) begin
            if (board.RP.tx_usrapp.BAR_INIT_P_BAR_ENABLED[board.RP.tx_usrapp.ii] > 2'b00) // bar is enabled
               case(board.RP.tx_usrapp.BAR_INIT_P_BAR_ENABLED[board.RP.tx_usrapp.ii])
                   2'b01 : // IO SPACE
                        begin

                          $display("[%t] : Transmitting TLPs to IO Space BAR %x", $realtime, board.RP.tx_usrapp.ii);

                          //--------------------------------------------------------------------------
                          // Event : IO Write bit TLP
                          //--------------------------------------------------------------------------



                          board.RP.tx_usrapp.TSK_TX_IO_WRITE(board.RP.tx_usrapp.DEFAULT_TAG,
                             board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0], 4'hF, 32'hdead_beef);

                          board.RP.com_usrapp.TSK_EXPECT_CPL(3'h0, 1'b0, 1'b0, 2'b0,
                             board.RP.tx_usrapp.COMPLETER_ID_CFG, 3'h0, 1'b0, 12'h4,
                             board.RP.tx_usrapp.COMPLETER_ID_CFG, board.RP.tx_usrapp.DEFAULT_TAG,
                             board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0], test_vars[0]);

                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;

                          //--------------------------------------------------------------------------
                          // Event : IO Read bit TLP
                          //--------------------------------------------------------------------------


                          // make sure P_READ_DATA has known initial value
                          board.RP.tx_usrapp.P_READ_DATA = 32'hffff_ffff;
                          fork
                             board.RP.tx_usrapp.TSK_TX_IO_READ(board.RP.tx_usrapp.DEFAULT_TAG,
                                board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0], 4'hF);
                             board.RP.tx_usrapp.TSK_WAIT_FOR_READ_DATA;
                          join
                          if  (board.RP.tx_usrapp.P_READ_DATA != 32'hdead_beef)
                             begin
                               $display("[%t] : Test FAILED --- Data Error Mismatch, Write Data %x != Read Data %x",
                                   $realtime, 32'hdead_beef, board.RP.tx_usrapp.P_READ_DATA);
                               test_failed_flag = 1;
                             end
                          else
                             begin
                               $display("[%t] : Test PASSED --- Write Data: %x successfully received",
                                   $realtime, board.RP.tx_usrapp.P_READ_DATA);
                             end


                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;


                        end

                   2'b10 : // MEM 32 SPACE
                        begin


                          $display("[%t] : Transmitting TLPs to Memory 32 Space BAR %x", $realtime,
                              board.RP.tx_usrapp.ii);

                          //--------------------------------------------------------------------------
                          // Event : Memory Write 32 bit TLP
                          //--------------------------------------------------------------------------

                          board.RP.tx_usrapp.DATA_STORE[0] = 8'h04;
                          board.RP.tx_usrapp.DATA_STORE[1] = 8'h03;
                          board.RP.tx_usrapp.DATA_STORE[2] = 8'h02;
                          board.RP.tx_usrapp.DATA_STORE[3] = 8'h01;

                          board.RP.tx_usrapp.TSK_TX_MEMORY_WRITE_32(board.RP.tx_usrapp.DEFAULT_TAG,
                              board.RP.tx_usrapp.DEFAULT_TC, 10'd1,
                              board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0]+8'h10, 4'h0, 4'hF, 1'b0);
                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;

                          //--------------------------------------------------------------------------
                          // Event : Memory Read 32 bit TLP
                          //--------------------------------------------------------------------------


                         // make sure P_READ_DATA has known initial value
                         board.RP.tx_usrapp.P_READ_DATA = 32'hffff_ffff;
                          fork
                             board.RP.tx_usrapp.TSK_TX_MEMORY_READ_32(board.RP.tx_usrapp.DEFAULT_TAG,
                                 board.RP.tx_usrapp.DEFAULT_TC, 10'd1,
                                 board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0]+8'h10, 4'h0, 4'hF);
                             board.RP.tx_usrapp.TSK_WAIT_FOR_READ_DATA;
                          join
                          if  (board.RP.tx_usrapp.P_READ_DATA != {board.RP.tx_usrapp.DATA_STORE[3],
                             board.RP.tx_usrapp.DATA_STORE[2], board.RP.tx_usrapp.DATA_STORE[1],
                             board.RP.tx_usrapp.DATA_STORE[0] })
                             begin
                               $display("[%t] : Test FAILED --- Data Error Mismatch, Write Data %x != Read Data %x",
                                    $realtime, {board.RP.tx_usrapp.DATA_STORE[3],board.RP.tx_usrapp.DATA_STORE[2],
                                     board.RP.tx_usrapp.DATA_STORE[1],board.RP.tx_usrapp.DATA_STORE[0]},
                                     board.RP.tx_usrapp.P_READ_DATA);
                               test_failed_flag = 1;

                             end
                          else
                             begin
                               $display("[%t] : Test PASSED --- Write Data: %x successfully received",
                                   $realtime, board.RP.tx_usrapp.P_READ_DATA);
                             end


                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;

                     end
                2'b11 : // MEM 64 SPACE
                     begin


                          $display("[%t] : Transmitting TLPs to Memory 64 Space BAR %x", $realtime,
                              board.RP.tx_usrapp.ii);


                          //--------------------------------------------------------------------------
                          // Event : Memory Write 64 bit TLP
                          //--------------------------------------------------------------------------

                          board.RP.tx_usrapp.DATA_STORE[0] = 8'h64;
                          board.RP.tx_usrapp.DATA_STORE[1] = 8'h63;
                          board.RP.tx_usrapp.DATA_STORE[2] = 8'h62;
                          board.RP.tx_usrapp.DATA_STORE[3] = 8'h61;

                          board.RP.tx_usrapp.TSK_TX_MEMORY_WRITE_64(board.RP.tx_usrapp.DEFAULT_TAG,
                              board.RP.tx_usrapp.DEFAULT_TC, 10'd1,
                              {board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii+1][31:0],
                              board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0]+8'h20}, 4'h0, 4'hF, 1'b0);
                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;

                          //--------------------------------------------------------------------------
                          // Event : Memory Read 64 bit TLP
                          //--------------------------------------------------------------------------


                          // make sure P_READ_DATA has known initial value
                          board.RP.tx_usrapp.P_READ_DATA = 32'hffff_ffff;
                          fork
                             board.RP.tx_usrapp.TSK_TX_MEMORY_READ_64(board.RP.tx_usrapp.DEFAULT_TAG,
                                 board.RP.tx_usrapp.DEFAULT_TC, 10'd1,
                                 {board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii+1][31:0],
                                 board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0]+8'h20}, 4'h0, 4'hF);
                             board.RP.tx_usrapp.TSK_WAIT_FOR_READ_DATA;
                          join
                          if  (board.RP.tx_usrapp.P_READ_DATA != {board.RP.tx_usrapp.DATA_STORE[3],
                             board.RP.tx_usrapp.DATA_STORE[2], board.RP.tx_usrapp.DATA_STORE[1],
                             board.RP.tx_usrapp.DATA_STORE[0] })

                             begin
                               $display("[%t] : Test FAILED --- Data Error Mismatch, Write Data %x != Read Data %x",
                                   $realtime, {board.RP.tx_usrapp.DATA_STORE[3],
                                   board.RP.tx_usrapp.DATA_STORE[2], board.RP.tx_usrapp.DATA_STORE[1],
                                   board.RP.tx_usrapp.DATA_STORE[0]}, board.RP.tx_usrapp.P_READ_DATA);
                               test_failed_flag = 1;
                             end
                          else
                             begin
                               $display("[%t] : Test PASSED --- Write Data: %x successfully received",
                                   $realtime, board.RP.tx_usrapp.P_READ_DATA);
                             end


                          board.RP.tx_usrapp.TSK_TX_CLK_EAT(10);
                          board.RP.tx_usrapp.DEFAULT_TAG = board.RP.tx_usrapp.DEFAULT_TAG + 1;


                     end
                default : $display("Error case in usrapp_tx\n");
            endcase

         end


    $display("[%t] : Finished transmission of PCI-Express TLPs", $realtime);
    if (!test_failed_flag) begin 
       $display ("Test Completed Successfully");
    end 
    $finish;
end

可以看到任务功能为:这个测试执行对32位内存空间的32位写操作,并执行回读操作。

  • 首先执行的任务是:board.RP.tx_usrapp.TSK_SIMULATION_TIMEOUT(10050);, 这个任务的作用是设置仿真的rx_usrapp中的timeout的值。我们可以在pci_exp_usrapp_rx.v中看到,这个值的作用是当超过这个值链路如果还没有建立,就会报错并结束仿真。
  • TSK_SYSTEM_INITIALIZATION任务:这个任务的作用是等待Transaction 复位的完成以及链路的建立。
  • TSK_BAR_INIT: 基于PCI核的配置初始化PCI核。
  • 上面的初始化完成后,就开始进行BAR的读写访问测试了。

2.2 仿真结果

这里使用Modelsim 进行仿真分析。

仿真完成后,可以在[工程名][工程名].sim\sim_1\behav文件夹中的simulate.log文件查看到仿真过程中打印的一些消息:

# Running default test {pio_writeReadBack_test0}......
# [                   0] : System Reset Asserted...
# [             4995000] : System Reset De-asserted...
# [            64025511] : Transaction Reset Is De-asserted...
# [            65025384] : Transaction Link Is Up...
# [            65057284] : TSK_PARSE_FRAME on Transmit
# [            66473286] : TSK_PARSE_FRAME on Receive
# [            69057326] :    Check Max Link Speed = 2.5GT/s - PASSED
# [            69057326] : Check Negotiated Link Width = 4x - PASSED
# [            69081328] : TSK_PARSE_FRAME on Transmit
# [            70329322] : TSK_PARSE_FRAME on Receive
# [            73081380] :    Check Device/Vendor ID - PASSED
# [            73105380] : TSK_PARSE_FRAME on Transmit
# [            74353380] : TSK_PARSE_FRAME on Receive
# [            77105265] :    Check CMPS ID - PASSED
# [            77105265] : SYSTEM CHECK PASSED
# [            77105265] : Inspecting Core Configuration Space...
# [            77129270] : TSK_PARSE_FRAME on Transmit
# [            77953284] : TSK_PARSE_FRAME on Transmit
# [            78361307] : TSK_PARSE_FRAME on Receive
# [            79201284] : TSK_PARSE_FRAME on Receive
# [            81977392] : TSK_PARSE_FRAME on Transmit
# [            82801289] : TSK_PARSE_FRAME on Transmit
# [            83209392] : TSK_PARSE_FRAME on Receive
# [            84049303] : TSK_PARSE_FRAME on Receive
# [            86825284] : TSK_PARSE_FRAME on Transmit
# [            87649322] : TSK_PARSE_FRAME on Transmit
# [            88057284] : TSK_PARSE_FRAME on Receive
# [            88897326] : TSK_PARSE_FRAME on Receive
# [            91673380] : TSK_PARSE_FRAME on Transmit
# [            92497270] : TSK_PARSE_FRAME on Transmit
# [            92905380] : TSK_PARSE_FRAME on Receive
# [            93745265] : TSK_PARSE_FRAME on Receive
# [            96521284] : TSK_PARSE_FRAME on Transmit
# [            97345392] : TSK_PARSE_FRAME on Transmit
# [            97753284] : TSK_PARSE_FRAME on Receive
# [            98593408] : TSK_PARSE_FRAME on Receive
# [           101369290] : TSK_PARSE_FRAME on Transmit
# [           102193284] : TSK_PARSE_FRAME on Transmit
# [           102601364] : TSK_PARSE_FRAME on Receive
# [           103441284] : TSK_PARSE_FRAME on Receive
# [           106217322] : TSK_PARSE_FRAME on Transmit
# [           107041380] : TSK_PARSE_FRAME on Transmit
# [           107449322] : TSK_PARSE_FRAME on Receive
# [           108289380] : TSK_PARSE_FRAME on Receive
# [           111041269] PCI EXPRESS BAR MEMORY/IO MAPPING PROCESS BEGUN...
# 	BAR 0: VALUE = 00000000 RANGE = ffffe000 TYPE =  MEM32 MAPPED
# 	BAR 1: VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# 	BAR 2: VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# 	BAR 3: VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# 	BAR 4: VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# 	BAR 5: VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# 	EROM : VALUE = 00000000 RANGE = 00000000 TYPE =      DISABLED
# [           111041269] : Setting Core Configuration Space...
# [           111065277] : TSK_PARSE_FRAME on Transmit
# [           111889284] : TSK_PARSE_FRAME on Transmit
# [           112297271] : TSK_PARSE_FRAME on Receive
# [           112713380] : TSK_PARSE_FRAME on Transmit
# [           113129284] : TSK_PARSE_FRAME on Receive
# [           113537290] : TSK_PARSE_FRAME on Transmit
# [           113945411] : TSK_PARSE_FRAME on Receive
# [           114361284] : TSK_PARSE_FRAME on Transmit
# [           114769303] : TSK_PARSE_FRAME on Receive
# [           115185322] : TSK_PARSE_FRAME on Transmit
# [           115593284] : TSK_PARSE_FRAME on Receive
# [           116009380] : TSK_PARSE_FRAME on Transmit
# [           116417326] : TSK_PARSE_FRAME on Receive
# [           116833284] : TSK_PARSE_FRAME on Transmit
# [           117241380] : TSK_PARSE_FRAME on Receive
# [           117657284] : TSK_PARSE_FRAME on Transmit
# [           118065265] : TSK_PARSE_FRAME on Receive
# [           118889284] : TSK_PARSE_FRAME on Receive
# [           125657292] : Transmitting TLPs to Memory 32 Space BAR 0
# [           125681289] : TSK_PARSE_FRAME on Transmit
# [           125785277] : TSK_PARSE_FRAME on Transmit
# [           126993313] : TSK_PARSE_FRAME on Receive
# [           129761284] : Test PASSED --- Write Data: 01020304 successfully received
# [           129841285] : Finished transmission of PCI-Express TLPs
# Test Completed Successfully
# ** Note: $finish    : ../../../imports/sample_tests1.vh(325)
#    Time: 129841285 ps  Iteration: 6  Instance: /board/RP/tx_usrapp
# 1
# Break in Module pci_exp_usrapp_tx at ../../../imports/sample_tests1.vh line 325

2.2.1 用到的任务说明

首先需要大概知道pio_writeReadBack_test0调用的一些基本子任务的功能,在【PG054】7 Series Integrated Block for PCI Express IP核的学习中2.6.1 Root Port模型TPI任务列表 章节介绍了一些,其他在PG054中可以查到。
其中,主要的几个任务功能大致说明:

任务说明
TSK_TX_TYPE0_CONFIGURATION_READ配置0读请求;TLP头大小为3个双字(double word);不带数据
TSK_TX_TYPE1_CONFIGURATION_READ配置1读请求;TLP头大小为3个双字(double word);不带数据
TSK_TX_TYPE0_CONFIGURATION_WRITE配置0写请求;TLP头大小为3个双字(double word);带数据
TSK_TX_TYPE1_CONFIGURATION_WRITE配置1写请求;TLP头大小为3个双字(double word);带数据
TSK_TX_TYPE0_CONFIGURATION_READ(tag_,reg_addr_,first_dw_be_)
报头byte0-7: trn_td <= #(Tcq){
                                 1'b0,
                                 2'b00,
                                 5'b00100,
                                 1'b0,
                                 3'b000,
                                 4'b0000,
                                 1'b0,
                                 1'b0,
                                 2'b00,
                                 2'b00,
                                 10'b0000000001,  // 32
                                 REQUESTER_ID, //COMPLETER_ID_CFG,
                                 tag_,
                                 4'b0000,
                                 first_dw_be_     // 64
                                 };
报头byte8-15:trn_td <= #(Tcq){
                                 COMPLETER_ID_CFG,
                                 4'b0000,
                                 reg_addr_[11:2],
                                 2'b00,
                                 32'b0
                                 };

配置请求报文头格式为:
在这里插入图片描述

对照TSK_TX_TYPE0_CONFIGURATION_READ任务与对应的配置请求报文头格式,我们就知道具体请求的含义了。以这个任务为例说明,其他任务的分析方法是类似的。

  • REQUESTER_ID = 16'b0000_0001_1010_1111;,tag_

在这里插入图片描述

Non-Posted请求需要完成报文来应答,才能结束一次完成的数据传递。如果发送端没有收到完成报文,则这个tag不能再次使用,直到这个tag的请求结束。

  • first_dw_be_: 首先我们可以看到TSK_TX_TYPE0_CONFIGURATION_READ任务给的报文中,length字段为10’b0000000001,表示需要从目标设备数据区域读取的数据长度,单位为DW。1st DW BE字段对应first_dw_be_,为payload数据的掩码,对应bit为1表示对应字节有效。

2.2.2 PCIe配置空间

PCIe配置空间包含三个主要的部分:

  1. 传统的PCI V3.0 类型0/1 配置空间头: 0x00~0x3F

    • 类型0 PCI配置空间头(PCI Agent设备的配置空间)
      在这里插入图片描述

    • 类型1 PCI配置空间头(PCI 桥的配置空间)
      在这里插入图片描述

  2. 传统的拓展配置空间: 0x40~0xFF

    • PCIe Capability
    • Power Management Capability
    • Message Signaled Interrupt (MSI) Capability
    • MSI-X Capability(optional)
  3. PCIe拓展配置空间:0x100~0xFFF

    • Device Serial Number Extended Capability Structure (optional)
    • Virtual Channel Extended Capability Structure (optional)
    • Vendor Specific Extended Capability Structure (optional)
    • Advanced Error Reporting Extended Capability Structure (optional)
    • Resizable BAR Extended Capability Structure (optional)

在这里插入图片描述

2.2.2 仿真执行过程分析:

  1. pci_exp_usrapp_tx的相关初始化

可以看到前两条消息为执行pci_exp_usrapp_tx的相关初始化过程发出的,表示执行的任务名称为{pio_writeReadBack_test0}。

  1. pio_writeReadBack_test0.line6: 设置board.RP.rx_usrapp.sim_timeout的值为10050。

在这里插入图片描述

  1. line8: TSK_SYSTEM_INITIALIZATION
  • 等待事务层复位完成,完成后输出消息“Transaction Reset Is De-asserted…”
  • 等待事务层链路建立,完成后输出消息“Transaction Link Is Up…”
  • 检查IP核生成器中的相关设置,包括Max Link Speed/Width, Device/Vendor ID, CMPS

检查Link Speed/Width:

  • TSK_TX_TYPE0_CONFIGURATION_READ(DEFAULT_TAG, 12’h70, 4’hF); //发送tag为0的,寄存器地址为12’h70,Register Number为10’h1C(由于都是32位的寄存器,所以寄存器号对应地址取高10位), first_dw_be_为4’b1111的Type 0 PCI Express Config Read TLP

在这里插入图片描述

在这里插入图片描述

查找PCIe标准,PCIe配置空间地址12’h70对应的寄存器名称为:Link Status(31:16) Link Control(15:0)

在这里插入图片描述

  • TSK_WAIT_FOR_READ_DATA:等待回包数据的到来。

关于接收数据这里不细说,大概的路径是:pci_exp_usrapp_rx收到数据 -> board.RP.com_usrapp.TSK_READ_DATA对数据进行处理 -> 收到的数据按字节存储在board.RP.com_usrapp.frame_store_rx[board.RP.com_usrapp.frame_store_rx_idx]中,其中指针frame_store_rx_idx随着收到的数据自增 -> board.RP.com_usrapp.TSK_PARSE_FRAME对这一帧数据进行解析。其中首先执行TSK_DECIPHER_FRAME对此帧进行解析,输出fmt, f_type, traffic_class, td, ep, attr, length等信息,然后执行TSK_3DW任务根据解析出来的信息进一步解析,然后执行board.RP.tx_usrapp.TSK_SET_READ_DATA将解析后的数据传递给tx_app, 在tx_usrapp中将收到的数据存在寄存器P_READ_DATA中。

  • 最后对收到的数据进行比对,看是哪一种Link Speed/Width

在这里插入图片描述

可以看到P_READ_DATA=32’h10410000=32’b00010000_01000001_00000000_00000000。
Link Status Register.Current Link Speed字段 = P_READ_DATA[19:16] = 4’b0001。所以输出消息“Check Max Link Speed = 2.5GT/s - PASSED”。

Link Status Register.Negotiated Link Width字段 = P_READ_DATA[23:20] = 4’b0100。所以输出消息“Check Negotiated Link Width = 4x - PASSED”。

检查Check Device/Vendor ID 与 检查CMPS 的分析过程类似,这里不再赘述。

  1. line10: TSK_BAR_INIT
  • TSK_BAR_SCAN:扫描PCIe核的配置寄存器。
    通过PCIe fabric接口将PCI_MASK写入bar的空间来查找范围。

PCI总线规范规定了获取BAR空间的标准实现方法。其步骤是首先向BAR寄存器全写1,之后再读取BAR寄存器的内容,即可获得BAR空间的大小。PCIe兼容PCI。

所以我们可以看到这个任务分别向12’h10(BAR0)、12’h14(BAR1)、12’h18(BAR2)、12’h1C(BAR3)、12’h20(BAR4)、12’h24(BAR5)和12’h30(ROM BAR)写了P_ADDRESS_MASK(32’hffff_ffff),再读取BAR的内容即范围并保存到寄存器BAR_INIT_P_BAR_RANGE:

在这里插入图片描述

当然,与我们设置的参数一致:

在这里插入图片描述

  • TSK_BUILD_PCIE_MAP: 从配置空间查看查看范围值,建立相应的mem/io映射。

可以看到这里根据读取的一些信息对寄存器BAR_INIT_P_BAR_ENABLED进行赋值,各BAR对应此寄存器的含义为:

含义
0disable
1bar is io mapped
2bar is mem32 mapped
3bar is mem64 mapped

在这里插入图片描述

  • TSK_DISPLAY_PCIE_MAP: 基于从PCI_E设备读取的范围值,显示出来。

消息line47~53:

在这里插入图片描述

  • TSK_BAR_PROGRAM: 配置的PCIe核的配置寄存器。
  1. line16~194: 进行BAR映射空间的读写测试

首先判断BAR是否使能,然后判断BAR的映射方式。

  • TSK_TX_MEMORY_WRITE_32:

往board.RP.tx_usrapp.BAR_INIT_P_BAR[board.RP.tx_usrapp.ii][31:0]+8’h10,也就是8’h10中写{DATA_STORE[0],DATA_STORE[1],DATA_STORE[2],DATA_STORE[3]}={8’h04,8’h03,8’h02,8’h01}。

  • TSK_TX_MEMORY_READ_32:

读取这个地址的数据并进行比对,如果一直输出消息“Test PASSED — Write Data: 01020304 successfully received”。

在这里插入图片描述

整个仿真的过程就是这样啦。

//每次摆开阵势想要好好看看,总被打断,耗了这么久终于分析完了,通过这个仿真,可以很好的理解PCIe的相关知识。包括事务类型,BAR的配置与分析等等,还是很不错的过程。

  • 37
    点赞
  • 195
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lu-ming.xyz

觉得有用的话点个赞吧 :)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值