diff --git a/litex/build/efinix/common.py b/litex/build/efinix/common.py index 50d78a8d98..0e1b23d6f4 100644 --- a/litex/build/efinix/common.py +++ b/litex/build/efinix/common.py @@ -109,7 +109,7 @@ def lower(dr): # Efinix Clk Output -------------------------------------------------------------------------------- class EfinixClkOutputImpl(LiteXModule): - def __init__(self, i, o): + def __init__(self, i, o, out_clk_inv=False): assert_is_signal_or_clocksignal(i) platform = LiteXContext.platform block = { @@ -119,6 +119,7 @@ def __init__(self, i, o): "properties" : platform.get_pin_properties(o), "name" : i, "mode" : "OUTPUT_CLK", + "out_clk_inv": 1 if out_clk_inv else 0, } platform.toolchain.ifacewriter.blocks.append(block) platform.toolchain.excluded_ios.append(o) @@ -126,7 +127,7 @@ def __init__(self, i, o): class EfinixClkOutput(LiteXModule): @staticmethod def lower(dr): - return EfinixClkOutputImpl(dr.i, dr.o) + return EfinixClkOutputImpl(dr.i, dr.o, **dr.kwargs) # Efinix Tristate ---------------------------------------------------------------------------------- @@ -274,7 +275,7 @@ 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, out_clk_inv=False, in_clk_inv=False, in_clk=None): assert oe1 == oe2 assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform @@ -300,12 +301,12 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): "properties" : io_prop, "size" : 1, "in_reg" : "DDIO_RESYNC", - "in_clk_pin" : clk, + "in_clk_pin" : clk if in_clk is None else in_clk, "out_reg" : "DDIO_RESYNC", "out_clk_pin" : clk, "oe_reg" : "REG", - "in_clk_inv" : 0, - "out_clk_inv" : 0, + "in_clk_inv" : 1 if in_clk_inv else 0, + "out_clk_inv" : 1 if out_clk_inv else 0, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } platform.toolchain.ifacewriter.blocks.append(block) @@ -314,12 +315,12 @@ 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.kwargs) # Efinix SDRTristate ------------------------------------------------------------------------------- class EfinixSDRTristateImpl(LiteXModule): - def __init__(self, io, o, oe, i, clk): + def __init__(self, io, o, oe, i, clk, out_clk_inv=False, in_clk_inv=False, in_clk=None): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(io) @@ -340,12 +341,12 @@ def __init__(self, io, o, oe, i, clk): "properties" : io_prop, "size" : 1, "in_reg" : "REG", - "in_clk_pin" : clk, + "in_clk_pin" : clk if in_clk is None else in_clk, "out_reg" : "REG", "out_clk_pin" : clk, "oe_reg" : "REG", - "in_clk_inv" : 0, - "out_clk_inv" : 0, + "in_clk_inv" : 1 if in_clk_inv else 0, + "out_clk_inv" : 1 if out_clk_inv else 0, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } platform.toolchain.ifacewriter.blocks.append(block) @@ -355,12 +356,12 @@ 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.kwargs) # Efinix SDROutput --------------------------------------------------------------------------------- class EfinixSDROutputImpl(LiteXModule): - def __init__(self, i, o, clk): + def __init__(self, i, o, clk, out_clk_inv=False): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(o) @@ -378,7 +379,7 @@ def __init__(self, i, o, clk): "size" : 1, "out_reg" : "REG", "out_clk_pin" : clk, - "out_clk_inv" : 0, + "out_clk_inv" : 1 if out_clk_inv else 0, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } platform.toolchain.ifacewriter.blocks.append(block) @@ -388,12 +389,12 @@ def __init__(self, i, o, clk): class EfinixSDROutput(LiteXModule): @staticmethod def lower(dr): - return EfinixSDROutputImpl(dr.i, dr.o, dr.clk) + return EfinixSDROutputImpl(dr.i, dr.o, dr.clk, **dr.kwargs) # Efinix DDROutput --------------------------------------------------------------------------------- class EfinixDDROutputImpl(LiteXModule): - def __init__(self, i1, i2, o, clk): + def __init__(self, i1, i2, o, clk, out_clk_inv=False): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(o) @@ -413,7 +414,7 @@ def __init__(self, i1, i2, o, clk): "size" : 1, "out_reg" : "DDIO_RESYNC", "out_clk_pin" : clk, - "out_clk_inv" : 0, + "out_clk_inv" : 1 if out_clk_inv else 0, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } platform.toolchain.ifacewriter.blocks.append(block) @@ -422,12 +423,12 @@ def __init__(self, i1, i2, o, clk): class EfinixDDROutput: @staticmethod def lower(dr): - return EfinixDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk) + return EfinixDDROutputImpl(dr.i1, dr.i2, dr.o, dr.clk, **dr.kwargs) # Efinix SDRInput ---------------------------------------------------------------------------------- class EfinixSDRInputImpl(LiteXModule): - def __init__(self, i, o, clk): + def __init__(self, i, o, clk, in_clk_inv=False): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(i) @@ -444,7 +445,7 @@ def __init__(self, i, o, clk): "size" : 1, "in_reg" : "REG", "in_clk_pin" : clk, - "in_clk_inv" : 0 + "in_clk_inv" : 1 if in_clk_inv else 0, } platform.toolchain.ifacewriter.blocks.append(block) platform.toolchain.excluded_ios.append(platform.get_pin(i)) @@ -452,12 +453,12 @@ def __init__(self, i, o, clk): class EfinixSDRInput: @staticmethod def lower(dr): - return EfinixSDRInputImpl(dr.i, dr.o, dr.clk) + return EfinixSDRInputImpl(dr.i, dr.o, dr.clk, **dr.kwargs) # Efinix DDRInput ---------------------------------------------------------------------------------- class EfinixDDRInputImpl(LiteXModule): - def __init__(self, i, o1, o2, clk): + def __init__(self, i, o1, o2, clk, in_clk_inv=False): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(i) @@ -476,7 +477,7 @@ def __init__(self, i, o1, o2, clk): "size" : 1, "in_reg" : "DDIO_RESYNC", "in_clk_pin" : clk, - "in_clk_inv" : 0 + "in_clk_inv" : 1 if in_clk_inv else 0, } platform.toolchain.ifacewriter.blocks.append(block) platform.toolchain.excluded_ios.append(platform.get_pin(i)) @@ -484,7 +485,7 @@ def __init__(self, i, o1, o2, clk): class EfinixDDRInput: @staticmethod def lower(dr): - return EfinixDDRInputImpl(dr.i, dr.o1, dr.o2, dr.clk) + return EfinixDDRInputImpl(dr.i, dr.o1, dr.o2, dr.clk, **dr.kwargs) # Efinix Special Overrides ------------------------------------------------------------------------- diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py index ffae3b2d94..df8a7362fd 100644 --- a/litex/build/efinix/ifacewriter.py +++ b/litex/build/efinix/ifacewriter.py @@ -275,6 +275,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) diff --git a/litex/build/io.py b/litex/build/io.py index b83cac4780..a038f0c559 100644 --- a/litex/build/io.py +++ b/litex/build/io.py @@ -11,11 +11,12 @@ # Differential Input/Output ------------------------------------------------------------------------ class DifferentialInput(Special): - def __init__(self, i_p, i_n, o): + def __init__(self, i_p, i_n, o, **kwargs): Special.__init__(self) self.i_p = wrap(i_p) self.i_n = wrap(i_n) self.o = wrap(o) + self.kwargs = kwargs def iter_expressions(self): yield self, "i_p", SPECIAL_INPUT @@ -28,11 +29,12 @@ def lower(dr): class DifferentialOutput(Special): - def __init__(self, i, o_p, o_n): + def __init__(self, i, o_p, o_n, **kwargs): Special.__init__(self) self.i = wrap(i) self.o_p = wrap(o_p) self.o_n = wrap(o_n) + self.kwargs = kwargs def iter_expressions(self): yield self, "i" , SPECIAL_INPUT @@ -46,10 +48,11 @@ def lower(dr): # Clk Input/Output --------------------------------------------------------------------------------- class ClkInput(Special): - def __init__(self, i, o): + def __init__(self, i, o, **kwargs): Special.__init__(self) self.i = wrap(i) self.o = o if isinstance(o, str) else wrap(o) + self.kwargs = kwargs def iter_expressions(self): yield self, "i", SPECIAL_INPUT @@ -61,10 +64,11 @@ def lower(dr): class ClkOutput(Special): - def __init__(self, i, o): + def __init__(self, i, o, **kwargs): Special.__init__(self) self.i = i if isinstance(i, str) else wrap(i) self.o = wrap(o) + self.kwargs = kwargs def iter_expressions(self): yield self, "i", SPECIAL_INPUT @@ -83,7 +87,7 @@ def __init__(self, i, o, clk): self.sync.sdrio += o.eq(i) class SDRIO(Special): - def __init__(self, i, o, clk=None): + def __init__(self, i, o, clk=None, **kwargs): assert len(i) == len(o) == 1 Special.__init__(self) self.i = wrap(i) @@ -92,6 +96,7 @@ def __init__(self, i, o, clk=None): clk = ClockSignal() self.clk = wrap(clk) self.clk_domain = None if not hasattr(clk, "cd") else clk.cd + self.kwargs = kwargs def iter_expressions(self): yield self, "i" , SPECIAL_INPUT @@ -119,7 +124,7 @@ def __init__(self, io, o, oe, i, 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, **kwargs): assert len(i) == len(o) == len(oe) Special.__init__(self) self.io = wrap(io) @@ -127,6 +132,7 @@ def __init__(self, io, o, oe, i, clk=None): self.oe = wrap(oe) self.i = wrap(i) self.clk = wrap(clk) if clk is not None else ClockSignal() + self.kwargs = kwargs def iter_expressions(self): yield self, "io" , SPECIAL_INOUT @@ -142,7 +148,7 @@ def lower(dr): # DDR Input/Output --------------------------------------------------------------------------------- class DDRInput(Special): - def __init__(self, i, o1, o2, clk=None): + def __init__(self, i, o1, o2, clk=None, **kwargs): Special.__init__(self) self.i = wrap(i) self.o1 = wrap(o1) @@ -150,6 +156,7 @@ def __init__(self, i, o1, o2, clk=None): if clk is None: clk = ClockSignal() self.clk = clk if isinstance(clk, str) else wrap(clk) + self.kwargs = kwargs def iter_expressions(self): yield self, "i" , SPECIAL_INPUT @@ -163,7 +170,7 @@ def lower(dr): class DDROutput(Special): - def __init__(self, i1, i2, o, clk=None): + def __init__(self, i1, i2, o, clk=None, **kwargs): Special.__init__(self) self.i1 = wrap(i1) self.i2 = wrap(i2) @@ -171,6 +178,7 @@ def __init__(self, i1, i2, o, clk=None): if clk is None: clk = ClockSignal() self.clk = clk if isinstance(clk, str) else wrap(clk) + self.kwargs = kwargs def iter_expressions(self): yield self, "i1" , SPECIAL_INPUT @@ -195,7 +203,7 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): self.specials += Tristate(io, _o, _oe, _i) class DDRTristate(Special): - def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk=None): + def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk=None, **kwargs): Special.__init__(self) self.io = io self.o1 = o1 @@ -205,6 +213,7 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk=None): self.i1 = i1 self.i2 = i2 self.clk = clk if clk is not None else ClockSignal() + self.kwargs = kwargs def iter_expressions(self): yield self, "io" , SPECIAL_INOUT