SDR 与 DDR IO 寄存器:双沿收发把引脚带宽翻倍
更新时间:2026-09-24。本文是「集成电路大类 · 芯片设计」入门层(beginner)数字逻辑基础的一篇。一个时钟周期只有一个上升沿,SDR 每拍在引脚上传一个数;想不提高时钟频率就把外部带宽翻倍,最直接的办法是让下降沿也传数据,这就是 DDR。这一篇讲清 DDR 为什么必须靠专用 IO 寄存器原语实现、ODDR/IDDR 怎么用普通正沿触发器和 MUX 拼出来,以及它和 SerDes 的分界在哪里。阅读前建议先掌握触发器与锁存器和 MUX 选择器。
本文要回答的问题
- DDR 相对 SDR 凭什么多一倍数据?两个沿的数据在芯片内部怎么表示?
- 为什么不能直接写
always @(posedge clk or negedge clk)给同一个 reg 赋两组值? - ODDR 发送端怎么用两个正沿触发器加一个 MUX 合成双沿输出?
- IDDR 接收端怎么把双沿串行数据重排成两路同相位的并行数据?
- 边沿对齐和中心对齐差在哪?占空比、抖动预算、IDELAY 是怎么回事?
- DDR 和 SerDes 的边界在哪里,哪些常见接口在用 DDR?
一、SDR 一个沿一个数,DDR 两个沿两个数
先看最朴素的 SDR(Single Data Rate,单倍数据率)。发送端只有一个触发器,时钟上升沿把 D 打到 Q,引脚电平每周期更新一次,随后稳稳保持整整一个周期。接收端同样用上升沿采样。于是引脚数据率严格等于时钟频率:100MHz 时钟,每根线每秒传 1 亿个 bit。
DDR(Double Data Rate,双倍数据率)改了一个地方:上升沿传一个数 D1,下降沿再传一个数 D2,引脚每半个周期更新一次。时钟还是 100MHz,每根线每秒却能传 2 亿个 bit,带宽立刻翻倍,而且完全不用提高时钟频率——这意味着不用换更快的晶体管、不用压缩内部组合逻辑、不用对付更高频带来的功耗和 EMI 问题。DDR 内存从 DDR 到 DDR5 一代代沿用的正是这个基本技巧。
这张图点出了全文的关键:翻倍只发生在 IO 边界,芯片内部仍旧是单沿逻辑。内部电路每个上升沿处理的是一对数据 (D1, D2),即「每拍两数、两路并行」;到了管脚上,这一对要被摊成「先 D1 后 D2、双沿串行」。负责这个格式转换的专用寄存器,发送方向叫 ODDR(Output DDR),接收方向叫 IDDR(Input DDR)。它们通常做在紧挨 PAD 的 IOE(IO 逻辑块)里,紧贴焊盘放置以最小化到管脚的路径偏斜,详见管脚与 PAD。
换句话说,内部逻辑看到的接口始终整齐划一:单时钟沿、每拍一对并行数据。设计者根本不需要在 RTL 主体里处理双沿,只要在顶层把普通并行总线接上 ODDR/IDDR 原语即可。
二、为什么不能写双沿敏感的 always
初学者的第一反应往往是:既然要两个沿都传数据,那 Verilog 里直接写双沿敏感不就行了?
always @(posedge clk or negedge clk)
q <= d;仿真波形上看,这段代码似乎确实在两个沿都更新 q。但它无法可靠综合,原因有三层。
第一,标准单元库里没有「双沿触发的单个触发器」。现实的触发器只有一个时钟引脚,只认一个边沿;真双沿采样要用两个触发器加锁存器或 MUX 拼,面积更大,库厂商通常不提供这种通用单元。第二,综合工具面对这种敏感列表的行为不可移植:可能报错、可能推断出锁存器,也可能拼出时序特性与预期不符的结构,换个工具版本结果就变。第三,即便勉强综合,静态时序分析器也不知道该按哪条半周期路径约束,时序签核无法进行。
正确做法只有两种。一是显式地用两个普通正沿触发器加 MUX 拼出来(下面两节展开),让每个寄存器、每条路径都是工具认识的常规结构;二是在 FPGA/ASIC 的 IO 边界直接例化厂商提供的 ODDR/IDDR 原语,例如 Xilinx 7 系列的 ODDRE1/IDDRE1、早期的 ODDR2/IDDR2,Intel 的 ALTDDIO_OUT/ALTDDIO_IN。原语本身已经把双沿结构和时序约束都封装好,时序分析器一看就知道这是一条受两个时钟沿约束的 IO 路径。
记住这条判据:双沿是接口格式,不是内部建模范式。RTL 主体永远只用单沿时钟,双沿的事情全部收敛到 IO 原语里。
三、ODDR:两个正沿触发器加一个半周 MUX
发送侧要把内部每拍一对 (D1, D2) 合成双沿串行波形。结构上需要两个寄存器和一个选择器。
D1、D2 先各自进入一个在时钟上升沿采样的普通触发器,两路同时被同一上升沿打入。随后一个 MUX 在它们之间二选一,选择信号就是时钟本身(或其等幅反相):时钟为高的前半周选通 D1,时钟为低的后半周选通 D2。于是引脚波形自然变成——上升沿之后是 D1,下降沿之后切换为 D2,下一个上升沿再切到新的 D1。
这张结构图有两个必须读出来的细节。其一,两个寄存器都由上升沿打入,并没有真的使用下降沿触发器——所谓「下降沿数据」D2 只是被安排在低电平半周送到引脚上而已,这就是双沿能被普通单沿单元实现的原因。其二,MUX 的选择信号与时钟严格同相,切换动作恰好发生在两个数据都已经稳定的时刻,输出在每个半周内保持不动。这本质上是一个无毛刺的时钟半周选择,和无毛刺时钟切换电路遵循同一类纪律:选择信号绝不能在数据通路中间产生竞争和毛刺。正因为这个 MUX 的对齐要求极严,ODDR 才被做成 IOE 里的专用硬件,而不是让用户用通用逻辑自行搭建——用普通布线资源拼出来的 MUX,选择信号到引脚的偏斜很难控制。
部分原语还提供时钟使能、置位复位(与 SR/CE 控制端同理),用于总线复位和节电。
四、IDDR:把双沿流拆回两路同沿并行
接收方向是发送的逆过程:引脚上一个比特流里混着两个半拍的数据,IDDR 要把它拆成同一拍可用的两路并行输出 Q1、Q2。
最直观的做法是两个寄存器分别在上升沿和下降沿采样。但下降沿那路的输出变化时刻和内部逻辑差半拍,不能直接使用,所以实际架构里它往往仍由上升沿触发器实现,只是在前面把数据或时钟做半周期相位调整,让两路输出重新对齐到同一个内部上升沿。对齐之后,内部逻辑在某个上升沿同时拿到同一拍的 Q1 和 Q2,完全感知不到外部双沿。
IDDR 几乎总搭配可编程延迟单元,Xilinx 器件里叫 IDELAY/IDELAYE2:对引脚数据插入几十皮秒一档、总量数百皮秒的精细延迟,把采样沿挪到眼图正中央。因为数据经过封装和 PCB 走线后,飞行时间随走线长短、温度、电压变化,采样沿未必落在数据最稳定处,IDELAY 就是逐比特校准的相位旋钮。
| 环节 | ODDR(发送) | IDDR(接收) |
|---|---|---|
| 内部接口 | 每拍输入 D1、D2 两路并行 | 每拍输出 Q1、Q2 两路并行 |
| 引脚形态 | 双沿串行输出 | 双沿串行采样 |
| 核心结构 | 两个正沿 FF + 时钟半周 MUX | 两套采样 + 相位对齐 |
| 常见搭档 | 输出延迟 ODELAY、串阻校准 | IDELAY、BITSLIP 字对齐 |
| 放置位置 | IOE 内,紧贴 PAD | IOE 内,紧贴 PAD |
高速 ADC/DAC 和一些图像接口还会用到 BITSLIP 之类的字对齐逻辑:当并行路数多于两路(如 4:1、8:1 DDR 解串),训练时逐拍滑动半拍,把字节边界对齐到协议规定的位置。
五、边沿对齐、中心对齐与时序预算
源同步系统(数据和时钟一起从发送端送出)有两种摆相位的方式,接收端采样的难度差别很大。
边沿对齐(edge-aligned):随路时钟与数据同时翻转,时钟边沿正好压在数据跳变沿上,接收端直接采样等于在数据最不稳的时刻下手,必须先把时钟反相或延迟半拍再采。中心对齐(center-aligned):发送端刻意把时钟挪半个周期,让时钟边沿落在数据眼图中央,接收端直接采样,裕量最大。DDR SDRAM 的 DQS 选通配合写平整、读平整训练,本质就是上电后自动测量这个相位,扫过各延迟档找出稳定采样窗口,再把 IDELAY 设到窗口中心。
双沿传输还把时序预算砍得更紧:SDR 每周期只有一个建立保持窗口,DDR 有两个,每条半周期路径的可用时间约为 SDR 的一半。占空比失真使两个半周一长一短,短的那半周率先违例;半周期抖动则让采样裕量被上升沿、下降沿两侧的抖动同时侵蚀。这两项的完整分析见建立保持时间与亚稳态。工程上配套应对:用 PLL/MMCM 生成占空比精确、相位可调的 IO 时钟,用 IDELAY/ODELAY 逐比特校准。
六、和 SerDes 的边界,以及哪些接口在用 DDR
DDR 再快,仍然属于源同步并行接口:每根数据线每个沿传 1 bit,旁边带一根或多根随路时钟(选通),收发双方靠这根时钟对齐。它的提速手段是加宽总线、提高沿速,引脚数随位宽线性增长。
SerDes(串行器/解串器)走另一条路:把时钟嵌进数据流,线上只有一对差分信号,接收端用 CDR(时钟数据恢复)从跳变中还原时钟,单线速率可达数 Gbps 乃至几十 Gbps,详见 SerDes 与 8b/10b 编码。判据很清楚:速率还能用随路时钟可靠跟踪、引脚预算允许,就用 DDR;高到随路时钟偏斜无法控制或必须压缩引脚,才上 SerDes。跨电平连接还需要电平转换。
身边用 DDR IO 的接口很多:QSPI 在 SCK 双沿收发,4 根线拿到 8 倍于普通 SPI 的吞吐;DDR SDRAM 整代建立在这套寄存器上;快速 ADC/DAC 用 DCO/DATA 双沿接口直连 FPGA;MIPI D-PHY 也大量使用双沿采样。看懂 ODDR/IDDR,这些接口手册基本是同一副骨架。
这一篇在知识体系里的位置
本篇属于芯片设计入门层的数字 IO 基础,回答「不提高时钟频率怎么把引脚带宽翻倍」。向前依赖触发器与锁存器、MUX 选择器和分频与时钟使能;横向配套管脚与 IOE、无毛刺时钟切换、建立保持与亚稳态与电平转换;继续提速的话题则通向 PLL 数字锁相环和更高速的 SerDes 与 CDR。把「双沿只是 IO 边界的格式转换」这句话记住,就拿到了阅读所有 DDR 类接口手册的钥匙。
总结
SDR 只在时钟一个沿每周期传一个数,DDR 让上升沿和下降沿各传一个,引脚数据率翻倍却不提高时钟频率;翻倍只发生在 IO 边界,内部始终是单沿逻辑,靠 ODDR 把每拍一对并行数据用两个正沿触发器加一个与时钟严格对齐的半周 MUX 拼成双沿串行,IDDR 再用两套采样加相位对齐把双沿流拆回同沿两路、并用 IDELAY 把采样点移到眼图中心;不能写 always @(posedge or negedge) 给同一个 reg 双沿赋值,因为标准单元没有通用双沿触发器、结果不可移植且无法时序签核;DDR 对占空比失真和半周期抖动比 SDR 敏感一倍,源同步系统还要靠随路选通和延迟训练在边沿对齐与中心对齐间找采样相位;QSPI、DDR 内存、高速 ADC/DAC 用的都是这套 DDR IO,只有到了更高速、更少引脚的场景才换成内嵌时钟加 CDR 的 SerDes。