PCIe系列第六讲、PCIe的数据链路层

作者:叫什么好呢啊,文章来源:根究FPGA微信公众号

本章将着重讲述TLP的数据链路层组成与操作,上一篇更新应该为第五讲,数据链路层位于事务层和物理层之间,使用容错和重传机制保证了数据传输的完整性和一致性,此外,数据链路层还需要对PCIe链路层进行监控和管理。

数据链路层的组成

数据链路层由发送和接收两部分组成,其中,数据链路层接收部件组成为:
1)、ACK/NAK DLLP发送逻辑
2)、“Error Check”逻辑
3)、TLP接收逻辑

发送部件组成:
1)、ACK/NAK接收逻辑
2)、Replay Buffer
3)、TLP发送逻辑

在数据链路层中,TLP的格式:
{Sequence , TLP Header , TLP Datapayload , TLP Digest , LCRC}

其中,Sequence为前缀,存放当前TLP的序列号;LCRC为当前TLP的CRC校验和。具体格式如下图所示:

数据链路层的状态

数据链路层通过物理层监控当前PCIe链路层的状态,数据链路层会处于以下3种状态:
(1)、DL Interactive:物理层通知数据链路层当前PCIe链路不可用,此时PCIe链路的对端可能未连接设备或未检测到对端设备。
复位后,数据链路层控制和管理状态机(Data Link Layer Controland manage State Macheine)进入该状态,只有传统复位(cold、warm、hot reset)才能使DLCMSM进入DL INIT状态。FLR方式不会影响DLCMSM状态机。
进入DL INIT状态后,数据链路层彻底复位,丢弃在Replay Buffer保存的所有报文,当处于DL INIT状态时,向事务层发送DL DOWN状态信息
(2)、DL Init:物理层通知数据链路层当前PCIe链路可用,此时数据链路层需要首先初始化VC0的流量控制机制,之后初始化其他通道的流量控制机制,且此时不可以收发DLLP或TLP。此时物理层处于链路初始化状态。
在DL INIT时,首先对PCIe的VC0的流量控制进行初始化,流量控制(Flow Control)初始化分为两个阶段(FC_INIT1&FC_INIT2):
FC_INIT1:数据链路层向事务层提交DL_DOWN信息。
FC_INIT2:数据链路层向事务层提交DL_UP信息。
(3)、DL Active:物理层通知数据链路层当前PCIe链路正常,此时物理层已经训练或重训练完毕。
此外,数据链路层还会向事务层TL通知以下状态:
(1)、DL Down:数据链路层通知事务层当前PCIe链路对端未检测到其他设备,当数据链路层处于DL Inactive状态时,该状态位有效。
(2)、DL Up:数据链路层通知事务层当前PCIe链路连接了其他设备,当DL处于Active状态时,该状态位有效。

数据链路层的管理DL_DOWN&DL_UP
当出现以下三种情况时,DL DOWN有效:
(1)、无当前PCIe链路对端设备的连接
(2)、数据链路层或物理层出现了异常
(3)、软件禁用当前PCIe链路

当链路处于DL DOWN状态时,Switch和PCIe桥的上游端口,将复位相关的内部逻辑和状态,并丢弃所有正在处理的TLP,此时Switch和PCIe桥将使用hot reset的方式复位所有下游端口。

当链路处于DL UP状态时,表示该设备已经与PCIe链路的对端设备建立连接,链路两端可以正常收发报文,当事务层发现DL DOWN向DL UP的转移时,将重新初始化相关寄存器。

DLLP格式
DLLP产生于数据链路层,终止于数据链路层,设置DLLP的目的是保证TLP的正确传输和管理PCIe链路。
一个DLLP长度为6byte,其中byte0存放DLLP的类型,byte1~byte3与DLLP的类型有关,byte4~byte5位DLLP的16bit的CRC校验结果。

DLLP报文类型有:
1、 ACK DLLP:由数据接收方发送给数据发送方,该DLLP表示接收方正确接收到来自发送方的TLP。
2、 NAK DLLP:由数据接收方发送给数据发送方,该DLLP表示哪些TLP没有被正确接收,在接收到该TLP时,接收方“Replay Buffer”加释放已经被正确接收的TLP。
3、 Power Management DLLPs:PCIe设备使用过该组DLLPs进行电源管理,并向对端设备通知当前PCIe链路的状态,拥有保证电源管理状态机的正确运行。
4、 FLOW Control Packet DLLPs:流控制DLLP,包括InitFC1、InitFC2、UpdateFC DLLP等类型,用于流量控制。
5、 Vendor_Defined DLLPs:厂商自定义DLLP。

ACK/NAK协议
ACK/NAK是一种滑动窗口协议,PCIe设备数据链路层的发送端和接收端分别有一个滑动窗口,发送端在发送TLP时,首先将这个TLP存放到发送窗口(这个窗口就是“Replay Buffer”)中,并对这些TLP从0~n进行编号,只要发送窗口不满,发送端就一直发送端就一直可以从事务层接收报文存放到发送窗口中。

当发送端收到接收端第n个ACK确认报文后,表示第n、n-1…..0等在“Replay Buffer”的报文已被正确接收,然后滑动窗口,释放已被确认的TLP,提高PCIe总线的传输效率。

4.5 发送端如何使用ACK/NAK协议
数据链路层在发送TLP之前,首先要给这个TLP添加一个Sequence前缀和LCRC后缀,之后再将TLP放入“Replay Buffer”中。
发送端设置了一个12bit的计数器NXT_TRANSMIT_SEQ,这个计数器的初始值为0,在数据链路层处于Inactive状态时该计数器保持为0.
发送端使用NXT_TRANSMIT_SEQ保存即将发送TLP的Sequence号,PCIe设备每发送完一个TLP,该计数器加一,直到4095。
同时接收方也有一个12bit的NXT_RCV_SEQ,该计数器记录接收端即将接收的TLP总线号(Sequence Number)。
发送端为了处理来自接收端的ACK/NAK DLLPs,设置了一个ACKD_SEQ,该计数器记录ACK/NAK DLLP中的AckNack_Seq_Num字段,该计数器的初始值为全1,数据链路层为Inactive状态时,保持为全1,在接收到接收方的ACK/NAK DLLP时,将使用ACK/NACK DLLP中的AckNak_Seq_Num字段更新ACKD_SEQ计数器。

4.6 接收端如何使用ACK/NAK协议
接收端首先从物理层获得TLP,此时这个TLP中包含Sequence前缀和LCRC后缀,接收端收到这个TLP后,首先将这个报文放入receive buffer中,然后进行CRC检查,检查成功时,结束段将根据缓存的阈值发送ACK DLLP给发送端。

ACK 应答原则:

(1)、接收端收到一定数量的报文后,统一发送给一个ACK给发送方

(2)、接收端收到的报文未达到阈值,但是ACK_NACK_LATENCY_TIMER计数器超时后,仍要发出ACK DLLP。

4.7 数据链路层发送报文的顺序
数据链路层还规定了报文发送的顺序,因为DLLP、TLP、PLP(物理层包)使用同一链路,因此PCIe链路需要合理安排报文发送顺序,防止死锁:
1、 正在发送的TLP、DLLP报文,为了报文的完整性,正在传输的报文享有最高优先级。
2、 PLP,协议底层的报文优先级高于协议高层的报文,这是避免传输死锁的一种有效方法。
3、 NACK(原因同2)
4、 ACK,(一般来说。错误信息报文具有更高优先级)
5、 重传的TLP,也是一种发现错误后的恢复手段,在错误未处理完毕之前,所有TLP的传递没有意义,接收端都将丢弃这些报文。
6、 数据缓冲区的TLP
7、 其他DLLP,包括地址路由、电源管理等报文,与数据报文的传递无关,是PCIe总线规定的一些控制报文,优先级高的话会占用较多传输资源,降低通信带宽,所有优先级最低。

最新文章

最新文章