From ee4fa597b4a1cdde833bd58853a7b4cf758d5a64 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 6 Feb 2018 14:43:20 +0100 Subject: [PATCH] boards: add nexys4ddr --- litex/boards/platforms/nexys4ddr.py | 82 +++++++++++++++++++ litex/boards/targets/nexys4ddr.py | 117 ++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 litex/boards/platforms/nexys4ddr.py create mode 100755 litex/boards/targets/nexys4ddr.py diff --git a/litex/boards/platforms/nexys4ddr.py b/litex/boards/platforms/nexys4ddr.py new file mode 100644 index 000000000..18175ab23 --- /dev/null +++ b/litex/boards/platforms/nexys4ddr.py @@ -0,0 +1,82 @@ +# This file is Copyright (c) 2018 Florent Kermarrec +# 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 index 000000000..391ac3818 --- /dev/null +++ b/litex/boards/targets/nexys4ddr.py @@ -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()