diff --git a/litex/build/altera/common.py b/litex/build/altera/common.py index f5491f7930..5ae5b6ba05 100644 --- a/litex/build/altera/common.py +++ b/litex/build/altera/common.py @@ -91,13 +91,14 @@ def lower(dr): class AlteraDDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ALTDDIO_OUT", - p_WIDTH = 1, - i_outclock = clk, - i_datain_h = i1, - i_datain_l = i2, - o_dataout = o, - ) + for j in range(len(o)): + self.specials += Instance("ALTDDIO_OUT", + p_WIDTH = 1, + i_outclock = clk, + i_datain_h = i1[j] if len(i1) > 1 else i1, + i_datain_l = i2[j] if len(i2) > 1 else i2, + o_dataout = o[j] if len(o) > 1 else o, + ) class AlteraDDROutput: @staticmethod @@ -108,13 +109,14 @@ def lower(dr): class AlteraDDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("ALTDDIO_IN", - p_WIDTH = 1, - i_inclock = clk, - i_datain = i, - o_dataout_h = o1, - o_dataout_l = o2 - ) + for j in range(len(i)): + self.specials += Instance("ALTDDIO_IN", + p_WIDTH = 1, + i_inclock = clk, + i_datain = i[j] if len(i) > 1 else i, + o_dataout_h = o1[j] if len(o1) > 1 else o1, + o_dataout_l = o2[j] if len(o2) > 1 else o2, + ) class AlteraDDRInput: @staticmethod @@ -169,18 +171,19 @@ def lower(dr): class Agilex5DDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("tennm_ph2_ddio_out", - p_mode = "MODE_DDR", - p_asclr_ena = "ASCLR_ENA_NONE", - p_sclr_ena = "SCLR_ENA_NONE", - o_dataout = o, - i_datainlo = i2, - i_datainhi = i1, - i_clk = clk, - i_ena = Constant(1, 1), - i_areset = Constant(1, 1), - i_sreset = Constant(1, 1), - ) + for j in range(len(o)): + self.specials += Instance("tennm_ph2_ddio_out", + p_mode = "MODE_DDR", + p_asclr_ena = "ASCLR_ENA_NONE", + p_sclr_ena = "SCLR_ENA_NONE", + o_dataout = o[j] if len(o) > 1 else o, + i_datainlo = i2[j] if len(i2) > 1 else i2, + i_datainhi = i1[j] if len(i1) > 1 else i1, + i_clk = clk, + i_ena = Constant(1, 1), + i_areset = Constant(1, 1), + i_sreset = Constant(1, 1), + ) class Agilex5DDROutput: @staticmethod @@ -191,18 +194,19 @@ def lower(dr): class Agilex5DDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("tennm_ph2_ddio_in", - p_mode = "MODE_DDR", - p_asclr_ena = "ASCLR_ENA_NONE", - p_sclr_ena = "SCLR_ENA_NONE", - i_clk = clk, - i_datain = i, - o_regouthi = o1, - o_regoutlo = o2, - i_ena = Constant(1, 1), - i_areset = Constant(1, 1), - i_sreset = Constant(1, 1), - ) + for j in range(len(i)): + self.specials += Instance("tennm_ph2_ddio_in", + p_mode = "MODE_DDR", + p_asclr_ena = "ASCLR_ENA_NONE", + p_sclr_ena = "SCLR_ENA_NONE", + i_clk = clk, + i_datain = i[j] if len(i) > 1 else i, + o_regouthi = o1[j] if len(o1) > 1 else o1, + o_regoutlo = o2[j] if len(o2) > 1 else o2, + i_ena = Constant(1, 1), + i_areset = Constant(1, 1), + i_sreset = Constant(1, 1), + ) class Agilex5DDRInput: @staticmethod @@ -227,25 +231,29 @@ def lower(dr): class Agilex5SDRTristateImpl(Module): def __init__(self, io, o, oe, i, clk): - _i = Signal() - _o = Signal() - _oe = Signal() + _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), - Instance("tennm_ph2_io_ibuf", - p_bus_hold = "BUS_HOLD_OFF", - io_i = io, # FIXME: its an input but io is needed to have correct dir at top module - o_o = _i, - ), - Instance("tennm_ph2_io_obuf", - p_open_drain = "OPEN_DRAIN_OFF", - i_i = _o, - i_oe = _oe, - io_o = io, # FIXME: its an output but io is needed to have correct dir at top module - ), + SDRIO(_i, i, clk) ] + + for j in range(len(io)): + self.specials += [ + Instance("tennm_ph2_io_ibuf", + p_bus_hold = "BUS_HOLD_OFF", + io_i = io[j] if len(io) > 1 else io , # FIXME: its an input but io is needed to have correct dir at top module + o_o = _i[j] if len(_i) > 1 else _i, + ), + Instance("tennm_ph2_io_obuf", + p_open_drain = "OPEN_DRAIN_OFF", + i_i = _o[j] if len(_o) > 1 else _o, + i_oe = _oe[j] if len(_oe) > 1 else _oe, + io_o = io[j] if len(io) > 1 else io, # FIXME: its an output but io is needed to have correct dir at top module + ), + ] class Agilex5SDRTristate(Module): @staticmethod diff --git a/litex/build/colognechip/common.py b/litex/build/colognechip/common.py index 54955c33a7..08c6659cb6 100644 --- a/litex/build/colognechip/common.py +++ b/litex/build/colognechip/common.py @@ -46,30 +46,32 @@ def lower(dr): class CologneChipDDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("CC_IDDR", - i_CLK = clk, - i_D = i, - o_Q0 = o1, - o_Q1 = o2, - ) + for j in range(len(i)): + self.specials += Instance("CC_IDDR", + i_CLK = clk, + i_D = i[j] if len(i) > 1 else i, + o_Q0 = o1[j] if len(o1) > 1 else o1, + o_Q1 = o2[j] if len(o2) > 1 else o2, + ) class CologneChipDDRInput: @staticmethod def lower(dr): - return CologneChipInputImpl(dr.i, dr.o1, dr.o2, dr.clk) + return CologneChipDDRInputImpl(dr.i, dr.o1, dr.o2, dr.clk) # CologneChip DDR Output --------------------------------------------------------------------------- class CologneChipDDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("CC_ODDR", - p_CLK_INV = 0, - i_CLK = clk, - i_DDR = ~clk, - i_D0 = i1, - i_D1 = i2, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("CC_ODDR", + p_CLK_INV = 0, + i_CLK = clk, + i_DDR = ~clk, + i_D0 = i1[j] if len(i1) > 1 else i1, + i_D1 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o, + ) class CologneChipDDROutput: @staticmethod @@ -110,10 +112,11 @@ def lower(dr): class CologneChipSDRInputImpl(Module): def __init__(self, i, o): - self.specials += Instance("CC_IBUF", - i_I = i, - o_O = o, - ) + for j in range(len(i)): + self.specials += Instance("CC_IBUF", + i_I = i[j] if len(i) > 1 else i, + o_O = o[j] if len(o) > 1 else o, + ) class CologneChipSDRInput: @staticmethod diff --git a/litex/build/efinix/common.py b/litex/build/efinix/common.py index ca9b73d997..77ae00bd36 100644 --- a/litex/build/efinix/common.py +++ b/litex/build/efinix/common.py @@ -297,15 +297,20 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): assert oe2 is None assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(io) - io_pad = platform.get_pin_location(io) - io_prop = platform.get_pin_properties(io) + if len(io) == 1: + io_name = platform.get_pin_name(io) + io_pad = platform.get_pin_location(io) + io_prop = platform.get_pin_properties(io) + else: + io_name = platform.get_pins_name(io) + io_pad = platform.get_pins_location(io) + io_prop = platform.get_pin_properties(io[0]) io_prop_dict = dict(io_prop) - io_data_i_h = platform.add_iface_io(io_name + "_OUT_HI") - io_data_i_l = platform.add_iface_io(io_name + "_OUT_LO") - io_data_o_h = platform.add_iface_io(io_name + "_IN_HI") - io_data_o_l = platform.add_iface_io(io_name + "_IN_LO") - io_data_e = platform.add_iface_io(io_name + "_OE") + io_data_i_h = platform.add_iface_io(io_name + "_OUT_HI", len(io)) + io_data_i_l = platform.add_iface_io(io_name + "_OUT_LO", len(io)) + io_data_o_h = platform.add_iface_io(io_name + "_IN_HI", len(io)) + io_data_o_l = platform.add_iface_io(io_name + "_IN_LO", len(io)) + io_data_e = platform.add_iface_io(io_name + "_OE", len(io)) self.comb += io_data_i_h.eq(o1) self.comb += io_data_i_l.eq(o2) self.comb += io_data_e.eq(oe1) @@ -317,7 +322,7 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(io), "in_reg" : "DDIO_RESYNC", "in_clk_pin" : clk, "out_reg" : "DDIO_RESYNC", @@ -341,18 +346,23 @@ class EfinixSDRTristateImpl(LiteXModule): def __init__(self, io, o, oe, i, clk): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(io) - io_pad = platform.get_pin_location(io) - io_prop = platform.get_pin_properties(io) + if len(io) == 1: + io_name = platform.get_pin_name(io) + io_pad = platform.get_pin_location(io) + io_prop = platform.get_pin_properties(io) + else: + io_name = platform.get_pins_name(io) + io_pad = platform.get_pins_location(io) + io_prop = platform.get_pin_properties(io[0]) io_prop_dict = dict(io_prop) if isinstance(o, Constant): const_output = const_output_calc(o, io) else: const_output = "NONE" - io_data_i = platform.add_iface_io(io_name + "_OUT") + io_data_i = platform.add_iface_io(io_name + "_OUT", len(io)) self.comb += io_data_i.eq(o) - io_data_o = platform.add_iface_io(io_name + "_IN") - io_data_e = platform.add_iface_io(io_name + "_OE") + io_data_o = platform.add_iface_io(io_name + "_IN", len(io)) + io_data_e = platform.add_iface_io(io_name + "_OE", len(io)) self.comb += io_data_e.eq(oe) self.comb += i.eq(io_data_o) block = { @@ -361,7 +371,7 @@ def __init__(self, io, o, oe, i, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(io), "in_reg" : "REG", "in_clk_pin" : clk, "out_reg" : "REG", @@ -387,15 +397,20 @@ class EfinixSDROutputImpl(LiteXModule): def __init__(self, i, o, clk): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(o) - io_pad = platform.get_pin_location(o) - io_prop = platform.get_pin_properties(o) + if len(o) == 1: + io_name = platform.get_pin_name(o) + io_pad = platform.get_pin_location(o) + io_prop = platform.get_pin_properties(o) + else: + io_name = platform.get_pins_name(o) + io_pad = platform.get_pins_location(o) + io_prop = platform.get_pin_properties(o[0]) io_prop_dict = dict(io_prop) if isinstance(i, Constant): const_output = const_output_calc(i, o) else: const_output = "NONE" - io_data_i = platform.add_iface_io(io_name) + io_data_i = platform.add_iface_io(io_name, len(o)) self.comb += io_data_i.eq(i) block = { "type" : "GPIO", @@ -403,7 +418,7 @@ def __init__(self, i, o, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(o), "out_reg" : "REG", "out_clk_pin" : clk, "const_output" : const_output, @@ -425,12 +440,17 @@ class EfinixDDROutputImpl(LiteXModule): def __init__(self, i1, i2, o, clk): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(o) - io_pad = platform.get_pin_location(o) - io_prop = platform.get_pin_properties(o) + if len(o) == 1: + io_name = platform.get_pin_name(o) + io_pad = platform.get_pin_location(o) + io_prop = platform.get_pin_properties(o) + else: + io_name = platform.get_pins_name(o) + io_pad = platform.get_pins_location(o) + io_prop = platform.get_pin_properties(o[0]) io_prop_dict = dict(io_prop) - io_data_h = platform.add_iface_io(io_name + "_HI") - io_data_l = platform.add_iface_io(io_name + "_LO") + io_data_h = platform.add_iface_io(io_name + "_HI", len(o)) + io_data_l = platform.add_iface_io(io_name + "_LO", len(o)) self.comb += io_data_h.eq(i1) self.comb += io_data_l.eq(i2) block = { @@ -439,7 +459,7 @@ def __init__(self, i1, i2, o, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(o), "out_reg" : "DDIO_RESYNC", "out_clk_pin" : clk, "out_clk_inv" : 0, @@ -459,10 +479,15 @@ class EfinixSDRInputImpl(LiteXModule): def __init__(self, i, o, clk): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(i) - io_pad = platform.get_pin_location(i) - io_prop = platform.get_pin_properties(i) - io_data = platform.add_iface_io(io_name) + if len(i) == 1: + io_name = platform.get_pin_name(i) + io_pad = platform.get_pin_location(i) + io_prop = platform.get_pin_properties(i) + else: + io_name = platform.get_pins_name(i) + io_pad = platform.get_pins_location(i) + io_prop = platform.get_pin_properties(i[0]) + io_data = platform.add_iface_io(io_name, len(i)) self.comb += o.eq(io_data) block = { "type" : "GPIO", @@ -470,7 +495,7 @@ def __init__(self, i, o, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(i), "in_reg" : "REG", "in_clk_pin" : clk, "in_clk_inv" : 0 @@ -489,11 +514,16 @@ class EfinixDDRInputImpl(LiteXModule): def __init__(self, i, o1, o2, clk): assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform - io_name = platform.get_pin_name(i) - io_pad = platform.get_pin_location(i) - io_prop = platform.get_pin_properties(i) - io_data_h = platform.add_iface_io(io_name + "_HI") - io_data_l = platform.add_iface_io(io_name + "_LO") + if len(i) == 1: + io_name = platform.get_pin_name(i) + io_pad = platform.get_pin_location(i) + io_prop = platform.get_pin_properties(i) + else: + io_name = platform.get_pins_name(i) + io_pad = platform.get_pins_location(i) + io_prop = platform.get_pin_properties(i[0]) + io_data_h = platform.add_iface_io(io_name + "_HI", len(i)) + io_data_l = platform.add_iface_io(io_name + "_LO", len(i)) self.comb += o1.eq(io_data_h) self.comb += o2.eq(io_data_l) block = { @@ -502,7 +532,7 @@ def __init__(self, i, o1, o2, clk): "name" : io_name, "location" : io_pad, "properties" : io_prop, - "size" : 1, + "size" : len(i), "in_reg" : "DDIO_RESYNC", "in_clk_pin" : clk, "in_clk_inv" : 0 diff --git a/litex/build/gowin/common.py b/litex/build/gowin/common.py index 6dd7ff0817..55a3460cfa 100644 --- a/litex/build/gowin/common.py +++ b/litex/build/gowin/common.py @@ -132,13 +132,14 @@ def lower(dr): class Gw5ASDROutputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("DFFSE", - i_D = i, - o_Q = o, - i_CLK = clk, - i_SET = Constant(0,1), - i_CE = Constant(1,1), - ) + for j in range(len(o)): + self.specials += Instance("DFFSE", + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + i_CLK = clk, + i_SET = Constant(0,1), + i_CE = Constant(1,1), + ) class Gw5ASDROutput: @staticmethod @@ -149,13 +150,14 @@ def lower(dr): class Gw5ASDRInputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("DFFSE", - i_D = i, - o_Q = o, - i_CLK = clk, - i_SET = Constant(0,1), - i_CE = Constant(1,1), - ) + for j in range(len(i)): + self.specials += Instance("DFFSE", + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + i_CLK = clk, + i_SET = Constant(0,1), + i_CE = Constant(1,1), + ) class Gw5ASDRInput: @staticmethod @@ -166,20 +168,22 @@ def lower(dr): class Gw5ASDRTristateImpl(Module): def __init__(self, io, o, oe, i, clk): - _o = Signal() - _oe_n = Signal() - _i = Signal() + _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), - Instance("IOBUF", - io_IO = io, - o_O = _i, - i_I = _o, - i_OEN = _oe_n, - ), ] + for j in range(len(io)): + self.specials += Instance("IOBUF", + io_IO = io[j] if len(io) > 1 else io, + o_O = _i[j] if len(_i) > 1 else _i, + i_I = _o[j] if len(_o) > 1 else _o, + i_OEN = _oe_n[j] if len(_oe_n) > 1 else _oe_n, + ) + class Gw5ASDRTristate: @staticmethod diff --git a/litex/build/io.py b/litex/build/io.py index 9c593795ea..6559cd2d4c 100644 --- a/litex/build/io.py +++ b/litex/build/io.py @@ -84,7 +84,6 @@ def __init__(self, i, o, clk): class SDRIO(Special): def __init__(self, i, o, clk=None): - assert len(i) == len(o) == 1 Special.__init__(self) self.i = wrap(i) self.o = wrap(o) @@ -92,6 +91,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 + assert len(self.i) == len(self.o) def iter_expressions(self): yield self, "i" , SPECIAL_INPUT @@ -102,7 +102,6 @@ def iter_expressions(self): def lower(dr): return InferedSDRIO(dr.i, dr.o, dr.clk) - class SDRInput(SDRIO): pass class SDROutput(SDRIO): pass @@ -110,9 +109,9 @@ class SDROutput(SDRIO): pass class InferedSDRTristate(Module): def __init__(self, io, o, oe, i, clk): - _o = Signal() - _oe = Signal() - _i = Signal() + _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.submodules += InferedSDRIO(oe, _oe, clk) @@ -186,9 +185,9 @@ def lower(dr): class InferedDDRTristate(Module): def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): - _o = Signal() - _oe = Signal() - _i = Signal() + _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) diff --git a/litex/build/lattice/common.py b/litex/build/lattice/common.py index 28bf247ad4..76c77cf897 100644 --- a/litex/build/lattice/common.py +++ b/litex/build/lattice/common.py @@ -45,13 +45,14 @@ def lower(dr): class LatticeECP5SDRInputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("IFS1P3BX", - i_SCLK = clk, - i_PD = 0, - i_SP = 1, - i_D = i, - o_Q = o, - ) + for j in range(len(i)): + self.specials += Instance("IFS1P3BX", + i_SCLK = clk, + i_PD = 0, + i_SP = 1, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeECP5SDRInput: @staticmethod @@ -62,13 +63,14 @@ def lower(dr): class LatticeECP5SDROutputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("OFS1P3BX", - i_SCLK = clk, - i_PD = 0, - i_SP = 1, - i_D = i, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("OFS1P3BX", + i_SCLK = clk, + i_PD = 0, + i_SP = 1, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeECP5SDROutput: @staticmethod @@ -79,12 +81,13 @@ def lower(dr): class LatticeECP5DDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("IDDRX1F", - i_SCLK = clk, - i_D = i, - o_Q0 = o1, - o_Q1 = o2, - ) + for j in range(len(i)): + self.specials += Instance("IDDRX1F", + i_SCLK = clk, + i_D = i[j] if len(i) > 1 else i, + o_Q0 = o1[j] if len(o1) > 1 else o1, + o_Q1 = o2[j] if len(o2) > 1 else o2, + ) class LatticeECP5DDRInput: @staticmethod @@ -95,12 +98,13 @@ def lower(dr): class LatticeECP5DDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDRX1F", - i_SCLK = clk, - i_D0 = i1, - i_D1 = i2, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("ODDRX1F", + i_SCLK = clk, + i_D0 = i1[j] if len(i1) > 1 else i1, + i_D1 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeECP5DDROutput: @staticmethod @@ -233,13 +237,14 @@ def lower(dr): class LatticeNXSDRInputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("IFD1P3BX", - i_CK = clk, - i_PD = 0, - i_SP = 1, - i_D = i, - o_Q = o, - ) + for j in range(len(i)): + self.specials += Instance("IFD1P3BX", + i_CK = clk, + i_PD = 0, + i_SP = 1, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeNXSDRInput: @staticmethod @@ -250,13 +255,14 @@ def lower(dr): class LatticeNXSDROutputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("OFD1P3BX", - i_CK = clk, - i_PD = 0, - i_SP = 1, - i_D = i, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("OFD1P3BX", + i_CK = clk, + i_PD = 0, + i_SP = 1, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeNXSDROutput: @staticmethod @@ -270,13 +276,14 @@ def lower(dr): class LatticeNXSDRFFImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("FD1P3BX", - i_CK = clk, - i_PD = 0, - i_SP = 1, - i_D = i, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("FD1P3BX", + i_CK = clk, + i_PD = 0, + i_SP = 1, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeNXSDRInputViaFlipFlop: @staticmethod @@ -292,12 +299,13 @@ def lower(dr): class LatticeNXDDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("IDDRX1", - i_SCLK = clk, - i_D = i, - o_Q0 = o1, - o_Q1 = o2, - ) + for j in range(len(i)): + self.specials += Instance("IDDRX1", + i_SCLK = clk, + i_D = i[j] if len(i) > 1 else i, + o_Q0 = o1[j] if len(o1) > 1 else o1, + o_Q1 = o2[j] if len(o2) > 1 else o2, + ) class LatticeNXDDRInput: @staticmethod @@ -308,12 +316,13 @@ def lower(dr): class LatticeNXDDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDRX1", - i_SCLK = clk, - i_D0 = i1, - i_D1 = i2, - o_Q = o, - ) + for j in range(len(o)): + self.specials += Instance("ODDRX1", + i_SCLK = clk, + i_D0 = i1[j] if len(i1) > 1 else i1, + i_D1 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o, + ) class LatticeNXDDROutput: @staticmethod @@ -325,9 +334,9 @@ def lower(dr): class LatticeNXDDRTristateImpl(Module): def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): assert oe2 is None - _o = Signal() - _oe = Signal() - _i = Signal() + _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) @@ -429,16 +438,17 @@ def lower(dr): class LatticeiCE40DDROutputImpl(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("SB_IO", - p_PIN_TYPE = C(0b010000, 6), # PIN_OUTPUT_DDR - p_IO_STANDARD = "SB_LVCMOS", - io_PACKAGE_PIN = o, - i_CLOCK_ENABLE = 1, - i_OUTPUT_CLK = clk, - i_OUTPUT_ENABLE = 1, - i_D_OUT_0 = i1, - i_D_OUT_1 = i2 - ) + for j in range(len(o)): + self.specials += Instance("SB_IO", + p_PIN_TYPE = C(0b010000, 6), # PIN_OUTPUT_DDR + p_IO_STANDARD = "SB_LVCMOS", + io_PACKAGE_PIN = o[j] if len(o) > 1 else o, + i_CLOCK_ENABLE = 1, + i_OUTPUT_CLK = clk, + i_OUTPUT_ENABLE = 1, + i_D_OUT_0 = i1[j] if len(i1) > 1 else i1, + i_D_OUT_1 = i2[j] if len(i2) > 1 else i2 + ) class LatticeiCE40DDROutput: @@ -450,15 +460,16 @@ def lower(dr): class LatticeiCE40DDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("SB_IO", - p_PIN_TYPE = C(0b000000, 6), # PIN_INPUT_DDR - p_IO_STANDARD = "SB_LVCMOS", - io_PACKAGE_PIN = i, - i_CLOCK_ENABLE = 1, - i_INPUT_CLK = clk, - o_D_IN_0 = o1, - o_D_IN_1 = o2 - ) + for j in range(len(i)): + self.specials += Instance("SB_IO", + p_PIN_TYPE = C(0b000000, 6), # PIN_INPUT_DDR + p_IO_STANDARD = "SB_LVCMOS", + io_PACKAGE_PIN = i[j] if len(i) > 1 else i, + i_CLOCK_ENABLE = 1, + i_INPUT_CLK = clk, + o_D_IN_0 = o1[j] if len(o1) > 1 else o1, + o_D_IN_1 = o2[j] if len(o2) > 1 else o2 + ) class LatticeiCE40DDRInput: @@ -470,18 +481,19 @@ def lower(dr): class LatticeiCE40SDROutputImpl(Module): def __init__(self, i, o, clk): - self.specials += Instance("SB_IO", - # i_INPUT_CLK must match between two SB_IOs in the same tile. - # In PIN_INPUT mode, this restriction is relaxed; an unconnected - # i_INPUT_CLK also works. - p_PIN_TYPE = C(0b010101, 6), # PIN_OUTPUT_REGISTERED + PIN_INPUT - p_IO_STANDARD = "SB_LVCMOS", - io_PACKAGE_PIN = o, - i_CLOCK_ENABLE = 1, - i_OUTPUT_CLK = clk, - i_OUTPUT_ENABLE = 1, - i_D_OUT_0 = i - ) + for j in range(len(o)): + self.specials += Instance("SB_IO", + # i_INPUT_CLK must match between two SB_IOs in the same tile. + # In PIN_INPUT mode, this restriction is relaxed; an unconnected + # i_INPUT_CLK also works. + p_PIN_TYPE = C(0b010101, 6), # PIN_OUTPUT_REGISTERED + PIN_INPUT + p_IO_STANDARD = "SB_LVCMOS", + io_PACKAGE_PIN = o[j] if len(o) > 1 else o, + i_CLOCK_ENABLE = 1, + i_OUTPUT_CLK = clk, + i_OUTPUT_ENABLE = 1, + i_D_OUT_0 = i[j] if len(i) > 1 else i + ) class LatticeiCE40SDROutput: @staticmethod @@ -499,15 +511,16 @@ def lower(dr): class LatticeiCE40SDRTristateImpl(Module): def __init__(self, io, o, oe, i, clk): - self.specials += Instance("SB_IO", - p_PIN_TYPE = C(0b110100, 6), # PIN_OUTPUT_REGISTERED_ENABLE_REGISTERED + PIN_INPUT_REGISTERED - io_PACKAGE_PIN = io, - i_INPUT_CLK = clk, - i_OUTPUT_CLK = clk, - i_OUTPUT_ENABLE = oe, - i_D_OUT_0 = o, - o_D_IN_0 = i, - ) + 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] if len(io) > 1 else io, + i_INPUT_CLK = clk, + i_OUTPUT_CLK = clk, + i_OUTPUT_ENABLE = oe[j] if len(oe) > 1 else oe, + i_D_OUT_0 = o[j] if len(o) > 1 else o, + o_D_IN_0 = i[j] if len(i) > 1 else i, + ) class LatticeiCE40SDRTristate(Module): @staticmethod diff --git a/litex/build/sim/common.py b/litex/build/sim/common.py index e6bc36e90d..8c57a6b6fb 100644 --- a/litex/build/sim/common.py +++ b/litex/build/sim/common.py @@ -25,12 +25,13 @@ def lower(dr): class SimDDROutputImpl(Module): def __init__(self, o, i1, i2, clk): - self.specials += Instance("DDR_OUTPUT", - i_i1 = i1, - i_i2 = i2, - o_o = o, - i_clk = clk - ) + for j in range(len(o)): + self.specials += Instance("DDR_OUTPUT", + i_i1 = i1[j] if len(i1) > 1 else i1, + i_i2 = i2[j] if len(i2) > 1 else i2, + o_o = o[j] if len(o) > 1 else o, + i_clk = clk + ) class SimDDROutput: @staticmethod @@ -41,12 +42,13 @@ def lower(dr): class SimDDRInputImpl(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("DDR_INPUT", - o_o1 = o1, - o_o2 = o2, - i_i = i, - i_clk = clk - ) + for j in range(len(i)): + self.specials += Instance("DDR_INPUT", + o_o1 = o1[j] if len(o1) > 1 else o1, + o_o2 = o2[j] if len(o2) > 1 else o2, + i_i = i[j] if len(i) > 1 else i, + i_clk = clk + ) class SimDDRInput: @staticmethod diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index 0f2231f70b..873ee52730 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -138,18 +138,19 @@ def lower(dr): class XilinxSDRTristateImpl(Module): def __init__(self, io, o, oe, i, clk): - _o = Signal() - _oe_n = Signal() - _i = Signal() + _o = Signal().like(o) + _oe_n = Signal().like(oe) + _i = Signal().like(i) self.specials += SDROutput(o, _o, clk) self.specials += SDROutput(~oe, _oe_n, clk) self.specials += SDRInput(_i, i, clk) - self.specials += Instance("IOBUF", - io_IO = io, - o_O = _i, - i_I = _o, - i_T = _oe_n, - ) + for j in range(len(io)): + self.specials += Instance("IOBUF", + io_IO = io[j] if len(io) > 1 else io, + o_O = _i[j] if len(_i) > 1 else _i, + i_I = _o[j] if len(_o) > 1 else _o, + i_T = _oe_n[j] if len(_oe_n) > 1 else _oe_n, + ) class XilinxSDRTristate: @staticmethod @@ -160,18 +161,19 @@ def lower(dr): class XilinxDDRTristateImpl(Module): def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): - _o = Signal() - _oe_n = Signal() - _i = Signal() + _o = Signal().like(o1) + _oe_n = Signal().like(oe1) + _i = Signal().like(i1) self.specials += DDROutput(o1, o2, _o, clk) self.specials += DDROutput(~oe1, ~oe2, _oe_n, clk) if oe2 is not None else SDROutput(~oe1, _oe_n, clk) self.specials += DDRInput(_i, i1, i2, clk) - self.specials += Instance("IOBUF", - io_IO = io, - o_O = _i, - i_I = _o, - i_T = _oe_n, - ) + for j in range(len(io)): + self.specials += Instance("IOBUF", + io_IO = io[j] if len(io) > 1 else io, + o_O = _i[j] if len(_i) > 1 else _i, + i_I = _o[j] if len(_o) > 1 else _o, + i_T = _oe_n[j] if len(_oe_n) > 1 else _oe_n, + ) class XilinxDDRTristate: @staticmethod @@ -193,19 +195,20 @@ def lower(dr): class XilinxDDROutputImplS6(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDR2", - p_DDR_ALIGNMENT = "C0", - p_INIT = 0, - p_SRTYPE = "ASYNC", - i_C0 = clk, - i_C1 = ~clk, - i_CE = 1, - i_S = 0, - i_R = 0, - i_D0 = i1, - i_D1 = i2, - o_Q = o - ) + for j in range(len(o)): + self.specials += Instance("ODDR2", + p_DDR_ALIGNMENT = "C0", + p_INIT = 0, + p_SRTYPE = "ASYNC", + i_C0 = clk, + i_C1 = ~clk, + i_CE = 1, + i_S = 0, + i_R = 0, + i_D0 = i1[j] if len(i1) > 1 else i1, + i_D1 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o + ) class XilinxDDROutputS6: @@ -217,20 +220,21 @@ def lower(dr): class XilinxDDRInputImplS6(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("IDDR2", - p_DDR_ALIGNMENT = "C0", - p_INIT_Q0 = 0, - p_INIT_Q1 = 0, - p_SRTYPE = "ASYNC", - i_C0 = clk, - i_C1 = ~clk, - i_CE = 1, - i_S = 0, - i_R = 0, - i_D = i, - o_Q0 = o1, - o_Q1 = o2 - ) + for j in range(len(i)): + self.specials += Instance("IDDR2", + p_DDR_ALIGNMENT = "C0", + p_INIT_Q0 = 0, + p_INIT_Q1 = 0, + p_SRTYPE = "ASYNC", + i_C0 = clk, + i_C1 = ~clk, + i_CE = 1, + i_S = 0, + i_R = 0, + i_D = i[j] if len(i) > 1 else i, + o_Q0 = o1[j] if len(o1) > 1 else o1, + o_Q1 = o2[j] if len(o2) > 1 else o2 + ) class XilinxDDRInputS6: @@ -266,16 +270,17 @@ def lower(dr): class XilinxDDROutputImplS7(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDR", - p_DDR_CLK_EDGE="SAME_EDGE", - i_C = clk, - i_CE = 1, - i_S = 0, - i_R = 0, - i_D1 = i1, - i_D2 = i2, - o_Q = o - ) + for j in range(len(o)): + self.specials += Instance("ODDR", + p_DDR_CLK_EDGE="SAME_EDGE", + i_C = clk, + i_CE = 1, + i_S = 0, + i_R = 0, + i_D1 = i1[j] if len(i1) > 1 else i1, + i_D2 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o + ) class XilinxDDROutputS7: @@ -287,16 +292,17 @@ def lower(dr): class XilinxDDRInputImplS7(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("IDDR", - p_DDR_CLK_EDGE="SAME_EDGE", - i_C = clk, - i_CE = 1, - i_S = 0, - i_R = 0, - i_D = i, - o_Q1 = o1, - o_Q2 = o2 - ) + for j in range(len(i)): + self.specials += Instance("IDDR", + p_DDR_CLK_EDGE="SAME_EDGE", + i_C = clk, + i_CE = 1, + i_S = 0, + i_R = 0, + i_D = i[j] if len(i) > 1 else i, + o_Q1 = o1[j] if len(o1) > 1 else o1, + o_Q2 = o2[j] if len(o2) > 1 else o2 + ) class XilinxDDRInputS7: @@ -332,13 +338,14 @@ def lower(dr): class XilinxDDROutputImplUS(Module): def __init__(self, i1, i2, o, clk): - self.specials += Instance("ODDRE1", - i_C = clk, - i_SR = 0, - i_D1 = i1, - i_D2 = i2, - o_Q = o - ) + for j in range(len(o)): + self.specials += Instance("ODDRE1", + i_C = clk, + i_SR = 0, + i_D1 = i1[j] if len(i1) > 1 else i1, + i_D2 = i2[j] if len(i2) > 1 else i2, + o_Q = o[j] if len(o) > 1 else o + ) class XilinxDDROutputUS: @@ -350,17 +357,18 @@ def lower(dr): class XilinxDDRInputImplUS(Module): def __init__(self, i, o1, o2, clk): - self.specials += Instance("IDDRE1", - p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", - p_IS_C_INVERTED = 0, - p_IS_CB_INVERTED = 1, - i_C = clk, - i_CB = clk, - i_R = 0, - i_D = i, - o_Q1 = o1, - o_Q2 = o2 - ) + for j in range(len(i)): + self.specials += Instance("IDDRE1", + p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", + p_IS_C_INVERTED = 0, + p_IS_CB_INVERTED = 1, + i_C = clk, + i_CB = clk, + i_R = 0, + i_D = i[j] if len(i) > 1 else i, + o_Q1 = o1[j] if len(o1) > 1 else o1, + o_Q2 = o2[j] if len(o2) > 1 else o2 + ) class XilinxDDRInputUS: @@ -372,13 +380,14 @@ def lower(dr): class XilinxSDROutputImplUS(Module): def __init__(self, i, o, clk): - self.specials += Instance("FDCE", - i_C = clk, - i_CE = 1, - i_CLR = 0, - i_D = i, - o_Q = o - ) + for j in range(len(o)): + self.specials += Instance("FDCE", + i_C = clk, + i_CE = 1, + i_CLR = 0, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o + ) class XilinxSDROutputUS: @staticmethod @@ -388,13 +397,14 @@ def lower(dr): # Ultrascale SDRInput ------------------------------------------------------------------------------ class XilinxSDRInputImplUS(Module): def __init__(self, i, o, clk): - self.specials += Instance("FDCE", - i_C = clk, - i_CE = 1, - i_CLR = 0, - i_D = i, - o_Q = o - ) + for j in range(len(i)): + self.specials += Instance("FDCE", + i_C = clk, + i_CE = 1, + i_CLR = 0, + i_D = i[j] if len(i) > 1 else i, + o_Q = o[j] if len(o) > 1 else o + ) class XilinxSDRInputUS: @staticmethod