Added more options for drawing guard rings to the device generator for magic: 5V nwell with guard ring, 1.8V substrate guard ring, and 5V substrate guard ring.
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl index 0c9019c..9d8cb9d 100644 --- a/sky130/magic/sky130.tcl +++ b/sky130/magic/sky130.tcl
@@ -141,12 +141,18 @@ magic::add_toolkit_command $layoutframe "substrate contact (1.8V)" \ "sky130::subconn_draw" pdk1 + magic::add_toolkit_command $layoutframe "substrate guard ring (1.8V)" \ + "sky130::subconn_guard_draw" pdk1 magic::add_toolkit_command $layoutframe "substrate contact (5.0V)" \ "sky130::mvsubconn_draw" pdk1 + magic::add_toolkit_command $layoutframe "substrate guard ring (5.0V)" \ + "sky130::mvsubconn_guard_draw" pdk1 magic::add_toolkit_command $layoutframe "deep n-well region" \ "sky130::deep_nwell_draw" pdk1 - magic::add_toolkit_command $layoutframe "n-well region with guard ring" \ + magic::add_toolkit_command $layoutframe "n-well region with guard ring (1.8V)" \ "sky130::nwell_draw" pdk1 + magic::add_toolkit_command $layoutframe "n-well region with guard ring (5.0V)" \ + "sky130::mvnwell_draw" pdk1 magic::add_toolkit_command $layoutframe "mcon" \ "sky130::mcon_draw" pdk1 magic::add_toolkit_command $layoutframe "via1" \ @@ -455,6 +461,120 @@ } #---------------------------------------------------------------- +# Helper function for drawing guard rings. +# Assumes that a box exists and defines the centerlines of the +# guard ring contacts. +# ctype = type to paint for contact +# dtype = type to paint for diffusion +#---------------------------------------------------------------- + +proc sky130::guard_ring_draw {ctype dtype} { + pushbox + box width 0 + box grow c 0.085um + paint li + pushbox + box grow n -0.3um + box grow s -0.3um + paint $ctype + popbox + paint $dtype + popbox + + pushbox + box height 0 + box grow c 0.085um + paint li + pushbox + box grow e -0.3um + box grow w -0.3um + paint $ctype + popbox + paint $dtype + popbox + + pushbox + box move n [box height]i + box height 0 + box grow c 0.085um + paint li + pushbox + box grow e -0.3um + box grow w -0.3um + paint $ctype + popbox + paint $dtype + popbox + + pushbox + box move e [box width]i + box width 0 + box grow c 0.085um + paint li + pushbox + box grow n -0.3um + box grow s -0.3um + paint $ctype + popbox + paint $dtype + popbox +} + +#---------------------------------------------------------------- + +proc sky130::subconn_guard_draw {} { + set w [magic::i2u [box width]] + set h [magic::i2u [box height]] + # NOTE: Width and height are determined by the requirement for + # a contact on each side. There is not much that can be done + # with an guarded nwell smaller than that, anyway. + if {$w < 0.6} { + puts stderr "Substrate guard ring width must be at least 0.6um" + return + } + if {$h < 0.6} { + puts stderr "Substrate guard ring height must be at least 0.6um" + return + } + suspendall + tech unlock * + pushbox + + sky130::guard_ring_draw psc psd + + popbox + tech revert + resumeall +} + +#---------------------------------------------------------------- + +proc sky130::mvsubconn_guard_draw {} { + set w [magic::i2u [box width]] + set h [magic::i2u [box height]] + # NOTE: Width and height are determined by the requirement for + # a contact on each side. There is not much that can be done + # with an guarded nwell smaller than that, anyway. + if {$w < 0.6} { + puts stderr "Substrate guard ring width must be at least 0.6um" + return + } + if {$h < 0.6} { + puts stderr "Substrate guard ring height must be at least 0.6um" + return + } + suspendall + tech unlock * + pushbox + + sky130::guard_ring_draw mvpsc mvpsd + + popbox + tech revert + resumeall +} + +#---------------------------------------------------------------- proc sky130::nwell_draw {} { set w [magic::i2u [box width]] @@ -478,61 +598,46 @@ paint nwell popbox - pushbox - box width 0 - box grow c 0.085um - paint li - pushbox - box grow n -0.3um - box grow s -0.3um - paint nsc - popbox - paint nsd - popbox - - pushbox - box height 0 - box grow c 0.085um - paint li - pushbox - box grow e -0.3um - box grow w -0.3um - paint nsc - popbox - paint nsd - popbox - - pushbox - box move n [box height]i - box height 0 - box grow c 0.085um - paint li - pushbox - box grow e -0.3um - box grow w -0.3um - paint nsc - popbox - paint nsd - popbox - - pushbox - box move e [box width]i - box width 0 - box grow c 0.085um - paint li - pushbox - box grow n -0.3um - box grow s -0.3um - paint nsc - popbox - paint nsd - popbox + sky130::guard_ring_draw nsc nsd popbox tech revert resumeall } +#---------------------------------------------------------------- + +proc sky130::mvnwell_draw {} { + set w [magic::i2u [box width]] + set h [magic::i2u [box height]] + # NOTE: Width and height are determined by the requirement for + # a contact on each side. There is not much that can be done + # with an guarded nwell smaller than that, anyway. + if {$w < 0.6} { + puts stderr "MV N-well region width must be at least 0.6um" + return + } + if {$h < 0.6} { + puts stderr "MV N-well region height must be at least 0.6um" + return + } + suspendall + tech unlock * + pushbox + pushbox + box grow c 0.415um + paint nwell + popbox + + sky130::guard_ring_draw mvnsc mvnsd + + popbox + tech revert + resumeall +} + +#---------------------------------------------------------------- + proc sky130::deep_nwell_draw {} { set w [magic::i2u [box width]] set h [magic::i2u [box height]]