数据链路层在事务层下面,它封装了TLP数据包,并加上前缀和后缀,形成了DLLP包。如下是层级关系
DLLP包是完全由硬件完成的
数据链路状态机如下
所有的DLLP包含1dword,前面8bit作为dllp的type,后面作为dllp的type的衍生字段。最后16bit作为crc校验,如下
这里关于dllp type的类型如下
所以根据不同类型的dllp的字段如下
对于数据链路层,先发送了DLLP包出去,里面标明了DLLP的type和DLLP的type对应字段,再加上CRC。然后再发送TLP,这时候的TLP包会包装前缀和后缀,用作标明TLP包的序列号以及TLP的LCRC校验,也就是如下
这里的Sequence ID 和LCRC是对TLP的封装。
所以数据链路层的通信流程如下
这里A是发送者,B是接收者,A会发送TLP包给B,所以B会发送ACK/NAK的DLLP给A接收,这里的DLLP就包含两个部分,一个是1dword+16bit crc的DLLP,一个是包装TLP包加上Sequence和LCRC的完整TLP包。
上面已经知道DLLP包括自定义的DLLP字段以及会在TLP添加前缀和后缀。这里根据文档描述,讲述DLLP的发送和接收流程
NEXT_TRANSMIT_SEQ:存放下一个待发TLP包的序列号,TLP包前缀。 AckNak_Seq_Num:DLLP的ACK/NAK字段,存放最后成功接收TLP的序列号 ACKD_SEQ:存放最近收到的序列号(从DLLP的ACK/NAK返回)
所以先判断下一个待发TLP的序列号,不能大于总Counter(4096)的一半。 如果ACKD_SEQ(存放的序列号)和AckNak_Seq_Num(DLLP的ACK/NAK)不相等,则意味着上一次的包发送成功,开始发下一个包,则清空原来的retry buffer,将新的包的序列号加载到ACKD_SEQ,开始发送,如果接收到ACK,则成功,如果为NAK,则重发。
将NEXT_RCV_SEQ:这里是一个计数器,对TLP包计数加1,用来判断NEXT_TRANSMIT_SEQ和自己是否相等
先计算收到的TLP包的LCRC值,然后判断物理层确定TLP是否有效,再获取这次接收到的TLP包的DLLP的后缀LCRC,判断自己计算的LCRC和DLLP的LCRC是否匹配,最后判断当前TLP包的序列号是否等于NEXT_RCV_SEQ,如果等于,将NEXT_RCV_SEQ自增加1,开始处理TLP包,发送ACK,否则发送NAK。