原创 Type0配置写函数

2019-8-8 14:46 3123 24 4 分类: FPGA/CPLD 文集: Xilinx PCIe仿真模型
在前面了解PCI配置空间、TLP以及Type0配置读的基础上,本文介绍Type0配置写子函数。该子函数产生一个Type0配置写TLP,先来看具体代码:
/************************************************************
  • Task : TSK_TX_TYPE0_CONFIGURATION_WRITE
  • Inputs : Tag, PCI/PCI-Express Reg Address, First BypeEn
  • Outputs : Transaction Tx Interface Signaling
  • Description : Generates a Type 0 Configuration Write TLP
  • *************************************************************/
  • task TSK_TX_TYPE0_CONFIGURATION_WRITE;
  • input [7:0] tag_;
  • input [11:0] reg_addr_;
  • input [31:0] reg_data_;
  • input [3:0] first_dw_be_;
  • begin
  • if (trn_lnk_up_n) begin
  • $display("[%t] : Trn interface is MIA", $realtime);
  • $finish(1);
  • end
  • TSK_TX_SYNCHRONIZE(0, 0, 0);
  • trn_td <= #(Tcq) {
  • 1'b0,
  • 2'b10,
  • 5'b00100,
  • 1'b0,
  • 3'b000,
  • 4'b0000,
  • 1'b0,
  • 1'b0,
  • 2'b00,
  • 2'b00,
  • 10'b0000000001, // 32
  • COMPLETER_ID_CFG,
  • tag_,
  • 4'b0000,
  • first_dw_be_, // 64
  • COMPLETER_ID_CFG,
  • 4'b0000,
  • reg_addr_[11:2],
  • 2'b00, // 32
  • reg_data_[7:0],
  • reg_data_[15:8],
  • reg_data_[23:16],
  • reg_data_[31:24] // 64
  • };
  • trn_tsof_n <= #(Tcq) 0;
  • trn_teof_n <= #(Tcq) 0;
  • trn_trem_n <= #(Tcq) 2'b00;
  • trn_tsrc_rdy_n <= #(Tcq) 0 ;
  • TSK_TX_SYNCHRONIZE(1, 1, 1);
  • trn_tsof_n <= #(Tcq) 1;
  • trn_teof_n <= #(Tcq) 1;
  • trn_trem_n <= #(Tcq) 2'b00;
  • trn_tsrc_rdy_n <= #(Tcq) 1;
  • end
  • endtask // TSK_TX_TYPE0_CONFIGURATION_WRITE
  • 复制代码
    有了对Type0配置读的了解,那么理解上面的代码就容易很多了,TLP前面32bit和配置读一样,唯一的区别在于TLP最后32bit带了1DW的写数据。写数据通过函数第三个参数调用的时候引入。

    需要注意的是,上述代码中两次调用了函数TSK_TX_SYNCHRONIZE,第一次调用(TSK_TX_SYNCHRONIZE(0, 0, 0);),只是为了同步trn_clk和trn_tdst_rdyn_n,之后TLP信息被赋值给trn_td。第二次调用(TSK_TX_SYNCHRONIZE(1, 1, 1);)是为了同步信号,也是为了将TLP信息添加到本地buffer,并最终发送到输出log。也就是说,我们在仿真的时候看到很多下图所示的信息都是第二次调用函数TSK_TX_SYNCHRONIZE的时候处理,第二次调用除了在仿真的时候的打印输出下图所示的信息外,还将TLP信息Log到输出文件(tx.dat和rx.dat)

    这里有个疑问是在TSK_BAR_SCAN函数中,对每个BAR先使用Type配置写,写入的数据是”P_ADDRESS_MASK   = 32'hffff_ffff;“,源代码给出的注释是对BAR空间写PCI_MASK来找到range。接着使用Type0配置读刚刚被写入MASK值的BAR空间,读回的数据保存在BAR_INIT_P_BAR_RANGE[?]里,也就是所谓“找到range”。我的问题是,为什么对BAR空间写入MASK后,再对其进行type0读就可以得到range?

    作者: coyoo, 来源:面包板社区

    链接: https://mbb.eet-china.com/blog/uid-me-1010859.html

    版权声明:本文为博主原创,未经本人允许,禁止转载!

    PARTNER CONTENT

    文章评论0条评论)

    登录后参与讨论
    我要评论
    0
    24
    关闭 站长推荐上一条 /3 下一条