PCIe总线

PCIe总线

与PCI总线不同,PCIe总线使用端到端的连接方式,在一条PCIe链路的两端只能各连接一个设备,这两个设备互为是数据发送端和数据接收端。PCIe链路可以由多条Lane组成,目前PCIe链路×1、×2、×4、×8、×16和×32宽度的PCIe链路,还有几乎不使用的×12链路。

PCIe总线_第1张图片

在PCIe总线中,使用GT(Gigatransfer)计算PCIe链路的峰值带宽。GT是在PCIe链路上传递的峰值带宽,其计算公式为 总线频率×数据位宽×2。

按照常理新一代的带宽要比上一代翻倍,PCIe3.0的原始数据传输带宽应该是10GT/s才对而实际却只有8.0GT/s。我们知道,在1.0,2.0标准中,采用的是8b/10b的编码方式,也就是说,每传输8比特有效数据,要附带两比特的校验位,实际要传输10比特数据。因此,有效带宽=原始数据传输带宽*80%。而3.0标准中,使用了更为有效的128b/130b编码方案从而避免20%带宽损失,3.0的浪费带宽仅为1.538%,基本可以忽略不计,因此8GT/s的信号不再仅仅是一个理论数值,它将是一个实在的传输值。 

PCIe总线采用了串行连接方式,并使用数据包(Packet)进行数据传输,采用这种结构有效去除了在PCI总线中存在的一些边带信号,如INTx和PME#等信号。在PCIe总线中,数据报文在接收和发送过程中,需要通过多个层次,包括事务层、数据链路层和物理层。PCIe总线的层次结构如下。

PCIe总线_第2张图片

PCIe总线的层次组成结构与网络中的层次结构有类似之处,但是PCIe总线的各个层次都是使用硬件逻辑实现的。在PCIe体系结构中,数据报文首先在设备的核心层(Device Core)中产生然后再经过该设备的事务层(TransactionLayer)数据链路层(Data Link Layer)和物理层(Physical Layer),最终发送出去。而接收端的数据也需要通过物理层、数据链路和事务层,并最终到达Device Core。

在PCIe总线层次结构中,事务层最易理解,同时也与系统软件直接相关。

事务层定义了PCIe总线使用总线事务,其中多数总线事务与PCI总线兼容。这些总线事务可以通过Switch等设备传送到其他PCIe设备或者RC,RC也可以使用这些总线事务访问PCIe设备。事务层接收来自PCIe设备核心层的数据,并将其封装为TLP(Transaction Layer Packet)后,发向数据链路层。此外事务层还可以从数据链路层中接收数据报文,然后转发至PCIe设备的核心层。事务层还使用流量控制机制保证PCIe链路的使用效率。

总线信号

在一个处理器系统中,一般提供×16的PCIe插槽,并使用PETp0~15、PETn0~15和PERp0~15、PERn0~15共64根信号线组成32对差分信号,其中16对PETxx信号用于发送链路,另外16对PERxx信号用于接收链路。除此之外PCIe总线还使用了下列辅助信号。

1 PERST#信号

该信号为全局复位信号,由处理器系统提供,处理器系统需要为PCIe插槽和PCIe设备提供该复位信号。PCIe设备使用该信号复位内部逻辑,当该信号有效时,PCIe设备将进行复位操作。PCIe总线定义了多种复位方式,其中Cold Reset和Warm Reset这两种复位方式的实现与该信号有关。

2 REFCLK+和REFCLK-信号

PCIe设备与PCIe插槽都具有REFCLK+和REFCLK-信号,其中PCIe插槽使用这组信号与处理器系统同步。

当PCIe设备作为Add-In卡连接在PCIe插槽时,可以直接使用PCIe插槽提供的REFCLK+和REFCLK-信号,也可以使用独立的参考时钟,只要这个参考时钟在100MHz±300ppm范围内即可。在PCIe设备配置空间的Link Control Register中,含有一个“Common ClockConfiguration”位。当该位为1时,表示该设备与PCIe链路的对端设备使用“同相位”的参考时钟;如果为0,表示该设备与PCIe链路的对端设备使用的参考时钟是异步的。如果主机系统使用用了扩谱时钟,那么最好使用这个参考时钟信号,不要使用自己的晶振产生时钟。

3 WAKE#信号

当PCIe设备进入休眠状态,主电源已经停止供电时,PCIe设备使用该信号向处理器系统提交唤醒请求,使处理器系统重新为该PCIe设备提供主电源Vcc。在PCIe总线中,WAKE#信号是可选的,因此使用WAKE#信号唤醒PCIe设备的机制也是可选的,产生该信号的硬件逻辑必须使用辅助电源Vaux供电。

WAKE#是一个Open Drain信号,一个处理器的所有PCIe设备可以将WAKE#信号进行线与后,统一发送给处理器系统的电源控制器。当某个PCIe设备需要被唤醒时,该设备首先置WAKE#信号有效,然后在经过一段延时之后,处理器系统开始为该设备提供主电源Vcc,并使用PERST#信号对该设备进行复位操作。此时WAKE#信号需要始终保持为低,当主电源Vcc上电完成之后,PERST#信号也将置为无效并结束复位,WAKE#信号也将随之置为无效,结束整个唤醒过程。

配置空间    

PCI总线定义了两类配置请求,一个是Type00h配置请求,另一个是Type 01h配置请求。

其中HOST主桥或者PCI桥使用Type 00h配置请求,访问与HOST主桥或者PCI桥直接相连的PCI Agent设备或者PCI桥;而使用Type 01h配置请求,需要至少穿越一个PCI桥,访问没有与其直接相连的PCI Agent设备或者PCI桥。在PCI总线中,只有PCI桥能够接收Type 01h配置请求。Type 01h配置请求不能直接发向最终的PCI Agent设备,而只能由PCI桥将其转换为Type 01h继续发向其他PCI桥,或者转换为Type 00h配置请求发向PCI Agent设备。

Legacy PCI v3.0 Type 0/1 Configuration Space Header

    Type 0 Configuration Space Header used by Endpoint applications

    Type 1 Configuration Space Header used by Root Port applications

基本配置空间

这个基本配置空间共由64个字节组成,其地址范围为0x00~0x3F,这64个字节是所有PCI设备必须支持的。

PCI设备都有独立的配置空间,HOST主桥通过配置读写总线事务访问这段空间。PCI总线规定了三种类型的PCI配置空间,分别是PCI Agent设备使用的配置空间,PCI桥使用的配置空间和Cardbus桥片使用的配置空间。

在PCI设备配置空间中出现的地址都是PCI总线地址,属于PCI总线域地址空间。

在PCI Agent设备的配置空间中包含了许多寄存器,这些寄存器决定了该设备在PCI总线中的使用方法,系统软件只对部分配置寄存器感兴趣。PCI Agent设备使用的Type 00配置空间如下。

PCIe总线_第3张图片

在PCI Agent设备配置空间中包含的寄存器如下所示。

(1) DeviceID和Vendor ID寄存器

这两个寄存器的值由PCISIG分配,只读。其中Vendor ID代表PCI设备的生产厂商,而Device ID代表这个厂商所生产的具体设备。如Xilinx公司的K7,其Vendor ID为0x10EE,而Device ID为0x7028。

(5) SubsystemID和Subsystem Vendor ID寄存器

这两个寄存器和DeviceID和Vendor ID类似,也是记录PCI设备的生产厂商和设备名称。但是这两个寄存器和Device ID与Vendor ID寄存器略有不同。下文以一个实例说明Subsystem ID和Subsystem

(6) ExpansionROM base address寄存器

有些PCI设备在处理器还没有运行操作系统之前,就需要完成基本的初始化设置,比如显卡、键盘和硬盘等设备。为了实现这个“预先执行”功能,PCI设备需要提供一段ROM程序,而处理器在初始化过程中将运行这段ROM程序,初始化这些PCI设备。ExpansionROM base address记载这段ROM程序的基地址。

(7) CapabilitiesPointer寄存器

在PCI设备中,该寄存器是可选的,但是在PCIe设备中必须支持这个寄存器,Capabilities Pointer寄存器存放Capabilities寄存器组的基地址,PCI设备使用Capabilities寄存器组存放一些与PCI设备相关的扩展配置信息。

(8) InterruptLine寄存器

这个寄存器是系统软件对PCI设备进行配置时写入的,该寄存器记录当前PCI设备使用的中断向量号,设备驱动程序可以通过这个寄存器,判断当前PCI设备使用处理器系统中的哪个中断向量号,并将驱动程序的中断服务例程注册到操作系统中。

(9) InterruptPin寄存器

这个寄存器保存PCI设备使用的中断引脚,PCI总线提供了四个中断引脚INTA#、INTB#、INTC#和INTD#。InterruptPin寄存器为1时表示使用INTA#引脚向中断控制器提交中断请求,为2表示使用INTB#,为3表示使用INTC#,为4表示使用INTD#。

如果PCI设备只有一个子设备时,该设备只能使用INTA#;如果有多个子设备时,可以使用INTB~D#信号。如果PCI设备不使用这些中断引脚,向处理器提交中断请求时,该寄存器的值必须为0。值得注意的是,虽然在PCIe设备中并不含有INTA~D#信号,但是依然可以使用该寄存器,因为PCIe设备可以使用INTx中断消息,模拟PCI设备的INTA~D#信号。

(10) BaseAddress Register 0~5寄存器

该组寄存器简称为BAR寄存器,BAR寄存器保存PCI设备使用的地址空间的基地址,该基地址保存的是该设备在PCI总线域中的地址。其中每一个设备最多可以有6个基址空间,但多数设备不会使用这么多组地址空间。

在PCI设备复位之后,该寄存器将存放PCI设备需要使用的基址空间大小,这段空间是I/O空间还是存储器空间,如果是存储器空间该空间是否可预取。

系统软件对PCI总线进行配置时,首先获得BAR寄存器中的初始化信息,之后根据处理器系统的配置,将合理的基地址写入相应的BAR寄存器中。系统软件还可以使用该寄存器,获得PCI设备使用的BAR空间的长度,其方法是向BAR寄存器写入0xFFFF-FFFF,之后再读取该寄存器。

处理器访问PCI设备的BAR空间时,需要使用BAR寄存器提供的基地址。值得注意的是,处理器使用存储器域的地址,而BAR寄存器存放PCI总线域的地址。因此处理器系统并不能直接使用“BAR寄存器+偏移”的方式访问PCI设备的寄存器空间,而需要将PCI总线域的地址转换为存储器域的地址。

扩展配置空间

此外PCI/PCI-X和PCIe设备还扩展了0x40~0xFF这段配置空间,在这段空间主要存放一些与MSI或者MSI-X中断机制和电源管理相关的Capability结构。其中所有能够提交中断请求的PCIe设备,必须支持MSI或者MSI-X Capability结构。

PCIe设备还支持0x100~0xFFF这段扩展配置空间。PCIe设备使用的扩展配置空间最大为4KB,在PCIe总线的扩展配置空间中,存放PCIe设备所独有的一些Capability结构,而PCI设备不能使用这段空间。

PCIe总线规范要求其设备必须支持Capabilities结构。在PCI总线的基本配置空间中,包含一个Capabilities Pointer寄存器,该寄存器存放Capabilities结构链表的头指针。在一个PCIe设备中,可能含有多个Capability结构,这些寄存器组成一个链表。一个PCIe设备可以包含多个Capability结构,包括与电源管理相关、与PCIe总线相关的结构、与中断请求相关的Capability结构、PCIe Capability结构和PCIe扩展的Capability结构。

PCIe总线_第4张图片

事务层协议

事务层是PCIe总线层次结构的最高层,该层次将接收PCIe设备核心层的数据请求,并将其转换为PCIe总线事务,PCIe总线使用的这些总线事务在TLP头中定义。

在PCIe总线中,Non-Posted总线事务分两部分进行,首先是发送端向接收端提交总线读写请求,之后接收端再向发送端发送完成(Completion)报文。PCIe总线使用Split传送方式处理所有Non-Posted总线事务,存储器读、I/O读写和配置读写这些Non-Posted总线事务都使用Split传送方式。PCIe的事务层还支持流量控制和虚通路管理等一系列特性。

TLP格式

当处理器或者其他PCIe设备访问PCIe设备时,所传送的数据报文首先通过事务层被封装为一个或者多个TLP,之后才能通过PCIe总线的各个层次发送出去。 

一个完整的TLP由1个或者多个TLP Prefix、TLP头、Data Payload(数据有效负载)和TLP Digest组成。TLP头是TLP最重要的标志,不同的TLP其头的定义并不相同。TLP头包含了当前TLP的总线事务类型、路由信息等一系列信息。在一个TLP中,Data Payload的长度可变,最小为0,最大为1024DW。

TLPDigest是一个可选项, 一个TLP是否需要TLP Digest由TLP头决定。DataPayload也是一个可选项,有些TLP并不需要DataPayload,如存储器读请求、配置和I/O写完成TLP并不需要Data Payload。

TLPPrefix由PCIe V2.1总线规范引入,分为LocalTLP Prefix和EP-EP TLP Prefix两类。其中Local TLP Prefix的主要作用是在PCIe链路的两端传递消息,而EP-EP TLP Prefix的主要作用是在发送设备和接收设备之间传递消息。

TLP头由3个或者4个双字(DW)组成。其中第一个双字中保存通用TLP头,其他字段与通用TLP头的Type字段相关。一个通用TLP头由Fmt、Type、TC、Length等字段组成,如图5‑2所示。

如果存储器读写TLP支持64位地址模式时,TLP头的长度为4DW,否则为3DW。而完成报文的TLP头不含有地址信息,使用的TLP头长度为3DW。

PCIe总线_第5张图片

    1.Fmt 和 Type 字段确认当前 TLP 使用的总线事务,TLP 头的大小是由 3 个双字还是 4 个双字组成,当前 TLP 是否包含有效负载。Fmt+Type配置信息如下 

PCIe总线_第6张图片

PCIe总线_第7张图片

2.TC 字段表示当前 TLP 的传送类型,PCIe 总线规定了 8 种传输类型,分别为TC0~TC7,缺省值为 TC0,该字段与 PCIe 的 QoS 相关。
    3.Attr 字段由 3 位组成,其中第 2 位表示该 TLP 是否支持 PCIe 总线的 ID-basedOrdering;第 1 位表示是否支持 Relaxed Ordering;而第 0 位表示该 TLP 在经过 RC 到达存储器时,是否需要进行 Cache 共享一致性处理。 

PCIe总线_第8张图片

    4.TH 位为 1 表示当前 TLP 中含有 TPH(TLP Processing Hint)信息,TPH 是 PCIe V2.1 总线规范引入的一个重要功能。TLP 的发送端可以使用 TPH 信息,通知接收端即将访问数据的特性,以便接收端合理地预读和管理数据。
    5.TD 位表示 TLP 中的 TLP Digest 是否有效,为 1 表示有效,为 0 表示无效。
    6.EP 位表示当前 TLP 中的数据是否有效,为 1 表示无效,为 0 表示有效。
    7.AT 与 PCIe 总线的地址转换相关,可暂时不考虑。
    8.Length字段用来描述 TLP 的有效负载(Data Payload)大小。PCIe 总线规范规定一个 TLP的 Data Payload 的大小。PCIe 总线设置 Length 字段的目的是提高总线的传送效率。Length 字段以 DW 为单位,其最小单位为 1 个 DW。
    9.Request ID字段包含“生成返个 TLP 报文”的 PCIe 设备的总线号(Bus Number)、设备号(Device Number)和功能号(Function Number) 

PCIe总线_第9张图片

     10.Last DW BEFirst DW BE,在PCIe 总线以字节为基本单位迕行数据传递,但是 Length 字段以 DW 为最小单位。为此TLP 使用 Last DW BE 和 First DW BE 返两个字段迕行字节使能,使得在一个 TLP 中,有效数据以字节为单位。

PCIe总线_第10张图片

PCIe总线_第11张图片

一个简单的TLP

PCIe总线_第12张图片

这是一个TLP报文:01a0090f40000001+0403020100000010,由于一次发送64位,因此这个报文的前64位是标头,后64位是数据和地址。
    按照上图的数据格式可知
    Request ID:16’b0000_0001_1010_0000
    Tag:8’b0000_1001
    Last DW BE:4’b0000
    First DW BE:4’b1111
    Fmt:2’b10
    Type:5’b0_0000
    Length:10’b00_0000_0001
    Data:32’h04030201
  Address:32’h00000010(低两位无效) 

完成报文(摘自PCIe入门
    当发送端发送一个TLP给接收端后,接收端有时需要发送一个完成报文返回给发送端,如发送端发送一个Memory Read(存储器读请求)到接收端,那么接收端就会读取相应地址下的数据,拼接到完成报文中反馈给发送端,这样就完成了一次存储器读请求。
    不是所有的请求都会反馈一个完成报文,下图中Non-Posted 表示需要反馈完成报文,而Posted 表示不需要反馈完成报文。

PCIe总线_第13张图片

完成报文的格式 

PCIe总线_第14张图片

  其中Byte0~Byte3的字段功能和普通TLP的一致,不一样的字段分析如下:
    Requester ID 和 Tag 字段完成报文使用 ID 路由方式。完成报文头的长度为 3DW,完成报文头包含 Transaction ID 信息,由 Requester IDTag 字段组成,返个 ID 必须与源设备发送的数据请求报文的 Transaction ID 对应,完成报文使用 Transaction ID 运行 ID 路由,并将数据发送给源设备。当 PCIe 设备收到存储器读、I/O 读写或者配置读写请求 TLP 时,需要首先保存返些报文的 Transaction ID,然后当该设备准备好完成报文后,将完成报文的 Requester IDTag 字段赋值为当前保存的 Transaction ID 字段。
    Completer ID 字段存放发送完成报文的PCIe设备的 ID号,PCIe设备运行数据请求时需要在TLP字段中包含Requester ID字段;而使用完成报文结束数据请求时,需要提供 Completer ID 字段。
    Lower Address 字段,如果当前完成报文为存储器读完成 TLP,该字段存放在存储器读完成 TLP 中第一个数据所对应地址的最低位。值得注意的是,在完成报文中,并不存在 First DW BE 和 Last DW BE字段,因此接收端必须使用存储器读完成 TLP 的 Low Address 字段,识别一个TLP中包含数据的起始地址。
    Status字段保存当前完成报文的完成状态,表示当前 TLP 是正确地将数据传递给数据请求端;还是在数据传递过程中出现错误;或者要求数据请求方运行重试。 

PCIe总线_第15张图片

PCIe总线_第16张图片

BAR空间
    PCIe板卡访问PC内存时,板卡向 PC 发送 TLP 包,例如 MWr 包,地址信息就是PC 的物理地址;如果是 MRd 包,那 PC 收到后回复一个完成包,板卡从完成包分析出数据即得到 MRd 读取地址的数据。这是PCIe板卡访问PC。
     PC访问PCIe板卡,简单的解释,PC 启动是,BIOS 探测所有的外设。对 PCIe (PCI)设备来说,BIOS 检测到板卡有多少个 BAR 空间,每个空间有多大,然后对应为这些 BAR 空间分配地址。对 PC 设备来说,它能“看”到 PCIe 板卡的空间只有 BAR 空间,也就只能访问这些 BAR 空间。也就是说,板卡可以发送合法的 PCIe TLP 包,并得到 PC 端的相应;但是 PC 端访问板卡被局限在 BAR 空间。

代码解读

    PIO_EP_MEM_ACCESS 用于控制FPGA的存储器的读写; 
    PIO_RX_ENGINE 是接收引擎,用于接收、解析TLP; 
    PIO_TX_ENGINE 是发送引擎,用于组装、发送TLP;

PIO 工作流程大概描述:

PCIe总线_第17张图片

首先差分接收接口(rxn、rxp)接收到信号,信号经过物理层、数据链路层、事务层之后变成TLP进入接收引擎(PIO_RX_ENGINE )进行解析;接着根据标头判断这个TLP是读存储器还是写存储器,若是写存储器,就将下一个TLP中的地址和数据解析出来(因为这里一次发送64bit,所以第一个TLP中不包含地址和数据,第二个TLP中包含地址和数据),然后通过PIO_EP_MEM_ACCESS 模块将数据写入指定的地址中;若是读存储器,就将下一个TLP中包含的地址解析出来,再通过PIO_EP_MEM_ACCESS 模块将数据从指定的地址中读取出来,然后经过发送引擎(PIO_TX_ENGINE )进行完成包拼接,最后通过事务层、数据链路层、物理层封装之后,通过差分发送接口(txn、txp)将数据发送出去。

--------------------- 本文来自 CLGo 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/cllovexyh/article/details/79828833?utm_source=copy

--------------------- 本文来宁静海111 的CSDN 博客,全文地址请点击:https://blog.csdn.net/ningjinghai11/article/details/80924209?utm_source=copy

你可能感兴趣的:(高速接口)