mirror of https://github.com/VLSIDA/OpenRAM.git
Getting single bank to work reliably. Removed tri_gate from bank
for now. Will add it in multibank arrays only. Not needed for separate DIN and DOUT ports.
This commit is contained in:
parent
834fbac8de
commit
f3ae29fe0b
|
|
@ -39,6 +39,7 @@ class layout(lef.lef):
|
|||
shift the origin in the lowest left corner """
|
||||
offset = self.find_lowest_coords()
|
||||
self.translate_all(offset)
|
||||
return offset
|
||||
|
||||
def get_gate_offset(self, x_offset, height, inv_num):
|
||||
"""Gets the base offset and y orientation of stacked rows of gates
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ class bank(design.design):
|
|||
# Can remove the following, but it helps for debug!
|
||||
self.add_lvs_correspondence_points()
|
||||
|
||||
self.offset_all_coordinates()
|
||||
# Remember the bank center for further placement
|
||||
self.bank_center=self.offset_all_coordinates()
|
||||
|
||||
self.DRC_LVS()
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ class bank(design.design):
|
|||
for i in range(self.word_size):
|
||||
self.add_pin("DOUT[{0}]".format(i),"OUT")
|
||||
for i in range(self.word_size):
|
||||
self.add_pin("DIN[{0}]".format(i),"IN")
|
||||
self.add_pin("BANK_DIN[{0}]".format(i),"IN")
|
||||
for i in range(self.addr_size):
|
||||
self.add_pin("A[{0}]".format(i),"INPUT")
|
||||
|
||||
|
|
@ -95,8 +96,9 @@ class bank(design.design):
|
|||
self.route_precharge_to_bitcell_array()
|
||||
self.route_col_mux_to_bitcell_array()
|
||||
self.route_sense_amp_to_col_mux_or_bitcell_array()
|
||||
self.route_sense_amp_to_trigate()
|
||||
self.route_tri_gate_out()
|
||||
#self.route_sense_amp_to_trigate()
|
||||
#self.route_tri_gate_out()
|
||||
self.route_sense_amp_out()
|
||||
self.route_wordline_driver()
|
||||
self.route_write_driver()
|
||||
self.route_row_decoder()
|
||||
|
|
@ -119,7 +121,8 @@ class bank(design.design):
|
|||
self.add_column_mux_array()
|
||||
self.add_sense_amp_array()
|
||||
self.add_write_driver_array()
|
||||
self.add_tri_gate_array()
|
||||
# Not needed for single bank
|
||||
#self.add_tri_gate_array()
|
||||
|
||||
# To the left of the bitcell array
|
||||
self.add_row_decoder()
|
||||
|
|
@ -294,14 +297,15 @@ class bank(design.design):
|
|||
def add_write_driver_array(self):
|
||||
""" Adding Write Driver """
|
||||
|
||||
y_offset = self.sense_amp_array.height + self.column_mux_height + + self.m2_gap + self.write_driver_array.height
|
||||
y_offset = self.sense_amp_array.height + self.column_mux_height \
|
||||
+ self.m2_gap + self.write_driver_array.height
|
||||
self.write_driver_array_inst=self.add_inst(name="write_driver_array",
|
||||
mod=self.write_driver_array,
|
||||
offset=vector(0,y_offset).scale(-1,-1))
|
||||
|
||||
temp = []
|
||||
for i in range(self.word_size):
|
||||
temp.append("DIN[{0}]".format(i))
|
||||
temp.append("BANK_DIN[{0}]".format(i))
|
||||
for i in range(self.word_size):
|
||||
if (self.words_per_row == 1):
|
||||
temp.append("bl[{0}]".format(i))
|
||||
|
|
@ -315,7 +319,7 @@ class bank(design.design):
|
|||
def add_tri_gate_array(self):
|
||||
""" data tri gate to drive the data bus """
|
||||
y_offset = self.sense_amp_array.height+self.column_mux_height \
|
||||
+ self.write_driver_array.height + self.m2_gap + self.tri_gate_array.height
|
||||
+ self.m2_gap + self.tri_gate_array.height
|
||||
self.tri_gate_array_inst=self.add_inst(name="tri_gate_array",
|
||||
mod=self.tri_gate_array,
|
||||
offset=vector(0,y_offset).scale(-1,-1))
|
||||
|
|
@ -443,7 +447,7 @@ class bank(design.design):
|
|||
self.precharge_array_inst,
|
||||
self.sense_amp_array_inst,
|
||||
self.write_driver_array_inst,
|
||||
self.tri_gate_array_inst,
|
||||
# self.tri_gate_array_inst,
|
||||
self.row_decoder_inst,
|
||||
self.wordline_driver_inst]
|
||||
# Add these if we use the part...
|
||||
|
|
@ -492,7 +496,8 @@ class bank(design.design):
|
|||
#the column decoder (if there is one) or the tristate output
|
||||
#driver.
|
||||
# Leave room for the output below the tri gate.
|
||||
tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch
|
||||
#tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch
|
||||
write_driver_min_y_offset = self.write_driver_array_inst.by() - 3*self.m2_pitch
|
||||
row_decoder_min_y_offset = self.row_decoder_inst.by()
|
||||
if self.col_addr_size > 0:
|
||||
col_decoder_min_y_offset = self.col_decoder_inst.by()
|
||||
|
|
@ -502,10 +507,10 @@ class bank(design.design):
|
|||
if self.num_banks>1:
|
||||
# The control gating logic is below the decoder
|
||||
# Min of the control gating logic and tri gate.
|
||||
self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, tri_gate_min_y_offset)
|
||||
self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, write_driver_min_y_offset)
|
||||
else:
|
||||
# Just the min of the decoder logic logic and tri gate.
|
||||
self.min_y_offset = min(col_decoder_min_y_offset, tri_gate_min_y_offset)
|
||||
self.min_y_offset = min(col_decoder_min_y_offset, write_driver_min_y_offset)
|
||||
|
||||
# The max point is always the top of the precharge bitlines
|
||||
# Add a vdd and gnd power rail above the array
|
||||
|
|
@ -620,6 +625,16 @@ class bank(design.design):
|
|||
offset=sa_data_out)
|
||||
self.add_path("metal3",[sa_data_out,tri_gate_in])
|
||||
|
||||
def route_sense_amp_out(self):
|
||||
""" Add pins for the sense amp output """
|
||||
for i in range(self.word_size):
|
||||
data_pin = self.sense_amp_array_inst.get_pin("data[{}]".format(i))
|
||||
self.add_layout_pin_rect_center(text="DOUT[{}]".format(i),
|
||||
layer="metal2",
|
||||
offset=data_pin.center(),
|
||||
height=data_pin.height(),
|
||||
width=data_pin.width()),
|
||||
|
||||
def route_tri_gate_out(self):
|
||||
""" Metal 3 routing of tri_gate output data """
|
||||
for i in range(self.word_size):
|
||||
|
|
@ -647,7 +662,7 @@ class bank(design.design):
|
|||
|
||||
for i in range(self.word_size):
|
||||
data_name = "data[{}]".format(i)
|
||||
din_name = "DIN[{}]".format(i)
|
||||
din_name = "BANK_DIN[{}]".format(i)
|
||||
self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name)
|
||||
|
||||
|
||||
|
|
@ -749,13 +764,13 @@ class bank(design.design):
|
|||
layer="metal2",
|
||||
offset=br_pin.center())
|
||||
|
||||
# Add the data output names to the sense amp output
|
||||
for i in range(self.word_size):
|
||||
data_name = "data[{}]".format(i)
|
||||
data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
||||
self.add_label(text="sa_out[{}]".format(i),
|
||||
layer="metal2",
|
||||
offset=data_pin.center())
|
||||
# # Add the data output names to the sense amp output
|
||||
# for i in range(self.word_size):
|
||||
# data_name = "data[{}]".format(i)
|
||||
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
||||
# self.add_label(text="sa_out[{}]".format(i),
|
||||
# layer="metal2",
|
||||
# offset=data_pin.center())
|
||||
|
||||
# Add labels on the decoder
|
||||
for i in range(self.word_size):
|
||||
|
|
@ -775,8 +790,8 @@ class bank(design.design):
|
|||
# Connection from the central bus to the main control block crosses
|
||||
# pre-decoder and this connection is in metal3
|
||||
connection = []
|
||||
connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
|
||||
connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
|
||||
#connection.append((self.prefix+"tri_en_bar", self.tri_gate_array_inst.get_pin("en_bar").lc()))
|
||||
#connection.append((self.prefix+"tri_en", self.tri_gate_array_inst.get_pin("en").lc()))
|
||||
connection.append((self.prefix+"clk_buf_bar", self.precharge_array_inst.get_pin("en").lc()))
|
||||
connection.append((self.prefix+"w_en", self.write_driver_array_inst.get_pin("en").lc()))
|
||||
connection.append((self.prefix+"s_en", self.sense_amp_array_inst.get_pin("en").lc()))
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class dff_array(design.design):
|
|||
if name=="":
|
||||
name = "dff_array_{0}x{1}".format(rows, columns)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
debug.info(1, "Creating {0} rows={1} cols={2}".format(self.name, self.rows, self.columns))
|
||||
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
|
|
@ -38,33 +38,33 @@ class dff_array(design.design):
|
|||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
for y in range(self.rows):
|
||||
for x in range(self.columns):
|
||||
self.add_pin(self.get_din_name(y,x))
|
||||
for y in range(self.rows):
|
||||
for x in range(self.columns):
|
||||
self.add_pin(self.get_dout_name(y,x))
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_din_name(row,col))
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
self.add_pin(self.get_dout_name(row,col))
|
||||
self.add_pin("clk")
|
||||
self.add_pin("vdd")
|
||||
self.add_pin("gnd")
|
||||
|
||||
def create_dff_array(self):
|
||||
self.dff_insts={}
|
||||
for y in range(self.rows):
|
||||
for x in range(self.columns):
|
||||
name = "Xdff_r{0}_c{1}".format(y,x)
|
||||
if (y % 2 == 0):
|
||||
base = vector(x*self.dff.width,y*self.dff.height)
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
name = "Xdff_r{0}_c{1}".format(row,col)
|
||||
if (row % 2 == 0):
|
||||
base = vector(col*self.dff.width,row*self.dff.height)
|
||||
mirror = "R0"
|
||||
else:
|
||||
base = vector(x*self.dff.width,(y+1)*self.dff.height)
|
||||
base = vector(col*self.dff.width,(row+1)*self.dff.height)
|
||||
mirror = "MX"
|
||||
self.dff_insts[x,y]=self.add_inst(name=name,
|
||||
self.dff_insts[row,col]=self.add_inst(name=name,
|
||||
mod=self.dff,
|
||||
offset=base,
|
||||
mirror=mirror)
|
||||
self.connect_inst([self.get_din_name(y,x),
|
||||
self.get_dout_name(y,x),
|
||||
self.connect_inst([self.get_din_name(row,col),
|
||||
self.get_dout_name(row,col),
|
||||
"clk",
|
||||
"vdd",
|
||||
"gnd"])
|
||||
|
|
@ -91,10 +91,9 @@ class dff_array(design.design):
|
|||
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
||||
for y in range(self.rows):
|
||||
for row in range(self.rows):
|
||||
# Continous vdd rail along with label.
|
||||
vdd_pin=self.dff_insts[0,y].get_pin("vdd")
|
||||
vdd_pin=self.dff_insts[row,0].get_pin("vdd")
|
||||
self.add_layout_pin(text="vdd",
|
||||
layer="metal1",
|
||||
offset=vdd_pin.ll(),
|
||||
|
|
@ -102,7 +101,7 @@ class dff_array(design.design):
|
|||
height=self.m1_width)
|
||||
|
||||
# Continous gnd rail along with label.
|
||||
gnd_pin=self.dff_insts[0,y].get_pin("gnd")
|
||||
gnd_pin=self.dff_insts[row,0].get_pin("gnd")
|
||||
self.add_layout_pin(text="gnd",
|
||||
layer="metal1",
|
||||
offset=gnd_pin.ll(),
|
||||
|
|
@ -110,19 +109,19 @@ class dff_array(design.design):
|
|||
height=self.m1_width)
|
||||
|
||||
|
||||
for y in range(self.rows):
|
||||
for x in range(self.columns):
|
||||
din_pin = self.dff_insts[x,y].get_pin("D")
|
||||
for row in range(self.rows):
|
||||
for col in range(self.columns):
|
||||
din_pin = self.dff_insts[row,col].get_pin("D")
|
||||
debug.check(din_pin.layer=="metal2","DFF D pin not on metal2")
|
||||
self.add_layout_pin(text=self.get_din_name(y,x),
|
||||
self.add_layout_pin(text=self.get_din_name(row,col),
|
||||
layer=din_pin.layer,
|
||||
offset=din_pin.ll(),
|
||||
width=din_pin.width(),
|
||||
height=din_pin.height())
|
||||
|
||||
dout_pin = self.dff_insts[x,y].get_pin("Q")
|
||||
dout_pin = self.dff_insts[row,col].get_pin("Q")
|
||||
debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2")
|
||||
self.add_layout_pin(text=self.get_dout_name(y,x),
|
||||
self.add_layout_pin(text=self.get_dout_name(row,col),
|
||||
layer=dout_pin.layer,
|
||||
offset=dout_pin.ll(),
|
||||
width=dout_pin.width(),
|
||||
|
|
@ -145,8 +144,8 @@ class dff_array(design.design):
|
|||
offset=vector(0,0),
|
||||
width=self.width,
|
||||
height=self.m3_width)
|
||||
for x in range(self.columns):
|
||||
clk_pin = self.dff_insts[x,0].get_pin("clk")
|
||||
for col in range(self.columns):
|
||||
clk_pin = self.dff_insts[0,col].get_pin("clk")
|
||||
# Make a vertical strip for each column
|
||||
self.add_layout_pin(text="clk",
|
||||
layer="metal2",
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class sram():
|
|||
num_words))
|
||||
start_time = datetime.datetime.now()
|
||||
|
||||
self.name = name
|
||||
|
||||
if num_banks == 1:
|
||||
from sram_1bank import sram_1bank
|
||||
self.s=sram_1bank(word_size, num_words, name)
|
||||
|
|
@ -53,8 +55,6 @@ class sram():
|
|||
if not OPTS.is_unit_test:
|
||||
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
||||
|
||||
def get_name(self):
|
||||
return self.s.name
|
||||
|
||||
def sp_write(self,name):
|
||||
self.s.sp_write(name)
|
||||
|
|
|
|||
|
|
@ -37,14 +37,18 @@ class sram_1bank(sram_base):
|
|||
self.add_control_logic(position=control_pos)
|
||||
|
||||
# Leave room for the control routes to the left of the flops
|
||||
addr_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch,
|
||||
row_addr_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch,
|
||||
control_pos.y + self.control_logic.height + self.m1_pitch)
|
||||
self.add_addr_dff(addr_pos)
|
||||
self.add_row_addr_dff(row_addr_pos)
|
||||
|
||||
# Leave room for the control routes to the left of the flops
|
||||
data_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch,
|
||||
control_pos.y + self.control_logic.height + self.m1_pitch)
|
||||
self.add_addr_dff(addr_pos)
|
||||
# Add the column address below the bank under the control
|
||||
if self.col_addr_dff:
|
||||
col_addr_pos = vector(-self.col_addr_dff.width, -1.5*self.col_addr_dff.height)
|
||||
self.add_col_addr_dff(col_addr_pos)
|
||||
|
||||
# Add the data flops below the bank
|
||||
data_pos = vector(-self.bank_inst.mod.bank_center.x, -1.5*self.data_dff.height)
|
||||
self.add_data_dff(data_pos)
|
||||
|
||||
# two supply rails are already included in the bank, so just 2 here.
|
||||
self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch
|
||||
|
|
@ -54,15 +58,22 @@ class sram_1bank(sram_base):
|
|||
"""
|
||||
Add the top-level pins for a single bank SRAM with control.
|
||||
"""
|
||||
# Connect the control pins as inputs
|
||||
for n in self.control_logic_inputs + ["clk"]:
|
||||
self.copy_layout_pin(self.control_logic_inst, n)
|
||||
|
||||
for i in range(self.word_size):
|
||||
self.copy_layout_pin(self.bank_inst, "DOUT[{}]".format(i))
|
||||
|
||||
for i in range(self.addr_size):
|
||||
self.copy_layout_pin(self.addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
|
||||
|
||||
# Lower address bits
|
||||
for i in range(self.col_addr_size):
|
||||
self.copy_layout_pin(self.col_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
|
||||
# Upper address bits
|
||||
for i in range(self.row_addr_size):
|
||||
self.copy_layout_pin(self.row_addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i+self.col_addr_size))
|
||||
|
||||
for i in range(self.word_size):
|
||||
self.copy_layout_pin(self.addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i))
|
||||
self.copy_layout_pin(self.data_dff_inst, "din[{}]".format(i),"DIN[{}]".format(i))
|
||||
|
||||
def route(self):
|
||||
""" Route a single bank SRAM """
|
||||
|
|
@ -79,14 +90,28 @@ class sram_1bank(sram_base):
|
|||
rotate=90)
|
||||
|
||||
|
||||
# Connect the output of the flops to the bank pins
|
||||
for i in range(self.addr_size):
|
||||
# Connect the output of the row flops to the bank pins
|
||||
for i in range(self.row_addr_size):
|
||||
flop_name = "dout[{}]".format(i)
|
||||
bank_name = "A[{}]".format(i)
|
||||
flop_pin = self.addr_dff_inst.get_pin(flop_name)
|
||||
bank_name = "A[{}]".format(i+self.col_addr_size)
|
||||
flop_pin = self.row_addr_dff_inst.get_pin(flop_name)
|
||||
bank_pin = self.bank_inst.get_pin(bank_name)
|
||||
flop_pos = flop_pin.center()
|
||||
bank_pos = vector(bank_pin.cx(),flop_pos.y)
|
||||
bank_pos = bank_pin.center()
|
||||
mid_pos = vector(bank_pos.x,flop_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos,bank_pos])
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=flop_pos,
|
||||
rotate=90)
|
||||
|
||||
# Connect the output of the row flops to the bank pins
|
||||
for i in range(self.col_addr_size):
|
||||
flop_name = "dout[{}]".format(i)
|
||||
bank_name = "A[{}]".format(i)
|
||||
flop_pin = self.col_addr_dff_inst.get_pin(flop_name)
|
||||
bank_pin = self.bank_inst.get_pin(bank_name)
|
||||
flop_pos = flop_pin.center()
|
||||
bank_pos = bank_pin.center()
|
||||
self.add_path("metal3",[flop_pos, bank_pos])
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=flop_pos,
|
||||
|
|
@ -95,17 +120,28 @@ class sram_1bank(sram_base):
|
|||
offset=bank_pos,
|
||||
rotate=90)
|
||||
|
||||
# Connect the control pins as inputs
|
||||
for n in self.control_logic_inputs + ["clk"]:
|
||||
self.copy_layout_pin(self.control_logic_inst, n)
|
||||
# Connect the output of the row flops to the bank pins
|
||||
for i in range(self.word_size):
|
||||
flop_name = "dout[{}]".format(i)
|
||||
bank_name = "BANK_DIN[{}]".format(i)
|
||||
flop_pin = self.data_dff_inst.get_pin(flop_name)
|
||||
bank_pin = self.bank_inst.get_pin(bank_name)
|
||||
flop_pos = flop_pin.center()
|
||||
bank_pos = bank_pin.center()
|
||||
mid_pos = vector(bank_pos.x,flop_pos.y)
|
||||
self.add_wire(("metal3","via2","metal2"),[flop_pos, mid_pos,bank_pos])
|
||||
self.add_via_center(layers=("metal2","via2","metal3"),
|
||||
offset=flop_pos,
|
||||
rotate=90)
|
||||
|
||||
|
||||
# Connect the clock between the flops and control module
|
||||
flop_pin = self.addr_dff_inst.get_pin("clk")
|
||||
ctrl_pin = self.control_logic_inst.get_pin("clk_buf")
|
||||
flop_pos = flop_pin.uc()
|
||||
ctrl_pos = ctrl_pin.bc()
|
||||
mid_ypos = 0.5*(ctrl_pos.y+flop_pos.y)
|
||||
mid1_pos = vector(flop_pos.x, mid_ypos)
|
||||
mid2_pos = vector(ctrl_pos.x, mid_ypos)
|
||||
self.add_wire(("metal1","via1","metal2"),[flop_pin.uc(), mid1_pos, mid2_pos, ctrl_pin.bc()])
|
||||
# # Connect the clock between the flops and control module
|
||||
# flop_pin = self.addr_dff_inst.get_pin("clk")
|
||||
# ctrl_pin = self.control_logic_inst.get_pin("clk_buf")
|
||||
# flop_pos = flop_pin.uc()
|
||||
# ctrl_pos = ctrl_pin.bc()
|
||||
# mid_ypos = 0.5*(ctrl_pos.y+flop_pos.y)
|
||||
# mid1_pos = vector(flop_pos.x, mid_ypos)
|
||||
# mid2_pos = vector(ctrl_pos.x, mid_ypos)
|
||||
# self.add_wire(("metal1","via1","metal2"),[flop_pin.uc(), mid1_pos, mid2_pos, ctrl_pin.bc()])
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ class sram_base(design):
|
|||
self.num_words = num_words
|
||||
self.num_banks = num_banks
|
||||
|
||||
def whoami():
|
||||
print("abstract")
|
||||
|
||||
def compute_sizes(self):
|
||||
""" Computes the organization of the memory using bitcell size by trying to make it square."""
|
||||
|
||||
|
|
@ -258,10 +255,18 @@ class sram_base(design):
|
|||
self.add_mod(self.control_logic)
|
||||
|
||||
# Create the address and control flops (but not the clk)
|
||||
dff_size = self.addr_size
|
||||
from dff_array import dff_array
|
||||
self.addr_dff = dff_array(name="dff_array", rows=dff_size, columns=1)
|
||||
self.add_mod(self.addr_dff)
|
||||
self.row_addr_dff = dff_array(name="row_addr_dff", rows=self.row_addr_size, columns=1)
|
||||
self.add_mod(self.row_addr_dff)
|
||||
|
||||
if self.col_addr_size > 0:
|
||||
self.col_addr_dff = dff_array(name="col_addr_dff", rows=1, columns=self.col_addr_size)
|
||||
self.add_mod(self.col_addr_dff)
|
||||
else:
|
||||
self.col_addr_dff = None
|
||||
|
||||
self.data_dff = dff_array(name="data_dff", rows=1, columns=self.word_size)
|
||||
self.add_mod(self.data_dff)
|
||||
|
||||
# Create the bank module (up to four are instantiated)
|
||||
from bank import bank
|
||||
|
|
@ -329,21 +334,49 @@ class sram_base(design):
|
|||
return bank_inst
|
||||
|
||||
|
||||
|
||||
def add_addr_dff(self, position):
|
||||
""" Add and place address and control flops """
|
||||
self.addr_dff_inst = self.add_inst(name="address",
|
||||
mod=self.addr_dff,
|
||||
offset=position)
|
||||
def add_row_addr_dff(self, position):
|
||||
""" Add and place all address flops for the main decoder """
|
||||
self.row_addr_dff_inst = self.add_inst(name="row_address",
|
||||
mod=self.row_addr_dff,
|
||||
offset=position)
|
||||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for i in range(self.addr_size):
|
||||
for i in range(self.row_addr_size):
|
||||
inputs.append("ADDR[{}]".format(i+self.col_addr_size))
|
||||
outputs.append("A[{}]".format(i+self.col_addr_size))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
|
||||
|
||||
|
||||
def add_col_addr_dff(self, position):
|
||||
""" Add and place all address flops for the column decoder """
|
||||
self.col_addr_dff_inst = self.add_inst(name="row_address",
|
||||
mod=self.col_addr_dff,
|
||||
offset=position)
|
||||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for i in range(self.col_addr_size):
|
||||
inputs.append("ADDR[{}]".format(i))
|
||||
outputs.append("A[{}]".format(i))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
|
||||
|
||||
|
||||
def add_data_dff(self, position):
|
||||
""" Add and place all data flops """
|
||||
self.data_dff_inst = self.add_inst(name="data_dff",
|
||||
mod=self.data_dff,
|
||||
offset=position)
|
||||
# inputs, outputs/output/bar
|
||||
inputs = []
|
||||
outputs = []
|
||||
for i in range(self.word_size):
|
||||
inputs.append("DIN[{}]".format(i))
|
||||
outputs.append("BANK_DIN[{}]".format(i))
|
||||
|
||||
self.connect_inst(inputs + outputs + ["clk_buf_bar", "vdd", "gnd"])
|
||||
|
||||
def add_control_logic(self, position):
|
||||
""" Add and place control logic """
|
||||
inputs = []
|
||||
|
|
|
|||
|
|
@ -32,14 +32,14 @@ class openram_test(unittest.TestCase):
|
|||
a.gds_write(tempgds)
|
||||
|
||||
import verify
|
||||
result=verify.run_drc(a.get_name(), tempgds)
|
||||
result=verify.run_drc(a.name, tempgds)
|
||||
if result != 0:
|
||||
self.fail("DRC failed: {}".format(a.get_name()))
|
||||
self.fail("DRC failed: {}".format(a.name))
|
||||
|
||||
|
||||
result=verify.run_lvs(a.get_name(), tempgds, tempspice, final_verification)
|
||||
result=verify.run_lvs(a.name, tempgds, tempspice, final_verification)
|
||||
if result != 0:
|
||||
self.fail("LVS mismatch: {}".format(a.get_name()))
|
||||
self.fail("LVS mismatch: {}".format(a.name))
|
||||
|
||||
if OPTS.purge_temp:
|
||||
self.cleanup()
|
||||
|
|
|
|||
Loading…
Reference in New Issue