引言

  1. PCI Express Base Specification Revision 3.0
  2. PCI Local Bus Specification Revision 3.0
  3. 书籍:PCI Express System Architecture,对应那本紫色的《PCI Express 体系结构标准教材》

  上面的两个Specification的文档虽然不是从官网找的,但是可信度还是有保证的。我们学校图书馆有那本中文的书,基本上跟规范里的内容是一致的,而且应该更好理解一点。第一个规范里主要看第七章“Software Initialization and Configuration”,里面介绍了PCIe配置空间的大部分寄存器;第二个规范介绍的是PCI协议,PCIe很多都跟PCI兼容,所以这个文档也很重要,这里主要看第六章“Configuration Space”,MSI相关的寄存器只有在这个文档里才有。在开发过程中,Xilinx的IP文档里没有对这些配置寄存器做具体的说明,所以需要查看这两个规范文档。
  目前我的需求是实现FPGA和DSP之间利用PCIe链路进行通信,所以准备先从FPGA这边的实现开始介绍,然后再写DSP相关的配置。我采用的方式是DSP作为RC(Root Complex)端,FPGA作为EP(End Point)端。我觉得作为嵌入式开发者,对于PCIe的协议其实不用理解特别深入,能够实现初始化配置、数据传输和中断就可以了。

PCIe协议简介

PCIe的配置空间

  首先最重要的就是PCIe的配置空间,当PCIe板卡插到主机上时,host可以通过这一块配置空间获取PCIe设备的信息,同时可以对其进行配置。

  这块空间的前64个字节(0x00~0x3F)作为这块空间的头部,有两种类型,Type 0 和Type 1 。Type 0 是作为端点设备(EP)的设置,Type 1 是作为跟复合体(RC)或者交换结构(Switch)的设置。也就是说,主机和从机,这块配置空间头部是不同的。

BAR空间

  BAR,Base Address Register,就是基址寄存器。什么的基址呢?PCIe的数据空间的基址。PCIe的EP有一块自己的数据空间,上游设备可以通过发包的形式直接对指定的数据空间进行读写。
  一般只在EP上实现BAR,很少有在RC上实现BAR。因为一般都是主机来方位PCIe设备的数据空间。
  如果EP上是32位的BAR,它会先用BAR中低位0的个数来表明BAR对应的数据空间的大小。比如BAR的初始值是“0xFFFF0000”,它的低位有16个0,这几个bit都是硬件上固定的,RC无法改写。这个BAR就表明了它的大小是64kB。RC先读这个BAR,根据低位0 的数量确定了BAR对应的数据空间大小之后,再对高位的“F”进行改写,改成需要的PCIe地址空间的地址。比如改写成“0x68000000”,那么从0x68000000开始的64kB的数据就是这个BAR对应的数据空间。
  如果EP是64位的BAR,情况会有点不一样,但是大同小异。

MSI中断

  MSI,Message Signaled Interrupts,EP可以用这个给RC发中断。MSI中断实际上是EP向RC发送双字数据包,这个双字的地址和内容由RC给定。就是在系统初始化的时候,需要由RC的系统软件往EP的MSI Capability Structure里面进行配置。不难理解,这里的一组寄存器只有RC能够对它改写,因为这是RC告诉EP可以往哪里写数据就表示发中断;如果EP随便往一个地址写数据,搞不好会出大问题。MSI Capability Structure有下面这几种结构:

  这几种结构的区别在于是32位地址还是64位地址,是否支持Per-vector Masking。
  地址的区别很好理解,如果是64位地址,就会多一个Message Upper Address的寄存器。
  Per-vector Masking是一个可选的功能。支持这一功能的话就会多一个Mask Bits的寄存和一个Pending Bits的寄存器。Mask Bits中每一个bit对应一个MSI vector,MSI总共支持32个中断向量。如果把相应的bit置一,EP想要发送这个中断向量的中断的话,就发不出去,而对应的Pending Bits中的bit会置一。如果把mask撤销,这个被挂起的中断就会被发送。
  Message Control寄存器中的有相应的只读的bit来表明目前这个设备是哪种结构的MSI Capability Structure。Xilinx的PCIe的IP好像是支持64bit地址,但是不支持Masking。

Xilinx提供的IP

  Xilinx 提供了三个和PCIe相关的IP,就是下面这三个。文档都可以在DocNav里很容易找到。

  1. Integrated Block for PCI Express
  2. AXI Memory Mapped to PCI Express
  3. DMA/Bridge Subsystem for PCI Express

  我感觉第一个IP的接口是最复杂的,有四个Stream通道,然后又有很多物理层的配置接口。这个应该是PCIe最底层的IP,Virtex 7系列的FPGA的IP文档还是独立的,但都是“Integrated Block for PCI Express”。这个文档里有一部分内容很重要,就是第二章的PCI Configuration Space,这里介绍了PCIe配置空间的寄存器分布。即使我们实际用的是另外两个IP,也需要通过这个文档查寄存器的位置。而这每个寄存器的功能就要查之前说的PCIe的协议规范了。
  第二个IP应该是用AXI接口封了一层,这个AXI接口直接访问PCIe的BAR寄存器对应的数据空间。这个就很方便了,相当于我可以直接从PCIe的数据空间读写数据。这个数据空间既可以是存储器,也可以是外设,总之非常方便灵活。然后这个IP还支持传统的PCI中断,也支持MSI中断。当我们拿它作EP时,可以给RC发中断,这个在之后的具体设计中应该也会经常用到。
  第三个IP的功能最强大,它不仅实现了第二个IP的功能,而且实现了数据上下行的DMA通道,这个IP也被称为XDMA。RC可以给它发送DMA传输的描述符,然后它自己就能搬数据。它也有DMA Bypass 的通道,就是RC也可以不用XDMA,而是像第二个IP一样直接对一块数据空间进行读写。
  第二个IP和第三个IP我觉得各有侧重点。第三个IP虽然既能DMA传输,又能DMA Bypass地直接访问,但是它的Bypass空间只能有一个BAR寄存器对应,而第二个IP可以灵活地设置多个BAR。而且因为第三个IP实现了XDMA,它把原有的最多32个MSI中断中的16个固定作为了DMA传输中断,剩余16个留给用户;而第二个IP则是32个MSI中断都可以由用户自己使用。
  不管是用哪个IP都可以根据实际需求来选择,在每个IP的文档中的Product Specification里面介绍了相关的寄存器。然后要看清楚有些寄存器写着“Only applicable to Root Port cores”,那就是它只能在用作RC的时候使用,要分清楚哪些寄存器是作为RC用的,哪些是作为EP用的。

电路设计

  • UG476 - 7 Series FPGAs GTX/GTH Transceivers
  • 对应器件的 Integrated Block for PCI Express(PG023、PG054、PG156、PG213)

  我用的FPGA是国产的的Virtex 7 系列的XC7VX690T,其实跟Xilinx的是一样的用法。FPGA的PCIe接口是在BANK115上做的,在设计电路的时候要查看上面两篇文档来选择BANK。

  先看Integrated Block for PCI Express,第四章Design Flow Steps里的Constraining the Core里的Transceiver Placemenet里面介绍了每条链路应该放在哪个Block里。要找准型号和封装,就比如我用的是XC7VX690T,就找到下面这张表,然后找到FFG1927的封装,准备用下面红框中的这几个Block来做一个x4的链路。

  找到Block之后就需要去另一个文档——UG476里面找对应的引脚位置。在附录A里面根据Tranceiver的类型和封装可以找到下面这张图。我们在上面已经知道了LANE0是在X1Y23的Block,就像下面红框中标注的一样,我们用红框内的引脚作为LANE0的引脚。所以我们就依次可以确定LANE0~LANE4的发送和接收的差分对应该接哪几个引脚。

  DSP的电路没有什么好说的,PCIe的模块引脚都是固定的。值得一提的是时钟的问题,PCIe通信的双方时钟可以是同步时钟,也可以使异步时钟。如果用异步时钟的话需要注意下面的问题。我用的是异步时钟,但是一般来说同步时钟用得比较多。

Block Design

  下面是我的整体的设计,主要是实现了让DSP通过PCIe接口访问FPGA上外接的DDR的功能。

  新建一个Block Design之后,加入“AXI Bridge for PCI Express”的IP,点击页面上方的“Run Block Automation”之后,可以做一下简单的配置(之后还要改),它就能够生成一个时钟输入的Buffer

  双击对其配置,这里的PCIe Block Location是和具体的引脚引脚分配有关的,已经在前面介绍了。如果这里的Block选得不对,后面的Implement就会报时序的问题。

  IP配置中的PCIe ID那一栏可以默认不管;MISC那一栏是中断相关的,根据需求配置即可;AXI:BARs是AXI地址到PCIe地址的转换,这个应该是用了AXI Slave接口之后才会用到,我这次的设计里没有用Slave接口所以这个也没配置;Debug Options也没啥东西。所以只剩下这个PCIe的BARs了,我分配了三个BAR空间,如下面的图所示。

  BAR0指向的是AXI PCIe的配置空间,它其实非常小,64kB已经完全能够访问到所有寄存器了;BAR1是指向的是我自己做的IP,用来从向RC发MSI中断;BAR2指向的是DDR内的128MB的数据空间。这里的PCIe to AXI Translation只要把AXI的基址填上去就行,要跟Address Editor里面的相对应。Address Editor里的地址我是自动分配的(很多可能BAR访问不到,但这不要紧)。用了XADC是因为DDR的MIG需要一个温度输入,如果MIG里面能直接Enable XADC那就很省事了,但我这不行所以在外面加了XADC。

一些经验

  Windows下的Vivado默认线程(thread)数是2个,Linux系统下的默认线程数是8个。可以用下面的tcl命令获取当前的最大线程数:

get_param general.maxthreads

  Windows下的支持的最大线程数是8个,可以用下面的tcl命令更改

set_param general.maxthreads 8

  每次启动Vivado,这个最大线程数都会回到默认的2个,可以用这个博主的方法来一劳永逸地更改Vivado的默认线程数:链接

  线程数量越多,实现每个job的速度越快。在Run Setting里面的Number of jobs是指可以同时运行的job个数,我们一般只有一个实现,所以即使把这个设置得很大,也不会有加速的效果。Number of jobs的设置在预先独立综合每个IP的时候很有用,每个IP可以各自综合,不同IP综合之间的并行会受到这个数量限制。

  我之前为了在一个工程里实现两个方案,所以新建了一个Run,同时把不用的源文件disable掉。但我看别人好像是用不同的约束文件来限制不同的Run,但是源文件是不用改的。我这么做的时候要改源文件,有时候会报一些奇怪的报错,但确实能在一个工程里做两个实现。

  最后是在读写DDR的时候,出现了这个Transaction Overflow的问题,但是数据都是没错的。DDR在读写的时候会有好几个Outstanding的Transaction,就是那种在读写,但是还没有响应完成的事务。我用的是加在Block Design里面的System ILA,只要在这个IP里面把Enable Transaction Tracing Counter的勾去掉或者把计数值加大就好了。

PCIe接口在FPGA上的实现相关推荐

  1. 关于PCI-E接口你要知道这些点

    PCI-E接口作为主板上可能是最大尺寸的接口,其应用范围非常广泛,不仅仅局限于我们经常用到的独立显卡,其他诸如网卡.声卡.图像采集卡等设备也是通过PCI-E标准来使用的. PCI-E接口是主板上比较通 ...

  2. 关于PCI-E接口你要知道这些点 1

    PCI-E接口作为主板上可能是最大尺寸的接口,其应用范围非常广泛,不仅仅局限于我们经常用到的独立显卡,其他诸如网卡.声卡.图像采集卡等设备也是通过PCI-E标准来使用的. PCI-E接口是主板上比较通 ...

  3. 基于FPGA的PCIe接口实现(具体讲解了数据流向)

    转载自:https://www.cnblogs.com/chengqi521/p/7094544.html 时间:2014-12-09 来源:西安电子科技大学电子工程学院 作者:姜 宁,陈建春,王 沛 ...

  4. 基于FPGA实现PCI-E接口和DMA控制器设计

    随着网络的飞速发展,人们可获取的信息量日益增长,数据的处理及存储速率的要求也越来越高.万兆网(10Gb以太网)的普及,高速存储设备的应用(如DDR2,传输速率可达800M)对系统带宽带来极大的挑战. ...

  5. DSP+FPGA评估板 TI TMS320C6657 1.25GHz-DSP PCIe接口

    本文介绍DSP+FPGA评估板 TMS320C6655/57主要特性,框图: 以及C6657+XC7Z035评估板XQ6657Z35-EVM主要特性,方框图,DSP PCIe接口. TI TMS320 ...

  6. (1)PCIE接口应用领域(学无止境)

    0 目录 0.1 PCIE接口应用领域 0.2 待更新 1 PCIE应用领域之交换机 交换机设计主要由硬件和软件两个部分组成 .软件运行在CPU芯片上,硬件运行在FPGA上.上位机软件通过PCIE总线 ...

  7. Windows下PCIe接口的多串口卡驱动开发小结

    近期在64位Win7下开发一款PCIe接口的多串口卡驱动程序,做个小结: 1. 因为在Win下对WDF不熟悉,加上市面上DDK.WDM书籍较多,故选用WDM框架: 2. 多串口卡的硬件接口为PCIe, ...

  8. EtherCAT 总线主站 FPGA 挂百兆网口串接伺服 ethercat 主站 FPGA verilog 代码 全部在 FPGA上实现,纯 Verilog 实现,无软核

    EtherCAT 总线 demo 板介绍 一.测试架构介绍 总线部分包括 EtherCAT 协议.Canopen 协议.1588 同步协议,全部在 FPGA上实现,纯 Verilog 实现,无软核,时 ...

  9. ZYNQ 高速接口系列(一) PCIe接口

    PCIe 学习笔记 一.PCIe概况 随着现代处理器技术的发展,使用高速差分总线替代并行总线已是大势所趋.与单端并行信号相比,高速差分信号可以使用更高的时钟频率,从而可以使用更少的信号线达到更高的通讯 ...

最新文章

  1. 深入浅出Python元编程
  2. 初次尝试HTML,用记事本编写代码并以html格式保存后用Google浏览器打开
  3. 24.command-executor
  4. html5图片长按保存,一文彻底解决HTML5页面中长按保存图片功能
  5. jsplumb拖线_基于jsplumb插件制作可拖拽、保存流程图、重绘保存后的流程图总结...
  6. 苹果自研5G调制解调器将在2023年量产 采用台积电4nm工艺
  7. 特斯拉最强自动驾驶系统登场,实测视频火热出炉
  8. STL的Vector介绍
  9. MATLAB三阶导怎么输入,三阶样条插值(一阶导数边界条件) matlab程序
  10. 单片机编程:软件定时器
  11. 多拨测试软件,openwrt一线多拨网速叠加操作(网友提供)测试速度请用的方式不要用360那些测试软件...
  12. Win11 ARM64深度解析
  13. 关于前端直播(videoJS与百度云web播放器:Cyberplayer3.0试用)
  14. SLAM【十】回环检测
  15. 成功并不是总要劳其筋骨,饿其体肤,成功的密码是: 专注!
  16. STM32 Mbed系列-ADC参考电压设置
  17. 聚合数据 自己定义接口 超简单demo
  18. unraid虚拟linux系统,UNRAID教程:3分钟用unraid自带的虚拟机安装黑群晖NAS DSM系统很强大!...
  19. visto VTL搭建
  20. cad立体图怎么旋转看图_CAD制图如何旋转图形?

热门文章

  1. 轻量便携 打工人的福音 黑爵320I办公蓝牙三模键盘评测
  2. esp32 ESP32D0WD 芯片引脚
  3. Spring基本使用(元素lookup-method使用)
  4. 一加ACE和OPPO K10 Pro参数 一加ACE和OPPO K10 Pro对比
  5. IntentNet: Learning to Predict Intention from Raw Sensor Data
  6. 软件测试35岁中年危机,如何改行,你首先想到的是做什么?
  7. linux查看后10000行的日志,查看线上日志常用命令
  8. LLVM框架/LLVM编译流程/Clang前端/LLVM IR/LLVM应用与实践-李明杰-专题视频课程
  9. Midjourney官方中文版在QQ开启内测申请;“Hi,Siri”将成历史,苹果计划修改语音助手唤醒方式|极客头条
  10. Java集合如何遍历删除指定元素