在大多数芯片中,IO焊 pad 的数量远多于实际需要的信号引脚。为了节省引脚资源,许多信号引脚设计为双向(Bidirectional)——既可作为输入,也可作为输出。GPIO(General Purpose IO)是典型的双向IO。
┌──────────────────────────────────────────────────┐
│ 双向IO单元架构 │
│ │
│ 内部逻辑 ────┬──→ [输出数据路径] ──→ PAD ──→ 外部 │
│ │ │ │
│ OE ──────── │ ──→ [方向控制逻辑] │ │
│ │ │ │
│ │ ←── [输入接收路径] ←───┘ │
│ │ [施密特+电平转换] │
│ │ │ │
│ 上拉/下拉 ──┘ ──→ [可配置电阻] │ │
│ │ │
│ ESD保护 ◄─────────────────────────┘ │
└──────────────────────────────────────────────────┘
方向控制是双向IO最核心的功能。OE信号决定焊 pad 是由输出驱动器驱动(输出模式),还是进入高阻态(输入模式)。
输出驱动器需要三态控制——输出高、输出低、高阻态:
* 三态输出控制逻辑
*
* 输入信号:
* DOUT - 输出数据
* OE - 输出使能 (1=输出, 0=高阻)
*
* 输出信号:
* PAD - 双向焊盘
*
* 控制逻辑:
* PMOS栅极 g_p = NOR(NOT(DOUT), NOT(OE)) = NAND(DOUT, OE) 取反
* NMOS栅极 g_n = NAND(DOUT, OE)
*
* 真值表:
* OE DOUT | g_p g_n | PAD
* 0 0 | 1 0 | Hi-Z
* 0 1 | 1 0 | Hi-Z
* 1 0 | 1 0 | 0 (VSS)
* 1 1 | 0 1 | 1 (VDDIO)
* 具体实现:
* PMOS栅极驱动:
Mp_gate_p g_p dout_b oe_b vddio pch W=4u L=0.35u ; NAND(dout_b, oe_b)
Mn_gate_p g_p dout_b oe_b 0 nch W=2u L=0.35u
* NMOS栅极驱动:
Mp_gate_n g_n dout oe vddio pch W=4u L=0.35u ; NAND(dout, oe)
Mn_gate_n g_n dout oe 0 nch W=2u L=0.35u
方向切换时,如果OE从1变0(输出→输入),需要确保输出驱动器完全关断后,输入接收器才开始有效采样。反之亦然。
在输出→输入切换时:
解决方案:在OE控制路径中加入额外延迟,确保先关断后切换。
现代GPIO通常支持软件配置的内部上拉或下拉,用于输入悬空时提供默认电平。
* 可配置上拉/下拉
*
* PULL_UP=1, PULL_DN=0: 上拉模式
* PULL_UP=0, PULL_DN=1: 下拉模式
* PULL_UP=0, PULL_DN=0: 无上下拉
* PULL_UP=1, PULL_DN=1: 禁止!(会短路)
* 上拉管(弱PMOS)
Mp_pullup pad pull_up_b vddio vddio pch W=2u L=5u
* 反相器驱动
Mp_pu_b pull_up_b pull_up vddio vddio pch W=1u L=0.35u
Mn_pu_b pull_up_b pull_up 0 0 nch W=0.5u L=0.35u
* 下拉管(弱NMOS)
Mn_pulldn pad pull_dn 0 0 nch W=1u L=5u
* 反相器驱动
Mp_pd_b pull_dn_b pull_dn vddio vddio pch W=1u L=0.35u
Mn_pd_b pull_dn_b pull_dn 0 0 nch W=0.5u L=0.35u
不同的应用需要不同的驱动能力。GPIO通常支持多种驱动强度配置,通过使能/禁用驱动管分段实现。
* 可配置驱动强度
* 4段驱动管,支持2/4/8/12mA驱动
*
* 段0: 始终使能 (2mA基础驱动)
* 段1: DRV[0]=1时使能 (+2mA)
* 段2: DRV[1]=1时使能 (+4mA)
* 段3: DRV[0]&DRV[1]=1时使能 (+4mA)
* PMOS输出管分段
Mp0 pad g_p0 vddio vddio pch W=67u L=0.35u ; 段0: 2mA
Mp1 pad g_p1 vddio vddio pch W=67u L=0.35u ; 段1: +2mA
Mp2 pad g_p2 vddio vddio pch W=134u L=0.35u ; 段2: +4mA
Mp3 pad g_p3 vddio vddio pch W=134u L=0.35u ; 段3: +4mA
* 段使能控制 (与OE和DOUT组合)
* g_p0 = NAND(dout, oe)
* g_p1 = NAND(dout, oe AND drv0)
* g_p2 = NAND(dout, oe AND drv1)
* g_p3 = NAND(dout, oe AND drv0 AND drv1)
回读(Read-back)功能允许在输出模式下读取焊盘的实际电平。这对于检测外部短路、验证输出状态等非常重要。
回读路径就是输入接收器持续采样焊盘电平。关键是要确保输入接收器不会被输出驱动器的信号干扰。
* 05-bidir-io-switching.sp
* 双向IO方向切换仿真
Vddio vddio 0 3.3
Vdd vdd 0 1.2
* 控制信号
Voe oe 0 pwl 0 0 20n 0 20.02n 1.2 80n 1.2 80.02n 0 120n 0
Vdout dout 0 pwl 0 0 40n 0 40.02n 1.2 60n 1.2 60.02n 0
* 方向控制逻辑
* OE电平转换
Mp_oe_h oeh oe_b vddio vddio pch W=4u L=0.35u
Mn_oe_h oeh oe_b 0 0 nch W=2u L=0.35u
Mp_oe_b oe_b oe vdd vdd pch W=2u L=0.18u
Mn_oe_b oe_b oe 0 0 nch W=1u L=0.18u
* DOUT电平转换
Mp_do_h doh dout_b vddio vddio pch W=4u L=0.35u
Mn_do_h doh dout_b 0 0 nch W=2u L=0.35u
Mp_do_b dout_b dout vdd vdd pch W=2u L=0.18u
Mn_do_b dout_b dout 0 0 nch W=1u L=0.18u
* 三态输出驱动
* PMOS栅极 = NAND(doh, oeh)
Mp_gp gp doh_b oeh_b vddio vddio pch W=8u L=0.35u
Mn_gp gp doh_b oeh_b 0 0 nch W=4u L=0.35u
* NMOS栅极 = NAND(doh, oeh) via separate logic
Mp_gn gn doh oeh vddio vddio pch W=8u L=0.35u
Mn_gn gn doh oeh 0 0 nch W=4u L=0.35u
* 输出驱动管
Mpout pad gp vddio vddio pch W=200u L=0.35u
Mnout pad gn 0 0 nch W=80u L=0.35u
* 焊盘负载
Cpad pad 0 10p
* 输入接收器(施密特触发器)
Mp_s1 a pad vddio vddio pch W=4u L=0.35u
Mp_s2 out a vddio vddio pch W=8u L=0.35u
Mp_s3 a out vddio vddio pch W=2u L=0.35u
Mn_s1 b pad 0 0 nch W=4u L=0.35u
Mn_s2 out b 0 0 nch W=4u L=0.35u
Mn_s3 b out 0 0 nch W=2u L=0.35u
* 电平转换到核心域
Mp_ls n1 out_b vdd vdd pch W=2u L=0.18u
Mn_ls n1 out 0 0 nch W=1u L=0.18u
Mp_out_core din n1 vdd vdd pch W=4u L=0.18u
Mn_out_core din n1 0 0 nch W=2u L=0.18u
.tran 0.02n 120n
.measure tran tpd_out TRIG V(dout) VAL=0.6 RISE=1 TARG V(pad) VAL=1.65 RISE=1
.measure tran tpd_in TRIG V(pad) VAL=2.0 RISE=1 TARG V(din) VAL=0.6 RISE=1
.print tran V(oe) V(dout) V(pad) V(din) V(gp) V(gn)
.end
* 05-pullup-pulldown.sp
* 可配置上拉/下拉功能仿真
Vddio vddio 0 3.3
* 弱上拉管
Mp_pu pad pu_b vddio vddio pch W=2u L=10u
Vpu pu_b 0 0 ; 使能上拉(pu_b=0,PMOS导通)
* 弱下拉管(禁用)
Mn_pd pad pd 0 0 nch W=1u L=10u
Vpd pd 0 0 ; 禁用下拉
* 焊盘电容
Cpad pad 0 5p
* 外部信号(模拟断开)
Vext ext 0 0 ; 外部无驱动
Rext ext pad 1g ; 高阻抗
.tran 0.1n 500n
.measure tran v_pullup FIND V(pad) AT=400n
.print tran V(pad) I(Mp_pu) I(Mn_pd)
.end
双向IO仿真关键结果:
在实际芯片中,双向IO的控制通常通过寄存器实现:
| 寄存器位 | 名称 | 功能 |
|---|---|---|
| [0] | OEN | 输出使能 (0=输入, 1=输出) |
| [1] | DOUT | 输出数据 |
| [2] | PULL_UP | 上拉使能 |
| [3] | PULL_DN | 下拉使能 |
| [5:4] | DRV_SEL | 驱动强度选择 (2/4/8/12mA) |
| [6] | SLEW | 压摆率选择 (0=慢, 1=快) |
| [7] | SCMIT | 施密特触发使能 |
| RO [0] | DIN | 输入数据(只读) |
| RO [1] | PAD_VAL | 焊盘回读值 |
双向IO中输出驱动器和输入接收器紧邻放置,大尺寸PMOS和NMOS形成寄生SCR结构,在ESD或过压条件下可能触发闩锁。
当IO电源域未上电(VDDIO=0V),但外部信号施加到焊盘时,可能通过ESD二极管向VDDIO充电,导致意外上电。
* 过压情况:
* VDDIO = 0V(未上电)
* PAD = 3.3V(外部信号)
*
* ESD上拉二极管导通:PAD → VDDIO
* 电流路径:3.3V → Desd_up → VDDIO → 芯片内部电路
* 结果:VDDIO被"偷电"到约2.5V,芯片意外上电!
*
* 解决方案:
* 1. VDDIO上加放电电阻(泄漏到地)
* 2. 使用隔离二极管(阻断反向电流)
* 3. IO电源域设计支持热插拔
一个GPIO需要支持2mA/4mA/8mA/16mA四种驱动强度。假设基础段为2mA(Wp=67μm, Wn=27μm)。设计4段驱动管的尺寸方案,使总驱动能力为16mA。写出每段的Wp和Wn值。
段0:Wp=67μm, Wn=27μm(2mA,始终使能)
段1:Wp=67μm, Wn=27μm(+2mA,使能后4mA)
段2:Wp=134μm, Wn=54μm(+4mA,使能后8mA)
段3:Wp=268μm, Wn=108μm(+8mA,使能后16mA)
总Wp = 67+67+134+268 = 536μm, 总Wn = 27+27+54+108 = 216μm
一个双向IO的输出驱动器关断时间为2ns(从OE=0到驱动器进入高阻态)。输入接收器的建立时间为0.5ns。如果外部驱动器在OE=0后3ns开始驱动焊盘,是否存在冲突?写出时序分析。
t=0ns: OE从1变0,输出驱动器开始关断
t=2ns: 输出驱动器完全关断(高阻态)
t=3ns: 外部驱动器开始驱动焊盘
从t=2ns到t=3ns有1ns的裕量,没有冲突。
但如果输出驱动器关断不够快(>3ns),或外部驱动器开始太早,就会冲突。实际设计中建议在OE=0后等待5-10ns再让外部驱动器接管。
完成本课学习,你已经完成了IO基础阶段!掌握了双向IO的完整设计!
✅ 已掌握 三态控制 ✅ 已掌握 可配置功能 ✅ 已掌握 方向切换 ✅ 已掌握 闩锁防护