2022-12-30 09:35:15 +01:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
|
|
|
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
|
|
|
# (acting for and on behalf of Oklahoma State University)
|
|
|
|
|
# All rights reserved.
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
from openram.sram_factory import factory
|
|
|
|
|
from openram.base import vector, design
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class rom_control_logic(design):
|
|
|
|
|
def __init__(self, num_outputs, name="", height=None):
|
|
|
|
|
self.output_size = num_outputs
|
|
|
|
|
self.mod_height = height
|
|
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
if "li" in layer:
|
|
|
|
|
self.route_layer = "li"
|
|
|
|
|
else:
|
|
|
|
|
self.route_layer = "m1"
|
|
|
|
|
|
2022-12-30 09:35:15 +01:00
|
|
|
# dff = factory.create(module_type="dff")
|
|
|
|
|
|
|
|
|
|
# if height == None:
|
|
|
|
|
# self.mod_height = dff.height * 0.5
|
|
|
|
|
# else:
|
|
|
|
|
# self.mod_height = height
|
|
|
|
|
|
|
|
|
|
super().__init__(name)
|
|
|
|
|
self.create_netlist()
|
|
|
|
|
self.create_layout()
|
|
|
|
|
self.add_boundary()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_netlist(self):
|
|
|
|
|
self.add_modules()
|
|
|
|
|
self.add_pins()
|
|
|
|
|
|
|
|
|
|
def create_layout(self):
|
|
|
|
|
self.create_instances()
|
|
|
|
|
self.height=self.nand_inst.height
|
|
|
|
|
self.width=self.nand_inst.width + self.inv_inst.width + self.driver_inst.width
|
|
|
|
|
self.place_instances()
|
|
|
|
|
self.route_insts()
|
|
|
|
|
|
|
|
|
|
def add_modules(self):
|
|
|
|
|
|
|
|
|
|
self.inv_mod = factory.create(module_type="pinv", module_name="rom_control_logic_pinv", height=self.mod_height)
|
|
|
|
|
self.nand_mod = factory.create(module_type="pnand2", module_name="rom_control_nand", height=self.mod_height)
|
2023-01-17 01:15:03 +01:00
|
|
|
self.driver_mod = factory.create(module_type="pdriver", inverting=True, fanout=self.output_size, height=self.mod_height, add_wells=True)
|
2022-12-30 09:35:15 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_pins(self):
|
2023-01-17 01:15:03 +01:00
|
|
|
self.add_pin("clk", "INPUT")
|
2022-12-30 09:35:15 +01:00
|
|
|
self.add_pin("CS", "INPUT")
|
|
|
|
|
self.add_pin("prechrg", "OUTPUT")
|
|
|
|
|
self.add_pin("vdd", "POWER")
|
|
|
|
|
self.add_pin("gnd", "GROUND")
|
|
|
|
|
|
|
|
|
|
def create_instances(self):
|
|
|
|
|
|
|
|
|
|
self.inv_inst = self.add_inst(name="read_signal_inv", mod=self.inv_mod)
|
2023-01-17 01:15:03 +01:00
|
|
|
self.connect_inst(["clk", "clk_bar", "vdd", "gnd"])
|
2022-12-30 09:35:15 +01:00
|
|
|
|
|
|
|
|
self.nand_inst = self.add_inst(name="control_nand", mod=self.nand_mod)
|
2023-01-17 01:15:03 +01:00
|
|
|
self.connect_inst(["CS", "clk_bar", "pre_drive", "vdd", "gnd"])
|
2022-12-30 09:35:15 +01:00
|
|
|
|
|
|
|
|
self.driver_inst = self.add_inst(name="driver_inst", mod=self.driver_mod)
|
|
|
|
|
self.connect_inst(["pre_drive", "prechrg", "vdd", "gnd"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def place_instances(self):
|
|
|
|
|
self.nand_inst.place(offset=[self.inv_inst.width, 0])
|
|
|
|
|
self.driver_inst.place(offset=[self.nand_inst.width + self.inv_inst.width, 0])
|
|
|
|
|
|
|
|
|
|
def route_insts(self):
|
|
|
|
|
|
|
|
|
|
self.copy_layout_pin(self.inv_inst, "A", "READ")
|
|
|
|
|
self.copy_layout_pin(self.driver_inst, "Z", "prechrg")
|
|
|
|
|
self.copy_layout_pin(self.nand_inst, "B", "CS")
|
|
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
self.add_path(self.route_layer, [self.inv_inst.get_pin("Z").center(), self.nand_inst.get_pin("A").center()])
|
2022-12-30 09:35:15 +01:00
|
|
|
|
2023-01-17 01:15:03 +01:00
|
|
|
self.add_path(self.route_layer, [self.nand_inst.get_pin("Z").center(), self.driver_inst.get_pin("A").center()])
|
2022-12-30 09:35:15 +01:00
|
|
|
|