Updated the technology file to better represent the exact DRC
errors for the RPM layer, and updated the device generator to
generate the precision resistors with either nwell or p-sub (or
HV version of either) underneath, with appropriate spacing.
diff --git a/VERSION b/VERSION
index 46bd1d8..be76a0c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.145
+1.0.146
diff --git a/sky130/magic/sky130.tcl b/sky130/magic/sky130.tcl
index 0ff4489..ee46bb7 100644
--- a/sky130/magic/sky130.tcl
+++ b/sky130/magic/sky130.tcl
@@ -2247,7 +2247,7 @@
 		rho 48.2 val 241 dummy 0 dw 0.0 term 0.0 \
 		sterm 0.0 caplen 0.4 snake 0 guard 1 \
 		glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
-		full_metal 1 hv_guard 0 vias 1 \
+		full_metal 1 hv_guard 0 n_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 
@@ -2259,7 +2259,7 @@
 		compatible {sky130_fd_pr__res_high_po_0p35 \
 		sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
 		sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
-		full_metal 1 wmax 0.350 vias 1 \
+		full_metal 1 wmax 0.350 vias 1 n_guard 0 hv_guard 0 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_high_po_0p69_defaults {} {
@@ -2269,7 +2269,7 @@
 		compatible {sky130_fd_pr__res_high_po_0p35 \
 		sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
 		sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
-		full_metal 1 wmax 0.690 vias 1 \
+		full_metal 1 wmax 0.690 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_high_po_1p41_defaults {} {
@@ -2279,7 +2279,7 @@
 		compatible {sky130_fd_pr__res_high_po_0p35 \
 		sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
 		sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
-		full_metal 1 wmax 1.410 vias 1 \
+		full_metal 1 wmax 1.410 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_high_po_2p85_defaults {} {
@@ -2289,7 +2289,7 @@
 		compatible {sky130_fd_pr__res_high_po_0p35 \
 		sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
 		sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
-		full_metal 1 wmax 2.850 vias 1 \
+		full_metal 1 wmax 2.850 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_high_po_5p73_defaults {} {
@@ -2299,7 +2299,7 @@
 		compatible {sky130_fd_pr__res_high_po_0p35 \
 		sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
 		sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
-		full_metal 1 wmax 5.730 vias 1 \
+		full_metal 1 wmax 5.730 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 
@@ -2312,7 +2312,7 @@
 		compatible {sky130_fd_pr__res_xhigh_po_0p35 \
 		sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
 		sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
-		full_metal 1 vias 1 \
+		full_metal 1 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_xhigh_po_0p69_defaults {} {
@@ -2323,7 +2323,7 @@
 		compatible {sky130_fd_pr__res_xhigh_po_0p35 \
 		sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
 		sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
-		full_metal 1 vias 1 \
+		full_metal 1 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_xhigh_po_1p41_defaults {} {
@@ -2334,7 +2334,7 @@
 		compatible {sky130_fd_pr__res_xhigh_po_0p35 \
 		sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
 		sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
-		full_metal 1 vias 1 \
+		full_metal 1 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_xhigh_po_2p85_defaults {} {
@@ -2345,7 +2345,7 @@
 		compatible {sky130_fd_pr__res_xhigh_po_0p35 \
 		sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
 		sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
-		full_metal 1 vias 1 \
+		full_metal 1 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 proc sky130::sky130_fd_pr__res_xhigh_po_5p73_defaults {} {
@@ -2356,7 +2356,7 @@
 		compatible {sky130_fd_pr__res_xhigh_po_0p35 \
 		sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
 		sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
-		full_metal 1 vias 1 \
+		full_metal 1 n_guard 0 hv_guard 0 vias 1 \
 		viagb 0 viagt 0 viagl 0 viagr 0}
 }
 
@@ -2616,6 +2616,9 @@
     	if {[dict exists $parameters hv_guard]} {
 	    magic::add_checkbox hv_guard "High-voltage guard ring" $parameters
 	}
+	if {[dict exists $parameters n_guard]} {
+	    magic::add_checkbox n_guard "N-well connected guard ring" $parameters
+	}
 	if {[dict exists $parameters full_metal]} {
 	    magic::add_checkbox full_metal "Full metal guard ring" $parameters
 	}
@@ -2632,6 +2635,7 @@
 	    magic::add_checkbox gbc "Add bottom guard ring contact" $parameters
 	}
 
+
     	magic::add_entry viagb "Bottom guard ring via coverage \[+/-\](%)" $parameters
     	magic::add_entry viagt "Top guard ring via coverage \[+/-\](%)" $parameters
     	magic::add_entry viagr "Right guard ring via coverage \[+/-\](%)" $parameters
@@ -3216,16 +3220,41 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
     if {[dict exists $parameters hv_guard]} {
-    	if {[dict get $parameters hv_guard] == 1} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
 	    set gdifftype mvnsd
 	    set gdiffcont mvnsc
-	    set gsurround 0.33
 	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
 	    set gdifftype nsd
 	    set gdiffcont nsc
-	    set gsurround $sub_surround
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
 	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+    } else {
+	set gsubtype psub
     }
 
     set newdict [dict create \
@@ -3234,7 +3263,7 @@
 	    end_contact_type	pc \
 	    plus_diff_type	$gdifftype \
 	    plus_contact_type	$gdiffcont \
-	    sub_type		nwell \
+	    sub_type		$gsubtype \
 	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
 	    end_spacing		0.48 \
@@ -3259,22 +3288,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.785
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		ppres \
 	    res_idtype		res0p35 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3289,22 +3360,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.615
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		ppres \
 	    res_idtype		res0p69 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3319,22 +3432,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		ppres \
 	    res_idtype		res1p41 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3349,22 +3504,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		ppres \
 	    res_idtype		res2p85 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3379,22 +3576,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		ppres \
 	    res_idtype		res5p73 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3411,22 +3650,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.785
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		xpres \
 	    res_idtype		res0p35 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3441,22 +3722,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.615
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		xpres \
 	    res_idtype		res0p69 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3471,22 +3794,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		xpres \
 	    res_idtype		res1p41 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3501,22 +3866,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		xpres \
 	    res_idtype		res2p85 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
@@ -3531,22 +3938,64 @@
         set $key [dict get $sky130::ruleset $key]
     }
 
+    # Handle options related to guard ring type (high/low voltage, nwell/psub)
+    if {[dict exists $parameters hv_guard]} {
+	set use_hv_guard [dict get $parameters hv_guard]
+    } else {
+	set use_hv_guard 0
+    }
+    if {[dict exists $parameters n_guard]} {
+	set use_n_guard [dict get $parameters n_guard]
+    } else {
+	set use_n_guard 0
+    }
+
+    if {$use_hv_guard == 1} {
+	if {$use_n_guard == 1} {
+	    set gdifftype mvnsd
+	    set gdiffcont mvnsc
+	} else {
+	    set gdifftype mvpsd
+	    set gdiffcont mvpsc
+	}
+	set gsurround 0.33
+    } else {
+	if {$use_n_guard == 1} {
+	    set gdifftype nsd
+	    set gdiffcont nsc
+	} else {
+	    set gdifftype psd
+	    set gdiffcont psc
+	}
+	set gsurround $sub_surround
+    }
+    if {$use_n_guard == 1} {
+	set gsubtype nwell
+	set gresdiff_spacing 0.525
+	set gresdiff_end 0.525
+    } else {
+	set gsubtype psub
+	set gresdiff_spacing 0.48
+	set gresdiff_end 0.48
+    }
+
     set newdict [dict create \
 	    res_type		xpres \
 	    res_idtype		res5p73 \
 	    end_type 		xpc \
 	    end_contact_type	xpc \
 	    end_contact_size	0 \
-	    plus_diff_type	psd \
-	    plus_contact_type	psc \
-	    sub_type		psub \
+	    plus_diff_type	$gdifftype \
+	    plus_contact_type	$gdiffcont \
+	    sub_type		$gsubtype \
+	    guard_sub_surround	$gsurround \
 	    end_surround	$poly_surround \
-	    end_spacing		0.48 \
+	    end_spacing		$gresdiff_end \
 	    end_to_end_space	0.52 \
 	    end_contact_size	0.19 \
 	    res_to_endcont	1.985 \
 	    res_spacing		1.24 \
-	    res_diff_spacing	0.48 \
+	    res_diff_spacing	$gresdiff_spacing \
 	    mask_clearance	0.52 \
 	    overlap_compress	0.36 \
     ]
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech
index d18b620..e5df31a 100644
--- a/sky130/magic/sky130.tech
+++ b/sky130/magic/sky130.tech
@@ -1651,6 +1651,30 @@
  shrink  345
  and-not hvntm_block
 
+ # RPM spacing checks require recreating RPM
+ templayer rpm_generate
+ bloat-all xhrpoly,uhrpoly xpc
+ grow 200
+ grow-min 1270
+ grow 420
+ shrink 420
+
+ # Check distance RPM to NSDM
+ templayer rpm_nsd_check rpm_generate
+ grow 325
+ and allndifflv,allndiffmv
+
+ # Check distance RPM to (unrelated) POLY
+ templayer rpm_poly_check rpm_generate
+ grow 200
+ and-not xhrpoly,uhrpoly,xpc
+ and allpoly
+
+ # Check distance RPM to HVNTM
+ templayer rpm_hvntm_check rpm_generate
+ grow 385
+ and allndiffmvnontap
+
  templayer m1_small_hole allm1,obsm1,obsmcon
  close   140000
 
@@ -4177,12 +4201,28 @@
  spacing xhrpoly,uhrpoly,xpc xhrpoly,uhrpoly,xpc 1240 touching_illegal \
 	"Distance between precision resistors < %d (rpm.2 + 2 * rpm.3)"
 
- spacing xhrpoly,uhrpoly,xpc allndifflv,allndiffmv 780 touching_illegal \
+ variants (fast)
+
+ spacing xhrpoly,uhrpoly,xpc allndifflv,allndiffmv 525 touching_illegal \
 	"Distance from precision resistor to N+ diffusion < %d (rpm.3 + rpm.6 + nsd.5a)"
  spacing xhrpoly,uhrpoly,xpc *poly 400 touching_illegal \
 	"Distance from precision resistor to unrelated poly < %d (rpm.3 + rpm.7)"
- spacing xhrpoly,uhrpoly,xpc allndiffmvnontap 830 touching_illegal \
-	"Distance from precision resistor to MV N+ diffusion < %d (rpm.3 + rpm.9)"
+ spacing xhrpoly,uhrpoly,xpc allndiffmvnontap 585 touching_illegal \
+	"Distance from precision resistor to MV N+ device < %d (rpm.3 + rpm.9 + hvntm.3)"
+
+ # Minimum width requirement means actual spacing from res to ndiff has to be
+ # constructed from mask rules.  These supercede the simpler checks.
+
+ variants (full)
+
+ cifmaxwidth rpm_nsd_check 0 bend_illegal \
+	"Distance from precision resistor to N+ diffusion < 0.525um (rpm.3 + rpm.6 + nsd.5a)"
+ cifmaxwidth rpm_poly_check 0 bend_illegal \
+	"Distance from precision resistor to unrelated poly < 0.4um (rpm.3 + rpm.7)"
+ cifmaxwidth rpm_hvntm_check 0 bend_illegal \
+	"Distance from precision resistor to MV N+ device < 0.585um (rpm.3 + rpm.9 + hvntm.3)"
+
+ variants (fast,full)
 
  angles allpoly,polyfill 90 "Only 90 degree angles permitted on poly (x.2)"