diff --git a/litex_boards/platforms/alveo_u250.py b/litex_boards/platforms/alveo_u250.py new file mode 100644 index 0000000..f2ff5f8 --- /dev/null +++ b/litex_boards/platforms/alveo_u250.py @@ -0,0 +1,326 @@ +# This file is Copyright (c) 2020 David Shah +# License: BSD + +# Note that this board file should also be applicable to +# the Alveo U200, VCU1525, BCU1525 and other 1525 variants. + +from litex.build.generic_platform import Pins, Subsignal, IOStandard, Misc +from litex.build.xilinx import XilinxPlatform, VivadoProgrammer + +# This part auto-generated by extract_xdc_pins.py + +_io = [ + ("clk300", 0, + Subsignal("n", Pins("AY38"), IOStandard("DIFF_SSTL12")), + Subsignal("p", Pins("AY37"), IOStandard("DIFF_SSTL12")), + ), + ("clk300", 1, + Subsignal("n", Pins("AW19"), IOStandard("DIFF_SSTL12")), + Subsignal("p", Pins("AW20"), IOStandard("DIFF_SSTL12")), + ), + ("clk300", 2, + Subsignal("n", Pins("E32"), IOStandard("DIFF_SSTL12")), + Subsignal("p", Pins("F32"), IOStandard("DIFF_SSTL12")), + ), + ("clk300", 3, + Subsignal("n", Pins("H16"), IOStandard("DIFF_SSTL12")), + Subsignal("p", Pins("J16"), IOStandard("DIFF_SSTL12")), + ), + ("cpu_reset", 0, Pins("AL20"), IOStandard("LVCMOS12")), + ("ddr4_reset_gate", 0, Pins("AU21"), IOStandard("LVCMOS12")), + ("ddram", 0, + Subsignal("a", Pins( + "AT36 AV36 AV37 AW35 AW36 AY36 AY35 BA40", + "BA37 BB37 AR35 BA39 BB40 AN36"), + IOStandard("SSTL12_DCI")), + Subsignal("act_n", Pins("BB39"), IOStandard("SSTL12_DCI")), + Subsignal("ba", Pins("AT35 AT34"), IOStandard("SSTL12_DCI")), + Subsignal("bg", Pins("BC37 BC39"), IOStandard("SSTL12_DCI")), + Subsignal("cas_n", Pins("AP36"), IOStandard("SSTL12_DCI")), + Subsignal("cke", Pins("BC38"), IOStandard("SSTL12_DCI")), + Subsignal("clk_n", Pins("AW38"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("clk_p", Pins("AV38"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("cs_n", Pins("AR33"), IOStandard("SSTL12_DCI")), + Subsignal("dq", Pins( + "AW28 AW29 BA28 BA27 BB29 BA29 BC27 BB27", + "BE28 BF28 BE30 BD30 BF27 BE27 BF30 BF29", + "BB31 BB32 AY32 AY33 BC32 BC33 BB34 BC34", + "AV31 AV32 AV34 AW34 AW31 AY31 BA35 BA34", + "AL30 AM30 AU32 AT32 AN31 AN32 AR32 AR31", + "AP29 AP28 AN27 AM27 AN29 AM29 AR27 AR28", + "AT28 AV27 AU27 AT27 AV29 AY30 AW30 AV28", + "BD34 BD33 BE33 BD35 BF32 BF33 BF34 BF35"), + IOStandard("POD12_DCI"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_n", Pins( + "BB30 BC26 BD29 BE26 BB36 BD31 AW33 BA33", + "AM32 AP31 AL29 AT30 AU30 AY28 BE36 BE32"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_p", Pins( + "BA30 BB26 BD28 BD26 BB35 BC31 AV33 BA32", + "AM31 AP30 AL28 AR30 AU29 AY27 BE35 BE31"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("odt", Pins("AP34"), IOStandard("SSTL12_DCI")), + Subsignal("ras_n", Pins("AR36"), IOStandard("SSTL12_DCI")), + Subsignal("reset_n", Pins("AU31"), IOStandard("LVCMOS12")), + Subsignal("we_n", Pins("AP35"), IOStandard("SSTL12_DCI")), + Misc("SLEW=FAST") + ), + ("ddram_ch2", 0, + Subsignal("a", Pins( + "AN24 AT24 AW24 AN26 AY22 AY23 AV24 BA22", + "AY25 BA23 AM26 BA25 BB22 AL24"), + IOStandard("SSTL12_DCI")), + Subsignal("act_n", Pins("AW25"), IOStandard("SSTL12_DCI")), + Subsignal("ba", Pins("AU24 AP26"), IOStandard("SSTL12_DCI")), + Subsignal("bg", Pins("BC22 AW26"), IOStandard("SSTL12_DCI")), + Subsignal("cas_n", Pins("AM25"), IOStandard("SSTL12_DCI")), + Subsignal("cke", Pins("BB25"), IOStandard("SSTL12_DCI")), + Subsignal("clk_n", Pins("AU25"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("clk_p", Pins("AT25"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("cs_n", Pins("AV23"), IOStandard("SSTL12_DCI")), + Subsignal("dq", Pins( + "BD9 BD7 BC7 BD8 BD10 BE10 BE7 BF7", + "AU13 AV13 AW13 AW14 AU14 AY11 AV14 BA11", + "BA12 BB12 BA13 BA14 BC9 BB9 BA7 BA8", + "AN13 AR13 AM13 AP13 AM14 AR15 AL14 AT15", + "BE13 BD14 BF12 BD13 BD15 BD16 BF14 BF13", + "AY17 BA17 AY18 BA18 BA15 BB15 BC11 BD11", + "AV16 AV17 AU16 AU17 BB17 BB16 AT18 AT17", + "AM15 AL15 AN17 AN16 AR18 AP18 AL17 AL16"), + IOStandard("POD12_DCI"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_n", Pins( + "BF9 BF8 AY15 AY12 BB10 BA9 AT13 AP14", + "BE11 BF15 BC12 BC14 AW18 AY16 AR16 AM16"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_p", Pins( + "BF10 BE8 AW15 AY13 BB11 BA10 AT14 AN14", + "BE12 BE15 BC13 BB14 AV18 AW16 AP16 AM17"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("odt", Pins("AW23"), IOStandard("SSTL12_DCI")), + Subsignal("ras_n", Pins("AN23"), IOStandard("SSTL12_DCI")), + Subsignal("reset_n", Pins("AR17"), IOStandard("LVCMOS12")), + Subsignal("we_n", Pins("AL25"), IOStandard("SSTL12_DCI")), + Misc("SLEW=FAST") + ), + ("ddram_ch3", 0, + Subsignal("a", Pins( + "L29 A33 C33 J29 H31 G31 C32 B32", + "A32 D31 A34 E31 M30 F33"), + IOStandard("SSTL12_DCI")), + Subsignal("act_n", Pins("B31"), IOStandard("SSTL12_DCI")), + Subsignal("ba", Pins("D33 B36"), IOStandard("SSTL12_DCI")), + Subsignal("bg", Pins("C31 J30"), IOStandard("SSTL12_DCI")), + Subsignal("cas_n", Pins("G32"), IOStandard("SSTL12_DCI")), + Subsignal("cke", Pins("G30"), IOStandard("SSTL12_DCI")), + Subsignal("clk_n", Pins("B34"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("clk_p", Pins("C34"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("cs_n", Pins("B35"), IOStandard("SSTL12_DCI")), + Subsignal("dq", Pins( + "R25 P25 M25 L25 P26 R26 N27 N28", + "J28 H29 H28 G29 K25 L27 K26 K27", + "F27 E27 E28 D28 G27 G26 F28 F29", + "D26 C26 B27 B26 A29 A30 C27 C28", + "F35 E38 D38 E35 E36 E37 F38 G38", + "P30 R30 P29 N29 L32 M32 P31 N32", + "J35 K35 L33 K33 J34 J33 N34 P34", + "H36 G36 H37 J36 K37 K38 G35 G34"), + IOStandard("POD12_DCI"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_n", Pins( + "M26 P28 J26 L28 D30 H27 A28 B29", + "E40 F37 M31 R31 L36 L34 H38 H34"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_p", Pins( + "N26 R28 J25 M27 D29 H26 A27 C29", + "E39 G37 N31 T30 L35 M34 J38 H33"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("odt", Pins("E33"), IOStandard("SSTL12_DCI")), + Subsignal("ras_n", Pins("K30"), IOStandard("SSTL12_DCI")), + Subsignal("reset_n", Pins("D36"), IOStandard("LVCMOS12")), + Subsignal("we_n", Pins("A35"), IOStandard("SSTL12_DCI")), + Misc("SLEW=FAST") + ), + ("ddram_ch4", 0, + Subsignal("a", Pins( + "K15 B15 F14 A15 C14 A14 B14 E13", + "F13 A13 D14 C13 B13 K16"), + IOStandard("SSTL12_DCI")), + Subsignal("act_n", Pins("H13"), IOStandard("SSTL12_DCI")), + Subsignal("ba", Pins("J15 H14"), IOStandard("SSTL12_DCI")), + Subsignal("bg", Pins("D13 J13"), IOStandard("SSTL12_DCI")), + Subsignal("cas_n", Pins("E15"), IOStandard("SSTL12_DCI")), + Subsignal("cke", Pins("K13"), IOStandard("SSTL12_DCI")), + Subsignal("clk_n", Pins("L13"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("clk_p", Pins("L14"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("cs_n", Pins("B16"), IOStandard("SSTL12_DCI")), + Subsignal("dq", Pins( + "P24 N24 T24 R23 N23 P21 P23 R21", + "J24 J23 H24 G24 L24 L23 K22 K21", + "G20 H17 F19 G17 J20 L19 L18 J19", + "M19 M20 R18 R17 R20 T20 N18 N19", + "A23 A22 B24 B25 B22 C22 C24 C23", + "C19 C18 C21 B21 A18 A17 A20 B20", + "E17 F20 E18 E20 D19 D20 H18 J18", + "F22 E22 G22 G21 F24 E25 F25 G25"), + IOStandard("POD12_DCI"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_n", Pins( + "R22 N21 H21 L22 K20 K17 P18 M17", + "A24 D23 B17 A19 F17 G19 E23 H22"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("dqs_p", Pins( + "T22 N22 J21 M22 L20 K18 P19 N17", + "A25 D24 C17 B19 F18 H19 F23 H23"), + IOStandard("DIFF_POD12"), + Misc("PRE_EMPHASIS=RDRV_240"), + Misc("EQUALIZATION=EQ_LEVEL2")), + Subsignal("odt", Pins("C16"), IOStandard("SSTL12_DCI")), + Subsignal("ras_n", Pins("F15"), IOStandard("SSTL12_DCI")), + Subsignal("reset_n", Pins("D21"), IOStandard("LVCMOS12")), + Subsignal("we_n", Pins("D15"), IOStandard("SSTL12_DCI")), + Misc("SLEW=FAST") + ), + ("dip_sw", 0, Pins("AN22"), IOStandard("LVCMOS12")), + ("dip_sw", 1, Pins("AM19"), IOStandard("LVCMOS12")), + ("dip_sw", 2, Pins("AL19"), IOStandard("LVCMOS12")), + ("dip_sw", 3, Pins("AP20"), IOStandard("LVCMOS12")), + ("gpio_msp", 0, Pins("AR20"), IOStandard("LVCMOS12")), + ("gpio_msp", 1, Pins("AM20"), IOStandard("LVCMOS12")), + ("gpio_msp", 2, Pins("AM21"), IOStandard("LVCMOS12")), + ("gpio_msp", 3, Pins("AN21"), IOStandard("LVCMOS12")), + ("i2c", 0, + Subsignal("scl", Pins("BF20"), IOStandard("LVCMOS12")), + Subsignal("sda", Pins("BF17"), IOStandard("LVCMOS12")), + ), + ("i2c_main_reset_n", 0, Pins("BF19"), IOStandard("LVCMOS12")), + ("mgt_si570_clock", 0, + Subsignal("n", Pins("M10")), + Subsignal("p", Pins("M11")), + ), + ("mgt_si570_clock", 1, + Subsignal("n", Pins("T10")), + Subsignal("p", Pins("T11")), + ), + ("pcie_x16", 0, + Subsignal("clk_n", Pins("AM10")), + Subsignal("clk_p", Pins("AM11")), + Subsignal("rst_n", Pins("BD21"), IOStandard("LVCMOS12")), + Subsignal("rx_n", Pins( + "AF1 AG3 AH1 AJ3 AK1 AL3 AM1 AN3", + "AP1 AR3 AT1 AU3 AV1 AW3 BA1 BC1")), + Subsignal("rx_p", Pins( + "AF2 AG4 AH2 AJ4 AK2 AL4 AM2 AN4", + "AP2 AR4 AT2 AU4 AV2 AW4 BA2 BC2")), + Subsignal("tx_n", Pins( + "AF6 AG8 AH6 AJ8 AK6 AL8 AM6 AN8", + "AP6 AR8 AT6 AU8 AV6 BB4 BD4 BF4")), + Subsignal("tx_p", Pins( + "AF7 AG9 AH7 AJ9 AK7 AL9 AM7 AN9", + "AP7 AR9 AT7 AU9 AV7 BB5 BD5 BF5")), + ), + ("qsfp28", 0, + Subsignal("clk_n", Pins("K10")), + Subsignal("clk_p", Pins("K11")), + Subsignal("fs0", Pins("AT20"), IOStandard("LVCMOS12")), + Subsignal("fs1", Pins("AU22"), IOStandard("LVCMOS12")), + Subsignal("intl", Pins("BE21")), + Subsignal("lpmode", Pins("BD18")), + Subsignal("modprsl", Pins("BE20")), + Subsignal("modskll", Pins("BE16")), + Subsignal("refclk_reset", Pins("AT22"), IOStandard("LVCMOS12")), + Subsignal("resetl", Pins("BE17")), + Subsignal("rxn", Pins("N3 M1 L3 K1")), + Subsignal("rxp", Pins("N4 M2 L4 K2")), + Subsignal("txn", Pins("N8 M6 L8 K6")), + Subsignal("txp", Pins("N9 M7 L9 K7")), + ), + ("qsfp28", 1, + Subsignal("clk_n", Pins("P10")), + Subsignal("clk_p", Pins("P11")), + Subsignal("fs0", Pins("AR22"), IOStandard("LVCMOS12")), + Subsignal("fs1", Pins("AU20"), IOStandard("LVCMOS12")), + Subsignal("intl", Pins("AV21")), + Subsignal("lpmode", Pins("AV22")), + Subsignal("modprsl", Pins("BC19")), + Subsignal("modskll", Pins("AY20")), + Subsignal("refclk_reset", Pins("AR21"), IOStandard("LVCMOS12")), + Subsignal("resetl", Pins("BC18")), + Subsignal("rxn", Pins("U3 T1 R3 P1")), + Subsignal("rxp", Pins("U4 T2 R4 P2")), + Subsignal("txn", Pins("U8 T6 R8 P6")), + Subsignal("txp", Pins("U9 T7 R9 P7")), + ), + ("serial", 0, + Subsignal("rx", Pins("BF18"), IOStandard("LVCMOS12")), + Subsignal("tx", Pins("BB20"), IOStandard("LVCMOS12")), + ), + ("serial_msp", 0, + Subsignal("rx", Pins("BA19"), IOStandard("LVCMOS12")), + Subsignal("tx", Pins("BB19"), IOStandard("LVCMOS12")), + ), + ("set_sw", 0, Pins("AL21")), + ("user_led", 0, Pins("BC21"), IOStandard("LVCMOS12")), + ("user_led", 1, Pins("BB21"), IOStandard("LVCMOS12")), + ("user_led", 2, Pins("BA20"), IOStandard("LVCMOS12")), + ("user_si570_clock", 0, + Subsignal("n", Pins("AV19"), IOStandard("DIFF_SSTL12")), + Subsignal("p", Pins("AU19"), IOStandard("DIFF_SSTL12")), + ), +] + +_connectors = [] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(XilinxPlatform): + default_clk_name = "clk300" + default_clk_period = 1e9/300e6 + + def __init__(self): + XilinxPlatform.__init__(self, "xcu250-figd2104-2L-e", _io, _connectors, toolchain="vivado") + + def create_programmer(self): + return VivadoProgrammer() + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + # For passively cooled boards, overheating is a significant risk if airflow isn't sufficient + self.add_platform_command("set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN ENABLE [current_design]") + # Reduce programming time + self.add_platform_command("set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]") + # DDR4 memory channel C1 Internal Vref + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 61]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 62]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 63]") + # DDR4 memory channel C2 Internal Vref + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 65]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 66]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 67]") + # DDR4 memory channel C3 Internal Vref + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 69]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 70]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 71]") + # DDR4 memory channel C4 Internal Vref + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 72]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 73]") + self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 74]") diff --git a/litex_boards/targets/alveo_u250.py b/litex_boards/targets/alveo_u250.py new file mode 100644 index 0000000..804fc69 --- /dev/null +++ b/litex_boards/targets/alveo_u250.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +# This file is Copyright (c) 2020 Fei Gao +# This file is Copyright (c) 2020 Florent Kermarrec +# This file is Copyright (c) 2020 David Shah + +# License: BSD + +import argparse + +from migen import * + +from litex_boards.platforms import alveo_u250 + +from litex.soc.cores.clock import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.soc_sdram import * +from litex.soc.integration.builder import * + +from litedram.modules import MTA18ASF2G72PZ +from litedram.phy import usddrphy + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + self.clock_domains.cd_pll4x = ClockDomain(reset_less=True) + self.clock_domains.cd_clk500 = ClockDomain() + + # # # + + self.submodules.pll = pll = USMMCM(speedgrade=-2) + self.comb += pll.reset.eq(0) + pll.register_clkin(platform.request("clk300", 0), 300e6) + pll.create_clkout(self.cd_pll4x, sys_clk_freq*4, buf=None, with_reset=False) + pll.create_clkout(self.cd_clk500, 500e6, with_reset=False) + + self.specials += [ + Instance("BUFGCE_DIV", name="main_bufgce_div", + p_BUFGCE_DIVIDE=4, + i_CE=1, i_I=self.cd_pll4x.clk, o_O=self.cd_sys.clk), + Instance("BUFGCE", name="main_bufgce", + i_CE=1, i_I=self.cd_pll4x.clk, o_O=self.cd_sys4x.clk), + AsyncResetSynchronizer(self.cd_clk500, ~pll.locked), + ] + + self.submodules.idelayctrl = USIDELAYCTRL(cd_ref=self.cd_clk500, cd_sys=self.cd_sys) + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + def __init__(self, sys_clk_freq=int(125e6), **kwargs): + platform = alveo_u250.Platform() + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq) + + # DDR4 SDRAM ------------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + self.submodules.ddrphy = usddrphy.USPDDRPHY(platform.request("ddram"), + memtype = "DDR4", + sys_clk_freq = sys_clk_freq, + iodelay_clk_freq = 500e6, + cmd_latency = 1, + is_rdimm = True) + self.add_csr("ddrphy") + self.add_constant("USDDRPHY_DEBUG") + self.add_sdram("sdram", + phy = self.ddrphy, + module = MTA18ASF2G72PZ(sys_clk_freq, "1:4"), + origin = self.mem_map["main_ram"], + size = kwargs.get("max_sdram_size", 0x40000000), + l2_cache_size = kwargs.get("l2_size", 8192), + l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128), + l2_cache_reverse = True + ) + + self.add_ram("firmware_ram", 0x20000000, 0x8000) + +# Build -------------------------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on Alveo U250") + builder_args(parser) + soc_sdram_args(parser) + args = parser.parse_args() + + soc = BaseSoC(**soc_sdram_argdict(args)) + builder = Builder(soc, **builder_argdict(args)) + builder.build() + + +if __name__ == "__main__": + main() diff --git a/litex_boards/tools/extract_xdc_pins.py b/litex_boards/tools/extract_xdc_pins.py new file mode 100644 index 0000000..121b890 --- /dev/null +++ b/litex_boards/tools/extract_xdc_pins.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 + +# This file is Copyright (c) 2020 David Shah + +# License: BSD + +import re, sys + +""" +This is a script to parse a Xilinx XDC file and produce a LiteX board Python file. + +It has been tested on the Alveo U250 XDC file from +https://www.xilinx.com/member/forms/download/design-license.html?cid=41a21059-3945-404a-a349-35140c65291a&filename=xtp573-alveo-u250-xdc.zip + +The "extras" section and name parsing rules will need modification to support other boards. +""" + +extras = { + ("ddram", "dm"): [("IOStandard", "POD12_DCI")], + ("ddram", "dq"): [ + ("IOStandard", "POD12_DCI"), + ("Misc", "PRE_EMPHASIS=RDRV_240"), + ("Misc", "EQUALIZATION=EQ_LEVEL2"), + ], + ("ddram", "dqs_p"): [ + ("IOStandard", "DIFF_POD12"), + ("Misc", "PRE_EMPHASIS=RDRV_240"), + ("Misc", "EQUALIZATION=EQ_LEVEL2"), + ], + ("ddram", "dqs_n"): [ + ("IOStandard", "DIFF_POD12"), + ("Misc", "PRE_EMPHASIS=RDRV_240"), + ("Misc", "EQUALIZATION=EQ_LEVEL2"), + ], + ("ddram", "clk_p"): [("IOStandard", "DIFF_SSTL12_DCI")], + ("ddram", "clk_n"): [("IOStandard", "DIFF_SSTL12_DCI")], + ("ddram", "reset_n"): [("IOStandard", "LVCMOS12")], + ("ddram", "*"): [("IOStandard", "SSTL12_DCI")], + ("ddram", ): [("Misc", "SLEW=FAST")], + ("clk300", "*"): [("IOStandard", "DIFF_SSTL12")], + ("cpu_reset", "*"): [("IOStandard", "LVCMOS12")], + ("ddr4_reset_gate", "*"): [("IOStandard", "LVCMOS12")], + ("gpio_msp", "*"): [("IOStandard", "LVCMOS12")], + ("user_led", "*"): [("IOStandard", "LVCMOS12")], + ("dip_sw", "*"): [("IOStandard", "LVCMOS12")], + ("set_w", "*"): [("IOStandard", "LVCMOS12")], + ("pcie_x16", "rst_n"): [("IOStandard", "LVCMOS12")], + ("serial", "*"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "modskll_ls"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "resetl_ls"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "intl_ls"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "lpmode_ls"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "refclk_reset"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "fs0"): [("IOStandard", "LVCMOS12")], + ("qsfp28", "fs1"): [("IOStandard", "LVCMOS12")], + ("i2c", "*"): [("IOStandard", "LVCMOS12")], + ("i2c_main_reset_n", "*"): [("IOStandard", "LVCMOS12")], + ("serial_msp", "*"): [("IOStandard", "LVCMOS12")], + ("user_si570_clock", "*"): [("IOStandard", "DIFF_SSTL12")], +} + +groups = {} + + +ddr4_re = re.compile(r'DDR4_C(\d)_(.*)') + +simple_ports = { + "CPU_RESET_FPGA": ("cpu_reset", 0), + "DDR4_RESET_GATE": ("ddr4_reset_gate", 0), + "GPIO_MSP0": ("gpio_msp", 0), + "GPIO_MSP1": ("gpio_msp", 1), + "GPIO_MSP2": ("gpio_msp", 2), + "GPIO_MSP3": ("gpio_msp", 3), + "STATUS_LED0_FPGA": ("user_led", 0), + "STATUS_LED1_FPGA": ("user_led", 1), + "STATUS_LED2_FPGA": ("user_led", 2), + "SW_DP0": ("dip_sw", 0), + "SW_DP1": ("dip_sw", 1), + "SW_DP2": ("dip_sw", 2), + "SW_DP3": ("dip_sw", 3), + "SW_SET1_FPGA": ("set_sw", 0), + "I2C_MAIN_RESET_B_LS": ("i2c_main_reset_n", 0), +} + +def permute_dqs(i): + # Huh? + if i >= 9: + return (i - 9) * 2 + 1 + else: + return i * 2 + +def parse_port(port): + dm = ddr4_re.match(port) + if dm: + res = ("ddram", int(dm.group(1))) + x = dm.group(2) + if x.startswith("ADR"): + i = int(x[3:]) + if i == 17: + return None # not used on included DIMM + if i == 16: + s = ("ras_n", ) + elif i == 15: + s = ("cas_n", ) + elif i == 14: + s = ("we_n", ) + else: + s = ("a", i) + elif x.startswith("BA"): + s = ("ba", int(x[2:])) + elif x.startswith("BG"): + s = ("bg", int(x[2:])) + elif x.startswith("CK_T"): + if int(x[4:]) > 0: + return None # not used on included DIMM + s = ("clk_p", int(x[4:])) + elif x.startswith("CK_C"): + if int(x[4:]) > 0: + return None # not used on included DIMM + s = ("clk_n", int(x[4:])) + elif x.startswith("CKE"): + if int(x[3:]) > 0: + return None # not used on included DIMM + s = ("cke", int(x[3:])) + elif x.startswith("CS_B"): + if int(x[4:]) > 0: + return None # not used on included DIMM + s = ("cs_n", int(x[4:])) + elif x.startswith("ODT"): + if int(x[3:]) > 0: + return None # not used on included DIMM + s = ("odt", int(x[3:])) + elif x in ("ACT_B", "ALERT_B", "EVENT_B", "PAR", "RESET_N"): + if x == "ALERT_B" or x == "PAR" or x == "EVENT_B": + return None # not used on included DIMM + x = x.replace("_B", "_N") + s = (x.lower(), ) + elif x.startswith("DQS_T"): + i = permute_dqs(int(x[5:])) + if i >= 16: + return None + s = ("dqs_p", int(i)) + elif x.startswith("DQS_C"): + i = permute_dqs(int(x[5:])) + if i >= 16: + return None + s = ("dqs_n", int(i)) + elif x.startswith("DQ"): + if int(x[2:]) >= 64: + return None + s = ("dq", int(x[2:])) + else: + assert False, port + return (res, s) + elif port in simple_ports: + return (simple_ports[port], (simple_ports[port][0], )) + elif port.startswith("SYSCLK") and "_300_" in port: + return (("clk300", int(port[6])), (port[-1].lower(), )) + elif port.startswith("PEX_"): + res = ("pcie_x16", 0) + if port[4:6] == "TX": + s = ("tx_" + port[-1].lower(), int(port[6:port.rfind('_')])) + elif port[4:6] == "RX": + s = ("rx_" + port[-1].lower(), int(port[6:port.rfind('_')])) + elif port[4:10] == "REFCLK": + s = ("clk_" + port[-1].lower(), ) + else: + assert False, port + return (res, s) + elif port == "PCIE_PERST_LS": + return (("pcie_x16", 0), ("rst_n", )) + elif port.startswith("USB_UART_"): + # This is from FTDI perspective, we want FPGA perspective + u = port[-2:].lower() + return (("serial", 0), ("tx" if u == "rx" else "rx", )) + elif port.startswith("MGT_SI570_CLOCK"): + return (("mgt_si570_clock", int(port[15])), (port[-1].lower(), )) + elif port.startswith("USER_SI570_CLOCK"): + return (("user_si570_clock", 0), (port[-1].lower(), )) + elif port.startswith("QSFP"): + res = ("qsfp28", int(port[4])) + if port[6:8] == "TX": + s = ("tx" + port[-1].lower(), int(port[8])-1) + elif port[6:8] == "RX": + s = ("rx" + port[-1].lower(), int(port[8])-1) + elif port[6:11] == "CLOCK": + s = ("clk_" + port[-1].lower(), ) + elif port.endswith("REFCLK_RESET") or "_FS" in port: + s = (port[6:].lower(), ) + elif port.endswith("_LS"): + s = (port.split("_")[1].lower(), ) + else: + assert False, port + return (res, s) + elif port.startswith("I2C_FPGA_"): + return (("i2c", 0), (port.split("_")[2].lower(), )) + elif port.endswith("_MSP"): + return (("serial_msp", 0), (port.split("_")[1].lower()[:-1], )) + elif port == "No" or port.startswith("VR") or port.startswith("N3") or "SYSMON" in port or port.startswith("TEST"): + pass + else: + assert False, port + return None + +with open(sys.argv[1], "r") as xf: + for line in xf: + if "PACKAGE_PIN" not in line: + continue + sl = [x.strip() for x in re.split(r'\s|\[', line.strip(), )] + sl = [x for x in sl if x != ""] + pin = sl[sl.index("PACKAGE_PIN") + 1] + port = sl[sl.index("get_ports") + 1] + rs = parse_port(port) + if rs is None: + continue + res, sig = rs + + if sig is None: + groups[res] = pin + else: + if res not in groups: + groups[res] = {} + if len(sig) == 2: + if sig[0] not in groups[res]: + groups[res][sig[0]] = {} + groups[res][sig[0]][sig[1]] = pin + else: + groups[res][sig[0]] = {0: pin} + +def format_extras(items, force_newline = False, indent=" ", lcomma=","): + extra = "{} \n{}".format(lcomma, indent) if force_newline else "{} ".format(lcomma) + extra += (", \n{}".format(indent)).join(['{}("{}")'.format(i[0], i[1]) for i in items]) + return extra +print("_io = [") +for res, sigs in sorted(groups.items(), key=lambda x: x[0]): + res_name = res[0] + res_index = res[1] + if res_name == "ddram" and res_index > 0: + res_name = "ddram_ch{}".format(res_index + 1) + res_index = 0 + print(' ("{}", {}, '.format(res_name, res_index), end='\n' if len(sigs) > 1 else '') + for sig, pins in sorted(sigs.items(), key=lambda x: x[0]): + max_idx = max(pins.keys()) + if len(pins) > 8: + p = "" + for j in range((len(pins) + 7) // 8): + p += '\n "{}"{}'.format(" ".join([pins[i] for i in range(j * 8, + min((j + 1) * 8, max_idx+1))]), "," if j < ((len(pins) + 7) // 8 - 1) else "") + else: + p = '"{}"'.format(" ".join([pins[i] for i in range(max_idx+1)])) + extra = "" + if (res[0], sig) in extras: + extra = format_extras(extras[res[0], sig], len(pins) > 8) + elif (res[0], "*") in extras: + extra = format_extras(extras[res[0], "*"], len(pins) > 8) + if len(sigs) == 1: + print('Pins({}){}'.format(p, extra), end='') + else: + print(' Subsignal("{}", Pins({}){}),'.format(sig, p, extra)) + if (res[0], ) in extras: + print(format_extras(extras[res[0], ], False, " ", " ")) + print(' ),' if len(sigs) > 1 else '),') +print("]")