Merge pull request #268 from antmicro/jboc/init-refactor
Refactor init code generation
This commit is contained in:
commit
ca609005bc
|
@ -11,6 +11,7 @@ import math
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
from operator import add
|
from operator import add
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from typing import Union, Optional
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
|
@ -203,11 +204,29 @@ class Settings:
|
||||||
|
|
||||||
|
|
||||||
class PhySettings(Settings):
|
class PhySettings(Settings):
|
||||||
def __init__(self, phytype, memtype, databits, dfi_databits,
|
def __init__(self,
|
||||||
nphases,
|
phytype: str,
|
||||||
rdphase, wrphase,
|
memtype: str, # SDR, DDR, DDR2, ...
|
||||||
cl, read_latency, write_latency, nranks=1, cwl=None,
|
databits: int, # number of DQ lines
|
||||||
cmd_latency=None, cmd_delay=None):
|
dfi_databits: int, # per-phase DFI data width
|
||||||
|
nphases: int, # number of DFI phases
|
||||||
|
rdphase: Union[int, Signal], # phase on which READ command will be issued by MC
|
||||||
|
wrphase: Union[int, Signal], # phase on which WRITE command will be issued by MC
|
||||||
|
cl: int, # latency (DRAM clk) from READ command to first data
|
||||||
|
read_latency: int, # latency (MC clk) from DFI.rddata_en to DFI.rddata_valid
|
||||||
|
write_latency: int, # latency (MC clk) from DFI.wrdata_en to DFI.wrdata
|
||||||
|
nranks: int = 1, # number of DRAM ranks
|
||||||
|
cwl: Optional[int] = None, # latency (DRAM clk) from WRITE command to first data
|
||||||
|
cmd_latency: Optional[int] = None, # additional command latency (MC clk)
|
||||||
|
cmd_delay: Optional[int] = None, # used to force cmd delay during initialization in BIOS
|
||||||
|
bitslips: int = 0, # number of write/read bitslip taps
|
||||||
|
delays: int = 0, # number of write/read delay taps
|
||||||
|
# PHY training capabilities
|
||||||
|
write_leveling: bool = False,
|
||||||
|
write_dq_dqs_training: bool = False,
|
||||||
|
write_latency_calibration: bool = False,
|
||||||
|
read_leveling: bool = False,
|
||||||
|
):
|
||||||
self.set_attributes(locals())
|
self.set_attributes(locals())
|
||||||
self.cwl = cl if cwl is None else cwl
|
self.cwl = cl if cwl is None else cwl
|
||||||
self.is_rdimm = False
|
self.is_rdimm = False
|
||||||
|
|
251
litedram/init.py
251
litedram/init.py
|
@ -11,6 +11,7 @@
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
|
@ -643,146 +644,169 @@ def get_sdram_phy_init_sequence(phy_settings, timing_settings):
|
||||||
|
|
||||||
# C Header -----------------------------------------------------------------------------------------
|
# C Header -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class CGenerator(list):
|
||||||
|
# C code generator - list of strings (=lines) or CGenerator instances (sub-generators)
|
||||||
|
def __init__(self, indent=0, indent_str="\t"):
|
||||||
|
self.indent = indent
|
||||||
|
self.indent_str = indent_str
|
||||||
|
|
||||||
|
def __iadd__(self, x):
|
||||||
|
# make `c += "int x = 0;"` append it as line, not char-by-char
|
||||||
|
if isinstance(x, str):
|
||||||
|
x = [x]
|
||||||
|
return super().__iadd__(x)
|
||||||
|
|
||||||
|
def header_guard(self, name):
|
||||||
|
self._header_guard = name
|
||||||
|
|
||||||
|
def generate_lines(self):
|
||||||
|
if getattr(self, "_header_guard", None) is not None:
|
||||||
|
self.insert(0, f"#ifndef {self._header_guard}")
|
||||||
|
self.insert(1, f"#define {self._header_guard}")
|
||||||
|
self.insert(2, "")
|
||||||
|
self.append("")
|
||||||
|
self.append(f"#endif /* {self._header_guard} */")
|
||||||
|
self._header_guard = None
|
||||||
|
lines = []
|
||||||
|
for entry in self:
|
||||||
|
if isinstance(entry, CGenerator):
|
||||||
|
lines.extend(entry.generate_lines())
|
||||||
|
else:
|
||||||
|
line = (self.indent * self.indent_str) + entry
|
||||||
|
lines.append(line.rstrip())
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
lines = self.generate_lines()
|
||||||
|
return "\n".join(lines).strip() + "\n"
|
||||||
|
|
||||||
|
def include(self, path):
|
||||||
|
self.append(f"#include {path}")
|
||||||
|
|
||||||
|
def define(self, var, value=None):
|
||||||
|
if isinstance(value, (int, float)):
|
||||||
|
value = str(value)
|
||||||
|
self.append(f"#define {var}" + (f" {value}" if value is not None else ""))
|
||||||
|
|
||||||
|
def newline(self, n=1):
|
||||||
|
self.extend([""] * n)
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def block(self, head=None, newline=True):
|
||||||
|
if head is not None:
|
||||||
|
self.append(head + (" {" if not newline else ""))
|
||||||
|
if newline:
|
||||||
|
self.append("{")
|
||||||
|
else:
|
||||||
|
self.append("{")
|
||||||
|
subgenerator = CGenerator(indent=self.indent + 1, indent_str=self.indent_str)
|
||||||
|
yield subgenerator
|
||||||
|
self.append(subgenerator)
|
||||||
|
self.append("}")
|
||||||
|
|
||||||
|
|
||||||
def get_sdram_phy_c_header(phy_settings, timing_settings):
|
def get_sdram_phy_c_header(phy_settings, timing_settings):
|
||||||
r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
|
r = CGenerator()
|
||||||
r += "#include <hw/common.h>\n"
|
r.header_guard("__GENERATED_SDRAM_PHY_H")
|
||||||
r += "#include <generated/csr.h>\n"
|
r.include("<hw/common.h>")
|
||||||
r += "\n"
|
r.include("<generated/csr.h>")
|
||||||
|
r.newline()
|
||||||
|
|
||||||
r += "#define DFII_CONTROL_SEL 0x01\n"
|
r.define("DFII_CONTROL_SEL", "0x01")
|
||||||
r += "#define DFII_CONTROL_CKE 0x02\n"
|
r.define("DFII_CONTROL_CKE", "0x02")
|
||||||
r += "#define DFII_CONTROL_ODT 0x04\n"
|
r.define("DFII_CONTROL_ODT", "0x04")
|
||||||
r += "#define DFII_CONTROL_RESET_N 0x08\n"
|
r.define("DFII_CONTROL_RESET_N", "0x08")
|
||||||
r += "\n"
|
r.newline()
|
||||||
|
|
||||||
r += "#define DFII_COMMAND_CS 0x01\n"
|
r.define("DFII_COMMAND_CS", "0x01")
|
||||||
r += "#define DFII_COMMAND_WE 0x02\n"
|
r.define("DFII_COMMAND_WE", "0x02")
|
||||||
r += "#define DFII_COMMAND_CAS 0x04\n"
|
r.define("DFII_COMMAND_CAS", "0x04")
|
||||||
r += "#define DFII_COMMAND_RAS 0x08\n"
|
r.define("DFII_COMMAND_RAS", "0x08")
|
||||||
r += "#define DFII_COMMAND_WRDATA 0x10\n"
|
r.define("DFII_COMMAND_WRDATA", "0x10")
|
||||||
r += "#define DFII_COMMAND_RDDATA 0x20\n"
|
r.define("DFII_COMMAND_RDDATA", "0x20")
|
||||||
r += "\n"
|
r.newline()
|
||||||
|
|
||||||
phytype = phy_settings.phytype.upper()
|
phytype = phy_settings.phytype.upper()
|
||||||
nphases = phy_settings.nphases
|
nphases = phy_settings.nphases
|
||||||
|
|
||||||
# Define PHY type and number of phases
|
# Define PHY type and number of phases
|
||||||
r += "#define SDRAM_PHY_"+phytype+"\n"
|
r.define(f"SDRAM_PHY_{phytype}")
|
||||||
r += "#define SDRAM_PHY_XDR "+str(1 if phy_settings.memtype == "SDR" else 2) + "\n"
|
r.define("SDRAM_PHY_XDR", 1 if phy_settings.memtype == "SDR" else 2)
|
||||||
r += "#define SDRAM_PHY_DATABITS "+str(phy_settings.databits) + "\n"
|
r.define("SDRAM_PHY_DATABITS", phy_settings.databits)
|
||||||
r += "#define SDRAM_PHY_PHASES "+str(nphases)+"\n"
|
r.define("SDRAM_PHY_DFI_DATABITS", phy_settings.dfi_databits)
|
||||||
if phy_settings.cl is not None:
|
r.define("SDRAM_PHY_PHASES", nphases)
|
||||||
r += "#define SDRAM_PHY_CL "+str(phy_settings.cl)+"\n"
|
for setting in ["cl", "cwl", "cmd_latency", "cmd_delay"]:
|
||||||
if phy_settings.cwl is not None:
|
if getattr(phy_settings, setting, None) is not None:
|
||||||
r += "#define SDRAM_PHY_CWL "+str(phy_settings.cwl)+"\n"
|
r.define(f"SDRAM_PHY_{setting.upper()}", getattr(phy_settings, setting))
|
||||||
if phy_settings.cmd_latency is not None:
|
|
||||||
r += "#define SDRAM_PHY_CMD_LATENCY "+str(phy_settings.cmd_latency)+"\n"
|
|
||||||
if phy_settings.cmd_delay is not None:
|
|
||||||
r += "#define SDRAM_PHY_CMD_DELAY "+str(phy_settings.cmd_delay)+"\n"
|
|
||||||
|
|
||||||
# Define PHY Read.Write phases
|
# Define PHY Read.Write phases
|
||||||
rdphase = phy_settings.rdphase
|
rdphase = phy_settings.rdphase
|
||||||
if isinstance(rdphase, Signal): rdphase = rdphase.reset.value
|
if isinstance(rdphase, Signal): rdphase = rdphase.reset.value
|
||||||
r += "#define SDRAM_PHY_RDPHASE "+str(rdphase)+"\n"
|
r.define("SDRAM_PHY_RDPHASE", rdphase)
|
||||||
wrphase = phy_settings.wrphase
|
wrphase = phy_settings.wrphase
|
||||||
if isinstance(wrphase, Signal): wrphase = wrphase.reset.value
|
if isinstance(wrphase, Signal): wrphase = wrphase.reset.value
|
||||||
r += "#define SDRAM_PHY_WRPHASE "+str(wrphase)+"\n"
|
r.define("SDRAM_PHY_WRPHASE", wrphase)
|
||||||
|
|
||||||
# Define Read/Write Leveling capability
|
# Define Read/Write Leveling capability
|
||||||
if phytype in ["USDDRPHY", "USPDDRPHY",
|
if phy_settings.write_leveling:
|
||||||
"K7DDRPHY", "V7DDRPHY",
|
r.define("SDRAM_PHY_WRITE_LEVELING_CAPABLE")
|
||||||
"K7LPDDR4PHY", "V7LPDDR4PHY"]:
|
if phy_settings.write_latency_calibration:
|
||||||
r += "#define SDRAM_PHY_WRITE_LEVELING_CAPABLE\n"
|
r.define("SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE")
|
||||||
if phytype in ["K7DDRPHY", "V7DDRPHY",
|
if phy_settings.write_dq_dqs_training:
|
||||||
"K7LPDDR4PHY", "V7LPDDR4PHY"]:
|
r.define("SDRAM_PHY_WRITE_DQ_DQS_TRAINING_CAPABLE")
|
||||||
r += "#define SDRAM_PHY_WRITE_DQ_DQS_TRAINING_CAPABLE\n"
|
if phy_settings.read_leveling:
|
||||||
if phytype in ["USDDRPHY", "USPDDRPHY",
|
r.define("SDRAM_PHY_READ_LEVELING_CAPABLE")
|
||||||
"A7DDRPHY", "K7DDRPHY", "V7DDRPHY",
|
|
||||||
"A7LPDDR4PHY", "K7LPDDR4PHY", "V7LPDDR4PHY"]:
|
|
||||||
r += "#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE\n"
|
|
||||||
r += "#define SDRAM_PHY_READ_LEVELING_CAPABLE\n"
|
|
||||||
if phytype in ["ECP5DDRPHY"]:
|
|
||||||
r += "#define SDRAM_PHY_READ_LEVELING_CAPABLE\n"
|
|
||||||
if phytype in ["LPDDR4SIMPHY"]:
|
|
||||||
r += "#define SDRAM_PHY_READ_LEVELING_CAPABLE\n"
|
|
||||||
|
|
||||||
# Define number of modules/delays/bitslips
|
# Define number of modules/delays/bitslips
|
||||||
r += "#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8\n"
|
r.define("SDRAM_PHY_MODULES", "(SDRAM_PHY_DATABITS/8)")
|
||||||
if phytype in ["USDDRPHY", "USPDDRPHY"]:
|
if phy_settings.delays > 0:
|
||||||
r += "#define SDRAM_PHY_DELAYS 512\n"
|
r.define("SDRAM_PHY_DELAYS", phy_settings.delays)
|
||||||
r += "#define SDRAM_PHY_BITSLIPS 8\n"
|
if phy_settings.bitslips > 0:
|
||||||
elif phytype in ["A7DDRPHY", "K7DDRPHY", "V7DDRPHY"]:
|
r.define("SDRAM_PHY_BITSLIPS", phy_settings.bitslips)
|
||||||
r += "#define SDRAM_PHY_DELAYS 32\n"
|
|
||||||
r += "#define SDRAM_PHY_BITSLIPS 8\n"
|
|
||||||
elif phytype in ["A7LPDDR4PHY", "K7LPDDR4PHY", "V7LPDDR4PHY"]:
|
|
||||||
r += "#define SDRAM_PHY_DELAYS 32\n"
|
|
||||||
r += "#define SDRAM_PHY_BITSLIPS 16\n"
|
|
||||||
elif phytype in ["ECP5DDRPHY"]:
|
|
||||||
r += "#define SDRAM_PHY_DELAYS 8\n"
|
|
||||||
r += "#define SDRAM_PHY_BITSLIPS 4\n"
|
|
||||||
elif phytype in ["LPDDR4SIMPHY"]:
|
|
||||||
r += "#define SDRAM_PHY_DELAYS 1\n"
|
|
||||||
r += "#define SDRAM_PHY_BITSLIPS 16\n"
|
|
||||||
|
|
||||||
if phy_settings.is_rdimm:
|
if phy_settings.is_rdimm:
|
||||||
assert phy_settings.memtype == "DDR4"
|
assert phy_settings.memtype == "DDR4"
|
||||||
r += "#define SDRAM_PHY_DDR4_RDIMM\n"
|
r.define("SDRAM_PHY_DDR4_RDIMM")
|
||||||
|
|
||||||
r += "\n"
|
r.newline()
|
||||||
|
|
||||||
r += "void cdelay(int i);\n"
|
r += "void cdelay(int i);"
|
||||||
|
r.newline()
|
||||||
|
|
||||||
# Commands functions
|
# Commands functions
|
||||||
for n in range(nphases):
|
for n in range(nphases):
|
||||||
r += """
|
with r.block(f"__attribute__((unused)) static inline void command_p{n}(int cmd)") as b:
|
||||||
__attribute__((unused)) static inline void command_p{n}(int cmd)
|
b += f"sdram_dfii_pi{n}_command_write(cmd);"
|
||||||
{{
|
b += f"sdram_dfii_pi{n}_command_issue_write(1);"
|
||||||
sdram_dfii_pi{n}_command_write(cmd);
|
r.newline()
|
||||||
sdram_dfii_pi{n}_command_issue_write(1);
|
|
||||||
}}""".format(n=str(n))
|
|
||||||
r += "\n\n"
|
|
||||||
|
|
||||||
# Write/Read functions
|
# Write/Read functions
|
||||||
pix_addr_fmt = """
|
r.define("DFII_PIX_DATA_SIZE", "CSR_SDRAM_DFII_PI0_WRDATA_SIZE")
|
||||||
static inline unsigned long {name}(int phase){{
|
r.newline()
|
||||||
switch (phase) {{
|
for data in ["wrdata", "rddata"]:
|
||||||
{cases}
|
with r.block(f"static inline unsigned long sdram_dfii_pix_{data}_addr(int phase)") as b:
|
||||||
default: return 0;
|
with b.block("switch (phase)", newline=False) as s:
|
||||||
}}
|
|
||||||
}}
|
|
||||||
"""
|
|
||||||
get_cases = lambda addrs: ["case {}: return {};".format(i, addr) for i, addr in enumerate(addrs)]
|
|
||||||
|
|
||||||
r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
|
|
||||||
sdram_dfii_pix_wrdata_addr = []
|
|
||||||
for n in range(nphases):
|
for n in range(nphases):
|
||||||
sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
|
s += f"case {n}: return CSR_SDRAM_DFII_PI{n}_{data.upper()}_ADDR;"
|
||||||
r += pix_addr_fmt.format(
|
s += "default: return 0;"
|
||||||
name = "sdram_dfii_pix_wrdata_addr",
|
r.newline()
|
||||||
cases = "\n\t\t".join(get_cases(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 += pix_addr_fmt.format(
|
|
||||||
name = "sdram_dfii_pix_rddata_addr",
|
|
||||||
cases = "\n\t\t".join(get_cases(sdram_dfii_pix_rddata_addr)))
|
|
||||||
r += "\n"
|
|
||||||
|
|
||||||
init_sequence, mr = get_sdram_phy_init_sequence(phy_settings, timing_settings)
|
init_sequence, mr = get_sdram_phy_init_sequence(phy_settings, timing_settings)
|
||||||
|
|
||||||
if phy_settings.memtype in ["DDR3", "DDR4"]:
|
if phy_settings.memtype in ["DDR3", "DDR4"]:
|
||||||
# The value of MR1[7] needs to be modified during write leveling
|
# The value of MR1[7] needs to be modified during write leveling
|
||||||
r += "#define DDRX_MR_WRLVL_ADDRESS {}\n".format(1)
|
r.define("DDRX_MR_WRLVL_ADDRESS", 1)
|
||||||
r += "#define DDRX_MR_WRLVL_RESET {}\n".format(mr[1])
|
r.define("DDRX_MR_WRLVL_RESET", mr[1])
|
||||||
r += "#define DDRX_MR_WRLVL_BIT {}\n\n".format(7)
|
r.define("DDRX_MR_WRLVL_BIT", 7)
|
||||||
|
r.newline()
|
||||||
elif phy_settings.memtype in ["LPDDR4"]:
|
elif phy_settings.memtype in ["LPDDR4"]:
|
||||||
# Write leveling enabled by MR2[7]
|
# Write leveling enabled by MR2[7]
|
||||||
r += "#define DDRX_MR_WRLVL_ADDRESS {}\n".format(2)
|
r.define("DDRX_MR_WRLVL_ADDRESS", 2)
|
||||||
r += "#define DDRX_MR_WRLVL_RESET {}\n".format(mr[2])
|
r.define("DDRX_MR_WRLVL_RESET", mr[2])
|
||||||
r += "#define DDRX_MR_WRLVL_BIT {}\n\n".format(7)
|
r.define("DDRX_MR_WRLVL_BIT", 7)
|
||||||
|
r.newline()
|
||||||
|
|
||||||
r += "static inline void init_sequence(void)\n{\n"
|
with r.block("static inline void init_sequence(void)") as b:
|
||||||
for comment, a, ba, cmd, delay in init_sequence:
|
for comment, a, ba, cmd, delay in init_sequence:
|
||||||
invert_masks = [(0, 0), ]
|
invert_masks = [(0, 0), ]
|
||||||
if phy_settings.is_rdimm:
|
if phy_settings.is_rdimm:
|
||||||
|
@ -800,21 +824,18 @@ static inline unsigned long {name}(int phase){{
|
||||||
invert_masks.append((0b10101111111000, 0b1111))
|
invert_masks.append((0b10101111111000, 0b1111))
|
||||||
|
|
||||||
for a_inv, ba_inv in invert_masks:
|
for a_inv, ba_inv in invert_masks:
|
||||||
r += "\t/* {0} */\n".format(comment)
|
b += f"/* {comment} */"
|
||||||
r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a ^ a_inv)
|
b += f"sdram_dfii_pi0_address_write({a ^ a_inv:#x});"
|
||||||
r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba ^ ba_inv)
|
b += f"sdram_dfii_pi0_baddress_write({ba ^ ba_inv:d});"
|
||||||
if cmd[:12] == "DFII_CONTROL":
|
if cmd.startswith("DFII_CONTROL"):
|
||||||
r += "\tsdram_dfii_control_write({0});\n".format(cmd)
|
b += f"sdram_dfii_control_write({cmd});"
|
||||||
else:
|
else:
|
||||||
r += "\tcommand_p0({0});\n".format(cmd)
|
b += f"command_p0({cmd});"
|
||||||
if delay:
|
if delay:
|
||||||
r += "\tcdelay({0:d});\n".format(delay)
|
b += f"cdelay({delay});\n"
|
||||||
r += "\n"
|
b.newline()
|
||||||
r += "}\n"
|
|
||||||
|
|
||||||
r += "#endif\n"
|
return r.generate()
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
# Python Header ------------------------------------------------------------------------------------
|
# Python Header ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,10 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
cl = cl,
|
cl = cl,
|
||||||
cwl = cwl,
|
cwl = cwl,
|
||||||
read_latency = cl_sys_latency + 10,
|
read_latency = cl_sys_latency + 10,
|
||||||
write_latency = cwl_sys_latency
|
write_latency = cwl_sys_latency,
|
||||||
|
read_leveling = True,
|
||||||
|
bitslips = 4,
|
||||||
|
delays = 8,
|
||||||
)
|
)
|
||||||
|
|
||||||
# DFI Interface ----------------------------------------------------------------------------
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -181,6 +181,7 @@ class LPDDR4PHY(Module, AutoCSR):
|
||||||
write_latency = write_latency,
|
write_latency = write_latency,
|
||||||
cmd_latency = cmd_latency,
|
cmd_latency = cmd_latency,
|
||||||
cmd_delay = cmd_delay,
|
cmd_delay = cmd_delay,
|
||||||
|
bitslips = 16,
|
||||||
)
|
)
|
||||||
|
|
||||||
# DFI Interface ----------------------------------------------------------------------------
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -30,6 +30,12 @@ class S7LPDDR4PHY(DoubleRateLPDDR4PHY):
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.settings.delays = 32
|
||||||
|
self.settings.write_leveling = True
|
||||||
|
self.settings.write_latency_calibration = True
|
||||||
|
self.settings.write_dq_dqs_training = True
|
||||||
|
self.settings.read_leveling = True
|
||||||
|
|
||||||
# Parameters -------------------------------------------------------------------------------
|
# Parameters -------------------------------------------------------------------------------
|
||||||
# Calculate value of taps needed to shift a signal by 90 degrees.
|
# Calculate value of taps needed to shift a signal by 90 degrees.
|
||||||
# Using iodelay_clk_freq of 300MHz/400MHz is only valid for -3 and -2/2E speed grades.
|
# Using iodelay_clk_freq of 300MHz/400MHz is only valid for -3 and -2/2E speed grades.
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
|
from litex.soc.interconnect.csr import CSR
|
||||||
|
|
||||||
from litedram.phy.utils import delayed, Serializer, Deserializer, Latency
|
from litedram.phy.utils import delayed, Serializer, Deserializer, Latency
|
||||||
from litedram.phy.sim_utils import SimPad, SimulationPads, SimSerDesMixin
|
from litedram.phy.sim_utils import SimPad, SimulationPads, SimSerDesMixin
|
||||||
from litedram.phy.lpddr4.basephy import LPDDR4PHY, DoubleRateLPDDR4PHY
|
from litedram.phy.lpddr4.basephy import LPDDR4PHY, DoubleRateLPDDR4PHY
|
||||||
|
@ -40,6 +42,12 @@ class LPDDR4SimPHY(SimSerDesMixin, LPDDR4PHY):
|
||||||
phytype = "LPDDR4SimPHY",
|
phytype = "LPDDR4SimPHY",
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
|
# fake delays (make no nsense in simulation, but sdram.c expects them)
|
||||||
|
self.settings.read_leveling = True
|
||||||
|
self.settings.delays = 1
|
||||||
|
self._rdly_dq_rst = CSR()
|
||||||
|
self._rdly_dq_inc = CSR()
|
||||||
|
|
||||||
delay = lambda sig, cycles: delayed(self, sig, cycles=cycles)
|
delay = lambda sig, cycles: delayed(self, sig, cycles=cycles)
|
||||||
sdr = dict(clkdiv="sys", clk="sys8x")
|
sdr = dict(clkdiv="sys", clk="sys8x")
|
||||||
sdr_90 = dict(clkdiv="sys", clk="sys8x_90")
|
sdr_90 = dict(clkdiv="sys", clk="sys8x_90")
|
||||||
|
@ -97,8 +105,14 @@ class DoubleRateLPDDR4SimPHY(SimSerDesMixin, DoubleRateLPDDR4PHY):
|
||||||
des_latency = Latency(sys2x=Deserializer.LATENCY),
|
des_latency = Latency(sys2x=Deserializer.LATENCY),
|
||||||
phytype = "LPDDR4SimPHY",
|
phytype = "LPDDR4SimPHY",
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
self.submodules.half_delay = ClockDomainsRenamer("sys2x")(Module())
|
self.submodules.half_delay = ClockDomainsRenamer("sys2x")(Module())
|
||||||
|
|
||||||
|
# fake delays (make no nsense in simulation, but sdram.c expects them)
|
||||||
|
self.settings.read_leveling = True
|
||||||
|
self.settings.delays = 1
|
||||||
|
self._rdly_dq_rst = CSR()
|
||||||
|
self._rdly_dq_inc = CSR()
|
||||||
|
|
||||||
delay = lambda sig, cycles: delayed(self.half_delay, sig, cycles=cycles)
|
delay = lambda sig, cycles: delayed(self.half_delay, sig, cycles=cycles)
|
||||||
|
|
||||||
sdr = dict(clkdiv="sys2x", clk="sys8x")
|
sdr = dict(clkdiv="sys2x", clk="sys8x")
|
||||||
|
|
|
@ -95,10 +95,6 @@ class SimSoC(SoCCore):
|
||||||
aligned_reset_zero = True,
|
aligned_reset_zero = True,
|
||||||
masked_write = masked_write,
|
masked_write = masked_write,
|
||||||
)
|
)
|
||||||
# fake delays (make no nsense in simulation, but sdram.c expects them)
|
|
||||||
self.ddrphy._rdly_dq_rst = CSR()
|
|
||||||
self.ddrphy._rdly_dq_inc = CSR()
|
|
||||||
self.add_csr("ddrphy")
|
|
||||||
|
|
||||||
for p in ["clk", "cke", "odt", "reset_n", "cs", "ca", "dq", "dqs", "dmi"]:
|
for p in ["clk", "cke", "odt", "reset_n", "cs", "ca", "dq", "dqs", "dmi"]:
|
||||||
self.comb += getattr(pads, p).eq(getattr(self.ddrphy.pads, p))
|
self.comb += getattr(pads, p).eq(getattr(self.ddrphy.pads, p))
|
||||||
|
|
|
@ -107,6 +107,12 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
write_latency = cwl_sys_latency - 1,
|
write_latency = cwl_sys_latency - 1,
|
||||||
cmd_latency = cmd_latency,
|
cmd_latency = cmd_latency,
|
||||||
cmd_delay = cmd_delay,
|
cmd_delay = cmd_delay,
|
||||||
|
write_leveling = with_odelay,
|
||||||
|
write_dq_dqs_training = with_odelay,
|
||||||
|
write_latency_calibration = True,
|
||||||
|
read_leveling = True,
|
||||||
|
delays = 32,
|
||||||
|
bitslips = 8,
|
||||||
)
|
)
|
||||||
|
|
||||||
# DFI Interface ----------------------------------------------------------------------------
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -107,6 +107,11 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
write_latency = cwl_sys_latency - 1,
|
write_latency = cwl_sys_latency - 1,
|
||||||
cmd_latency = cmd_latency,
|
cmd_latency = cmd_latency,
|
||||||
cmd_delay = cmd_delay,
|
cmd_delay = cmd_delay,
|
||||||
|
write_leveling = True,
|
||||||
|
write_latency_calibration = True,
|
||||||
|
read_leveling = True,
|
||||||
|
delays = 512,
|
||||||
|
bitslips = 8,
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_rdimm:
|
if is_rdimm:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef __GENERATED_SDRAM_PHY_H
|
#ifndef __GENERATED_SDRAM_PHY_H
|
||||||
#define __GENERATED_SDRAM_PHY_H
|
#define __GENERATED_SDRAM_PHY_H
|
||||||
|
|
||||||
#include <hw/common.h>
|
#include <hw/common.h>
|
||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
#define SDRAM_PHY_K7DDRPHY
|
#define SDRAM_PHY_K7DDRPHY
|
||||||
#define SDRAM_PHY_XDR 2
|
#define SDRAM_PHY_XDR 2
|
||||||
#define SDRAM_PHY_DATABITS 64
|
#define SDRAM_PHY_DATABITS 64
|
||||||
|
#define SDRAM_PHY_DFI_DATABITS 128
|
||||||
#define SDRAM_PHY_PHASES 4
|
#define SDRAM_PHY_PHASES 4
|
||||||
#define SDRAM_PHY_CL 7
|
#define SDRAM_PHY_CL 7
|
||||||
#define SDRAM_PHY_CWL 6
|
#define SDRAM_PHY_CWL 6
|
||||||
|
@ -25,10 +27,10 @@
|
||||||
#define SDRAM_PHY_RDPHASE 1
|
#define SDRAM_PHY_RDPHASE 1
|
||||||
#define SDRAM_PHY_WRPHASE 2
|
#define SDRAM_PHY_WRPHASE 2
|
||||||
#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
|
#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
|
||||||
#define SDRAM_PHY_WRITE_DQ_DQS_TRAINING_CAPABLE
|
|
||||||
#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
|
#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
|
||||||
|
#define SDRAM_PHY_WRITE_DQ_DQS_TRAINING_CAPABLE
|
||||||
#define SDRAM_PHY_READ_LEVELING_CAPABLE
|
#define SDRAM_PHY_READ_LEVELING_CAPABLE
|
||||||
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
|
#define SDRAM_PHY_MODULES (SDRAM_PHY_DATABITS/8)
|
||||||
#define SDRAM_PHY_DELAYS 32
|
#define SDRAM_PHY_DELAYS 32
|
||||||
#define SDRAM_PHY_BITSLIPS 8
|
#define SDRAM_PHY_BITSLIPS 8
|
||||||
|
|
||||||
|
@ -57,7 +59,8 @@ __attribute__((unused)) static inline void command_p3(int cmd)
|
||||||
|
|
||||||
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
||||||
|
|
||||||
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase){
|
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase)
|
||||||
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
||||||
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
|
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
|
||||||
|
@ -66,8 +69,8 @@ static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase){
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase)
|
||||||
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase){
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
||||||
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
|
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
|
||||||
|
@ -123,4 +126,5 @@ static inline void init_sequence(void)
|
||||||
cdelay(200);
|
cdelay(200);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif /* __GENERATED_SDRAM_PHY_H */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef __GENERATED_SDRAM_PHY_H
|
#ifndef __GENERATED_SDRAM_PHY_H
|
||||||
#define __GENERATED_SDRAM_PHY_H
|
#define __GENERATED_SDRAM_PHY_H
|
||||||
|
|
||||||
#include <hw/common.h>
|
#include <hw/common.h>
|
||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
|
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
#define SDRAM_PHY_USDDRPHY
|
#define SDRAM_PHY_USDDRPHY
|
||||||
#define SDRAM_PHY_XDR 2
|
#define SDRAM_PHY_XDR 2
|
||||||
#define SDRAM_PHY_DATABITS 64
|
#define SDRAM_PHY_DATABITS 64
|
||||||
|
#define SDRAM_PHY_DFI_DATABITS 128
|
||||||
#define SDRAM_PHY_PHASES 4
|
#define SDRAM_PHY_PHASES 4
|
||||||
#define SDRAM_PHY_CL 9
|
#define SDRAM_PHY_CL 9
|
||||||
#define SDRAM_PHY_CWL 9
|
#define SDRAM_PHY_CWL 9
|
||||||
|
@ -27,7 +29,7 @@
|
||||||
#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
|
#define SDRAM_PHY_WRITE_LEVELING_CAPABLE
|
||||||
#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
|
#define SDRAM_PHY_WRITE_LATENCY_CALIBRATION_CAPABLE
|
||||||
#define SDRAM_PHY_READ_LEVELING_CAPABLE
|
#define SDRAM_PHY_READ_LEVELING_CAPABLE
|
||||||
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
|
#define SDRAM_PHY_MODULES (SDRAM_PHY_DATABITS/8)
|
||||||
#define SDRAM_PHY_DELAYS 512
|
#define SDRAM_PHY_DELAYS 512
|
||||||
#define SDRAM_PHY_BITSLIPS 8
|
#define SDRAM_PHY_BITSLIPS 8
|
||||||
|
|
||||||
|
@ -56,7 +58,8 @@ __attribute__((unused)) static inline void command_p3(int cmd)
|
||||||
|
|
||||||
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
||||||
|
|
||||||
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase){
|
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase)
|
||||||
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
||||||
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
|
case 1: return CSR_SDRAM_DFII_PI1_WRDATA_ADDR;
|
||||||
|
@ -65,8 +68,8 @@ static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase){
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase)
|
||||||
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase){
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
||||||
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
|
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
|
||||||
|
@ -137,4 +140,5 @@ static inline void init_sequence(void)
|
||||||
cdelay(200);
|
cdelay(200);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif /* __GENERATED_SDRAM_PHY_H */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef __GENERATED_SDRAM_PHY_H
|
#ifndef __GENERATED_SDRAM_PHY_H
|
||||||
#define __GENERATED_SDRAM_PHY_H
|
#define __GENERATED_SDRAM_PHY_H
|
||||||
|
|
||||||
#include <hw/common.h>
|
#include <hw/common.h>
|
||||||
#include <generated/csr.h>
|
#include <generated/csr.h>
|
||||||
|
|
||||||
|
@ -18,12 +19,13 @@
|
||||||
#define SDRAM_PHY_GENSDRPHY
|
#define SDRAM_PHY_GENSDRPHY
|
||||||
#define SDRAM_PHY_XDR 1
|
#define SDRAM_PHY_XDR 1
|
||||||
#define SDRAM_PHY_DATABITS 16
|
#define SDRAM_PHY_DATABITS 16
|
||||||
|
#define SDRAM_PHY_DFI_DATABITS 16
|
||||||
#define SDRAM_PHY_PHASES 1
|
#define SDRAM_PHY_PHASES 1
|
||||||
#define SDRAM_PHY_CL 2
|
#define SDRAM_PHY_CL 2
|
||||||
#define SDRAM_PHY_CWL 2
|
#define SDRAM_PHY_CWL 2
|
||||||
#define SDRAM_PHY_RDPHASE 0
|
#define SDRAM_PHY_RDPHASE 0
|
||||||
#define SDRAM_PHY_WRPHASE 0
|
#define SDRAM_PHY_WRPHASE 0
|
||||||
#define SDRAM_PHY_MODULES SDRAM_PHY_DATABITS/8
|
#define SDRAM_PHY_MODULES (SDRAM_PHY_DATABITS/8)
|
||||||
|
|
||||||
void cdelay(int i);
|
void cdelay(int i);
|
||||||
|
|
||||||
|
@ -35,14 +37,15 @@ __attribute__((unused)) static inline void command_p0(int cmd)
|
||||||
|
|
||||||
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE
|
||||||
|
|
||||||
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase){
|
static inline unsigned long sdram_dfii_pix_wrdata_addr(int phase)
|
||||||
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase)
|
||||||
static inline unsigned long sdram_dfii_pix_rddata_addr(int phase){
|
{
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
case 0: return CSR_SDRAM_DFII_PI0_RDDATA_ADDR;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
|
@ -92,4 +95,5 @@ static inline void init_sequence(void)
|
||||||
cdelay(200);
|
cdelay(200);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#endif /* __GENERATED_SDRAM_PHY_H */
|
||||||
|
|
Loading…
Reference in New Issue