Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a generator for constant bias-voltage generator. #327

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from glayout.flow.blocks.bias_gen.bias_gen import bias_gen
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Primitives
from glayout.flow.primitives.fet import pmos
from glayout.flow.primitives.fet import nmos
from glayout.flow.primitives.fet import via_stack

from glayout.flow.primitives.guardring import tapring

# Standard
from glayout.flow.pdk.mappedpdk import MappedPDK
from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk
from gdsfactory import Component

# Utility
from glayout.flow.pdk.util.comp_utils import evaluate_bbox, prec_center

# Routing
from glayout.flow.routing.straight_route import straight_route
from glayout.flow.routing.c_route import c_route
from glayout.flow.routing.L_route import L_route
from glayout.flow.routing.smart_route import smart_route

def bias_gen(pdk: MappedPDK):
# Create a top level component
bias_gen = Component()

# Bias Generator requires two NFETs of different thresholds. Retain dummies on east and west sides
nfet_M1 = nmos(pdk, width=3, with_tie=False, with_substrate_tap=False, with_dummy=(True, False), with_dnwell=True)
nfet_M2 = nmos(pdk, width=3, with_tie=False, with_substrate_tap=False, with_dummy=(False, True), with_dnwell=True)
bias_gen_M1 = bias_gen << nfet_M1
bias_gen_M2 = bias_gen << nfet_M2

# Relative Movement of the M1 transistor so that it doesn't overlap on M2
# Manual ratio applied so that d-nwell could overlap and eliminate the dnwell violation.
M2_dimension = evaluate_bbox(nfet_M2)
bias_gen_M1.movex(-0.85*M2_dimension[0]-pdk.util_max_metal_seperation())

# Routing
## Route the Gate from M1 to M2
bias_gen << straight_route(pdk, bias_gen_M1.ports["multiplier_0_source_E"], bias_gen_M2.ports["multiplier_0_drain_W"])
## Route the Drain to Gate of M2 to create G-D shorted instance
bias_gen << c_route(pdk, bias_gen_M2.ports["multiplier_0_drain_E"], bias_gen_M2.ports["multiplier_0_gate_E"])

## Calculate the centre of the bias_gen component so that the tapring could be centered around the component.
shift_amount = -prec_center(bias_gen.flatten())[0]

tap_ring = tapring(pdk, enclosed_rectangle=evaluate_bbox(bias_gen.flatten(), padding=pdk.util_max_metal_seperation()))
tap_ring_ref = bias_gen << tap_ring
tap_ring_ref.movex(shift_amount)

return bias_gen

bias_gen_component = bias_gen(sky130_mapped_pdk)
bias_gen_component.show()

# Write to GDS
bias_gen_component.write_gds('bias_gen.gds')

# Run magic DRC
# magic_drc_result = gf180_mapped_pdk.drc_magic(bias_gen_component, bias_gen_component.name)
magic_drc_result = sky130_mapped_pdk.drc_magic(bias_gen_component, bias_gen_component.name)
if magic_drc_result :
print("DRC is clean: ", magic_drc_result)
else:
print("DRC failed. Please try again.")

# klayout_drc_result = gf180_mapped_pdk.drc(bias_gen_component)
# print ("KLAYOUT_DRC_RESULT: ", klayout_drc_result)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from glayout.flow.blocks.cascode_common_source import common_source
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from gdsfactory import Component
from glayout.flow.pdk.mappedpdk import MappedPDK
from glayout.flow.placement.two_transistor_interdigitized import two_nfet_interdigitized
from glayout.flow.placement.two_transistor_interdigitized import two_pfet_interdigitized
from glayout.flow.primitives.fet import pmos
from glayout.flow.primitives.fet import nmos
from glayout.flow.primitives.guardring import tapring

from glayout.flow.pdk.util.comp_utils import prec_ref_center, prec_center, movey, evaluate_bbox
from glayout.flow.pdk.util.port_utils import remove_ports_with_prefix
from glayout.flow.routing.smart_route import smart_route
from glayout.flow.routing.c_route import c_route
from glayout.flow.routing.straight_route import straight_route

from glayout.flow.pdk.gf180_mapped import gf180_mapped_pdk
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk

def Cascode_CS(pdk: MappedPDK, L1, W1, L2, W2, cs_type="nfet"):
Cascode_CS = Component(name="Cascode_cs")

# Add two nfets for the cascode.
if (cs_type=="nfet"):
fet_M1=nmos(pdk, length=L1, width=W1, with_tie=False)#, sd_route_topmet="met3", gate_route_topmet="met3")
fet_M2=nmos(pdk, length=L2, width=W2, with_tie=False)#, sd_route_topmet="met3", gate_route_topmet="met3")
elif (cs_type=="pfet"):
fet_M1=pmos(pdk, length=L1, width=W1)
fet_M2=pmos(pdk, length=L2, width=W2)

# Generate a reference to M1, M2 for placement and routing
M1_ref = prec_ref_center(fet_M1)
Cascode_CS.add(M1_ref)
Cascode_CS.add_ports(M1_ref.get_ports_list(), prefix="M1_")
M2_ref = prec_ref_center(fet_M2)
Cascode_CS.add(M2_ref)
Cascode_CS.add_ports(M2_ref.get_ports_list(), prefix="M2_")

# Get dimensions of M1, M2 for displacing M1 above M2
M1_dim = prec_ref_center(M1_ref)
M2_dim = prec_ref_center(M2_ref)
movey(M2_ref, 0.5*(evaluate_bbox(M1_ref)[1]+evaluate_bbox(M2_ref)[1]) + pdk.util_max_metal_seperation())
# Remove ports and add them after moving a component as positions need to be updated from the movement
remove_ports_with_prefix(Cascode_CS, "M2_")
Cascode_CS.add_ports(M2_ref.get_ports_list(), prefix="M2_")

# Routing the Source of M2 to drain of M1:
Cascode_CS << smart_route(pdk,
Cascode_CS.ports["M1_multiplier_0_drain_N"],
Cascode_CS.ports["M2_multiplier_0_source_S"],
M1_ref, M2_ref)

# Add a guard tap ring around the cascode
shift_amount = -prec_center(Cascode_CS.flatten())[1]
tap_ring = tapring(pdk,
enclosed_rectangle=evaluate_bbox(Cascode_CS.flatten(), padding=pdk.util_max_metal_seperation()))
tap_ring_ref = Cascode_CS << tap_ring
tap_ring_ref.movey(shift_amount)

return Cascode_CS

mapped_pdk_build = sky130_mapped_pdk
Cascode_cs_component = Cascode_CS(mapped_pdk_build,2,3,4,6, cs_type="pfet")
Cascode_cs_component.show()

magic_drc_result = sky130_mapped_pdk.drc_magic(Cascode_cs_component, Cascode_cs_component.name)
if magic_drc_result :
print("DRC is clean: ", magic_drc_result)
else:
print("DRC failed. Please try again.")