boards: add nexys4ddr
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 6 Feb 2018 13:43:20 +0000 (14:43 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 6 Feb 2018 13:43:20 +0000 (14:43 +0100)
litex/boards/platforms/nexys4ddr.py [new file with mode: 0644]
litex/boards/targets/nexys4ddr.py [new file with mode: 0755]

diff --git a/litex/boards/platforms/nexys4ddr.py b/litex/boards/platforms/nexys4ddr.py
new file mode 100644 (file)
index 0000000..18175ab
--- /dev/null
@@ -0,0 +1,82 @@
+# This file is Copyright (c) 2018 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
+from litex.build.generic_platform import *
+from litex.build.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer
+
+_io = [
+    ("user_led",  0, Pins("H17"), IOStandard("LVCMOS33")),
+    ("user_led",  1, Pins("K15"), IOStandard("LVCMOS33")),
+    ("user_led",  2, Pins("J13"), IOStandard("LVCMOS33")),
+    ("user_led",  3, Pins("N14"), IOStandard("LVCMOS33")),
+    ("user_led",  4, Pins("R18"), IOStandard("LVCMOS33")),
+    ("user_led",  5, Pins("V17"), IOStandard("LVCMOS33")),
+    ("user_led",  6, Pins("U17"), IOStandard("LVCMOS33")),
+    ("user_led",  7, Pins("U16"), IOStandard("LVCMOS33")),
+    ("user_led",  8, Pins("V16"), IOStandard("LVCMOS33")),
+    ("user_led",  9, Pins("T15"), IOStandard("LVCMOS33")),
+    ("user_led", 10, Pins("U14"), IOStandard("LVCMOS33")),
+    ("user_led", 11, Pins("T16"), IOStandard("LVCMOS33")),
+    ("user_led", 12, Pins("V15"), IOStandard("LVCMOS33")),
+    ("user_led", 13, Pins("V14"), IOStandard("LVCMOS33")),
+    ("user_led", 14, Pins("V12"), IOStandard("LVCMOS33")),
+    ("user_led", 15, Pins("V11"), IOStandard("LVCMOS33")),
+
+    ("clk100", 0, Pins("E3"), IOStandard("LVCMOS33")),
+
+    ("cpu_reset", 0, Pins("C12"), IOStandard("LVCMOS33")),
+
+    ("serial", 0,
+        Subsignal("tx", Pins("D4")),
+        Subsignal("rx", Pins("C4")),
+        IOStandard("LVCMOS33"),
+    ),
+
+    ("ddram", 0,
+        Subsignal("a", Pins(
+            "M4 P4 M6 T1 L3 P5 M2 N1",
+            "L4 N5 R2 K5 N6"),
+            IOStandard("SSTL18_II")),
+        Subsignal("ba", Pins("P2 P3 R1"), IOStandard("SSTL18_II")),
+        Subsignal("ras_n", Pins("N4"), IOStandard("SSTL18_II")),
+        Subsignal("cas_n", Pins("L3"), IOStandard("SSTL18_II")),
+        Subsignal("we_n", Pins("N2"), IOStandard("SSTL18_II")),
+        Subsignal("dm", Pins("T6 U1"), IOStandard("SSTL18_II")),
+        Subsignal("dq", Pins(
+            "R7 V6 R8 U7 V7 R6 U6 R5",
+            "T5 U3 V5 U4 V4 T4 V1 T3"),
+            IOStandard("SSTL18_II"),
+            Misc("IN_TERM=UNTUNED_SPLIT_50")),
+        Subsignal("dqs_p", Pins("U9 U2"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("dqs_n", Pins("V9 V2"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("clk_p", Pins("L6"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("clk_n", Pins("L5"), IOStandard("DIFF_SSTL18_II")),
+        Subsignal("cke", Pins("M1"), IOStandard("SSTL18_II")),
+        Subsignal("odt", Pins("M3"), IOStandard("SSTL18_II")),
+        Subsignal("cs_n", Pins("K6"), IOStandard("SSTL18_II")),
+        Misc("SLEW=FAST"),
+    ),
+]
+
+
+class Platform(XilinxPlatform):
+    default_clk_name = "clk100"
+    default_clk_period = 10.0
+
+    def __init__(self, programmer="vivado"):
+        XilinxPlatform.__init__(self, "xc7a100t-CSG324-1", _io, toolchain="vivado")
+        self.programmer = programmer
+        self.add_platform_command("set_property INTERNAL_VREF 0.750 [get_iobanks 35]")
+
+
+    def create_programmer(self):
+        if self.programmer == "xc3sprog":
+            return XC3SProg("nexys4")
+        elif self.programmer == "vivado":
+            return VivadoProgrammer()
+        else:
+            raise ValueError("{} programmer is not supported"
+                             .format(self.programmer))
+
+    def do_finalize(self, fragment):
+        XilinxPlatform.do_finalize(self, fragment)
diff --git a/litex/boards/targets/nexys4ddr.py b/litex/boards/targets/nexys4ddr.py
new file mode 100755 (executable)
index 0000000..391ac38
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+
+import argparse
+
+from litex.gen import *
+from litex.gen.genlib.resetsync import AsyncResetSynchronizer
+
+from litex.boards.platforms import nexys4ddr
+
+from litex.soc.integration.soc_core import mem_decoder
+from litex.soc.integration.soc_sdram import *
+from litex.soc.integration.builder import *
+
+from litedram.modules import MT41K256M16
+from litedram.phy import a7ddrphy
+
+
+class _CRG(Module):
+    def __init__(self, platform):
+        self.clock_domains.cd_sys = ClockDomain()
+        self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
+        self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
+        self.clock_domains.cd_clk200 = ClockDomain()
+        self.clock_domains.cd_clk100 = ClockDomain()
+
+        clk100 = platform.request("clk100")
+        rst = ~platform.request("cpu_reset")
+
+        pll_locked = Signal()
+        pll_fb = Signal()
+        self.pll_sys = Signal()
+        pll_sys4x = Signal()
+        pll_sys4x_dqs = Signal()
+        pll_clk200 = Signal()
+        self.specials += [
+            Instance("PLLE2_BASE",
+                     p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
+
+                     # VCO @ 1600 MHz
+                     p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0,
+                     p_CLKFBOUT_MULT=16, p_DIVCLK_DIVIDE=1,
+                     i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
+
+                     # 100 MHz
+                     p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0,
+                     o_CLKOUT0=self.pll_sys,
+
+                     # 400 MHz
+                     p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.0,
+                     o_CLKOUT1=pll_sys4x,
+
+                     # 400 MHz dqs
+                     p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=90.0,
+                     o_CLKOUT2=pll_sys4x_dqs,
+
+                     # 200 MHz
+                     p_CLKOUT3_DIVIDE=8, p_CLKOUT3_PHASE=0.0,
+                     o_CLKOUT3=pll_clk200
+            ),
+            Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_sys.clk),
+            Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk),
+            Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk),
+            Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk),
+            Instance("BUFG", i_I=clk100, o_O=self.cd_clk100.clk),
+            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst),
+            AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst),
+            AsyncResetSynchronizer(self.cd_clk100, ~pll_locked | rst),
+        ]
+
+        reset_counter = Signal(4, reset=15)
+        ic_reset = Signal(reset=1)
+        self.sync.clk200 += \
+            If(reset_counter != 0,
+                reset_counter.eq(reset_counter - 1)
+            ).Else(
+                ic_reset.eq(0)
+            )
+        self.specials += Instance("IDELAYCTRL", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset)
+
+
+class BaseSoC(SoCSDRAM):
+    csr_map = {
+        "ddrphy": 16,
+    }
+    csr_map.update(SoCSDRAM.csr_map)
+    def __init__(self, **kwargs):
+        platform = nexys4ddr.Platform()
+        SoCSDRAM.__init__(self, platform, clk_freq=100*1000000,
+                         integrated_rom_size=0x8000,
+                         integrated_sram_size=0x8000,
+                         **kwargs)
+
+        self.submodules.crg = _CRG(platform)
+
+        # sdram
+        self.submodules.ddrphy = a7ddrphy.A7DDRPHY(platform.request("ddram"))
+        self.add_constant("READ_LEVELING_BITSLIP", 3)
+        self.add_constant("READ_LEVELING_DELAY", 14)
+        sdram_module = MT41K256M16(self.clk_freq, "1:4")
+        self.register_sdram(self.ddrphy,
+                            sdram_module.geom_settings,
+                            sdram_module.timing_settings)
+
+
+def main():
+    parser = argparse.ArgumentParser(description="LiteX SoC port to Nexys4DDR")
+    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()