+++ /dev/null
-#!/usr/bin/env python3
-
-# This file is Copyright (c) 2018-2020 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2020 Stefan Schrijvers <ximin@ximinity.net>
-# License: BSD
-
-"""
-LiteDRAM standalone core generator
-
-LiteDRAM aims to be directly used as a python package when the SoC is created using LiteX. However,
-for some use cases it could be interesting to generate a standalone verilog file of the core:
-- integration of the core in a SoC using a more traditional flow.
-- need to version/package the core.
-- avoid Migen/LiteX dependencies.
-- etc...
-
-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 DDR2/DDR3 Xilinx 7-Series FPGA and DDR3 on Lattice
-ECP5.
-"""
-
-import os
-import sys
-import math
-import struct
-import yaml
-import argparse
-
-from migen import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
-
-from litex.build.tools import replace_in_file
-from litex.build.generic_platform import *
-from litex.build.xilinx import XilinxPlatform
-from litex.build.lattice import LatticePlatform
-from litex.boards.platforms import versa_ecp5
-
-from litex.soc.cores.clock import *
-from litex.soc.integration.soc_core import *
-from litex.soc.integration.builder import *
-from litex.soc.interconnect import wishbone
-from litex.soc.cores.uart import *
-
-from gram import modules as litedram_modules
-from gram import phy as litedram_phys
-from gram.phy.ecp5ddrphy import ECP5DDRPHY
-from gram.phy.s7ddrphy import S7DDRPHY
-from gram.core.controller import ControllerSettings
-from gram.frontend.axi import *
-from gram.frontend.wishbone import *
-from gram.frontend.bist import LiteDRAMBISTGenerator
-from gram.frontend.bist import LiteDRAMBISTChecker
-from gram.frontend.fifo import LiteDRAMFIFO
-
-# IOs/Interfaces -----------------------------------------------------------------------------------
-
-
-def get_common_ios():
- return [
- # clk / rst
- ("clk", 0, Pins(1)),
- ("rst", 0, Pins(1)),
-
- # serial
- ("serial", 0,
- Subsignal("tx", Pins(1)),
- Subsignal("rx", Pins(1))
- ),
-
- # crg status
- ("pll_locked", 0, Pins(1)),
-
- # init status
- ("init_done", 0, Pins(1)),
- ("init_error", 0, Pins(1)),
-
- # iodelay clk / rst
- ("clk_iodelay", 0, Pins(1)),
- ("rst_iodelay", 0, Pins(1)),
-
- # user clk / rst
- ("user_clk", 0, Pins(1)),
- ("user_rst", 0, Pins(1))
- ]
-
-
-def get_dram_ios(core_config):
- sdram_module = core_config["sdram_module"]
- return [
- ("ddram", 0,
- Subsignal("a", Pins(
- log2_int(core_config["sdram_module"].nrows))),
- Subsignal("ba", Pins(
- log2_int(core_config["sdram_module"].nbanks))),
- Subsignal("ras_n", Pins(1)),
- Subsignal("cas_n", Pins(1)),
- Subsignal("we_n", Pins(1)),
- Subsignal("cs_n", Pins(core_config["sdram_rank_nb"])),
- Subsignal("dm", Pins(core_config["sdram_module_nb"])),
- Subsignal("dq", Pins(8*core_config["sdram_module_nb"])),
- Subsignal("dqs_p", Pins(core_config["sdram_module_nb"])),
- Subsignal("dqs_n", Pins(core_config["sdram_module_nb"])),
- Subsignal("clk_p", Pins(core_config["sdram_rank_nb"])),
- Subsignal("clk_n", Pins(core_config["sdram_rank_nb"])),
- Subsignal("cke", Pins(core_config["sdram_rank_nb"])),
- Subsignal("odt", Pins(core_config["sdram_rank_nb"])),
- Subsignal("reset_n", Pins(1))
- ),
- ]
-
-
-def get_native_user_port_ios(_id, aw, dw):
- return [
- ("user_port_{}".format(_id), 0,
- # cmd
- Subsignal("cmd_valid", Pins(1)),
- Subsignal("cmd_ready", Pins(1)),
- Subsignal("cmd_we", Pins(1)),
- Subsignal("cmd_addr", Pins(aw)),
-
- # wdata
- Subsignal("wdata_valid", Pins(1)),
- Subsignal("wdata_ready", Pins(1)),
- Subsignal("wdata_we", Pins(dw//8)),
- Subsignal("wdata_data", Pins(dw)),
-
- # rdata
- Subsignal("rdata_valid", Pins(1)),
- Subsignal("rdata_ready", Pins(1)),
- Subsignal("rdata_data", Pins(dw))
- ),
- ]
-
-
-def get_wishbone_user_port_ios(_id, aw, dw):
- return [
- ("user_port_{}".format(_id), 0,
- Subsignal("adr", Pins(aw)),
- Subsignal("dat_w", Pins(dw)),
- Subsignal("dat_r", Pins(dw)),
- Subsignal("sel", Pins(dw//8)),
- Subsignal("cyc", Pins(1)),
- Subsignal("stb", Pins(1)),
- Subsignal("ack", Pins(1)),
- Subsignal("we", Pins(1)),
- Subsignal("err", Pins(1)),
- ),
- ]
-
-
-def get_axi_user_port_ios(_id, aw, dw, iw):
- return [
- ("user_port_{}".format(_id), 0,
- # aw
- Subsignal("awvalid", Pins(1)),
- Subsignal("awready", Pins(1)),
- Subsignal("awaddr", Pins(aw)),
- Subsignal("awburst", Pins(2)),
- Subsignal("awlen", Pins(8)),
- Subsignal("awsize", Pins(4)),
- Subsignal("awid", Pins(iw)),
-
- # w
- Subsignal("wvalid", Pins(1)),
- Subsignal("wready", Pins(1)),
- Subsignal("wlast", Pins(1)),
- Subsignal("wstrb", Pins(dw//8)),
- Subsignal("wdata", Pins(dw)),
-
- # b
- Subsignal("bvalid", Pins(1)),
- Subsignal("bready", Pins(1)),
- Subsignal("bresp", Pins(2)),
- Subsignal("bid", Pins(iw)),
-
- # ar
- Subsignal("arvalid", Pins(1)),
- Subsignal("arready", Pins(1)),
- Subsignal("araddr", Pins(aw)),
- Subsignal("arburst", Pins(2)),
- Subsignal("arlen", Pins(8)),
- Subsignal("arsize", Pins(4)),
- Subsignal("arid", Pins(iw)),
-
- # r
- Subsignal("rvalid", Pins(1)),
- Subsignal("rready", Pins(1)),
- Subsignal("rlast", Pins(1)),
- Subsignal("rresp", Pins(2)),
- Subsignal("rdata", Pins(dw)),
- Subsignal("rid", Pins(iw))
- ),
- ]
-
-
-def get_fifo_user_port_ios(_id, dw):
- return [
- ("user_fifo_{}".format(_id), 0,
- # in
- Subsignal("in_valid", Pins(1)),
- Subsignal("in_ready", Pins(1)),
- Subsignal("in_data", Pins(dw)),
-
- # out
- Subsignal("out_valid", Pins(1)),
- Subsignal("out_ready", Pins(1)),
- Subsignal("out_data", Pins(dw)),
- ),
- ]
-
-
-class Platform(XilinxPlatform):
- def __init__(self):
- XilinxPlatform.__init__(self, "", io=[], toolchain="vivado")
-
-# CRG ----------------------------------------------------------------------------------------------
-
-
-class LiteDRAMECP5DDRPHYCRG(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
- clk = platform.request("clk")
- rst = platform.request("rst")
-
- # 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(clk, core_config["input_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),
- AsyncResetSynchronizer(
- self.cd_sys, ~por_done | ~pll.locked | rst),
- ]
-
-
-class LiteDRAMS7DDRPHYCRG(Module):
- def __init__(self, platform, core_config):
- self.clock_domains.cd_sys = ClockDomain()
- if core_config["memtype"] == "DDR3":
- self.clock_domains.cd_sys4x = ClockDomain(reset_less=True)
- self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True)
- else:
- self.clock_domains.cd_sys2x = ClockDomain(reset_less=True)
- self.clock_domains.cd_sys2x_dqs = ClockDomain(reset_less=True)
- self.clock_domains.cd_iodelay = ClockDomain()
-
- # # #
-
- clk = platform.request("clk")
- rst = platform.request("rst")
-
- self.submodules.sys_pll = sys_pll = S7PLL(
- speedgrade=core_config["speedgrade"])
- self.comb += sys_pll.reset.eq(rst)
- sys_pll.register_clkin(clk, core_config["input_clk_freq"])
- sys_pll.create_clkout(self.cd_sys, core_config["sys_clk_freq"])
- if core_config["memtype"] == "DDR3":
- sys_pll.create_clkout(self.cd_sys4x, 4*core_config["sys_clk_freq"])
- sys_pll.create_clkout(self.cd_sys4x_dqs, 4 *
- core_config["sys_clk_freq"], phase=90)
- else:
- sys_pll.create_clkout(self.cd_sys2x, 2*core_config["sys_clk_freq"])
- sys_pll.create_clkout(self.cd_sys2x_dqs, 2 *
- core_config["sys_clk_freq"], phase=90)
- self.comb += platform.request("pll_locked").eq(sys_pll.locked)
-
- self.submodules.iodelay_pll = iodelay_pll = S7PLL(
- speedgrade=core_config["speedgrade"])
- self.comb += iodelay_pll.reset.eq(rst)
- iodelay_pll.register_clkin(clk, core_config["input_clk_freq"])
- iodelay_pll.create_clkout(
- self.cd_iodelay, core_config["iodelay_clk_freq"])
- self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_iodelay)
-
-# LiteDRAMCoreControl ------------------------------------------------------------------------------
-
-
-class LiteDRAMCoreControl(Module, AutoCSR):
- def __init__(self):
- self.init_done = CSRStorage()
- self.init_error = CSRStorage()
-
-# LiteDRAMCore -------------------------------------------------------------------------------------
-
-
-class LiteDRAMCore(SoCCore):
- def __init__(self, platform, core_config, **kwargs):
- platform.add_extension(get_common_ios())
-
- # Parameters -------------------------------------------------------------------------------
- sys_clk_freq = core_config["sys_clk_freq"]
- cpu_type = core_config["cpu"]
- cpu_variant = core_config.get("cpu_variant", "standard")
- csr_alignment = core_config.get("csr_alignment", 32)
- if cpu_type is None:
- kwargs["integrated_rom_size"] = 0
- kwargs["integrated_sram_size"] = 0
- kwargs["with_uart"] = False
- kwargs["with_timer"] = False
- kwargs["with_ctrl"] = False
-
- # SoCCore ----------------------------------------------------------------------------------
- SoCCore.__init__(self, platform, sys_clk_freq,
- cpu_type=cpu_type,
- cpu_variant=cpu_variant,
- csr_alignment=csr_alignment,
- **kwargs)
-
- # CRG --------------------------------------------------------------------------------------
- if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
- self.submodules.crg = crg = LiteDRAMECP5DDRPHYCRG(
- platform, core_config)
- if core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
- self.submodules.crg = LiteDRAMS7DDRPHYCRG(platform, core_config)
-
- # DRAM -------------------------------------------------------------------------------------
- platform.add_extension(get_dram_ios(core_config))
- # ECP5DDRPHY
- if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
- assert core_config["memtype"] in ["DDR3"]
- self.submodules.ddrphy = core_config["sdram_phy"](
- pads=platform.request("ddram"),
- sys_clk_freq=sys_clk_freq)
- self.comb += crg.stop.eq(self.ddrphy.init.stop)
- self.add_constant("ECP5DDRPHY")
- sdram_module = core_config["sdram_module"](sys_clk_freq, "1:2")
- # S7DDRPHY
- if core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
- assert core_config["memtype"] in ["DDR2", "DDR3"]
- self.submodules.ddrphy = core_config["sdram_phy"](
- pads=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"])
- self.add_csr("ddrphy")
-
- 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.add_sdram("sdram",
- phy=self.ddrphy,
- module=sdram_module,
- origin=self.mem_map["main_ram"],
- # Only expose 16MB to the CPU, enough for Init/Calib.
- size=0x01000000,
- with_soc_interconnect=cpu_type is not None,
- l2_cache_size=0,
- l2_cache_min_data_width=0,
- controller_settings=controller_settings,
- )
-
- # DRAM Control/Status ----------------------------------------------------------------------
- # Expose calibration status to user.
- self.submodules.ddrctrl = LiteDRAMCoreControl()
- self.add_csr("ddrctrl")
- self.comb += platform.request("init_done").eq(
- self.ddrctrl.init_done.storage)
- self.comb += platform.request("init_error").eq(
- self.ddrctrl.init_error.storage)
- # If no CPU, expose a bus control interface to user.
- if cpu_type is None:
- wb_bus = wishbone.Interface()
- self.bus.add_master(master=wb_bus)
- platform.add_extension(wb_bus.get_ios("wb_ctrl"))
- wb_pads = platform.request("wb_ctrl")
- self.comb += wb_bus.connect_to_pads(wb_pads, mode="slave")
-
- # User ports -------------------------------------------------------------------------------
- self.comb += [
- platform.request("user_clk").eq(ClockSignal()),
- platform.request("user_rst").eq(ResetSignal())
- ]
- for name, port in core_config["user_ports"].items():
- # Native -------------------------------------------------------------------------------
- if port["type"] == "native":
- user_port = self.sdram.crossbar.get_port()
- platform.add_extension(get_native_user_port_ios(name,
- user_port.address_width,
- user_port.data_width))
- _user_port_io = platform.request("user_port_{}".format(name))
- self.comb += [
- # cmd
- user_port.cmd.valid.eq(_user_port_io.cmd_valid),
- _user_port_io.cmd_ready.eq(user_port.cmd.ready),
- user_port.cmd.we.eq(_user_port_io.cmd_we),
- user_port.cmd.addr.eq(_user_port_io.cmd_addr),
-
- # wdata
- user_port.wdata.valid.eq(_user_port_io.wdata_valid),
- _user_port_io.wdata_ready.eq(user_port.wdata.ready),
- user_port.wdata.we.eq(_user_port_io.wdata_we),
- user_port.wdata.data.eq(_user_port_io.wdata_data),
-
- # rdata
- _user_port_io.rdata_valid.eq(user_port.rdata.valid),
- user_port.rdata.ready.eq(_user_port_io.rdata_ready),
- _user_port_io.rdata_data.eq(user_port.rdata.data),
- ]
- # Wishbone -----------------------------------------------------------------------------
- elif port["type"] == "wishbone":
- user_port = self.sdram.crossbar.get_port()
- wb_port = wishbone.Interface(
- user_port.data_width,
- user_port.address_width)
- wishbone2native = LiteDRAMWishbone2Native(wb_port, user_port)
- self.submodules += wishbone2native
- platform.add_extension(get_wishbone_user_port_ios(name,
- len(wb_port.adr),
- len(wb_port.dat_w)))
- _wb_port_io = platform.request("user_port_{}".format(name))
- self.comb += [
- wb_port.adr.eq(_wb_port_io.adr),
- wb_port.dat_w.eq(_wb_port_io.dat_w),
- _wb_port_io.dat_r.eq(wb_port.dat_r),
- wb_port.sel.eq(_wb_port_io.sel),
- wb_port.cyc.eq(_wb_port_io.cyc),
- wb_port.stb.eq(_wb_port_io.stb),
- _wb_port_io.ack.eq(wb_port.ack),
- wb_port.we.eq(_wb_port_io.we),
- _wb_port_io.err.eq(wb_port.err),
- ]
- # AXI ----------------------------------------------------------------------------------
- elif port["type"] == "axi":
- user_port = self.sdram.crossbar.get_port()
- axi_port = LiteDRAMAXIPort(
- user_port.data_width,
- user_port.address_width +
- log2_int(user_port.data_width//8),
- port["id_width"])
- axi2native = LiteDRAMAXI2Native(axi_port, user_port)
- self.submodules += axi2native
- platform.add_extension(get_axi_user_port_ios(name,
- axi_port.address_width,
- axi_port.data_width,
- port["id_width"]))
- _axi_port_io = platform.request("user_port_{}".format(name))
- self.comb += [
- # aw
- axi_port.aw.valid.eq(_axi_port_io.awvalid),
- _axi_port_io.awready.eq(axi_port.aw.ready),
- axi_port.aw.addr.eq(_axi_port_io.awaddr),
- axi_port.aw.burst.eq(_axi_port_io.awburst),
- axi_port.aw.len.eq(_axi_port_io.awlen),
- axi_port.aw.size.eq(_axi_port_io.awsize),
- axi_port.aw.id.eq(_axi_port_io.awid),
-
- # w
- axi_port.w.valid.eq(_axi_port_io.wvalid),
- _axi_port_io.wready.eq(axi_port.w.ready),
- axi_port.w.last.eq(_axi_port_io.wlast),
- axi_port.w.strb.eq(_axi_port_io.wstrb),
- axi_port.w.data.eq(_axi_port_io.wdata),
-
- # b
- _axi_port_io.bvalid.eq(axi_port.b.valid),
- axi_port.b.ready.eq(_axi_port_io.bready),
- _axi_port_io.bresp.eq(axi_port.b.resp),
- _axi_port_io.bid.eq(axi_port.b.id),
-
- # ar
- axi_port.ar.valid.eq(_axi_port_io.arvalid),
- _axi_port_io.arready.eq(axi_port.ar.ready),
- axi_port.ar.addr.eq(_axi_port_io.araddr),
- axi_port.ar.burst.eq(_axi_port_io.arburst),
- axi_port.ar.len.eq(_axi_port_io.arlen),
- axi_port.ar.size.eq(_axi_port_io.arsize),
- axi_port.ar.id.eq(_axi_port_io.arid),
-
- # r
- _axi_port_io.rvalid.eq(axi_port.r.valid),
- axi_port.r.ready.eq(_axi_port_io.rready),
- _axi_port_io.rlast.eq(axi_port.r.last),
- _axi_port_io.rresp.eq(axi_port.r.resp),
- _axi_port_io.rdata.eq(axi_port.r.data),
- _axi_port_io.rid.eq(axi_port.r.id),
- ]
- # FIFO ---------------------------------------------------------------------------------
- elif port["type"] == "fifo":
- platform.add_extension(
- get_fifo_user_port_ios(name, user_port.data_width))
- _user_fifo_io = platform.request("user_fifo_{}".format(name))
- fifo = LiteDRAMFIFO(
- data_width=user_port.data_width,
- base=port["base"],
- depth=port["depth"],
- write_port=self.sdram.crossbar.get_port("write"),
- write_threshold=port["depth"] - 32, # FIXME
- read_port=self.sdram.crossbar.get_port("read"),
- read_threshold=32 # FIXME
- )
- self.submodules += fifo
- self.comb += [
- # in
- fifo.sink.valid.eq(_user_fifo_io.in_valid),
- _user_fifo_io.in_ready.eq(fifo.sink.ready),
- fifo.sink.data.eq(_user_fifo_io.in_data),
-
- # out
- _user_fifo_io.out_valid.eq(fifo.source.valid),
- fifo.source.ready.eq(_user_fifo_io.out_ready),
- _user_fifo_io.out_data.eq(fifo.source.data),
- ]
- else:
- raise ValueError(
- "Unsupported port type: {}".format(port["type"]))
-
-# Build --------------------------------------------------------------------------------------------
-
-
-def main():
- parser = argparse.ArgumentParser(
- description="LiteDRAM standalone core generator")
- builder_args(parser)
- parser.set_defaults(output_dir="build")
- parser.add_argument("config", help="YAML config file")
- args = parser.parse_args()
- core_config = yaml.load(open(args.config).read(), Loader=yaml.Loader)
-
- # Convert YAML elements to Python/LiteX --------------------------------------------------------
- for k, v in core_config.items():
- replaces = {"False": False, "True": True, "None": None}
- for r in replaces.keys():
- if v == r:
- core_config[k] = replaces[r]
- if "clk_freq" in k:
- core_config[k] = float(core_config[k])
- if k == "sdram_module":
- core_config[k] = getattr(litedram_modules, core_config[k])
- if k == "sdram_phy":
- core_config[k] = getattr(litedram_phys, core_config[k])
-
- # Generate core --------------------------------------------------------------------------------
- if core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]:
- # FIXME: allow other devices.
- platform = LatticePlatform(
- "LFE5UM5G-45F-8BG381C", io=[], toolchain="trellis")
- elif core_config["sdram_phy"] in [litedram_phys.A7DDRPHY, litedram_phys.K7DDRPHY, litedram_phys.V7DDRPHY]:
- platform = XilinxPlatform("", io=[], toolchain="vivado")
- else:
- raise ValueError("Unsupported SDRAM PHY: {}".format(
- core_config["sdram_phy"]))
-
- builder_arguments = builder_argdict(args)
- builder_arguments["compile_gateware"] = False
-
- soc = LiteDRAMCore(platform, core_config, integrated_rom_size=0x6000)
- builder = Builder(soc, **builder_arguments)
- vns = builder.build(build_name="litedram_core", regular_comb=False)
-
- if soc.cpu_type is not None:
- init_filename = "mem.init"
- os.system("mv {} {}".format(
- os.path.join(builder.gateware_dir, init_filename),
- os.path.join(builder.gateware_dir, "litedram_core.init"),
- ))
- replace_in_file(os.path.join(builder.gateware_dir,
- "litedram_core.v"), init_filename, "litedram_core.init")
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-# This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq <sb@m-labs.hk>
-# This file is Copyright (c) 2013-2020 Florent Kermarrec <florent@enjoy-digital.fr>
-# This file is Copyright (c) 2017 whitequark <whitequark@whitequark.org>
-# This file is Copyright (c) 2014 Yann Sionneau <ys@m-labs.hk>
-# This file is Copyright (c) 2018 bunnie <bunnie@kosagi.com>
-# This file is Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
-# License: BSD
-
-from nmigen.utils import log2_int
-
-cmds = {
- "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
- "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
- "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
-}
-
-# SDR ----------------------------------------------------------------------------------------------
-
-
-def get_sdr_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 1
- mr = log2_int(bl) + (cl << 4)
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(
- cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl,
- bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- return init_sequence, None
-
-# DDR ----------------------------------------------------------------------------------------------
-
-
-def get_ddr_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 4
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(
- cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl,
- bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- return init_sequence, None
-
-# LPDDR --------------------------------------------------------------------------------------------
-
-
-def get_lpddr_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 4
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(
- cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl,
- bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- return init_sequence, None
-
-# DDR2 ---------------------------------------------------------------------------------------------
-
-
-def get_ddr2_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 4
- wr = 2
- mr = log2_int(bl) + (cl << 4) + (wr << 9)
- emr = 0
- emr2 = 0
- emr3 = 0
- ocd = 7 << 7
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(
- cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl,
- bl), mr, 0, cmds["MODE_REGISTER"], 200),
- ("Load Extended Mode Register / OCD Default",
- emr+ocd, 1, cmds["MODE_REGISTER"], 0),
- ("Load Extended Mode Register / OCD Exit",
- emr, 1, cmds["MODE_REGISTER"], 0),
- ]
-
- return init_sequence, None
-
-# DDR3 ---------------------------------------------------------------------------------------------
-
-
-def get_ddr3_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 8
- cwl = phy_settings.cwl
-
- def format_mr0(bl, cl, wr, dll_reset):
- bl_to_mr0 = {
- 4: 0b10,
- 8: 0b00
- }
- cl_to_mr0 = {
- 5: 0b0010,
- 6: 0b0100,
- 7: 0b0110,
- 8: 0b1000,
- 9: 0b1010,
- 10: 0b1100,
- 11: 0b1110,
- 12: 0b0001,
- 13: 0b0011,
- 14: 0b0101
- }
- wr_to_mr0 = {
- 16: 0b000,
- 5: 0b001,
- 6: 0b010,
- 7: 0b011,
- 8: 0b100,
- 10: 0b101,
- 12: 0b110,
- 14: 0b111
- }
- mr0 = bl_to_mr0[bl]
- mr0 |= (cl_to_mr0[cl] & 1) << 2
- mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
- mr0 |= dll_reset << 8
- mr0 |= wr_to_mr0[wr] << 9
- return mr0
-
- def format_mr1(ron, rtt_nom):
- mr1 = ((ron >> 0) & 1) << 1
- mr1 |= ((ron >> 1) & 1) << 5
- mr1 |= ((rtt_nom >> 0) & 1) << 2
- mr1 |= ((rtt_nom >> 1) & 1) << 6
- mr1 |= ((rtt_nom >> 2) & 1) << 9
- return mr1
-
- def format_mr2(cwl, rtt_wr):
- mr2 = (cwl-5) << 3
- mr2 |= rtt_wr << 9
- return mr2
-
- z_to_rtt_nom = {
- "disabled": 0,
- "60ohm": 1,
- "120ohm": 2,
- "40ohm": 3,
- "20ohm": 4,
- "30ohm": 5
- }
-
- z_to_rtt_wr = {
- "disabled": 0,
- "60ohm": 1,
- "120ohm": 2,
- }
-
- z_to_ron = {
- "40ohm": 0,
- "34ohm": 1,
- }
-
- # default electrical settings (point to point)
- rtt_nom = "60ohm"
- rtt_wr = "60ohm"
- ron = "34ohm"
-
- # override electrical settings if specified
- if hasattr(phy_settings, "rtt_nom"):
- rtt_nom = phy_settings.rtt_nom
- if hasattr(phy_settings, "rtt_wr"):
- rtt_wr = phy_settings.rtt_wr
- if hasattr(phy_settings, "ron"):
- ron = phy_settings.ron
-
- # >= ceiling(tWR/tCK)
- wr = max(timing_settings.tWTR*phy_settings.nphases, 5)
- mr0 = format_mr0(bl, cl, wr, 1)
- mr1 = format_mr1(z_to_ron[ron], z_to_rtt_nom[rtt_nom])
- mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr])
- mr3 = 0
-
- init_sequence = [
- ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
- ("Load Mode Register 2, CWL={0:d}".format(
- cwl), mr2, 2, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(
- cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
- ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
- ]
-
- return init_sequence, mr1
-
-# DDR4 ---------------------------------------------------------------------------------------------
-
-
-def get_ddr4_phy_init_sequence(phy_settings, timing_settings):
- cl = phy_settings.cl
- bl = 8
- cwl = phy_settings.cwl
-
- def format_mr0(bl, cl, wr, dll_reset):
- bl_to_mr0 = {
- 4: 0b10,
- 8: 0b00
- }
- cl_to_mr0 = {
- 9: 0b00000,
- 10: 0b00001,
- 11: 0b00010,
- 12: 0b00011,
- 13: 0b00100,
- 14: 0b00101,
- 15: 0b00110,
- 16: 0b00111,
- 18: 0b01000,
- 20: 0b01001,
- 22: 0b01010,
- 24: 0b01011,
- 23: 0b01100,
- 17: 0b01101,
- 19: 0b01110,
- 21: 0b01111,
- 25: 0b10000,
- 26: 0b10001,
- 27: 0b10010,
- 28: 0b10011,
- 29: 0b10100,
- 30: 0b10101,
- 31: 0b10110,
- 32: 0b10111,
- }
- wr_to_mr0 = {
- 10: 0b0000,
- 12: 0b0001,
- 14: 0b0010,
- 16: 0b0011,
- 18: 0b0100,
- 20: 0b0101,
- 24: 0b0110,
- 22: 0b0111,
- 26: 0b1000,
- 28: 0b1001,
- }
- mr0 = bl_to_mr0[bl]
- mr0 |= (cl_to_mr0[cl] & 0b1) << 2
- mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
- mr0 |= ((cl_to_mr0[cl] >> 4) & 0b1) << 12
- mr0 |= dll_reset << 8
- mr0 |= (wr_to_mr0[wr] & 0b111) << 9
- mr0 |= (wr_to_mr0[wr] >> 3) << 13
- return mr0
-
- def format_mr1(dll_enable, ron, rtt_nom):
- mr1 = dll_enable
- mr1 |= ((ron >> 0) & 0b1) << 1
- mr1 |= ((ron >> 1) & 0b1) << 2
- mr1 |= ((rtt_nom >> 0) & 0b1) << 8
- mr1 |= ((rtt_nom >> 1) & 0b1) << 9
- mr1 |= ((rtt_nom >> 2) & 0b1) << 10
- return mr1
-
- def format_mr2(cwl, rtt_wr):
- cwl_to_mr2 = {
- 9: 0b000,
- 10: 0b001,
- 11: 0b010,
- 12: 0b011,
- 14: 0b100,
- 16: 0b101,
- 18: 0b110,
- 20: 0b111
- }
- mr2 = cwl_to_mr2[cwl] << 3
- mr2 |= rtt_wr << 9
- return mr2
-
- def format_mr3(fine_refresh_mode):
- fine_refresh_mode_to_mr3 = {
- "1x": 0b000,
- "2x": 0b001,
- "4x": 0b010
- }
- mr3 = fine_refresh_mode_to_mr3[fine_refresh_mode] << 6
- return mr3
-
- def format_mr6(tccd):
- tccd_to_mr6 = {
- 4: 0b000,
- 5: 0b001,
- 6: 0b010,
- 7: 0b011,
- 8: 0b100
- }
- mr6 = tccd_to_mr6[tccd] << 10
- return mr6
-
- z_to_rtt_nom = {
- "disabled": 0b000,
- "60ohm": 0b001,
- "120ohm": 0b010,
- "40ohm": 0b011,
- "240ohm": 0b100,
- "48ohm": 0b101,
- "80ohm": 0b110,
- "34ohm": 0b111
- }
-
- z_to_rtt_wr = {
- "disabled": 0b000,
- "120ohm": 0b001,
- "240ohm": 0b010,
- "high-z": 0b011,
- "80ohm": 0b100,
- }
-
- z_to_ron = {
- "34ohm": 0b00,
- "48ohm": 0b01,
- }
-
- # default electrical settings (point to point)
- rtt_nom = "40ohm"
- rtt_wr = "120ohm"
- ron = "34ohm"
-
- # override electrical settings if specified
- if hasattr(phy_settings, "rtt_nom"):
- rtt_nom = phy_settings.rtt_nom
- if hasattr(phy_settings, "rtt_wr"):
- rtt_wr = phy_settings.rtt_wr
- if hasattr(phy_settings, "ron"):
- ron = phy_settings.ron
-
- # >= ceiling(tWR/tCK)
- wr = max(timing_settings.tWTR*phy_settings.nphases, 10)
- mr0 = format_mr0(bl, cl, wr, 1)
- mr1 = format_mr1(1, z_to_ron[ron], z_to_rtt_nom[rtt_nom])
- mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr])
- mr3 = format_mr3(timing_settings.fine_refresh_mode)
- mr4 = 0
- mr5 = 0
- mr6 = format_mr6(4) # FIXME: tCCD
-
- rdimm_init = []
- if phy_settings.is_rdimm:
- def get_coarse_speed(tck, pll_bypass):
- # JESD82-31A page 78
- f_to_coarse_speed = {
- 1600e6: 0,
- 1866e6: 1,
- 2133e6: 2,
- 2400e6: 3,
- 2666e6: 4,
- 2933e6: 5,
- 3200e6: 6,
- }
- if pll_bypass:
- return 7
- else:
- for f, speed in f_to_coarse_speed.items():
- if tck >= 2/f:
- return speed
- raise ValueError
-
- def get_fine_speed(tck):
- # JESD82-31A page 83
- freq = 2/tck
- fine_speed = (freq - 1240e6) // 20e6
- fine_speed = max(fine_speed, 0)
- fine_speed = min(fine_speed, 0b1100001)
- return fine_speed
-
- coarse_speed = get_coarse_speed(
- phy_settings.tck, phy_settings.rcd_pll_bypass)
- fine_speed = get_fine_speed(phy_settings.tck)
-
- # F0RC06: command space control; 0: reset RCD
- rcd_reset = 0x060 | 0x0
-
- f0rc0f = 0x0F0 | 0x4 # F0RC05: 0 nCK latency adder
-
- f0rc03 = 0x030 | phy_settings.rcd_ca_cs_drive # F0RC03: CA/CS drive strength
- f0rc04 = 0x040 | phy_settings.rcd_odt_cke_drive # F0RC04: ODT/CKE drive strength
- f0rc05 = 0x050 | phy_settings.rcd_clk_drive # F0RC04: ODT/CKE drive strength
-
- # F0RC0A: coarse speed selection and PLL bypass
- f0rc0a = 0x0A0 | coarse_speed
- f0rc3x = 0x300 | fine_speed # F0RC3x: fine speed selection
-
- rdimm_init = [
- ("Reset RCD", rcd_reset, 7, cmds["MODE_REGISTER"], 50000),
- ("Load RCD F0RC0F", f0rc0f, 7, cmds["MODE_REGISTER"], 100),
- ("Load RCD F0RC03", f0rc03, 7, cmds["MODE_REGISTER"], 100),
- ("Load RCD F0RC04", f0rc04, 7, cmds["MODE_REGISTER"], 100),
- ("Load RCD F0RC05", f0rc05, 7, cmds["MODE_REGISTER"], 100),
- ("Load RCD F0RC0A", f0rc0a, 7, cmds["MODE_REGISTER"], 100),
- ("Load RCD F0RC3X", f0rc3x, 7, cmds["MODE_REGISTER"], 100),
- ]
-
- init_sequence = [
- ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
- ] + rdimm_init + [
- ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 6", mr6, 6, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 5", mr5, 5, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 4", mr4, 4, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 2, CWL={0:d}".format(
- cwl), mr2, 2, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(
- cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
- ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
- ]
-
- return init_sequence, mr1
-
-# Init Sequence ------------------------------------------------------------------------------------
-
-
-def get_sdram_phy_init_sequence(phy_settings, timing_settings):
- return {
- "SDR": get_sdr_phy_init_sequence,
- "DDR": get_ddr_phy_init_sequence,
- "LPDDR": get_lpddr_phy_init_sequence,
- "DDR2": get_ddr2_phy_init_sequence,
- "DDR3": get_ddr3_phy_init_sequence,
- "DDR4": get_ddr4_phy_init_sequence,
- }[phy_settings.memtype](phy_settings, timing_settings)
-
-# C Header -----------------------------------------------------------------------------------------
-
-
-def get_sdram_phy_c_header(phy_settings, timing_settings):
- r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
- r += "#include <hw/common.h>\n"
- r += "#include <generated/csr.h>\n"
- r += "\n"
-
- r += "#define DFII_CONTROL_SEL 0x01\n"
- r += "#define DFII_CONTROL_CKE 0x02\n"
- r += "#define DFII_CONTROL_ODT 0x04\n"
- r += "#define DFII_CONTROL_RESET_N 0x08\n"
- r += "\n"
-
- r += "#define DFII_COMMAND_CS 0x01\n"
- r += "#define DFII_COMMAND_WE 0x02\n"
- r += "#define DFII_COMMAND_CAS 0x04\n"
- r += "#define DFII_COMMAND_RAS 0x08\n"
- r += "#define DFII_COMMAND_WRDATA 0x10\n"
- r += "#define DFII_COMMAND_RDDATA 0x20\n"
- r += "\n"
-
- phytype = phy_settings.phytype.upper()
- nphases = phy_settings.nphases
-
- # Define PHY type and number of phases
- r += "#define SDRAM_PHY_"+phytype+"\n"
- r += "#define SDRAM_PHY_PHASES "+str(nphases)+"\n"
-
- # Define Read/Write Leveling capability
- if phytype in ["USDDRPHY", "USPDDRPHY", "K7DDRPHY", "V7DDRPHY"]:
- r += "#define SDRAM_PHY_WRITE_LEVELING_CAPABLE\n"
- if phytype in ["USDDRPHY", "USPDDRPHY"]:
- r += "#define SDRAM_PHY_WRITE_LEVELING_REINIT\n"
- if phytype in ["USDDRPHY", "USPDDRPHY", "A7DDRPHY", "K7DDRPHY", "V7DDRPHY", "ECP5DDRPHY"]:
- r += "#define SDRAM_PHY_READ_LEVELING_CAPABLE\n"
-
- # Define number of modules/delays/bitslips
- if phytype in ["USDDRPHY", "USPDDRPHY"]:
- r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2\n"
- r += "#define SDRAM_PHY_DELAYS 512\n"
- r += "#define SDRAM_PHY_BITSLIPS 16\n"
- elif phytype in ["A7DDRPHY", "K7DDRPHY", "V7DDRPHY"]:
- r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/2\n"
- r += "#define SDRAM_PHY_DELAYS 32\n"
- r += "#define SDRAM_PHY_BITSLIPS 16\n"
- elif phytype in ["ECP5DDRPHY"]:
- r += "#define SDRAM_PHY_MODULES DFII_PIX_DATA_BYTES/4\n"
- r += "#define SDRAM_PHY_DELAYS 8\n"
- r += "#define SDRAM_PHY_BITSLIPS 4\n"
-
- if phy_settings.is_rdimm:
- assert phy_settings.memtype == "DDR4"
- r += "#define SDRAM_PHY_DDR4_RDIMM\n"
-
- r += "\n"
-
- r += "static void cdelay(int i);\n"
-
- # commands_px functions
- for n in range(nphases):
- r += """
-__attribute__((unused)) static void command_p{n}(int cmd)
-{{
- sdram_dfii_pi{n}_command_write(cmd);
- sdram_dfii_pi{n}_command_issue_write(1);
-}}""".format(n=str(n))
- r += "\n\n"
-
- # rd/wr access macros
- r += """
-#define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X)
-#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X)
-#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X)
-#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X)
-#define command_prd(X) command_p{rdphase}(X)
-#define command_pwr(X) command_p{wrphase}(X)
-""".format(rdphase=str(phy_settings.rdphase), wrphase=str(phy_settings.wrphase))
- r += "\n"
-
- #
- # sdrrd/sdrwr functions utilities
- #
- r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
- sdram_dfii_pix_wrdata_addr = []
- for n in range(nphases):
- sdram_dfii_pix_wrdata_addr.append(
- "CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
- r += """
-const unsigned long sdram_dfii_pix_wrdata_addr[SDRAM_PHY_PHASES] = {{
-\t{sdram_dfii_pix_wrdata_addr}
-}};
-""".format(sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr))
-
- sdram_dfii_pix_rddata_addr = []
- for n in range(nphases):
- sdram_dfii_pix_rddata_addr.append(
- "CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n))
- r += """
-const unsigned long sdram_dfii_pix_rddata_addr[SDRAM_PHY_PHASES] = {{
-\t{sdram_dfii_pix_rddata_addr}
-}};
-""".format(sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr))
- r += "\n"
-
- init_sequence, mr1 = get_sdram_phy_init_sequence(
- phy_settings, timing_settings)
-
- if phy_settings.memtype in ["DDR3", "DDR4"]:
- # the value of MR1 needs to be modified during write leveling
- r += "#define DDRX_MR1 {}\n\n".format(mr1)
-
- r += "static void init_sequence(void)\n{\n"
- for comment, a, ba, cmd, delay in init_sequence:
- invert_masks = [(0, 0), ]
- if phy_settings.is_rdimm:
- assert phy_settings.memtype == "DDR4"
- # JESD82-31A page 38
- #
- # B-side chips have certain usually-inconsequential address and BA
- # bits inverted by the RCD to reduce SSO current. For mode register
- # writes, however, we must compensate for this. BG[1] also directs
- # writes either to the A side (BG[1]=0) or B side (BG[1]=1)
- #
- # The 'ba != 7' is because we don't do this to writes to the RCD
- # itself.
- if ba != 7:
- invert_masks.append((0b10101111111000, 0b1111))
-
- for a_inv, ba_inv in invert_masks:
- r += "\t/* {0} */\n".format(comment)
- r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a ^ a_inv)
- r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(
- ba ^ ba_inv)
- if cmd[:12] == "DFII_CONTROL":
- r += "\tsdram_dfii_control_write({0});\n".format(cmd)
- else:
- r += "\tcommand_p0({0});\n".format(cmd)
- if delay:
- r += "\tcdelay({0:d});\n".format(delay)
- r += "\n"
- r += "}\n"
-
- r += "#endif\n"
-
- return r
-
-# Python Header ------------------------------------------------------------------------------------
-
-
-def get_sdram_phy_py_header(phy_settings, timing_settings):
- r = ""
- r += "dfii_control_sel = 0x01\n"
- r += "dfii_control_cke = 0x02\n"
- r += "dfii_control_odt = 0x04\n"
- r += "dfii_control_reset_n = 0x08\n"
- r += "\n"
- r += "dfii_command_cs = 0x01\n"
- r += "dfii_command_we = 0x02\n"
- r += "dfii_command_cas = 0x04\n"
- r += "dfii_command_ras = 0x08\n"
- r += "dfii_command_wrdata = 0x10\n"
- r += "dfii_command_rddata = 0x20\n"
- r += "\n"
-
- init_sequence, mr1 = get_sdram_phy_init_sequence(
- phy_settings, timing_settings)
-
- if mr1 is not None:
- r += "ddrx_mr1 = 0x{:x}\n".format(mr1)
- r += "\n"
-
- r += "init_sequence = [\n"
- for comment, a, ba, cmd, delay in init_sequence:
- r += " "
- r += "(\"" + comment + "\", "
- r += str(a) + ", "
- r += str(ba) + ", "
- r += cmd.lower() + ", "
- r += str(delay) + "),"
- r += "\n"
- r += "]\n"
- return r