From 5249e20c1aaada2c5496be1adddaf53d56dd30f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fin=20Maa=C3=9F?= Date: Wed, 13 Nov 2024 16:22:27 +0100 Subject: [PATCH] build: common: extend SDR/DDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit extend SDR/DDR variants to support Signals longer than 1. Signed-off-by: Fin Maaß --- litex/build/altera/common.py | 114 ++++++++-------- litex/build/colognechip/common.py | 41 +++--- litex/build/gowin/common.py | 50 +++---- litex/build/lattice/common.py | 217 ++++++++++++++++-------------- litex/build/sim/common.py | 26 ++-- litex/build/xilinx/common.py | 204 +++++++++++++++------------- 6 files changed, 346 insertions(+), 306 deletions(-) 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/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/lattice/common.py b/litex/build/lattice/common.py index 3f3f78e637..6888ebd0a1 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 @@ -214,13 +218,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 @@ -231,13 +236,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 @@ -251,13 +257,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 @@ -273,12 +280,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 @@ -289,12 +297,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 @@ -305,9 +314,9 @@ def lower(dr): class LatticeNXDDRTristateImpl(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 += SDROutput(oe1 | oe2, _oe, clk) self.specials += DDRInput(_i, i1, i2, clk) @@ -409,16 +418,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: @@ -430,15 +440,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: @@ -450,18 +461,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 @@ -479,15 +491,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 d0d6bf0f63..1c2a192f5b 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) 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