Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: efinix: allow clk inverting and different in clk on reg tristates #2087

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions litex/build/altera/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ def lower(dr):
# Agilex5 SDRTristate ------------------------------------------------------------------------------

class Agilex5SDRTristateImpl(Module):
def __init__(self, io, o, oe, i, clk):
def __init__(self, io, o, oe, i, clk, in_clk):
_i = Signal().like(i)
_o = Signal().like(o)
_oe = Signal().like(oe)
self.specials += [
SDRIO(o, _o, clk),
SDRIO(oe, _oe, clk),
SDRIO(_i, i, clk)
SDRIO(_i, i, in_clk)
]

for j in range(len(io)):
Expand All @@ -258,7 +258,7 @@ def __init__(self, io, o, oe, i, clk):
class Agilex5SDRTristate(Module):
@staticmethod
def lower(dr):
return Agilex5SDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk)
return Agilex5SDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk, dr.in_clk)

# Agilex5 Special Overrides ------------------------------------------------------------------------

Expand Down
46 changes: 32 additions & 14 deletions litex/build/efinix/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from litex.build.generic_platform import Pins
from litex.build.efinix.efinity import EfinityToolchain

from migen.fhdl.structure import _Operator

# Colorama -----------------------------------------------------------------------------------------

try:
Expand All @@ -35,6 +37,12 @@

# Helpers ------------------------------------------------------------------------------------------

def check_clk_inverted(obj):
if isinstance(obj, _Operator):
if obj.op == "~":
return (obj.operands[0]), 1
return obj, 0

def assert_is_signal_or_clocksignal(obj):
assert isinstance(obj, (ClockSignal, Signal)), f"Object {obj} is not a ClockSignal or Signal"

Expand Down Expand Up @@ -124,6 +132,7 @@ def lower(dr):

class EfinixClkOutputImpl(LiteXModule):
def __init__(self, i, o):
i, out_clk_inv = check_clk_inverted(i)
assert_is_signal_or_clocksignal(i)
platform = LiteXContext.platform
block = {
Expand All @@ -133,6 +142,7 @@ def __init__(self, i, o):
"properties" : platform.get_pin_properties(o),
"name" : i,
"mode" : "OUTPUT_CLK",
"out_clk_inv": out_clk_inv,
}
platform.toolchain.ifacewriter.blocks.append(block)
platform.toolchain.excluded_ios.append(o)
Expand Down Expand Up @@ -293,8 +303,10 @@ def lower(dr):
# Efinix DDRTristate -------------------------------------------------------------------------------

class EfinixDDRTristateImpl(LiteXModule):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk, in_clk):
assert oe2 is None
clk, out_clk_inv = check_clk_inverted(clk)
in_clk, in_clk_inv = check_clk_inverted(in_clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(io) == 1:
Expand Down Expand Up @@ -324,12 +336,12 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk):
"properties" : io_prop,
"size" : len(io),
"in_reg" : "DDIO_RESYNC",
"in_clk_pin" : clk,
"in_clk_pin" : in_clk,
"out_reg" : "DDIO_RESYNC",
"out_clk_pin" : clk,
"oe_reg" : "REG",
"in_clk_inv" : 0,
"out_clk_inv" : 0,
"in_clk_inv" : in_clk_inv,
"out_clk_inv" : out_clk_inv,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
platform.toolchain.ifacewriter.blocks.append(block)
Expand All @@ -338,12 +350,14 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk):
class EfinixDDRTristate:
@staticmethod
def lower(dr):
return EfinixDDRTristateImpl(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk)
return EfinixDDRTristateImpl(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk, dr.in_clk)

# Efinix SDRTristate -------------------------------------------------------------------------------

class EfinixSDRTristateImpl(LiteXModule):
def __init__(self, io, o, oe, i, clk):
def __init__(self, io, o, oe, i, clk, in_clk):
clk, out_clk_inv = check_clk_inverted(clk)
in_clk, in_clk_inv = check_clk_inverted(in_clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(io) == 1:
Expand Down Expand Up @@ -373,13 +387,13 @@ def __init__(self, io, o, oe, i, clk):
"properties" : io_prop,
"size" : len(io),
"in_reg" : "REG",
"in_clk_pin" : clk,
"in_clk_pin" : in_clk,
"out_reg" : "REG",
"out_clk_pin" : clk,
"const_output" : const_output,
"oe_reg" : "REG",
"in_clk_inv" : 0,
"out_clk_inv" : 0,
"in_clk_inv" : in_clk_inv,
"out_clk_inv" : out_clk_inv,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
platform.toolchain.ifacewriter.blocks.append(block)
Expand All @@ -389,12 +403,13 @@ def __init__(self, io, o, oe, i, clk):
class EfinixSDRTristate(LiteXModule):
@staticmethod
def lower(dr):
return EfinixSDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk)
return EfinixSDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk, dr.in_clk)

# Efinix SDROutput ---------------------------------------------------------------------------------

class EfinixSDROutputImpl(LiteXModule):
def __init__(self, i, o, clk):
clk, out_clk_inv = check_clk_inverted(clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(o) == 1:
Expand Down Expand Up @@ -422,7 +437,7 @@ def __init__(self, i, o, clk):
"out_reg" : "REG",
"out_clk_pin" : clk,
"const_output" : const_output,
"out_clk_inv" : 0,
"out_clk_inv" : out_clk_inv,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
platform.toolchain.ifacewriter.blocks.append(block)
Expand All @@ -438,6 +453,7 @@ def lower(dr):

class EfinixDDROutputImpl(LiteXModule):
def __init__(self, i1, i2, o, clk):
clk, out_clk_inv = check_clk_inverted(clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(o) == 1:
Expand All @@ -462,7 +478,7 @@ def __init__(self, i1, i2, o, clk):
"size" : len(o),
"out_reg" : "DDIO_RESYNC",
"out_clk_pin" : clk,
"out_clk_inv" : 0,
"out_clk_inv" : out_clk_inv,
"drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4")
}
platform.toolchain.ifacewriter.blocks.append(block)
Expand All @@ -477,6 +493,7 @@ def lower(dr):

class EfinixSDRInputImpl(LiteXModule):
def __init__(self, i, o, clk):
clk, in_clk_inv = check_clk_inverted(clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(i) == 1:
Expand All @@ -498,7 +515,7 @@ def __init__(self, i, o, clk):
"size" : len(i),
"in_reg" : "REG",
"in_clk_pin" : clk,
"in_clk_inv" : 0
"in_clk_inv" : in_clk_inv,
}
platform.toolchain.ifacewriter.blocks.append(block)
platform.toolchain.excluded_ios.append(platform.get_pin(i))
Expand All @@ -512,6 +529,7 @@ def lower(dr):

class EfinixDDRInputImpl(LiteXModule):
def __init__(self, i, o1, o2, clk):
clk, in_clk_inv = check_clk_inverted(clk)
assert_is_signal_or_clocksignal(clk)
platform = LiteXContext.platform
if len(i) == 1:
Expand All @@ -535,7 +553,7 @@ def __init__(self, i, o1, o2, clk):
"size" : len(i),
"in_reg" : "DDIO_RESYNC",
"in_clk_pin" : clk,
"in_clk_inv" : 0
"in_clk_inv" : in_clk_inv,
}
platform.toolchain.ifacewriter.blocks.append(block)
platform.toolchain.excluded_ios.append(platform.get_pin(i))
Expand Down
2 changes: 2 additions & 0 deletions litex/build/efinix/ifacewriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ def generate_gpio(self, block, verbose=True):
cmd += 'design.create_clockout_gpio("{}")\n'.format(name)
cmd += 'design.set_property("{}","OUT_CLK_PIN","{}")\n'.format(name, name)
cmd += 'design.assign_pkg_pin("{}","{}")\n\n'.format(name, block["location"])
if "out_clk_inv" in block:
cmd += f'design.set_property("{name}","IS_OUTCLK_INVERTED","{block["out_clk_inv"]}")\n'
if prop:
for p, val in prop:
cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val)
Expand Down
6 changes: 3 additions & 3 deletions litex/build/gowin/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ def lower(dr):
# Gw5A SDRTristate ---------------------------------------------------------------------------------

class Gw5ASDRTristateImpl(Module):
def __init__(self, io, o, oe, i, clk):
def __init__(self, io, o, oe, i, clk, in_clk):
_o = Signal().like(o)
_oe_n = Signal().like(oe)
_i = Signal().like(i)
self.specials += [
SDROutput(o, _o, clk),
SDROutput(~oe, _oe_n, clk),
SDRInput(_i, i, clk),
SDRInput(_i, i, in_clk),
]
for j in range(len(io)):
self.specials += Instance("IOBUF",
Expand All @@ -188,7 +188,7 @@ def __init__(self, io, o, oe, i, clk):
class Gw5ASDRTristate:
@staticmethod
def lower(dr):
return Gw5ASDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk)
return Gw5ASDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk, dr.in_clk)

# Gw5A Special Overrides ---------------------------------------------------------------------------

Expand Down
20 changes: 12 additions & 8 deletions litex/build/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,24 @@ class SDROutput(SDRIO): pass
# SDR Tristate -------------------------------------------------------------------------------------

class InferedSDRTristate(Module):
def __init__(self, io, o, oe, i, clk):
def __init__(self, io, o, oe, i, clk, in_clk):
_o = Signal().like(o)
_oe = Signal().like(oe)
_i = Signal().like(i)
self.specials += SDROutput(o, _o, clk)
self.specials += SDRInput(_i, i, clk)
self.specials += SDRInput(_i, i, in_clk)
self.submodules += InferedSDRIO(oe, _oe, clk)
self.specials += Tristate(io, _o, _oe, _i)

class SDRTristate(Special):
def __init__(self, io, o, oe, i, clk=None):
def __init__(self, io, o, oe, i, clk=None, in_clk=None):
Special.__init__(self)
self.io = wrap(io)
self.o = wrap(o)
self.oe = wrap(oe)
self.i = wrap(i)
self.clk = wrap(clk) if clk is not None else ClockSignal()
self.in_clk = wrap(in_clk) if in_clk is not None else self.clk
assert len(self.i) == len(self.o) == len(self.oe)

def iter_expressions(self):
Expand All @@ -133,10 +134,11 @@ def iter_expressions(self):
yield self, "oe" , SPECIAL_INPUT
yield self, "i" , SPECIAL_OUTPUT
yield self, "clk", SPECIAL_INPUT
yield self, "in_clk", SPECIAL_INPUT

@staticmethod
def lower(dr):
return InferedSDRTristate(dr.io, dr.o, dr.oe, dr.i, dr.clk)
return InferedSDRTristate(dr.io, dr.o, dr.oe, dr.i, dr.clk, dr.in_clk)

# DDR Input/Output ---------------------------------------------------------------------------------

Expand Down Expand Up @@ -184,17 +186,17 @@ def lower(dr):
# DDR Tristate -------------------------------------------------------------------------------------

class InferedDDRTristate(Module):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk, in_clk):
_o = Signal().like(o1)
_oe = Signal().like(oe1)
_i = Signal().like(i1)
self.specials += DDROutput(o1, o2, _o, clk)
self.specials += DDROutput(oe1, oe2, _oe, clk) if oe2 is not None else SDROutput(oe1, _oe, clk)
self.specials += DDRInput(_i, i1, i2, clk)
self.specials += DDRInput(_i, i1, i2, in_clk)
self.specials += Tristate(io, _o, _oe, _i)

class DDRTristate(Special):
def __init__(self, io, o1, o2, oe1, oe2=None, i1=None, i2=None, clk=None):
def __init__(self, io, o1, o2, oe1, oe2=None, i1=None, i2=None, clk=None, in_clk=None):
Special.__init__(self)
self.io = io
self.o1 = o1
Expand All @@ -204,6 +206,7 @@ def __init__(self, io, o1, o2, oe1, oe2=None, i1=None, i2=None, clk=None):
self.i1 = i1 if i1 is not None else Signal()
self.i2 = i2 if i2 is not None else Signal()
self.clk = clk if clk is not None else ClockSignal()
self.in_clk = in_clk if in_clk is not None else self.clk

def iter_expressions(self):
yield self, "io" , SPECIAL_INOUT
Expand All @@ -214,10 +217,11 @@ def iter_expressions(self):
yield self, "i1" , SPECIAL_OUTPUT
yield self, "i2" , SPECIAL_OUTPUT
yield self, "clk", SPECIAL_INPUT
yield self, "in_clk", SPECIAL_INPUT

@staticmethod
def lower(dr):
return InferedDDRTristate(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk)
return InferedDDRTristate(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk, dr.in_clk)

# Clock Reset Generator ----------------------------------------------------------------------------

Expand Down
12 changes: 6 additions & 6 deletions litex/build/lattice/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,21 +332,21 @@ def lower(dr):
# NX DDR Tristate ----------------------------------------------------------------------------------

class LatticeNXDDRTristateImpl(Module):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk):
def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk, in_clk):
assert oe2 is None
_o = Signal().like(o1)
_oe = Signal().like(oe1)
_i = Signal().like(i1)
self.specials += DDROutput(o1, o2, _o, clk)
self.specials += SDROutput(oe1, _oe, clk)
self.specials += DDRInput(_i, i1, i2, clk)
self.specials += DDRInput(_i, i1, i2, in_clk)
self.specials += Tristate(io, _o, _oe, _i)
_oe.attr.add("syn_useioff")

class LatticeNXDDRTristate:
@staticmethod
def lower(dr):
return LatticeNXDDRTristateImpl(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk)
return LatticeNXDDRTristateImpl(dr.io, dr.o1, dr.o2, dr.oe1, dr.oe2, dr.i1, dr.i2, dr.clk, dr.in_clk)

# NX Special Overrides -----------------------------------------------------------------------------

Expand Down Expand Up @@ -533,12 +533,12 @@ def lower(dr):
# iCE40 SDR Tristate -------------------------------------------------------------------------------

class LatticeiCE40SDRTristateImpl(Module):
def __init__(self, io, o, oe, i, clk):
def __init__(self, io, o, oe, i, clk, in_clk):
for j in range(len(io)):
self.specials += Instance("SB_IO",
p_PIN_TYPE = C(0b110100, 6), # PIN_OUTPUT_REGISTERED_ENABLE_REGISTERED + PIN_INPUT_REGISTERED
io_PACKAGE_PIN = io[j],
i_INPUT_CLK = clk,
i_INPUT_CLK = in_clk,
i_OUTPUT_CLK = clk,
i_OUTPUT_ENABLE = oe[j],
i_D_OUT_0 = o[j] ,
Expand All @@ -548,7 +548,7 @@ def __init__(self, io, o, oe, i, clk):
class LatticeiCE40SDRTristate(Module):
@staticmethod
def lower(dr):
return LatticeiCE40SDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk)
return LatticeiCE40SDRTristateImpl(dr.io, dr.o, dr.oe, dr.i, dr.clk, dr.in_clk)

# iCE40 Trellis Special Overrides ------------------------------------------------------------------

Expand Down
Loading