Revised the code that generates MiM caps in the PDK Tcl scripts,
because the DRC rules specifically prevent cap2m overlapping via3; so
to make an actual stacked capacitor, the contacts for the lower cap
cannot be directly under the first. So the options have been enhanced
to allow the contact to the MiM caps to only partially cover the
capacitor plate area. Also decreased the spacing from cap plate to
contact to the minimum required, and added code to increase that
distance as necessary to enforce the minimum metal spacing rule on
the capacitor top. Also updated the extraction rule for the
diffusion resistor types to match the added subcircuit definitions
for both.
diff --git a/sky130/Makefile.in b/sky130/Makefile.in
index a90cc87..f07db8f 100644
--- a/sky130/Makefile.in
+++ b/sky130/Makefile.in
@@ -302,7 +302,7 @@
openlane-a: openlane/common_pdn.tcl openlane/config.tcl openlane/sky130_fd_sc_hd/config.tcl openlane/sky130_fd_sc_hs/config.tcl openlane/sky130_fd_sc_ms/config.tcl openlane/sky130_fd_sc_ls/config.tcl openlane/sky130_fd_sc_hdll/config.tcl openlane/sky130_osu_sc_t18/config.tcl
mkdir -p ${OPENLANETOP_STAGING_A}
mkdir -p ${OPENLANE_STAGING_A}
- rm -f ${OPENLANE_STAGING_A}/custom_cells/*
+ rm -rf ${OPENLANE_STAGING_A}/custom_cells/*
mkdir -p ${OPENLANE_STAGING_A}/sky130_fd_sc_hd
mkdir -p ${OPENLANE_STAGING_A}/sky130_fd_sc_hs
mkdir -p ${OPENLANE_STAGING_A}/sky130_fd_sc_ls
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl
index c09ad4a..bfebee0 100644
--- a/sky130/magic/sky130.tcl
+++ b/sky130/magic/sky130.tcl
@@ -1423,12 +1423,14 @@
proc sky130::sky130_fd_pr__cap_mim_m3_1_defaults {} {
return {w 2.00 l 2.00 val 4.0 carea 1.00 cperi 0.17 \
nx 1 ny 1 dummy 0 square 0 lmin 2.00 wmin 2.00 \
- lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1}
+ lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1 \
+ ccov 100}
}
proc sky130::sky130_fd_pr__cap_mim_m3_2_defaults {} {
return {w 2.00 l 2.00 val 4.0 carea 1.00 cperi 0.17 \
nx 1 ny 1 dummy 0 square 0 lmin 2.00 wmin 2.00 \
- lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1}
+ lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1 \
+ ccov 100}
}
#endif (MIM)
@@ -1533,6 +1535,9 @@
if {[dict exists $parameters tconnect]} {
magic::add_checkbox tconnect "Connect top plates in array" $parameters
}
+ if {[dict exists $parameters ccov]} {
+ magic::add_entry ccov "Capacitor contact coverage \[+/-\](%)" $parameters
+ }
if {[dict exists $parameters guard]} {
magic::add_checkbox guard "Add guard ring" $parameters
}
@@ -1578,9 +1583,13 @@
set cap_surround 0
set bot_surround 0
set top_surround 0
+ set end_spacing 0
set bconnect 0 ;# bottom plates are connected in array
set cap_spacing 0 ;# cap spacing in array
set top_metal_space 0 ;# top metal spacing (if larger than cap spacing)
+ set top_metal_width 0 ;# top metal minimum width
+ set contact_size 0 ;# cap contact minimum size
+ set ccov 100 ;# amount of contact coverage
# Set a local variable for each parameter (e.g., $l, $w, etc.)
foreach key [dict keys $parameters] {
@@ -1604,11 +1613,34 @@
box grow s ${hl}um
paint ${cap_type}
pushbox
+
+ # Find contact width if ccov is other than 100
+ set cmaxw [- $w [* $cap_surround 2]]
+ set cw [* $cmaxw [/ [expr abs($ccov)] 100.0]]
+ # Contact width must meet minimum
+ if {$cw < $contact_size} {set cw $contact_size}
+ if {$cw < $top_metal_width} {set cw $top_metal_width}
+ # Difference between maximum contact width and actual contact width
+ set cdif [- $cmaxw $cw]
+
+ # Reduce the box to the maximum contact area
box grow n -${cap_surround}um
box grow s -${cap_surround}um
box grow e -${cap_surround}um
box grow w -${cap_surround}um
+
+ set anchor [string index $ccov 0]
+ if {$anchor == "+"} {
+ box grow e -${cdif}um
+ } elseif {$anchor == "-"} {
+ box grow w -${cdif}um
+ } else {
+ set cdif [/ ${cdif} 2]
+ box grow w -${cdif}um
+ box grow e -${cdif}um
+ }
paint ${cap_contact_type}
+
pushbox
box grow n ${top_surround}um
box grow s ${top_surround}um
@@ -1629,8 +1661,24 @@
property FIXED_BBOX [box values]
set cext [sky130::unionbox $cext [sky130::getbox]]
+ # Calculate the distance from the top metal on the cap contact
+ # to the top metal on the end contact.
+ set top_met_sep [+ $end_spacing [- $cdif $top_surround]]
+
+ # Diagnostic!
+ puts stdout "cdif = $cdif"
+ puts stdout "top_met_sep = $top_met_sep"
+
+ # Increase end spacing if top metal spacing rule is not met
+ set loc_end_spacing $end_spacing
+ if {$top_met_sep < $top_metal_space} {
+ set loc_end_spacing [+ $loc_end_spacing [- $top_metal_space $top_met_sep]]
+ }
+ # Diagnostic!
+ puts stdout "loc_end_spacing = $loc_end_spacing"
+
# Extend bottom metal under contact to right
- box grow e ${end_spacing}um
+ box grow e ${loc_end_spacing}um
set chw [/ ${contact_size} 2.0]
box grow e ${chw}um
box grow e ${end_surround}um
@@ -1652,7 +1700,7 @@
pushbox
box move e ${hw}um
box move e ${bot_surround}um
- box move e ${end_spacing}um
+ box move e ${loc_end_spacing}um
set cl [- [+ ${lcont} [* ${bot_surround} 2.0]] [* ${end_surround} 2.0]]
set cl [- ${cl} ${metal_surround}] ;# see below
set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cl} \
@@ -2023,7 +2071,7 @@
cap_surround 0.2 \
top_surround 0.005 \
end_surround 0.1 \
- end_spacing 0.60 \
+ end_spacing 0.1 \
contact_size 0.32 \
metal_surround 0.08 \
]
@@ -2043,7 +2091,7 @@
cap_surround 0.2 \
top_surround 0.12 \
end_surround 0.1 \
- end_spacing 2.10 \
+ end_spacing 0.1 \
contact_size 1.18 \
metal_surround 0.21 \
top_metal_width 1.6 \
@@ -2063,6 +2111,7 @@
# In case wmax and/or lmax are undefined
set lmax 0
set wmax 0
+ set ccov 100
# Set a local variable for each parameter (e.g., $l, $w, etc.)
foreach key [dict keys $parameters] {
@@ -2118,6 +2167,14 @@
dict set parameters l $lmax
set l $lmax
}
+ if {[catch {expr abs($ccov)}]} {
+ puts stderr "Capacitor contact coverage must be numeric!"
+ dict set parameters ccov 100
+ } elseif {[expr abs($ccov)] > 100} {
+ puts stderr "Capaitor contact coverage can't be more than 100%"
+ dict set parameters ccov 100
+ }
+
# Calculate value from L and W
set cval [expr ($l * $w * $carea + 2 * ($l + $w) * $cperi - 4 * $dc)]
dict set parameters val [magic::float2spice $cval]
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech
index afd368b..8c68327 100644
--- a/sky130/magic/sky130.tech
+++ b/sky130/magic/sky130.tech
@@ -6320,11 +6320,13 @@
*pdiff nwell error l=l w=w
device rsubcircuit sky130_fd_pr__res_iso_pw rpw \
pwell dnwell error l=l w=w
+ device rsubcircuit sky130_fd_pr__res_generic_nd__hv mvndiffres \
+ *mvndiff pwell,space/w error l=l w=w
+ device rsubcircuit sky130_fd_pr__res_generic_pd__hv mvpdiffres \
+ *mvpdiff nwell error l=l w=w
device resistor sky130_fd_pr__res_generic_po rmp *poly
device resistor sky130_fd_pr__res_generic_po mrp1 *poly
- device resistor sky130_fd_pr__res_generic_nd__hv mvndiffres *mvndiff
- device resistor sky130_fd_pr__res_generic_pd__hv mvpdiffres *mvpdiff
device subcircuit sky130_fd_pr__diode_pd2nw_05v5 *pdiode \
nwell a=area