Layout script for NAND gate
[code] def draw_layout(self):
#============================================== # Extracting parameters from the __init__.py #==============================================
lch = self.params['lch'] tran_intent = self.params['tran_intent'] nmos_nf = self.params['nmos_nf'] pmos_nf = self.params['pmos_nf'] guard_ring_nf = self.params['guard_ring_nf'] pin_loc = self.params['pin_loc'] nmos_w = self.params['nmos_w'] pmos_w = self.params['pmos_w'] ntap_w = self.params['ntap_w'] ptap_w = self.params['ptap_w'] flip_well = self.params['flip_well'] show_pins = True
#============================================== # Setting up other variables in here #==============================================
# 2 x the longest finger size
# Because we'll instance 2 transistors in one row # We added more fingers for allowance on the sides # This sets how wide the base is
fg_tot = 2*max(nmos_nf,pmos_nf)+8
# Drawing parameters
# We only need 1 row of NMOS and 1 row of PMOS # Both of them are of the same transistor flavor
nw_list = [nmos_w ] n_intent_list = [tran_intent] pw_list = [pmos_w ] p_intent_list = [tran_intent]
# Routing track definitions ng_tracks = [2] pg_tracks = [2]
nds_tracks = [2] pds_tracks = [6]
# MX means orient the gate up
# R0 means orient the gate down # All NMOS orient up while all PMOS orient down
n_orientations=['MX'] p_orientations=['R0'] top_layer=5
#============================================== # Drawing the base #==============================================
self.draw_base(lch, fg_tot, ptap_w, ntap_w, nw_list, n_intent_list, pw_list, p_intent_list, ng_tracks=ng_tracks, nds_tracks=nds_tracks, pg_tracks=pg_tracks, pds_tracks=pds_tracks, n_orientations=n_orientations, p_orientations=p_orientations, top_layer=top_layer, guard_ring_nf=guard_ring_nf)
#============================================== # Drawing transistors #============================================== # As a quick guide: # mos_type = pick 'nch' for NMOS or 'pch' for PMOS # row = row # relative to the NMOS or PMOS # start_col = starting horizontal location # source_dir = source direction. If it's 2 it points downward, if it's 0 it points upward. # drain_dir = same as source_dir # s_net = assigning source terminal name # d_net = assigning source terminal name # Simply call the self.draw_mos_conn() function to draw the transistor.
mos_type = 'nch' row = 0 start_col = 3 nf = nmos_nf source_dir = 2 drain_dir = 0 s_net = 'X' d_net = 'Q' nmos0 = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
start_col = 3 + nmos_nf + 2 s_net = 'VSS' d_net = 'X' nmos1 = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
mos_type = 'pch' start_col = 3 nf = pmos_nf source_dir = 0 drain_dir = 2 s_net = 'VDD' d_net = 'Q' pmos0 = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net )
start_col = 3 + pmos_nf + 2 pmos1 = self.draw_mos_conn(mos_type, row, start_col, nf, source_dir, drain_dir, s_net=s_net, d_net=d_net ) #==============================================
# Routing proper #==============================================
# Gate routing tid_A_G = self.make_track_id('nch', row_idx=0, tr_type='g', tr_idx=-2, width=1) gate_A_warr = self.connect_to_tracks([nmos0['g'],pmos0['g']], tid_A_G) self.add_pin(self.get_pin_name('A'), gate_A_warr, show=show_pins)
tid_B_G = self.make_track_id('nch', row_idx=0, tr_type='g', tr_idx=-2, width=1) gate_B_warr = self.connect_to_tracks([nmos1['g'],pmos1['g']], tid_B_G) self.add_pin(self.get_pin_name('B'), gate_B_warr, show=show_pins)
# Drain routings tid_P_D = self.make_track_id('pch', row_idx=0, tr_type='ds', tr_idx=0, width=1) drain_P_warr = self.connect_to_tracks([pmos0['d'], pmos1['d']], tid_P_D)
tid_N_D = self.make_track_id('nch', row_idx=0, tr_type='ds', tr_idx=0, width=1) drain_N_warr = self.connect_to_tracks(nmos0['d'], tid_N_D)
# Setting a horizontal track # Get location of vertical track loc = (drain_N_warr.get_bbox_array(self.grid).left + drain_N_warr.get_bbox_array(self.grid).right/2) idx = self.grid.coord_to_nearest_track(layer_id=5, coord=loc)
# Vertical track to connect drains ver_id = TrackID(layer_id=5, track_idx=idx, width=1) out_warr = self.connect_to_tracks([drain_N_warr, drain_P_warr], ver_id) self.add_pin(self.get_pin_name('Q'), out_warr, show=show_pins)
# NMOS drain-source routing tid_N0_N1_DS = self.make_track_id('nch', row_idx=0, tr_type='ds', tr_idx=0, width=1) N0_N1_DS_warr = self.connect_to_tracks([nmos0['s'], nmos1['d']], tid_N0_N1_DS)
# Connection to VSS and VDD self.connect_to_substrate('ptap', nmos1['s']) self.connect_to_substrate('ntap', pmos0['s']) self.connect_to_substrate('ntap', pmos1['s'])
# Filling dummies and adding VDD and VSS pins ptap_wire_arrs, ntap_wire_arrs = self.fill_dummy(vss_width=6, vdd_width=6, lower=0, upper=self.bound_box.right) self.add_pin(self.get_pin_name('VDD'), ntap_wire_arrs, label='VDD',show=True) self.add_pin(self.get_pin_name('VSS'), ptap_wire_arrs, label='VSS',show=True)
# Create schematic parameters for update self.sch_params = dict() for key in ('lch', 'tran_intent', 'nmos_nf', 'nmos_w', 'pmos_nf', 'pmos_w', 'ntap_w', 'ptap_w', 'flip_well' ): self.sch_params[key] = self.params[key] sch_dummy_info = self.get_sch_dummy_info() self.sch_params['sch_dummy_info'] = sch_dummy_info self.sch_dummy_info=sch_dummy_info
[/code]