前两天有朋友问怎么检查出有超压风险的器件。他们应用的场景是存在负压的情况。导致在电源与这个负压电源之间的器件有耐压不够的风险。下面是我搭个简单示意图,主要就是找出粉色的器件是否是5v器件,如果不是需要报出来。上面的pmos也是需要做检查如果在正压电源域下,衬底不是接正压电源同样需要报出来。
如果在复杂的电路中快速检查出这些风险点,我推荐他使用perc来检查。以前有写过多篇检查低压器件接到高压信号的perc脚本。稍作修改即可满足这样的检查需求。
很方便的检查出risk的mos,perc支持flatten和hierarchy的cdl,同样可以检查spice和layout 数据。
Perc的参考code在文章最后面。
是否还有其他方式可以检查出来,这里介绍下PrimeSim 的CCK feature也可以提供类似的检查。
CCK 是primeSim 中用于做ERC和ESD 检查的feature。像一些floating gate node analysis,Hi-Z node analysis,DC path analysis,device parameter analysis,misssing level shifter analysis,等等。我们可以使用built-in command 与API 来定制相关的检查。跟perc 有些相似。
这里举个简单的例子:检查mos的width/length的比是否小于8.
对应的网表如下:
下面是cck的tcl script:
# callback function to check the device w/l ratio
proc wlratioCheck {inst} {
global resultFile
global wlratioMax
set type [ cckGetInstType $inst ]
if { $type==$::CCK_MOS } {
set w [cckGetInstProp $inst "w"]
set l [cckGetInstProp $inst "l"]
if { $w/$l < $wlratioMax } {
set instName [ cckGetInstFullName $inst ]
puts $resultFile "device $instName W/L ratio is smaller than $wlratioMax"
}
}
return $CCK_FALSE
}
# checking flow starts from reading in the netlist
set wlratioMax 8.0
netlist add20.sp
set fileName "cck.wl"
set resultFile [ open $fileName w ]
cckSearcInst -proc wlratioCheck
close $resultFile
The cck.wl output file contains the following example result:
device m172 W/L ratio is smaller than 8.0
device m174 W/L ratio is smaller than 8.0
device m175 W/L ratio is smaller than 8.0
PERC的参考代码如下:
LVS POWER NAME "?VDD?"
LVS GROUND NAME "?VSS?"
VARIABLE HV_POWER "VDD25"
VARIABLE HV_NPOWER "VDDN25"
LAYOUT CASE YES
SOURCE CASE YES
PERC NETLIST SOURCE
PERC REPORT "perc.rep"
MASK SVDB DIRECTORY "svdb" QUERY
PERC LOAD perclib INIT init SELECT
deviceInRiskVoltageCheck
//========= Include Files ===========
TVF FUNCTION perclib [/*
package require CalibreLVS_PERC
proc deviceInRiskVoltageCheck {} {
set rules "Device has risk\n"
perc::check_device \
-pinPathType { {s d} {HV_Domain} } -condition voltageRisk_cond \
-comment "$rules"
}
proc init {} {
array set ::mos {}
set ::mos(IO5_mos) [list pch45 nch45]
set ::mos(IO_mos) [list pch18 nch18 pch25 nch25]
set ::mos(All) [concat $::mos(IO5_mos) $::mos(IO_mos)]
perc::define_net_type "Power" lvsPower
perc::define_net_type "Ground" lvsGround
perc::define_net_type "AllPad" lvsTopPorts
if {[perc::expand_list [tvf::svrf_var HV_POWER] -type net] != ""} {
puts ">>[perc::expand_list [tvf::svrf_var HV_POWER] -type net]"
perc::define_net_type "HV_Domain" [perc::expand_list [tvf::svrf_var HV_POWER] -type net]
}
if {[perc::expand_list [tvf::svrf_var HV_NPOWER] -type net] != ""} {
puts ">>[perc::expand_list [tvf::svrf_var HV_NPOWER] -type net]"
perc::define_net_type "NHV_Domain" [perc::expand_list [tvf::svrf_var HV_NPOWER] -type net]
}
perc::create_net_path -subtype $::mos(All) -pin {s d} -break {Power || Ground} -exclude {Power Ground}
perc::create_net_path -type $::mos(All) -pin {s d}
}
proc voltageRisk_cond {instance} {
set select 0
set mosType [perc::type $instance]
set mosName [perc::subtype $instance]
if {[lsearch $::mos(IO_mos) $mosType] || [lsearch $::mos(IO_mos) $mosName]} {
if {[perc::is_pin_of_path_type $instance {S D} {HV_Domain}] == 1 && \
[perc::is_pin_of_path_type $instance {S D} {NHV_Domain}] == 1 } {
if {[perc::is_pin_of_path_type $instance {B} {HV_Domain}] ==1} {
set select 0
} else {
set select 1
}
}
} else {
set select 0
}
return $select
}
*/]