Skip to content

Commit

Permalink
vendor._lattice: OFS1P3DX -> OFD1P3DX and IFS1P3DX -> IFD1P3DX for nexus
Browse files Browse the repository at this point in the history
More specialized buffers required
  • Loading branch information
richardeoin authored and whitequark committed May 4, 2024
1 parent 79d9f5e commit 653a51b
Showing 1 changed file with 58 additions and 7 deletions.
65 changes: 58 additions & 7 deletions amaranth/vendor/_lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def elaborate(self, platform):
return m


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


class FFBuffer(io.FFBuffer):
def _make_oereg_nexus(m, domain, oe, q):
for bit in range(len(q)):
m.submodules[f"oe_ff{bit}"] = Instance("OFD1P3DX",
i_CK=ClockSignal(domain),
i_SP=Const(1),
i_CD=Const(0),
i_D=oe,
o_Q=q[bit],
)


class FFBufferECP5(io.FFBuffer):
def elaborate(self, platform):
m = Module()

Expand Down Expand Up @@ -118,7 +129,42 @@ def elaborate(self, platform):
i_D=o_inv[bit],
o_Q=buf.o[bit],
)
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)

return m


class FFBufferNexus(io.FFBuffer):
def elaborate(self, platform):
m = Module()

m.submodules.buf = buf = InnerBuffer(self.direction, self.port)
inv_mask = sum(inv << bit for bit, inv in enumerate(self.port.invert))

if self.direction is not io.Direction.Output:
i_inv = Signal.like(self.i)
for bit in range(len(self.port)):
m.submodules[f"i_ff{bit}"] = Instance("IFD1P3DX",
i_CK=ClockSignal(self.i_domain),
i_SP=Const(1),
i_CD=Const(0),
i_D=buf.i[bit],
o_Q=i_inv[bit],
)
m.d.comb += self.i.eq(i_inv ^ inv_mask)

if self.direction is not io.Direction.Input:
o_inv = Signal.like(self.o)
m.d.comb += o_inv.eq(self.o ^ inv_mask)
for bit in range(len(self.port)):
m.submodules[f"o_ff{bit}"] = Instance("OFD1P3DX",
i_CK=ClockSignal(self.o_domain),
i_SP=Const(1),
i_CD=Const(0),
i_D=o_inv[bit],
o_Q=buf.o[bit],
)
_make_oereg_nexus(m, self.o_domain, ~self.oe, buf.t)

return m

Expand Down Expand Up @@ -159,7 +205,7 @@ def elaborate(self, platform):
i_D1=o1_inv[bit],
o_Q=buf.o[bit],
)
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)

return m

Expand Down Expand Up @@ -200,7 +246,7 @@ def elaborate(self, platform):
i_D1=o1_inv[bit],
o_Q=buf.o[bit],
)
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
_make_oereg_ecp5_machxo2(m, self.o_domain, ~self.oe, buf.t)

return m

Expand Down Expand Up @@ -241,7 +287,7 @@ def elaborate(self, platform):
i_D1=o1_inv[bit],
o_Q=buf.o[bit],
)
_make_oereg(m, self.o_domain, ~self.oe, buf.t)
_make_oereg_nexus(m, self.o_domain, ~self.oe, buf.t)

return m

Expand Down Expand Up @@ -951,7 +997,12 @@ def get_io_buffer(self, buffer):
if isinstance(buffer, io.Buffer):
result = IOBuffer(buffer.direction, buffer.port)
elif isinstance(buffer, io.FFBuffer):
result = FFBuffer(buffer.direction, buffer.port)
if self.family in ("ecp5", "machxo2"):
result = FFBufferECP5(buffer.direction, buffer.port)
elif self.family == "nexus":
result = FFBufferNexus(buffer.direction, buffer.port)
else:
raise NotImplementedError # :nocov:
elif isinstance(buffer, io.DDRBuffer):
if self.family == "ecp5":
result = DDRBufferECP5(buffer.direction, buffer.port)
Expand Down

0 comments on commit 653a51b

Please sign in to comment.