2、SATA物理层基本架构与分层模型
说实话,做了这么多年SATA协议相关的项目,我见过不少工程师一上来就盯着PHY层的电气参数猛啃,结果搞了半天连数据是怎么从应用层一路走到物理线上的都没搞清楚。这章我们就先把SATA的整体分层模型捋一遍,然后重点拆开物理层看看里面到底藏着什么。
2.1 SATA协议的四层模型
SATA协议栈从上到下分为四层。我个人习惯把这个模型想象成一套快递系统——应用层是寄件人,传输层是打包员,链路层是快递员,物理层就是那辆送货的卡车。每一层各司其职,又通过严格的接口互相配合。
下面这个表格整理了各层的核心职责。你注意看,每一层只跟相邻层打交道,这种分层设计让调试和维护变得清爽很多。
| 层次 | 核心功能 | 关键协议/技术 |
|---|---|---|
| 应用层 | 主机与设备间的命令交互 | ATA/ATAPI 命令集、AHCI 接口 |
| 传输层 | FIS 的封装与解封装 | FIS 格式定义、DMA 传输控制 |
| 链路层 | 数据帧封装、8b/10b 编码、CRC 校验 | 原语握手、流量控制、重传机制 |
| 物理层 | 串行化/解串、时钟恢复、信号驱动 | OOB 信号、差分传输、扩频时钟 |
举个实际例子。当主机想读一个扇区,应用层先构造 READ DMA 命令,传到传输层打包成 FIS,再交给链路层做 8b/10b 编码并加上 CRC,最后物理层把编码后的比特流通过差分信号发出去。反过来,设备端物理层收到信号,逐层往上解,最终把数据送回到应用层。
2.2 物理层的内部子层
物理层本身还可以再往下拆。标准定义里,它分成两个子层:PCS(Physical Coding Sublayer)和PMA(Physical Media Attachment)。有些资料还会提到 PMD,但实际项目中 PMD 的功能通常被合并到 PMA 里了。
为什么会这样拆?我当年也有过这个疑问。后来在一次链路调试中发现,PCS 负责的是"码字"层面的处理,而 PMA 管的是"比特"和"模拟信号"。这两者的关注点完全不同,分开设计才方便独立优化和测试。
下面这张图把整个分层模型和物理层的内部结构一起画了出来。你一看就明白。
2.3 PCS 子层——码字处理的核心
PCS 子层在物理层里扮演的是"翻译官"角色。链路层传过来的 8 位数据,PCS 先用 8b/10b 编码转成 10 位码字,再交给 PMA 发出去。反过来收到数据时,PCS 做 10b/8b 解码,同时检查编码是否合法。
PCS 还有几个关键任务:
- OOB 信号检测与生成:设备刚上电时,链路还没建立,PCS 负责识别 COMRESET、COMWAKE、COMINIT 这些带外信号。我记得在第一个 SATA 项目的联调阶段,OOB 时序总是不达标,后来发现是 PCS 里的去毛刺滤波器参数没配对。
- 扩频时钟跟踪:SATA 允许 ±5000 ppm 的时钟偏差,PCS 要配合 PMA 的 CDR 做频率跟踪。
- 信号电平检测:判断差分信号幅度是否在有效范围内。
重要:PCS 的 8b/10b 编码本身并不提供纠错能力,它的主要作用是保证位流有足够的跳变沿,方便接收端恢复时钟。同时 DC 平衡特性也避免了信号经过交流耦合电容时出现基线漂移。
2.4 PMA 子层——模拟信号的硬功夫
PMA 子层是物理层里最"硬"的部分。如果说 PCS 是在数字域干活,那 PMA 就在模拟域里摸爬滚打。它直接面对差分信号线,处理的是电压、电流、抖动这些模拟量。
PMA 的核心模块包括:
- 串行化器(Serializer):把 PCS 送来的 10 位并行数据转成 1 位串行比特流,送到差分驱动器上。
- 解串器(Deserializer):接收端的反向操作,把串行比特流转回 10 位并行数据。
- 时钟恢复(CDR):从接收到的串行数据里提取出时钟信号。这是一项技术活——数据里没有单独的时钟线,全靠跳变沿来恢复。我曾经遇到过一个很奇怪的问题,低温环境下 CDR 锁定失败,排查到最后是参考时钟的抖动偏大,锁相环无法收敛。
- 差分驱动器与接收器:负责输出/输入符合 SATA 电气规范的差分信号。
- 阻抗匹配与终端校准:保证信号完整性,减少反射。
实战小技巧:调试 PMA 时,我建议你先用 PRBS 测试码流单独验证串行化器和 CDR 能否正常锁定。不要一上来就跑整条链路,否则出了问题很难定位。我自己习惯在 PHY 的测试模式下把发送端设成 PRBS7 或者 PRBS15 码型,然后在接收端检查误码率。
2.5 物理层与链路层的接口
物理层和链路层之间通过一组并行信号线通信。链路层发给物理层的是 10 位编码后的数据,物理层发给链路层的也是 10 位解码后的数据。我在很多项目中看到新手工程师搞混了这里的位宽——链路层内部用 8 位,但交到物理层接口时已经是 10 位了。
下面是一个简化的 PHY-Link 接口 Verilog 定义,你看一眼就明白了:
// PHY-Link 接口信号定义
module sata_phy_link_interface (
input wire clk_ref, // 参考时钟(通常 150 MHz)
input wire rst_n, // 异步复位,低有效
// 链路层 → PHY 的发送通路
input wire [9:0] tx_data, // 10 位编码数据(8b/10b 后)
input wire tx_valid, // 发送有效标志
output wire tx_ready, // PHY 可接收新数据
// PHY → 链路层的接收通路
output wire [9:0] rx_data, // 10 位解码数据
output wire rx_valid, // 接收数据有效
output wire rx_error, // 接收错误(编码违例或 CRC 错误)
// 串行差分信号
output wire txp, txn, // 发送差分对
input wire rxp, rxn // 接收差分对
);
注意:在实际项目中,接口上还有一些重要的控制信号,比如 PHY 就绪标志、电源状态指示、OOB 状态机触发等。这些信号在不同厂商的 PHY IP 里命名和时序可能略有差异,但核心的 10 位数据通路是统一的。
2.6 链路训练与初始化流程
物理层不是上电就能直接传数据的。它需要经历一套完整的链路训练流程,才能与对端建立稳定的连接。这套流程主要靠 OOB 信号来驱动。
典型的初始化步骤如下:
- 步骤 1:主机发送 COMRESET 脉冲序列,通知设备复位。
- 步骤 2:设备回应 COMINIT,表示已准备好进入链路初始化。
- 步骤 3:主机发送 COMWAKE,设备收到后也回复 COMWAKE,完成唤醒握手。
- 步骤 4:双方进入 ALIGN 原语交换阶段,对接速率、校验链路质量。
- 步骤 5:链路层开始发送训练帧,进一步确认链路可靠性。
- 步骤 6:物理层上报 PHY Ready 信号,链路层开始正常数据传输。
这个过程中,PCS 子层负责 OOB 信号的时序检测与生成,PMA 子层负责在 ALIGN 阶段调整 CDR 锁定参数。双方配合稍有偏差,链路就可能训练失败。
我记得曾经有个项目,因为 PCB 走线过长导致信号衰减偏大,ALIGN 阶段总是有少量符号错误,链路层反复重试后最终超时。后来我们在 PHY 的寄存器里调高了接收均衡器的增益档位,问题就解决了。所以说,物理层的调试往往需要结合 PCB 布局和信号完整性来综合考虑。
核心要点:SATA 物理层的工作可以概括为"并串转换 + 时钟恢复 + 信号驱动"。PCS 负责码字域的编码和 OOB 检测,PMA 负责比特域的串行化和时钟恢复。两者协同完成从并行数据到差分信号的完整链路。掌握了这个分层逻辑,后面遇到 PHY 相关的问题时,你至少知道该去哪个子层里找原因。