From 340a7961294ce9b5833dab2104bdfab6d66e1c84 Mon Sep 17 00:00:00 2001 From: Stefan Schrijvers Date: Sat, 25 Jan 2020 18:31:51 +0100 Subject: [PATCH] litedram_gen: add ecp5 support --- examples/arty.yml | 1 + examples/genesys2.yml | 3 +- examples/nexys4ddr.yml | 1 + examples/versa_ecp5.yml | 45 ++++++++++++++ litedram/gen.py | 129 +++++++++++++++++++++++++++++++--------- 5 files changed, 149 insertions(+), 30 deletions(-) create mode 100644 examples/versa_ecp5.yml mode change 100644 => 100755 litedram/gen.py diff --git a/examples/arty.yml b/examples/arty.yml index e73068c..aa8ae21 100644 --- a/examples/arty.yml +++ b/examples/arty.yml @@ -3,6 +3,7 @@ { # General ------------------------------------------------------------------ + "platform": "xilinx", # Platform type "cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32) "speedgrade": -1, # FPGA speedgrade "memtype": "DDR3", # DRAM type diff --git a/examples/genesys2.yml b/examples/genesys2.yml index d89f239..cf8e73d 100644 --- a/examples/genesys2.yml +++ b/examples/genesys2.yml @@ -3,9 +3,10 @@ { # General ------------------------------------------------------------------ + "platform": "xilinx", # Platform type "cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32) "speedgrade": -2, # FPGA speedgrade - "memtype": "DDR3", # DRAM type + "memtype": "DDR3", # DRAM type # PHY ---------------------------------------------------------------------- "cmd_delay": 0, # Command additional delay (in taps) diff --git a/examples/nexys4ddr.yml b/examples/nexys4ddr.yml index f61a810..a9f293d 100644 --- a/examples/nexys4ddr.yml +++ b/examples/nexys4ddr.yml @@ -3,6 +3,7 @@ { # General ------------------------------------------------------------------ + "platform": "xilinx", # Platform type "cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32) "speedgrade": -1, # FPGA speedgrade "memtype": "DDR2", # DRAM type diff --git a/examples/versa_ecp5.yml b/examples/versa_ecp5.yml new file mode 100644 index 0000000..a46fa45 --- /dev/null +++ b/examples/versa_ecp5.yml @@ -0,0 +1,45 @@ +# This file is Copyright (c) 2018-2019 Florent Kermarrec +# License: BSD + +{ + # General ------------------------------------------------------------------ + "platform": "ecp5", # Platform type + "cpu": None, # Type of CPU used for init/calib (vexriscv, lm32) + + # PHY ---------------------------------------------------------------------- + "sdram_module": "MT41K64M16", # SDRAM modules of the board or SO-DIMM + "sdram_module_nb": 2, # Number of byte groups + "sdram_rank_nb": 1, # Number of ranks + "sdram_phy": "ECP5DDRPHY", # Type of FPGA PHY + + # Frequency ---------------------------------------------------------------- + "input_clk_freq": 100e6, # Input clock frequency + "sys_clk_freq": 50e6, # System clock frequency (DDR_clk = 4 x sys_clk) + "init_clk_freq": 25e6, # Init clock frequency + + # Core --------------------------------------------------------------------- + "cmd_buffer_depth": 16, # Depth of the command buffer + + # User Ports --------------------------------------------------------------- + "user_ports": { + "axi_0" : { + "type": "axi", + "id_width": 32, + }, + "wishbone_0" : { + "type": "wishbone", + }, + "native_0" : { + "type": "native", + }, + "fifo_0" : { + "type": "fifo", + "base": 0x00000000, + "depth": 0x01000000, + }, + }, + + # CSR Port ----------------------------------------------------------------- + "csr_expose": "False", # Expose CSR bus as I/Os + "csr_align" : 32, # CSR alignment +} diff --git a/litedram/gen.py b/litedram/gen.py old mode 100644 new mode 100755 index c59260f..8622bdc --- a/litedram/gen.py +++ b/litedram/gen.py @@ -16,7 +16,8 @@ for some use cases it could be interesting to generate a standalone verilog file The standalone core is generated from a YAML configuration file that allows the user to generate easily a custom configuration of the core. -Current version of the generator is limited to Xilinx 7-Series FPGA for DDR2/DDR3 memories. +Current version of the generator is limited to Xilinx 7-Series FPGA for +DDR2/DDR3 memories and the versa ECP5-5G. """ import os @@ -31,6 +32,7 @@ from migen.genlib.resetsync import AsyncResetSynchronizer from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform +from litex.boards.platforms import versa_ecp5 from litex.soc.cores.clock import * from litex.soc.integration.soc_sdram import * @@ -247,6 +249,50 @@ class LiteDRAMCRG(Module): iodelay_pll.create_clkout(self.cd_iodelay, core_config["iodelay_clk_freq"]) self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_iodelay) +class LatticeDRAMCRG(Module): + def __init__(self, platform, core_config): + self.clock_domains.cd_init = ClockDomain() + self.clock_domains.cd_por = ClockDomain(reset_less=True) + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys2x = ClockDomain() + self.clock_domains.cd_sys2x_i = ClockDomain(reset_less=True) + + # # # + + self.stop = Signal() + + # clk / rst + clk100 = platform.request("clk100") + rst_n = platform.request("rst_n") + platform.add_period_constraint(clk100, 10.0) + + # power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += self.cd_por.clk.eq(ClockSignal()) + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count - 1)) + + # pll + self.submodules.pll = pll = ECP5PLL() + pll.register_clkin(clk100, core_config['sys_clk_freq']) + pll.create_clkout(self.cd_sys2x_i, 2*core_config["sys_clk_freq"]) + pll.create_clkout(self.cd_init, core_config['init_clk_freq']) + self.specials += [ + Instance("ECLKSYNCB", + i_ECLKI=self.cd_sys2x_i.clk, + i_STOP=self.stop, + o_ECLKO=self.cd_sys2x.clk), + Instance("CLKDIVF", + p_DIV="2.0", + i_ALIGNWD=0, + i_CLKI=self.cd_sys2x.clk, + i_RST=self.cd_sys2x.rst, + o_CDIVX=self.cd_sys.clk), + AsyncResetSynchronizer(self.cd_init, ~por_done | ~pll.locked | ~rst_n), + AsyncResetSynchronizer(self.cd_sys, ~por_done | ~pll.locked | ~rst_n) + ] + # LiteDRAMCoreControl ------------------------------------------------------------------------------ class LiteDRAMCoreControl(Module, AutoCSR): @@ -278,10 +324,10 @@ class LiteDRAMCore(SoCSDRAM): kwargs["with_uart"] = False kwargs["with_timer"] = False kwargs["with_ctrl"] = False - kwargs["with_wishbone"] = (cpu_type != None) + kwargs["with_wishbone"] = False else: - kwargs["l2_size"] = 0 - kwargs["min_l2_data_width"] = 0 + kwargs["l2_size"] = 0 + kwargs["min_l2_data_width"] = 0 # SoCSDRAM --------------------------------------------------------------------------------- SoCSDRAM.__init__(self, platform, sys_clk_freq, @@ -290,32 +336,50 @@ class LiteDRAMCore(SoCSDRAM): **kwargs) # CRG -------------------------------------------------------------------------------------- - self.submodules.crg = LiteDRAMCRG(platform, core_config) - # DRAM ------------------------------------------------------------------------------------- - platform.add_extension(get_dram_ios(core_config)) - assert core_config["memtype"] in ["DDR2", "DDR3"] - self.submodules.ddrphy = core_config["sdram_phy"]( - platform.request("ddram"), - memtype=core_config["memtype"], - nphases=4 if core_config["memtype"] == "DDR3" else 2, - sys_clk_freq=sys_clk_freq, - iodelay_clk_freq=core_config["iodelay_clk_freq"], - cmd_latency=core_config["cmd_latency"]) - self.add_constant("CMD_DELAY", core_config["cmd_delay"]) - if core_config["memtype"] == "DDR3": - self.ddrphy.settings.add_electrical_settings( - rtt_nom=core_config["rtt_nom"], - rtt_wr=core_config["rtt_wr"], - ron=core_config["ron"]) - sdram_module = core_config["sdram_module"](sys_clk_freq, - "1:4" if core_config["memtype"] == "DDR3" else "1:2") - controller_settings = controller_settings=ControllerSettings( - cmd_buffer_depth=core_config["cmd_buffer_depth"]) - self.register_sdram(self.ddrphy, - sdram_module.geom_settings, - sdram_module.timing_settings, - controller_settings=controller_settings) + if core_config["platform"] == "ecp5": + crg = LatticeDRAMCRG(platform, core_config) + self.submodules.crg = crg + + self.submodules.ddrphy = core_config["sdram_phy"]( + platform.request("ddram"), + sys_clk_freq=sys_clk_freq) + self.comb += crg.stop.eq(self.ddrphy.init.stop) + sdram_module = core_config["sdram_module"](sys_clk_freq, "1:2") + + controller_settings = controller_settings=ControllerSettings( + cmd_buffer_depth=core_config["cmd_buffer_depth"]) + self.register_sdram(self.ddrphy, + sdram_module.geom_settings, + sdram_module.timing_settings, + controller_settings=controller_settings) + else: + self.submodules.crg = LiteDRAMCRG(platform, core_config) + + # DRAM ------------------------------------------------------------------------------------- + platform.add_extension(get_dram_ios(core_config)) + assert core_config["memtype"] in ["DDR2", "DDR3"] + self.submodules.ddrphy = core_config["sdram_phy"]( + platform.request("ddram"), + memtype=core_config["memtype"], + nphases=4 if core_config["memtype"] == "DDR3" else 2, + sys_clk_freq=sys_clk_freq, + iodelay_clk_freq=core_config["iodelay_clk_freq"], + cmd_latency=core_config["cmd_latency"]) + self.add_constant("CMD_DELAY", core_config["cmd_delay"]) + if core_config["memtype"] == "DDR3": + self.ddrphy.settings.add_electrical_settings( + rtt_nom=core_config["rtt_nom"], + rtt_wr=core_config["rtt_wr"], + ron=core_config["ron"]) + sdram_module = core_config["sdram_module"](sys_clk_freq, + "1:4" if core_config["memtype"] == "DDR3" else "1:2") + controller_settings = controller_settings=ControllerSettings( + cmd_buffer_depth=core_config["cmd_buffer_depth"]) + self.register_sdram(self.ddrphy, + sdram_module.geom_settings, + sdram_module.timing_settings, + controller_settings=controller_settings) # DRAM Initialization ---------------------------------------------------------------------- self.submodules.ddrctrl = LiteDRAMCoreControl() @@ -502,6 +566,13 @@ def main(): # Generate core -------------------------------------------------------------------------------- platform = Platform() + if core_config["platform"] == "ecp5": + platform = versa_ecp5.Platform(toolchain="trellis") + elif core_config["platform"] == "xilinx": + platform = XilinxPlatform("", io=[], toolchain="vivado") + else: + raise ValueError("Unknown platform specified in {}".format(args.config)); + soc = LiteDRAMCore(platform, core_config, integrated_rom_size=0x6000, integrated_sram_size=0x1000) builder = Builder(soc, output_dir="build", compile_gateware=False) vns = builder.build(build_name="litedram_core", regular_comb=False)