Skip to content

Commit 0853089

Browse files
committed
Tidy up pad side OE logic
1 parent 22bc01c commit 0853089

File tree

1 file changed

+34
-27
lines changed

1 file changed

+34
-27
lines changed

chipflow_lib/platforms/silicon.py

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,60 +96,67 @@ def __init__(self,
9696
self._i = Signal(width, name=f"{self._name}$i")
9797
self._ie = Signal(width, name=f"{self._name}$ie", init=-1)
9898
if self.direction in (io.Direction.Output, io.Direction.Bidir):
99-
self._o = Signal(width, name=f"{self._name}$o")
99+
init = 0
100+
if 'init' in port_desc.iomodel and port_desc.iomodel['init']:
101+
init = port_desc.iomodel['init']
102+
logger.debug(f"'init' found for self._name. Initialising outputs with {init}")
103+
104+
self._o = Signal(width, name=f"{self._name}$o", init=init)
100105

101106
init_oe = -1
102107
if 'init_oe' in port_desc.iomodel and port_desc.iomodel['init_oe']:
103108
init_oe = port_desc.iomodel['init_oe']
109+
logger.debug(f"'init_oe' found for self._name. Initialising oe with {init_oe}")
104110

105111
# user side either gets single oe or multiple, depending on 'individual_oe'
106112
# cells side always gets <width> oes. Wired together in the wire method below
107113
if "individual_oe" not in self.iomodel or not self.iomodel["individual_oe"]:
108114
self._oe = Signal(1, name=f"{self._name}$oe", init=init_oe)
109-
self._oes = Signal(width, name=f"{self._name}$oe")
115+
self._oes = Signal(width, name=f"{self._name}$oe")
110116
else:
111117
self._oes = Signal(width, name=f"{self._name}$oe", init=init_oe)
112118
self._oe = self._oes
113-
114119
logger.debug(f"Created SiliconPlatformPort {self._name}, with port description:\n{pformat(self._port_desc)}")
115120

116-
def wire(self, m: Module, interface: PureInterface):
117-
assert self.direction == interface.signature.direction #type: ignore
118-
if hasattr(interface, '_i'):
119-
m.d.comb += interface.i.eq(self.i) # type: ignore
120-
for d in ['_o', '_oe', '_ie']:
121-
if hasattr(interface, d):
122-
m.d.comb += getattr(self, d).eq(getattr(interface, d))
123-
# wire user side _oe to _oes if necessary
124-
if self._oe is not None and self._oe.shape().width == 1 and self._oes.shape().width > 1:
125-
m.d.comb += self._oe.eq(self._oes)
126-
127121
def instantiate_toplevel(self):
128122
ports = []
129123
if self.direction in (io.Direction.Input, io.Direction.Bidir):
130124
ports.append((f"io${self._name}$i", self._i, PortDirection.Input))
131125
ports.append((f"io${self._name}$ie", self._ie, PortDirection.Output))
132126
if self.direction in (io.Direction.Output, io.Direction.Bidir):
133127
ports.append((f"io${self._name}$o", self._o, PortDirection.Output))
134-
if self._oe is not None and self._oe.shape().width == 1 and self._oes.shape().width > 1:
128+
if self._oe is not None and len(self._oe) == 1 and len(self._oes) > 1:
135129
ports.append((f"io${self._name}$oe", self._oes, PortDirection.Output))
136130
else:
137131
ports.append((f"io${self._name}$oe", self._oe, PortDirection.Output))
138132
return ports
139133

140134
def wire_up(self, m, wire):
135+
assert self.direction == wire.signature.direction #type: ignore
136+
# wire user side _oe to _oes if necessary
137+
if self._oe is not None and len(self._oe) == 1 and len(self._oes) > 1:
138+
self._oes.eq(self._oe.replicate(len(self._oes)))
139+
141140
inv_mask = sum(inv << bit for bit, inv in enumerate(self.invert))
142-
if hasattr(wire, 'i'):
143-
m.d.comb += wire.i.eq(self.i ^ inv_mask)
144-
if hasattr(wire, 'o'):
145-
m.d.comb += self.o.eq(wire.o ^ inv_mask)
146-
if hasattr(wire, 'oe'):
147-
m.d.comb += self.oe.eq(wire.oe)
141+
if hasattr(wire, 'i') and wire.i is not None:
142+
assert self._i is not None
143+
m.d.comb += wire.i.eq(self._i ^ inv_mask)
144+
if hasattr(wire, 'o') and wire.o is not None:
145+
assert self._o is not None
146+
m.d.comb += self._o.eq(wire.o ^ inv_mask)
147+
if hasattr(wire, 'oe') and wire.oe is not None:
148+
assert self._oe is not None
149+
m.d.comb += self._oe.eq(wire.oe)
150+
elif self.direction in (io.Direction.Output, io.Direction.Bidir):
151+
m.d.comb += self._oes.eq(-1) # set output enabled if the user hasn't connected
148152

149153
if hasattr(wire, 'ie'):
150-
m.d.comb += self.ie.eq(wire.ie)
151-
elif hasattr(wire, 'oe'):
152-
m.d.comb += self.ie.eq(~wire.oe)
154+
assert self._ie is not None
155+
m.d.comb += self._ie.eq(wire.ie)
156+
elif self.direction is io.Direction.Bidir:
157+
assert self._oes is not None
158+
assert self._ie is not None
159+
m.d.comb += self._ie.eq(~self._oes)
153160

154161

155162
@property
@@ -240,7 +247,7 @@ class Sky130Port(SiliconPlatformPort):
240247
"""
241248
Specialisation of `SiliconPlatformPort` for the `Skywater sky130_fd_io__gpiov2 IO cell <https://skywater-pdk.readthedocs.io/en/main/contents/libraries/sky130_fd_io/docs/user_guide.html>`_
242249
243-
Includes wires and configuration for `Drive Modes <IODriveMode>`, `Input buffer trip point <IOTripPoint>`and buffer control~
250+
Includes wires and configuration for `Drive Modes <IODriveMode>`, `Input buffer trip point <IOTripPoint>`and buffer control
244251
"""
245252

246253
_DriveMode_map = {
@@ -308,8 +315,8 @@ def __init__(self,
308315
dm = Sky130DriveMode.STRONG_UP_STRONG_DOWN
309316
dm_init = __class__._DriveMode_map[dm]
310317
dm_init_bits = [ int(b) for b in f"{dm_init:b}"]
311-
dms_shape = data.ArrayLayout(unsigned(3), self.width)
312-
self._dms = Signal(dms_shape, name=f"{self._name}$dms", init=[dm_init]*self.width)
318+
dms_layout = data.ArrayLayout(unsigned(3), self.width)
319+
self._dms = Signal(dms_layout, name=f"{self._name}$dms", init=[dm_init]*self.width)
313320
all_ones = (2<<(self.width-1))-1
314321
self._dm0 = Signal(self.width, name=f"{self._name}$dm0", init=dm_init_bits[0]*all_ones)
315322
self._dm1 = Signal(self.width, name=f"{self._name}$dm1", init=dm_init_bits[1]*all_ones)

0 commit comments

Comments
 (0)