Completed the first full implementation of the LDNMOS and LDPMOS
(16V) devices in the magic tech file and device generator for
sky130. This includes validating the device generator for
fingered devices and multiple devices, with and without
overlapping diffusions, and cifinput rules for reading the
devices from GDS and producing a valid database in magic from
which the device can again be extracted.
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl
index 69465d4..c4d8517 100644
--- a/sky130/magic/sky130.tcl
+++ b/sky130/magic/sky130.tcl
@@ -5786,19 +5786,21 @@
box grow n ${hw}um
box grow s ${hw}um
box move $dside ${hl}um
+ pushbox
box grow $dside ${extension}um
paint ed
set cext [sky130::getbox]
- box width 0.26um
- box move $dside 0.26um
+ popbox
+ box move $dside ${extension}um
+ box move $dside 0.13um
+ box grow e 0.13um
+ box grow w 0.13um
paint mvnsd
+ # Test: Do not include nwell in bounding box
+ set cext [sky130::unionbox $cext [sky130::getbox]]
pushbox
box grow c 0.66um
paint nwell
- # Force box 0.48um larger so that spacing to guard ring
- # comes out to 0.86um.
- box grow c 0.48um
- set cext [sky130::unionbox $cext [sky130::getbox]]
popbox
popbox
# Back to the center point
@@ -5836,7 +5838,7 @@
if {$cdw > $cdwfull} [set cdw $cdwfull]
set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
- 0.045 ${metal_surround} ${contact_size}\
+ ${drain_diff_surround} ${metal_surround} ${contact_size}\
mvnsd mvnsc li vert]]
popbox
return $cext
@@ -5866,36 +5868,24 @@
# Starts with point at the device center
box grow n ${hw}um
box grow s ${hw}um
- # Draw nwell under the entire device
- pushbox
- box grow e ${hl}um
- box grow w ${hl}um
- # Well should cover device and meet well width on
- # top and bottom of the area cut out for the drain
- box grow c 0.84um
- box grow c 0.86um
- box grow $dside ${extension}um
- box grow $dside 0.26um
- box grow $sside -1.08um
- paint nwell
- popbox
box move $dside ${hl}um
+ pushbox
box grow $dside ${extension}um
paint ed
set cext [sky130::getbox]
- box width 0.26um
- box move $dside 0.26um
+ popbox
+ box move $dside ${extension}um
+ box move $dside 0.13um
+ box grow e 0.13um
+ box grow w 0.13um
paint mvpsd
pushbox
box grow c 0.86um
- # Shorter on gate side to avoid DRC error; actual
+ # Shorter than necessary to avoid DRC error; actual
# nwell is erased under gate by GDS generation rules.
- box grow $sside -0.13um
+ box grow e -0.15um
+ box grow w -0.15um
paint pwell
- # Force box 0.28um larger so that spacing to guard ring
- # comes out to 0.66um.
- box grow c 0.28um
- set cext [sky130::unionbox $cext [sky130::getbox]]
popbox
popbox
# Back to the center point
@@ -5933,7 +5923,7 @@
if {$cdw > $cdwfull} [set cdw $cdwfull]
set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
- 0.045 ${metal_surround} ${contact_size}\
+ ${drain_diff_surround} ${metal_surround} ${contact_size}\
mvpsd mvpsc li vert]]
popbox
return $cext
@@ -6313,11 +6303,19 @@
set id2_type "" ;# additional type covering everything
set id2_surround 0 ;# amount of surround on above type
+ set set_x_to_guard "" ;# override x distance to guard ring
+ set set_y_to_guard "" ;# override y distance to guard ring
+
# Set a local variable for each parameter (e.g., $l, $w, etc.)
foreach key [dict keys $parameters] {
set $key [dict get $parameters $key]
}
+ # Diff surround on drain is by default the same as diff surround
+ if {![dict exist $parameters drain_diff_surround]} {
+ set drain_diff_surround $diff_surround
+ }
+
# Diff-to-tap spacing is by default the same as diff spacing
if {![dict exist $parameters diff_tap_space]} {
set diff_tap_space $diff_spacing
@@ -6361,7 +6359,7 @@
tech lock *
set bbox [sky130::mos_device $parameters]
- # puts stdout "Diagnostic: Device bounding box e $bbox (um)"
+ puts stdout "Diagnostic: Device bounding box e $bbox (um)"
tech unlock *
set fw [- [lindex $bbox 2] [lindex $bbox 0]]
@@ -6369,6 +6367,10 @@
set lw [+ [lindex $bbox 2] [lindex $bbox 0]]
set lh [+ [lindex $bbox 3] [lindex $bbox 1]]
+ # If the bounding box is not symmetric about x=0, then find the
+ # offset. Assumed to be needed only for X (asymmetric drain)
+ set xoffset [+ [lindex $bbox 0] [lindex $bbox 2]]
+
# If dev_sub_dist > 0 then each device must be in its own substrate
# (well) area, and overlaps are disallowed. dev_sub_space determines
# the distance between individual devices in an array.
@@ -6399,7 +6401,7 @@
set dx [+ $fw $diff_spacing]
} else {
# overlap diffusions
- set dx [- $fw [+ $diff_surround $diff_surround $contact_size]]
+ set dx [- $fw [+ $drain_diff_surround $drain_diff_surround $contact_size]]
}
}
@@ -6450,6 +6452,14 @@
set corelly [- $corelly [/ $sdiff 2.0]]
}
}
+
+ # set_x|y_to_guard overrides the above calculations if present.
+ if {$set_x_to_guard != ""} {
+ set gx [+ $corex [* 2.0 $set_x_to_guard]]
+ }
+ if {$set_y_to_guard != ""} {
+ set gy [+ $corey [* 2.0 $set_y_to_guard]]
+ }
}
if {$guard != 0} {
# Draw the guard ring first, as MOS well may interact with guard ring substrate
@@ -6488,7 +6498,9 @@
set saveeo $evenodd
}
for {set yp 0} {$yp < $m} {incr yp} {
+ if {$evens != 0} {box move e ${xoffset}um}
sky130::mos_device $parameters
+ if {$evens != 0} {box move w ${xoffset}um}
box move n ${dy}um
if {$intc == 1} {
set evenodd [- 1 $evenodd]
@@ -6808,6 +6820,9 @@
diff_spacing 0.31 \
diff_tap_space 0.38 \
diff_gate_space 0.38 \
+ drain_diff_surround 0.045 \
+ set_x_to_guard 1.665 \
+ set_y_to_guard 1.225 \
drain_proc sky130::draw_ldnmos_drain \
]
set drawdict [dict merge $sky130::ruleset $newdict $parameters]
@@ -6824,11 +6839,16 @@
poly_type poly \
poly_contact_type pc \
sub_type nwell \
+ id_type nwell \
+ id_surround 0.035 \
guard_sub_surround 0.33 \
gate_to_polycont 0.32 \
diff_spacing 0.31 \
diff_tap_space 0.38 \
diff_gate_space 0.38 \
+ drain_diff_surround 0.045 \
+ set_x_to_guard 1.665 \
+ set_y_to_guard 1.180 \
drain_proc sky130::draw_ldpmos_drain \
]
set drawdict [dict merge $sky130::ruleset $newdict $parameters]
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech
index 41e13ff..df1f908 100644
--- a/sky130/magic/sky130.tech
+++ b/sky130/magic/sky130.tech
@@ -1136,7 +1136,9 @@
# HVI (includes rules NWELL 8-11 and DIFFTAP 14-26)
#----------------------------------------------------------------
- templayer thkox_area alldiffmv,mvvar
+ templayer thkox_area ed
+ grow 475
+ or alldiffmv,mvvar
grow 185
bloat-all alldiffmv nwell
grow 345
@@ -2987,6 +2989,47 @@
labels TAP
labels TAPTXT text
+ # Fill in FET under extended drain
+ layer mvpfet EDID
+ and POLY
+ and-not DIFF
+ and-not TAP
+ and-not NWELL
+
+ layer mvnfet EDID
+ and POLY
+ and-not DIFF
+ and-not TAP
+ and NWELL
+
+ # Restrict where nwell is merged
+ templayer ldmos_nwell EDID
+ grow 1200
+ and NWELL
+
+ # Remove or add well under extended FET gate
+ layer nwell EDID
+ and POLY
+ and DIFF
+ and PSDM
+ grow 685
+ or ldmos_nwell
+ grow 420
+ shrink 420
+
+ layer pwell EDID
+ and POLY
+ and DIFF
+ and NSDM
+ grow 660
+ grow 420
+ shrink 420
+
+ layer ed EDID
+ and-not POLY
+ and-not DIFF
+ and-not TAP
+
templayer mvnsdexpand mvnsdarea
grow 500
@@ -3977,6 +4020,8 @@
calma PSDM 94 20
# HVI (THKOX)
calma HVI 75 20
+ # EDID
+ calma EDID 81 57
# NPC
calma NPC 95 20
# P+ POLY MASK