Skip to content

Commit f17e5ee

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

File tree

1 file changed

+56
-7
lines changed

1 file changed

+56
-7
lines changed

amaranth/vendor/_lattice.py

+56-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),
@@ -87,8 +87,18 @@ def _make_oereg(m, domain, oe, q):
8787
o_Q=q[bit],
8888
)
8989

90+
def _make_oereg_nexus(m, domain, oe, q):
91+
for bit in range(len(q)):
92+
m.submodules[f"oe_ff{bit}"] = Instance("OFD1P3DX",
93+
i_CK=ClockSignal(domain),
94+
i_SP=Const(1),
95+
i_CD=Const(0),
96+
i_D=oe,
97+
o_Q=q[bit],
98+
)
99+
90100

91-
class FFBuffer(io.FFBuffer):
101+
class FFBufferECP5(io.FFBuffer):
92102
def elaborate(self, platform):
93103
m = Module()
94104

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

123167
return m
124168

@@ -159,7 +203,7 @@ def elaborate(self, platform):
159203
i_D1=o1_inv[bit],
160204
o_Q=buf.o[bit],
161205
)
162-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
206+
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)
163207

164208
return m
165209

@@ -200,7 +244,7 @@ def elaborate(self, platform):
200244
i_D1=o1_inv[bit],
201245
o_Q=buf.o[bit],
202246
)
203-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
247+
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)
204248

205249
return m
206250

@@ -241,7 +285,7 @@ def elaborate(self, platform):
241285
i_D1=o1_inv[bit],
242286
o_Q=buf.o[bit],
243287
)
244-
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
288+
_make_oereg_nexus(m, self.o_domain, ~self.oe, buf.t)
245289

246290
return m
247291

@@ -951,7 +995,12 @@ def get_io_buffer(self, buffer):
951995
if isinstance(buffer, io.Buffer):
952996
result = IOBuffer(buffer.direction, buffer.port)
953997
elif isinstance(buffer, io.FFBuffer):
954-
result = FFBuffer(buffer.direction, buffer.port)
998+
if self.family in ("ecp5", "machxo2"):
999+
result = FFBufferECP5(buffer.direction, buffer.port)
1000+
elif self.family == "nexus":
1001+
result = FFBufferNexus(buffer.direction, buffer.port)
1002+
else:
1003+
raise NotImplementedError # :nocov:
9551004
elif isinstance(buffer, io.DDRBuffer):
9561005
if self.family == "ecp5":
9571006
result = DDRBufferECP5(buffer.direction, buffer.port)

0 commit comments

Comments
 (0)