4. 电平转换器(Level Shifter):为什么需要电平转换?LS类型(H2L/L2H)、插入策略、UPF中set_level_shifter用法
各位同学,咱们今天聊聊电平转换器。说实话,这东西在单电压域设计里根本用不上,但一旦你开始做多电压域,它就绕不开了。
我记得刚入行那会儿,第一次接触多电压项目,看到网表里密密麻麻的LS cell,心里直犯嘀咕:这玩意儿到底是干嘛的?后来被老工程师带着调了一个bug,才真正明白——没有电平转换,芯片根本没法正常工作。
为什么需要电平转换?
道理其实很简单。你想想看,一个模块工作在0.8V,另一个模块工作在1.2V。0.8V模块输出的高电平,也就0.8V左右。这个信号直接送到1.2V模块的输入端,能可靠地被识别为高电平吗?
不一定。1.2V模块的输入缓冲器,它的翻转阈值可能设计在0.6V~0.7V左右。0.8V的信号勉强能过,但噪声余量太小了。万一有IR drop,0.8V变成0.75V,那就直接误判了。
反过来呢?1.2V模块输出1.2V信号,送到0.8V模块。0.8V模块的管子栅氧化层可能只有1.0V的耐压。1.2V怼上去,时间长了栅氧击穿,芯片就废了。
所以,电平转换器的核心作用就两个:
- 保证逻辑电平正确识别——低电压域到高电压域,把信号抬上去
- 防止过压损坏器件——高电压域到低电压域,把信号降下来
核心原则:跨电压域的信号,必须经过电平转换。这不是可选项,是必选项。
LS类型:H2L与L2H
电平转换器分两种,方向不同,结构也不同。
| 类型 | 方向 | 典型应用场景 | 结构特点 |
|---|---|---|---|
| L2H (Low to High) | 低电压域 → 高电压域 | 核心逻辑(0.8V) → IO接口(1.8V) | 交叉耦合PMOS对,需要两个电源 |
| H2L (High to Low) | 高电压域 → 低电压域 | IO接口(1.8V) → 核心逻辑(0.8V) | 简单反相器链或特殊降压电路 |
我个人习惯把L2H叫做「升压型」,H2L叫做「降压型」。L2H的结构相对复杂,因为它需要把低摆幅信号转换成高摆幅信号,内部有正反馈环路。H2L反而简单,有时候用几个反相器串联,配合电源电压就能实现。
不过要注意,H2L虽然结构简单,但功耗不一定小。我在项目中遇到过一种情况:H2L cell的短路电流很大,因为输入信号摆幅小,PMOS和NMOS同时导通的时间变长了。所以选型的时候,不能只看面积,还得看功耗。
插入策略:什么时候插?谁来插?
这个问题,很多初学者搞不清楚。电平转换器到底是谁负责插入?是RTL设计师?还是后端工程师?
答案是:都可以,但通常由后端工具自动插入。
RTL设计师可以在代码里例化电平转换器,但我不推荐这么做。原因很简单:
- RTL里硬编码LS cell,灵活性差,后期换工艺库得改代码
- LS的插入位置和驱动强度,需要结合物理信息才能优化
- UPF里用set_level_shifter,工具会自动处理,省心
那后端工具怎么插?一般分两步:
- 综合阶段:DC或者Genus根据UPF约束,在跨域路径上插入LS cell
- 布局布线阶段:ICC2或者Innovus在place阶段,根据物理位置优化LS的摆放
我曾经踩过一个坑:综合阶段插了LS,但布局阶段发现LS cell被放到了很远的地方,导致跨域路径绕线过长。后来我学乖了,在UPF里加了约束,让工具把LS cell放在电压域边界附近。
个人建议:LS的插入策略,优先考虑「边界插入」。也就是把LS cell放在电压域边界,靠近接收端。这样跨域走线是低电压信号,功耗更低。
UPF中set_level_shifter用法
好了,到了实操环节。UPF里控制电平转换器的命令,就是set_level_shifter。这个命令的语法,我给大家拆解一下。
set_level_shifter <ls_name> \
-domain <pd_name> \
-applies_to <input|output|both> \
-rule <low_to_high|high_to_low|both> \
-location <self|parent|fanout> \
-threshold <voltage> \
-source <primary|secondary>
参数解释:
- -domain:指定哪个电压域需要插入LS。一般是低电压域
- -applies_to:LS插在域的输入端口还是输出端口。input表示从外部进入本域的信号需要LS,output表示本域输出到外部的信号需要LS
- -rule:指定转换方向。low_to_high就是L2H,high_to_low就是H2L
- -location:LS cell放在哪里。self表示放在本域内,parent表示放在父域内,fanout表示放在扇出端
- -threshold:电压阈值。当两个域的电压差超过这个值,才插入LS
- -source:LS cell使用哪个电源。primary用主电源,secondary用备用电源
举个例子,实际项目中我常用的写法:
# 在PD_CORE域的所有输入端口上,插入L2H电平转换器
set_level_shifter ls_core_input \
-domain PD_CORE \
-applies_to input \
-rule low_to_high \
-location self \
-threshold 0.3 \
-source primary
这条命令的意思是:凡是进入PD_CORE域的信号,如果来自更低电压的域,并且电压差超过0.3V,就在PD_CORE域内部插入L2H电平转换器。
注意:-threshold参数很关键。如果设得太小,不必要的路径也会插LS,浪费面积和功耗。设得太大,该插的路径没插,功能出问题。我一般设0.2V~0.3V,具体看工艺库的容忍范围。
另外,-location参数也值得多说两句。我习惯用self,也就是LS放在接收域内部。这样做的好处是:
- 跨域走线是低电压信号,动态功耗小
- LS cell靠近接收寄存器,时序更容易收敛
但有些设计团队喜欢用parent,把LS放在发送域。各有优劣,没有绝对的对错。我个人偏向self,因为低电压走线对IR drop更敏感,走线长了容易出问题。
避坑指南
最后,分享几个我踩过的坑:
- 漏插LS:UPF里忘了设set_level_shifter,工具默认不插。结果仿真没问题,流片回来跨域信号全乱套。嗯,从那以后我每次都要检查UPF的LS覆盖率。
- LS驱动强度不够:工具自动选的LS cell驱动能力偏小,高负载路径上信号斜率变差。我后来在UPF里加了驱动强度约束,或者手动例化大驱动LS cell。
- LS和ISO顺序搞反:有些路径既需要电平转换,又需要隔离。顺序很重要——先隔离再电平转换,还是先电平转换再隔离?这个得看具体场景,我一般遵循「先处理电压,再处理逻辑」的原则。
好了,关于电平转换器,今天就聊到这儿。下一章咱们讲隔离单元,这两个东西经常一起出现,到时候再细说它们之间的配合关系。