PCell Generators

From EDA Wiki
Jump to navigationJump to search

PCell generators are created to draw layouts of various circuit components. These are written in SKILL and can be modified based on a given technology or specifications. See this How to install a PCell for instructions on how to install a PCell generator into the Cadence environment.

Capacitor PCell

This PCell generator draws a capacitor in AMI C5N 0.5u technology using the scalable CMOS rules in the NCSU CDK.


pcDefinePCell(list(ddGetObj("AMI_06_Layout") "cap" "layout")
    ((Width float 2.4)
     (Length float 2.4)
     (numRows int 1)
     (numCols int 1)
     (DrawPOLY1 boolean "TRUE")
     (DrawM1 boolean "TRUE")
     (AbutM1 boolean "TRUE")
     (ShieldWithM2 boolean "FALSE")
     (ShieldWithNWELL boolean "FALSE")
     (CapSeparation float 0.9)
    )
    let(
        (Width Length numRows numCols DrawPOLY1 DrawM1 AbutM1 ShieldWithM2 ShieldWithNWELL CapSeparation
	 pcLib pcParameters pcParamProp pcLayer pcPurpose pcList
	 Ox Oy stepX stepY cntStepX cntStepY totalContactsX totalContactsY
	 POLY2W PLY2SP P2EOCT BCEOTC CNTW CNTSP
	 layerM1 layerM2 layerPOLY1 layerPOLY2 layerCNT layerNFIELD layerTUB layerCAPM
	)

	; Technology Rules
	POLY2W = 2.4		; Min POLY2 Width
	PLY2SP = 0.90		; Min POLY2 SPacing
	P2EOCT = 0.90		; Min POLY2 Enclosure of CnT (DRC rules do not really tell what this should be)
	BCEOTC = 1.5		; Min BotCap plate Enclosure Of TopCap plate
	CNTW   = 0.60		; Min CNT Width
	CNTSP  = 0.90		; Min CNT Spacing

	; Calculations

	pcLib = pcCellView->lib
	pcParameters = (pcCellView->parameters)->value

	Ox = 0.0
	Oy = 0.0

	; Get the PCell parameters.
	pcParamProp = car(exists(prop pcParameters ((prop->name) == "Width")))
	Width = pcParamProp->value

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "Length")))
	Length = pcParamProp->value

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "numRows")))
	numRows = pcParamProp->value

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "numCols")))
	numCols = pcParamProp->value

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "DrawPOLY1")))
	DrawPOLY1 = (pcParamProp->value == "TRUE")

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "DrawM1")))
	DrawM1 = (pcParamProp->value == "TRUE")

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "AbutM1")))
	AbutM1 = (pcParamProp->value == "TRUE")

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "ShieldWithM2")))
	ShieldWithM2 = (pcParamProp->value == "TRUE")

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "ShieldWithNWELL")))
	ShieldWithNWELL = (pcParamProp->value == "TRUE")

	pcParamProp = car(exists(prop pcParameters ((prop->name) == "CapSeparation")))
	CapSeparation = pcParamProp->value

	; Check the parameter values and make adjustments
	if((Length < POLY2W) then Length = POLY2W)
	if((Width < POLY2W) then Width = POLY2W)
	if((CapSeparation < PLY2SP) then CapSeparation = PLY2SP)

	stepX = Width + CapSeparation
	stepY = Length + CapSeparation

	C5N = nil
	SCMOS = t

	; Define layer constants
	if((C5N == t) then
		layerM1 = 9
		layerM2 = 11
		layerCNT = 8
		layerPOLY1 = 4
		layerPOLY2 = 37 ; 26
		layerNFIELD = 3
		layerTUB = 1
		layerCAPM = 56
	else if((SCMOS == t) then
		layerM1 = 45
		layerM2 = 50
		layerCNT = 59
		layerPOLY1 = 35
		layerPOLY2 = 37
		layerNFIELD = nil
		layerTUB = 12
		layerCAPM = nil
	))

	; Draw POLY1 for the bottom plate of the capacitor.
	if((DrawPOLY1 == t) then
		pcLayer = layerPOLY1
		pcPurpose = "drawing"
		pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC))
		pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
	)

	; Draw CAPM pseudo layer.
	if((layerCAPM != nil) then
		pcLayer = layerCAPM
		pcPurpose = "drawing"
		pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC))
		pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
	)

	; Draw POLY2 for the top plate of the capacitor.
	pcLayer = layerPOLY2
	pcPurpose = "drawing"
	for(j 0 numRows-1
		for(i 0 numCols-1
			pcList = list((Ox+i*stepX:Oy-j*stepY) (Ox+i*stepX+Width:Oy-j*stepY-Length))
			pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
		)
	)

	; Draw M1 over the top plate of the capacitor.
	if((DrawM1 == t) then
		pcLayer = layerM1
		pcPurpose = "drawing"
		if((AbutM1 == t) then
			pcList = list((Ox:Oy) (Ox+(numCols-1)*stepX+Width:Oy-(numRows-1)*stepY-Length))
			pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
		else
			for(j 0 numRows-1
				for(i 0 numCols-1
					pcList = list((Ox+i*stepX:Oy-j*stepY) (Ox+i*stepX+Width:Oy-j*stepY-Length))
					pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
				)
			)
		)
	)

	; Draw M2 over the capacitor for shielding.
	if((ShieldWithM2 == t) then
		pcLayer = layerM2
		pcPurpose = "drawing"
		pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC))
		pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
	)

	; Draw NWELL under the capacitor for shielding.
	if((ShieldWithNWELL == t) then
		pcLayer = layerTUB
		pcPurpose = "drawing"
		pcList = list((Ox-BCEOTC:Oy+BCEOTC) (Ox+(numCols-1)*stepX+Width+BCEOTC:Oy-(numRows-1)*stepY-Length-BCEOTC))
		pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)

		if((layerNFIELD != nil) then
			pcLayer = layerNFIELD
			pcPurpose = "drawing"
			pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
		)
	)

	; Draw contacts from POLY2 to M1.
	pcLayer = layerCNT
	pcPurpose = "drawing"
	for(j 0 numRows-1
		for(i 0 numCols-1
			cntStepX = cntStepY = CNTW + CNTSP
			totalContactsX = fix((Width-(2*P2EOCT+CNTW)+cntStepX+0.00001)/cntStepX)
			offsetX = (Width - (cntStepX*(totalContactsX-1.0)+(2*P2EOCT+CNTW))) / 2.0
			totalContactsY = fix((Length-(2*P2EOCT+CNTW)+cntStepY+0.00001)/cntStepY)
			offsetY = (Length - (cntStepY*(totalContactsY-1.0)+(2*P2EOCT+CNTW))) / 2.0

			for(k 0 totalContactsX-1
				for(l 0 totalContactsY-1
					pcList = list((Ox+P2EOCT+i*stepX+k*cntStepX+offsetX:Oy-P2EOCT-j*stepY-l*cntStepY-offsetY) (Ox+P2EOCT+CNTW+i*stepX+k*cntStepX+offsetX:Oy-P2EOCT-CNTW-j*stepY-l*cntStepY-offsetY))
					pcInst = dbCreateRect(pcCellView list(pcLayer pcPurpose) pcList)
				)
			)
		)
	)

	t
    )
)