一、前言
在之前的内容中,我们已经知道了PCIe是一种外设总线协议,其前身是PCI和PCI-X,虽然PCIe在硬件上有了很大的进步,但其使用的软件与PCI系统几乎保持不变。这种向后兼容性设计,目的是使从旧设计到新设计的迁移更加顺畅,通过尽可能简单、低成本的方式进行软件更改。因此,旧的PCI软件在PCIe系统中可以不做任何更改地运行,而新的软件也会继续使用相同的操作模型。虽然现在PCI和PCI-X已经基本退出市场,但是PCIe中的很多设计和机制都是源自于此,所以,理解PCI及其操作模型将有助于更好地理解PCIe的工作原理。
二、PCI总线的基本概念
图1-1展示了基于PCI总线的旧系统架构。在该系统中,有一个北桥(North Bridge),它之所以被称为“北桥”,是因为在系统图中位于中央PCI总线的北侧。如果把图看作一张地图,北桥的位置位于图中“北边”。北桥的主要功能是作为处理器和PCI总线之间的接口。与北桥相关的总线包括处理器总线、系统内存总线、AGP图形总线和PCI总线。
在PCI总线上,有多个设备共享这条总线,这些设备要么直接连接在总线上,要么插入到扩展卡插槽中。除此之外,南桥(South Bridge)负责将PCI连接到系统的外围设备,例如ISA总线,用于支持一些过渡时期的旧设备。南桥通常也是PCI的中央资源,负责提供系统信号,如复位、参考时钟以及错误报告。
这种架构的设计通过北桥和南桥的分工,北桥负责高速设备(如CPU和内存)的互连,而南桥则连接低速的外围设备。随着技术的进步,这种北桥和南桥的架构逐渐被更高效的集成芯片所替代,例如现在的许多处理器中已经集成了内存控制器和I/O控制器,从而简化了系统设计并提高了性能。
PCI总线是一种共享总线,所以需要特定的仲裁器(Arbiter)来决定当前时刻的总线的控制权。一般该仲裁器位于北桥中,而仲裁器(主机)则通过一对引脚,REQ#(request) 和GNT# (grant)来与各个从机连接。如下图所示:
正如图1-2所示,请求(REQ#)引脚表示 initiator需要使用总线,并将请求发送给总线仲裁器,由仲裁器对所有同时发出的请求进行评估。仲裁器通常位于总线之上的桥接器中,负责接收来自总线上的所有控制器(Bus Masters)的仲裁请求。
仲裁器根据请求情况决定哪个请求者将成为下一个总线的所有者,并向其发送授权(GNT#)信号。根据PCI协议,当前一次事务完成后,当总线处于空闲状态时,看到其GNT#信号被断言的设备将被指定为下一任总线控制器( initiator),并可以开始其事务操作。
这种机制确保了多个设备在共享总线上能够有序地发起数据传输,避免冲突,并通过仲裁器的调度来平衡总线的使用,保证系统的高效运行。
三、一个典型的PCIe总线周期
图1-3展示了一个典型的PCI总线周期。PCI是同步总线,这意味着所有事件都在时钟的边沿发生。此外,PCI总线是一种地址和数据复用的总线,即地址和数据占用同一组信号线AD。
为了保持PCI的低成本设计目标,多个信号在总线上被赋予了多重含义以减少引脚数量。32位的地址和数据线是复用的,而C/BE#(命令/字节启用)信号共享了四根引脚,目的也是为了减少引脚数量。虽然减少引脚数可以降低成本,但也因此导致了PCI需要使用“转换周期”(turn-around cycles),这会增加额外的延迟。这种设计限制了同时传输地址和数据的能力,意味着在前一个事务的数据传输完成之前,无法为下一个事务发送地址信息,也因此无法实现流水线事务处理。这虽然简化了硬件设计,但带来了性能上的一些限制。
为协调数据传输过程中的时序,PCI使用了一些握手信号,包括FRAME#、DEVSEL#、TRDY#、IRDY#和STOP#。FRAME#信号用于指示总线事务的开始和进行;DEVSEL#是设备选择信号,用于目标设备响应事务;TRDY#(目标设备就绪)和IRDY#(发起设备就绪)分别用于表示目标设备和发起设备已经准备好进行数据传输;STOP#则用于在目标设备希望终止事务时断言。这些握手信号在事务期间控制事件的时序,确保发起者和目标设备之间的同步与协调。虽然PCI通过这种设计达到了低成本的目标,但在一定程度上牺牲了传输效率和速度。
时钟边沿1:FRAME#和IRDY#信号均为无效状态,表示总线处于空闲状态。同时,GNT#信号为生效状态,表明总线仲裁器已授权当前设备成为下一次总线访问的发起者(initiator),但事务尚未开始。
时钟边沿2:发起者断言FRAME#信号,表示新的事务开始。同时,它发送该事务的地址和命令信息,总线上的所有设备接收并解码该地址,判断是否与自身匹配。
时钟边沿3:发起者通过断言IRDY#信号表示准备好进行数据传输。由于这是读取操作,AD线进入“转换周期”(turn-around cycle),切换信号方向,以避免冲突。
时钟边沿4:目标设备响应,断言DEVSEL#信号,表明它已被选中并准备参与事务。同时,目标设备通过TRDY#信号表示准备好发送数据。如果IRDY#和TRDY#信号同时生效,数据传输在该时钟周期完成,表示第一个数据阶段结束。FRAME#信号仍然为生效状态,表示事务未完成。
时钟边沿5:目标设备未准备好传输下一组数据,取消了TRDY#信号,进入“等待状态”(Wait State),导致事务延迟一个时钟周期。
时钟边沿6:目标设备准备好第二组数据,数据传输完成,FRAME#信号仍然为生效状态,表示还会有更多数据。
时钟边沿7:发起者进入“等待状态”,暂时暂停数据传输,用以处理内部缓冲。这会延迟事务但不终止它。
时钟边沿8:第三组数据传输完成,此时发起者取消FRAME#信号,目标设备知道这是最后一个数据阶段,事务结束。总线返回空闲状态,准备下一次使用。
四、PCI的反射波信号
PCI架构理论上支持每个总线上最多32个设备,但在实际的电气限制下,这个数量远小于理论值,大约在10到12个电气负载的范围内,且这是基于33MHz的基础频率。这种限制的原因是PCI总线使用了一种称为“反射波信号传输”的技术来降低总线的功耗(详见图1-4)。在这种模型中,设备通过实现较弱的发送缓冲器来节约成本和功耗,这些缓冲器只能将信号驱动到大约一半的电压,尚不足以完全切换信号。
信号的入射波沿着传输线传播,直到到达传输线末端。由于设计上末端没有终端电阻,波前会遇到无限阻抗并反射回去。这种反射是累加的,会使信号电压在返回发射端的过程中逐渐增加到全电压水平。当信号到达源缓冲器时,驱动器的低输出阻抗将终止信号,防止进一步反射。整个过程,从缓冲器发送信号到接收器检测到有效信号的时间,包括信号在传输线上的传播时间、反射延迟以及设置时间,必须小于时钟周期。
随着总线上的电气负载数量增加或传输线长度加长,信号完成这一往返的时间也会增加。在33MHz频率下的PCI总线,只能满足约10到12个电气负载的信号时序要求。一个电气负载是指系统板上的一个设备,但一个插满扩展卡的插槽实际上算作两个负载。因此,33MHz的PCI总线在可靠运行时,最多只能支持4到5个扩展卡插槽。
这种设计确保了在不增加功耗的情况下,能够实现信号的可靠传输,但也因此限制了PCI总线上的设备数量和扩展能力。
为了在系统中连接更多的负载,需要使用PCI到PCI桥接器,如图1-5所示。当更现代化的芯片组出现时,外围设备的数量迅速增长,它们之间对共享PCI总线的访问竞争导致性能受到限制。尽管PCI仍然广泛用于外设,但其速度没有跟上发展需求,成为系统瓶颈。
为了解决这一问题,PCI被从系统外围设备和内存之间的主路径中移出,芯片组互连被专有解决方案(如Intel的Hub Link接口)取代。PCI桥接器是拓扑结构的延伸。每个桥接器都会创建一个新的PCI总线,这条总线在电气上与其上方的总线隔离,从而允许连接另外10到12个负载。一些设备也可以是桥接器,这样就允许在系统中连接大量设备。
PCI架构允许在单个系统中最多支持256条总线,每条总线上最多可以连接32个设备。这种设计大大扩展了系统可连接的设备数量,同时通过电气隔离解决了原始共享总线结构带来的负载限制问题。