Skip to content

Commit 7c7f9e3

Browse files
committed
vendor._lattice: OFS1P3DX -> OFD1P3DX and IFS1P3DX -> IFD1P3DX for nexus
More specialized buffers required
1 parent 9201cc3 commit 7c7f9e3

File tree

1 file changed

+58
-7
lines changed

1 file changed

+58
-7
lines changed

amaranth/vendor/_lattice.py

+58-7
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def elaborate(self, platform):
7777
return m
7878

7979

80-
def _make_oereg(m, domain, oe, q):
80+
def _make_oereg_ecp5_machxo2(m, domain, oe, q):
8181
for bit in range(len(q)):
8282
m.submodules[f"oe_ff{bit}"] = Instance("OFS1P3DX",
8383
i_SCLK=ClockSignal(domain),
@@ -88,7 +88,18 @@ def _make_oereg(m, domain, oe, q):
8888
)
8989

9090

91-
class FFBuffer(io.FFBuffer):
91+
def _make_oereg_nexus(m, domain, oe, q):
92+
for bit in range(len(q)):
93+
m.submodules[f"oe_ff{bit}"] = Instance("OFD1P3DX",
94+
i_CK=ClockSignal(domain),
95+
i_SP=Const(1),
96+
i_CD=Const(0),
97+
i_D=oe,
98+
o_Q=q[bit],
99+
)
100+
101+
102+
class FFBufferECP5(io.FFBuffer):
92103
def elaborate(self, platform):
93104
m = Module()
94105

@@ -118,7 +129,42 @@ def elaborate(self, platform):
118129
i_D=o_inv[bit],
119130
o_Q=buf.o[bit],
120131
)
121-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
132+
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)
133+
134+
return m
135+
136+
137+
class FFBufferNexus(io.FFBuffer):
138+
def elaborate(self, platform):
139+
m = Module()
140+
141+
m.submodules.buf = buf = InnerBuffer(self.direction, self.port)
142+
inv_mask = sum(inv << bit for bit, inv in enumerate(self.port.invert))
143+
144+
if self.direction is not io.Direction.Output:
145+
i_inv = Signal.like(self.i)
146+
for bit in range(len(self.port)):
147+
m.submodules[f"i_ff{bit}"] = Instance("IFD1P3DX",
148+
i_CK=ClockSignal(self.i_domain),
149+
i_SP=Const(1),
150+
i_CD=Const(0),
151+
i_D=buf.i[bit],
152+
o_Q=i_inv[bit],
153+
)
154+
m.d.comb += self.i.eq(i_inv ^ inv_mask)
155+
156+
if self.direction is not io.Direction.Input:
157+
o_inv = Signal.like(self.o)
158+
m.d.comb += o_inv.eq(self.o ^ inv_mask)
159+
for bit in range(len(self.port)):
160+
m.submodules[f"o_ff{bit}"] = Instance("OFD1P3DX",
161+
i_CK=ClockSignal(self.o_domain),
162+
i_SP=Const(1),
163+
i_CD=Const(0),
164+
i_D=o_inv[bit],
165+
o_Q=buf.o[bit],
166+
)
167+
_make_oereg_nexus(m, self.o_domain, ~self.oe, buf.t)
122168

123169
return m
124170

@@ -159,7 +205,7 @@ def elaborate(self, platform):
159205
i_D1=o1_inv[bit],
160206
o_Q=buf.o[bit],
161207
)
162-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
208+
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)
163209

164210
return m
165211

@@ -200,7 +246,7 @@ def elaborate(self, platform):
200246
i_D1=o1_inv[bit],
201247
o_Q=buf.o[bit],
202248
)
203-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
249+
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)
204250

205251
return m
206252

@@ -241,7 +287,7 @@ def elaborate(self, platform):
241287
i_D1=o1_inv[bit],
242288
o_Q=buf.o[bit],
243289
)
244-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
290+
_make_oereg_nexus(m, self.o_domain, ~self.oe, buf.t)
245291

246292
return m
247293

@@ -951,7 +997,12 @@ def get_io_buffer(self, buffer):
951997
if isinstance(buffer, io.Buffer):
952998
result = IOBuffer(buffer.direction, buffer.port)
953999
elif isinstance(buffer, io.FFBuffer):
954-
result = FFBuffer(buffer.direction, buffer.port)
1000+
if self.family in ("ecp5", "machxo2"):
1001+
result = FFBufferECP5(buffer.direction, buffer.port)
1002+
elif self.family == "nexus":
1003+
result = FFBufferNexus(buffer.direction, buffer.port)
1004+
else:
1005+
raise NotImplementedError # :nocov:
9551006
elif isinstance(buffer, io.DDRBuffer):
9561007
if self.family == "ecp5":
9571008
result = DDRBufferECP5(buffer.direction, buffer.port)

0 commit comments

Comments
 (0)