From 228245075a4d18af246a475e534f32cae207b288 Mon Sep 17 00:00:00 2001 From: Alessandro Comodi Date: Tue, 21 Sep 2021 13:28:23 +0200 Subject: [PATCH] boards: added datacenter DDR4 RDIMM tester board Signed-off-by: Alessandro Comodi --- .../antmicro_datacenter_ddr4_test_board.py | 144 +++++++++++++++ .../antmicro_datacenter_ddr4_test_board.py | 172 ++++++++++++++++++ 2 files changed, 316 insertions(+) create mode 100644 litex_boards/platforms/antmicro_datacenter_ddr4_test_board.py create mode 100755 litex_boards/targets/antmicro_datacenter_ddr4_test_board.py diff --git a/litex_boards/platforms/antmicro_datacenter_ddr4_test_board.py b/litex_boards/platforms/antmicro_datacenter_ddr4_test_board.py new file mode 100644 index 0000000..eb2e3b9 --- /dev/null +++ b/litex_boards/platforms/antmicro_datacenter_ddr4_test_board.py @@ -0,0 +1,144 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Antmicro +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # TODO: change clock when assigned to schematic + ("clk100", 0, Pins("AC23"), IOStandard("LVCMOS33")), + + ("user_led", 0, Pins("D21"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("B20"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("B21"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("C22"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("E22"), IOStandard("LVCMOS33")), + + ("user_btn", 0, Pins("C21"), IOStandard("LVCMOS33")), + ("user_btn", 1, Pins("A20"), IOStandard("LVCMOS33")), + ("user_btn", 2, Pins("E21"), IOStandard("LVCMOS33")), + ("user_btn", 3, Pins("D23"), IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("E26")), + Subsignal("rx", Pins("F25")), + IOStandard("LVCMOS33") + ), + ("serial", 1, + Subsignal("tx", Pins("D26")), + Subsignal("rx", Pins("E25")), + IOStandard("LVCMOS33") + ), + + # DDR4 + ("ddr4", 0, + Subsignal("a", Pins( + "AF10 AC11 AD11 AD10 AC9 AD9 AB9 AF7 AE8", + "AE7 Y12 AC7 AB7 AD13"), + IOStandard("SSTL12_DCI")), + Subsignal("ba", Pins("AB11 AB10"), IOStandard("SSTL12_DCI")), + Subsignal("bg", Pins("AA9 AF9"), IOStandard("SSTL12_DCI")), + Subsignal("ras_n", Pins("AA12"), IOStandard("SSTL12_DCI")), # A16 + Subsignal("cas_n", Pins("AF13"), IOStandard("SSTL12_DCI")), # A15 + Subsignal("we_n", Pins("AA13"), IOStandard("SSTL12_DCI")), # A14 + Subsignal("cs_n", Pins("W13 AA14 AC14 AF15"), IOStandard("SSTL12_DCI")), + Subsignal("act_n", Pins("Y8"), IOStandard("SSTL12_DCI")), + Subsignal("alert_n", Pins("AE10"), IOStandard("SSTL12_DCI")), + Subsignal("par", Pins("AE13"), IOStandard("SSTL12_DCI")), + Subsignal("dm", Pins("AF3 AE5 AD6 AC6 AF2 AE3 AE6 AD5"), + IOStandard("SSTL12_DCI")), + Subsignal("dq", Pins( + "W11 Y11 V7 Y7 V11 V9 V8 W8", + "U2 V6 Y2 Y3 U5 U4 W3 Y1", + "AA2 AB2 AE1 AE2 V2 W1 AD1 AC2", + "W4 AA3 AD3 AC4 V3 V4 AB4 AC3", + "AC16 AC17 AB16 AA19 AB15 AD16 AC18 AC19", + "AF17 AE17 AF20 AD19 AE15 AE16 AF19 AD18", + "Y18 Y17 W14 V14 AA20 AA15 V18 W16", + "AA18 AB19 V16 W15 AB17 AA17 V19 V17"), + IOStandard("SSTL12")), + Subsignal("dqs_p", Pins( + "W10 W6 AB1 AA5 AD20 AE18 W18 Y15 AF5", + "B17 D19 L19 J15 T24 P19 R16 M25 AC8"), + IOStandard("DIFF_HSUL_12")), + Subsignal("dqs_n", Pins( + "W9 W5 AC1 AB5 AE20 AF18 W19 Y16 AF4", + "A17 D20 L20 J16 T25 P20 R17 L25 AD8"), + IOStandard("DIFF_HSUL_12")), + Subsignal("clk_p", Pins("AE12 AB12"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("clk_n", Pins("AF12 AC12"), IOStandard("DIFF_SSTL12_DCI")), + Subsignal("cke", Pins("AA8 AA7"), IOStandard("SSTL12_DCI")), # also AM15 for larger SODIMMs + Subsignal("odt", Pins("Y13 AB14"), IOStandard("SSTL12_DCI")), # also AM16 for larger SODIMMs + Subsignal("reset_n", Pins("AB6"), IOStandard("SSTL12")), + Misc("SLEW=FAST"), + ), + + # RGMII Ethernet + ("eth_ref_clk", 0, Pins("AA23"), IOStandard("LVCMOS33")), + ("eth_clocks", 0, + Subsignal("tx", Pins("Y23")), + Subsignal("rx", Pins("AA24")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("AA22")), + Subsignal("mdio", Pins("AB26")), + Subsignal("mdc", Pins("AA25")), + Subsignal("rx_ctl", Pins("Y25")), + Subsignal("rx_data", Pins("W26 W25 V26 U25")), + Subsignal("tx_ctl", Pins("U26")), + Subsignal("tx_data", Pins("W24 Y26 Y22 Y21")), + IOStandard("LVCMOS33") + ), + + # HyperRAM + ("hyperram", 0, + Subsignal("clk_n", Pins("AE26")), + Subsignal("clk_p", Pins("AD26")), + Subsignal("rst_n", Pins("AC24")), + Subsignal("cs_n", Pins("AC26")), + Subsignal("dq", Pins("AE23 AD25 AF24 AE22 AF23 AF25 AE25 AD24")), + Subsignal("rwds", Pins("AD23")), + IOStandard("LVCMOS33") + ), + + # SD Card + ("sdcard", 0, + Subsignal("data", Pins("E10 F8 C9 D9"), Misc("PULLUP True")), + Subsignal("cmd", Pins("D8"), Misc("PULLUP True")), + Subsignal("clk", Pins("D10")), + Subsignal("cd", Pins("F9")), + Misc("SLEW=FAST"), + IOStandard("LVCMOS33"), + ), +] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(XilinxPlatform): + default_clk_name = "clk100" + default_clk_period = 1e9/100e6 + + def __init__(self, device="xc7k160tffg676-1"): + XilinxPlatform.__init__(self, device, _io, toolchain="vivado") + self.toolchain.bitstream_commands = \ + ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] + self.toolchain.additional_commands = \ + ["write_cfgmem -force -format bin -interface spix4 -size 16 " + "-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] + self.add_platform_command("set_property INTERNAL_VREF 0.6 [get_iobanks 32]") + self.add_platform_command("set_property INTERNAL_VREF 0.6 [get_iobanks 33]") + self.add_platform_command("set_property INTERNAL_VREF 0.6 [get_iobanks 34]") + + def create_programmer(self): + return OpenOCD("openocd_xc7_ft4232.cfg", "bscan_spi_xc7k100t.bit") + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) diff --git a/litex_boards/targets/antmicro_datacenter_ddr4_test_board.py b/litex_boards/targets/antmicro_datacenter_ddr4_test_board.py new file mode 100755 index 0000000..637a8bc --- /dev/null +++ b/litex_boards/targets/antmicro_datacenter_ddr4_test_board.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Antmicro +# SPDX-License-Identifier: BSD-2-Clause + +import os +import argparse + +from migen import * + +from litex_boards.platforms import datacenter_ddr4_test_board +from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict + +from litex.soc.cores.clock import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * +from litex.soc.cores.led import LedChaser + +from litedram.modules import MTA18ASF2G72PZ +from litedram.phy.s7ddrphy import K7DDRPHY + +from liteeth.phy import LiteEthS7PHYRGMII +from litehyperbus.core.hyperbus import HyperRAM + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, iodelay_clk_freq): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys2x = ClockDomain(reset_less=True) + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + self.clock_domains.cd_idelay = ClockDomain() + + # # # + + self.submodules.pll = pll = S7PLL(speedgrade=-1) + pll.register_clkin(platform.request("clk100"), 100e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + pll.create_clkout(self.cd_sys2x, 2 * sys_clk_freq) + pll.create_clkout(self.cd_sys4x, 4 * sys_clk_freq) + pll.create_clkout(self.cd_idelay, iodelay_clk_freq) + + self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay) + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + mem_map = { + "hyperram": 0x20000000, + } + mem_map.update(SoCCore.mem_map) + + def __init__(self, *, sys_clk_freq=int(100e6), iodelay_clk_freq=200e6, + with_ethernet=False, with_etherbone=False, eth_ip="192.168.1.50", eth_dynamic_ip=False, + with_hyperram=False, with_sdcard=False, with_jtagbone=True, with_uartbone=False, + with_led_chaser=True, ident_version=True, **kwargs): + platform = datacenter_ddr4_test_board.Platform() + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, + ident = "LiteX SoC on data center test board", + ident_version = ident_version, + **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq, iodelay_clk_freq=iodelay_clk_freq) + + # DDR4 SDRAM RDIMM ------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + self.submodules.ddrphy = K7DDRPHY(platform.request("ddr4"), + memtype = "DDR4", + iodelay_clk_freq = iodelay_clk_freq, + sys_clk_freq = sys_clk_freq, + is_rdimm = True, + ) + self.add_sdram("sdram", + phy = self.ddrphy, + module = MTA18ASF2G72PZ(sys_clk_freq, "1:4"), + l2_cache_size = kwargs.get("l2_size", 8192), + l2_cache_min_data_width = 256, + size = 0x40000000, + ) + + # HyperRAM --------------------------------------------------------------------------------- + if with_hyperram: + self.submodules.hyperram = HyperRAM(platform.request("hyperram")) + self.register_mem("hyperram", self.mem_map["hyperram"], self.hyperram.bus, 8*1024*1024) + + # SD Card ---------------------------------------------------------------------------------- + if with_sdcard: + self.add_sdcard() + + # Ethernet / Etherbone --------------------------------------------------------------------- + if with_ethernet or with_etherbone: + # Traces between PHY and FPGA introduce ignorable delays of ~0.165ns +/- 0.015ns. + # PHY chip does not introduce delays on TX (FPGA->PHY), however it includes 1.2ns + # delay for RX CLK so we only need 0.8ns to match the desired 2ns. + self.submodules.ethphy = LiteEthS7PHYRGMII( + clock_pads = self.platform.request("eth_clocks"), + pads = self.platform.request("eth"), + rx_delay = 0.8e-9, + ) + if with_ethernet: + self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip) + if with_etherbone: + self.add_etherbone(phy=self.ethphy, ip_address=eth_ip) + + # UartBone --------------------------------------------------------------------------------- + if with_uartbone: + self.add_uartbone("serial", baudrate=1e6) + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.submodules.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) + +# Build -------------------------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on LPDDR4 Test Board") + target = parser.add_argument_group(title="Target options") + target.add_argument("--build", action="store_true", help="Build bitstream") + target.add_argument("--load", action="store_true", help="Load bitstream") + target.add_argument("--flash", action="store_true", help="Flash bitstream") + target.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency") + target.add_argument("--iodelay-clk-freq", default=200e6, help="IODELAYCTRL frequency") + ethopts = target.add_mutually_exclusive_group() + ethopts.add_argument("--with-ethernet", action="store_true", help="Add Ethernet") + ethopts.add_argument("--with-etherbone", action="store_true", help="Add EtherBone") + target.add_argument("--eth-ip", default="192.168.1.50", help="Ethernet/Etherbone IP address") + target.add_argument("--eth-dynamic-ip", action="store_true", help="Enable dynamic Ethernet IP addresses setting") + target.add_argument("--with-hyperram", action="store_true", help="Add HyperRAM") + target.add_argument("--with-sdcard", action="store_true", help="Add SDCard") + target.add_argument("--with-jtagbone", action="store_true", help="Add JTAGBone") + target.add_argument("--with-uartbone", action="store_true", help="Add UartBone on 2nd serial") + parser.add_argument("--no-ident-version", action="store_false", help="Disable build time output") + builder_args(parser) + soc_core_args(parser) + vivado_build_args(parser) + args = parser.parse_args() + + assert not (args.with_etherbone and args.eth_dynamic_ip) + + soc = BaseSoC( + sys_clk_freq = int(float(args.sys_clk_freq)), + iodelay_clk_freq = int(float(args.iodelay_clk_freq)), + with_ethernet = args.with_ethernet, + with_etherbone = args.with_etherbone, + eth_ip = args.eth_ip, + eth_dynamic_ip = args.eth_dynamic_ip, + with_hyperram = args.with_hyperram, + with_sdcard = args.with_sdcard, + with_jtagbone = args.with_jtagbone, + with_uartbone = args.with_uartbone, + ident_version = args.no_ident_version, + **soc_core_argdict(args)) + builder = Builder(soc, **builder_argdict(args)) + vns = builder.build(**vivado_build_argdict(args), run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit")) + + if args.flash: + prog = soc.platform.create_programmer() + prog.flash(0, os.path.join(builder.gateware_dir, soc.build_name + ".bin")) + +if __name__ == "__main__": + main()