第三讲:物理层共享设计——Pad共享技术、IO Buffer复用、电平转换与阻抗匹配
各位同学,欢迎来到第三讲。今天聊的话题,说白了就是芯片的「嘴巴」怎么共用。
你想想看,一颗芯片要支持多种协议——SPI、I2C、UART、甚至SDIO。每个协议都独占一组Pad?那芯片面积得大到飞起。所以,物理层共享是必须的。
我个人习惯把物理层共享分成三个层次:Pad共享、IO Buffer复用、电平转换与阻抗匹配。咱们一层层剥开。
3.1 Pad共享技术
Pad就是芯片的引脚焊盘。一颗芯片的Pad数量是固定的,封装定了就改不了。所以,多个协议共用一组Pad,是设计的起点。
核心思路: 根据工作模式,把Pad动态分配给不同的协议控制器。
举个例子,一个Pad既可以做SPI的SCLK,也可以做I2C的SCL。怎么选?靠模式选择信号。
关键点: Pad共享不是简单的「线或」连接。必须保证未选中的协议输出为高阻态,否则会打架。
我在项目中遇到过一个问题:两个协议共用一个Pad,结果其中一个协议没配置好输出使能,导致总线冲突,整块板子都拉不起来。排查了整整两天。
所以,我建议在RTL设计时,每个Pad的驱动源必须有一个明确的优先级和使能逻辑。下面是一个典型的Pad共享结构:
// Pad共享示例:SPI与I2C共用SCL/SCLK引脚
module pad_mux (
input wire mode_sel, // 0: SPI模式, 1: I2C模式
// SPI侧
input wire spi_sclk_o,
input wire spi_sclk_oe,
// I2C侧
input wire i2c_scl_o,
input wire i2c_scl_oe,
// Pad侧
output wire pad_sclk_i,
output reg pad_sclk_o,
output reg pad_sclk_oe
);
always @(*) begin
if (mode_sel) begin
// I2C模式
pad_sclk_o = i2c_scl_o;
pad_sclk_oe = i2c_scl_oe;
end else begin
// SPI模式
pad_sclk_o = spi_sclk_o;
pad_sclk_oe = spi_sclk_oe;
end
end
assign pad_sclk_i = (mode_sel) ? i2c_scl_i : spi_sclk_i;
endmodule
嗯,这里要注意:输入路径不需要使能控制,因为输入永远是高阻态监听。但输出路径必须严格用OE控制。
3.2 IO Buffer复用
Pad共享解决的是「哪个协议用这个Pad」的问题。但Pad后面连的是什么?是IO Buffer。
IO Buffer是芯片和外部世界的接口电路。它包含驱动、接收、ESD保护等。不同协议对Buffer的要求不一样:
- SPI: 需要推挽输出,速率高,驱动能力强
- I2C: 需要开漏输出,速率相对低
- UART: 推挽或开漏都可以,看具体实现
所以,IO Buffer复用不是简单的「选通」,而是配置Buffer的工作模式。
我的经验: 设计一个可配置的IO Buffer,通常包含以下可编程位:
- 输出模式:推挽 / 开漏 / 高阻
- 驱动强度:2mA / 4mA / 8mA / 12mA
- 上拉/下拉使能:弱上拉 / 弱下拉 / 无
- 施密特触发使能:用于噪声环境
说白了,一个Buffer要能「变形」。SPI模式下它是推挽强驱动,I2C模式下它变成开漏带上拉。
我曾经在一个项目中,为了省面积,把Buffer的配置寄存器做得太简单,结果I2C模式下驱动强度降不下来,导致信号过冲严重。后来不得不改版,多花了三个月。
所以,Buffer的配置粒度要够细。别想着省那几十个寄存器位。
3.3 电平转换与阻抗匹配
这是物理层共享里最容易被忽视、但坑最多的地方。
电平转换: 不同协议可能工作在不同电压域。比如SPI可能是3.3V,I2C可能是1.8V。共用一个Pad时,电平怎么处理?
有两种做法:
- 片内电平转换: 在IO Buffer内部集成电平转换电路。优点是省PCB面积,缺点是增加芯片面积和功耗。
- 片外电平转换: 靠外部电平转换芯片。优点是灵活,缺点是增加BOM成本。
我个人更倾向于片内电平转换,前提是芯片的电压域设计支持。你想想看,如果一颗芯片内部有多个电压域(比如1.2V核心、1.8V IO、3.3V IO),那电平转换就是顺理成章的事。
避坑指南: 我曾经在一个多协议芯片中,把1.8V的I2C和3.3V的SPI共用一个Pad,结果I2C模式下Pad电压被拉到3.3V,直接把I2C从设备烧了。后来加了电平检测和钳位电路才解决。
阻抗匹配: 这个更多是针对高速协议。比如SPI跑50MHz以上时,信号完整性就很重要了。
阻抗匹配的核心是:驱动端的输出阻抗 + 走线阻抗 = 接收端的输入阻抗。如果不匹配,信号会反射,导致眼图闭合。
在IO Buffer复用场景下,不同协议的速率不同,对阻抗的要求也不同:
| 协议 | 典型速率 | 阻抗匹配要求 | Buffer配置建议 |
|---|---|---|---|
| SPI | 10-100 MHz | 需要,通常50Ω | 可调驱动强度,匹配走线 |
| I2C | 100 kHz - 3.4 MHz | 不需要,靠上拉电阻 | 开漏输出,弱驱动 |
| UART | 115.2 kbps - 10 Mbps | 低速不需要,高速需要 | 推挽输出,中等驱动 |
| SDIO | 25-200 MHz | 需要,通常50Ω | 强驱动,可调 slew rate |
嗯,这里有个技巧:对于可调驱动强度的Buffer,建议在芯片上电初始化时,根据工作模式自动配置驱动强度。不要留给软件去配,软件工程师经常忘记。
3.4 综合设计建议
讲了这么多,总结几条实战经验:
- Pad共享要早规划: 在芯片架构阶段,就要确定哪些Pad可以复用。别等到后端布局布线了才改,那代价太大了。
- Buffer复用要留余量: 驱动强度、上拉电阻、施密特触发,这些配置位能多不要少。我见过太多因为配置不够而改版的案例。
- 电平转换要加保护: 跨电压域的信号,一定要加电平检测和钳位。别问我怎么知道的,都是泪。
- 阻抗匹配要仿真: 高速协议一定要跑IBIS仿真,别靠猜。我有个项目就是靠仿真发现了50Ω匹配下的过冲问题,改成了33Ω才解决。
最后说一句: 物理层共享设计,表面上是电路问题,实际上是系统问题。你不仅要懂数字逻辑,还要懂模拟电路、信号完整性、甚至PCB layout。多协议芯片的成败,往往就取决于这些「不起眼」的物理层细节。
好,这一讲就到这里。下一讲我们聊聊时钟域的复用与切换,那又是另一番天地了。