原创 Type0配置写函数

2019-8-8 14:46 3067 23 4 分类: FPGA/CPLD 文集: Xilinx PCIe仿真模型
在前面了解PCI配置空间、TLP以及Type0配置读的基础上,本文介绍Type0配置写子函数。该子函数产生一个Type0配置写TLP,先来看具体代码:
  1. /************************************************************
  2. Task : TSK_TX_TYPE0_CONFIGURATION_WRITE
  3. Inputs : Tag, PCI/PCI-Express Reg Address, First BypeEn
  4. Outputs : Transaction Tx Interface Signaling
  5. Description : Generates a Type 0 Configuration Write TLP
  6. *************************************************************/
  7. task TSK_TX_TYPE0_CONFIGURATION_WRITE;
  8. input [7:0] tag_;
  9. input [11:0] reg_addr_;
  10. input [31:0] reg_data_;
  11. input [3:0] first_dw_be_;
  12. begin
  13. if (trn_lnk_up_n) begin
  14. $display("[%t] : Trn interface is MIA", $realtime);
  15. $finish(1);
  16. end
  17. TSK_TX_SYNCHRONIZE(0, 0, 0);
  18. trn_td <= #(Tcq) {
  19. 1'b0,
  20. 2'b10,
  21. 5'b00100,
  22. 1'b0,
  23. 3'b000,
  24. 4'b0000,
  25. 1'b0,
  26. 1'b0,
  27. 2'b00,
  28. 2'b00,
  29. 10'b0000000001, // 32
  30. COMPLETER_ID_CFG,
  31. tag_,
  32. 4'b0000,
  33. first_dw_be_, // 64
  34. COMPLETER_ID_CFG,
  35. 4'b0000,
  36. reg_addr_[11:2],
  37. 2'b00, // 32
  38. reg_data_[7:0],
  39. reg_data_[15:8],
  40. reg_data_[23:16],
  41. reg_data_[31:24] // 64
  42. };
  43. trn_tsof_n <= #(Tcq) 0;
  44. trn_teof_n <= #(Tcq) 0;
  45. trn_trem_n <= #(Tcq) 2'b00;
  46. trn_tsrc_rdy_n <= #(Tcq) 0 ;
  47. TSK_TX_SYNCHRONIZE(1, 1, 1);
  48. trn_tsof_n <= #(Tcq) 1;
  49. trn_teof_n <= #(Tcq) 1;
  50. trn_trem_n <= #(Tcq) 2'b00;
  51. trn_tsrc_rdy_n <= #(Tcq) 1;
  52. end
  53. 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

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

文章评论0条评论)

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