Merge pull request #268 from antmicro/jboc/init-refactor

Refactor init code generation
This commit is contained in:
enjoy-digital 2021-08-23 18:51:51 +02:00 committed by GitHub
commit ca609005bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 347 additions and 264 deletions

View File

@ -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

View File

@ -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,178 +644,198 @@ 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:
}} for n in range(nphases):
}} s += f"case {n}: return CSR_SDRAM_DFII_PI{n}_{data.upper()}_ADDR;"
""" s += "default: return 0;"
get_cases = lambda addrs: ["case {}: return {};".format(i, addr) for i, addr in enumerate(addrs)] r.newline()
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 += pix_addr_fmt.format(
name = "sdram_dfii_pix_wrdata_addr",
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:
assert phy_settings.memtype == "DDR4" assert phy_settings.memtype == "DDR4"
# JESD82-31A page 38 # JESD82-31A page 38
# #
# B-side chips have certain usually-inconsequential address and BA # B-side chips have certain usually-inconsequential address and BA
# bits inverted by the RCD to reduce SSO current. For mode register # bits inverted by the RCD to reduce SSO current. For mode register
# writes, however, we must compensate for this. BG[1] also directs # 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) # 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 # The 'ba != 7' is because we don't do this to writes to the RCD
# itself. # itself.
if ba != 7: if ba != 7:
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 ------------------------------------------------------------------------------------

View File

@ -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 ----------------------------------------------------------------------------

View File

@ -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 ----------------------------------------------------------------------------

View File

@ -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.

View File

@ -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")

View File

@ -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))

View File

@ -93,20 +93,26 @@ class S7DDRPHY(Module, AutoCSR):
# PHY settings ----------------------------------------------------------------------------- # PHY settings -----------------------------------------------------------------------------
self.settings = PhySettings( self.settings = PhySettings(
phytype = phytype, phytype = phytype,
memtype = memtype, memtype = memtype,
databits = databits, databits = databits,
dfi_databits = 2*databits, dfi_databits = 2*databits,
nranks = nranks, nranks = nranks,
nphases = nphases, nphases = nphases,
rdphase = self._rdphase.storage, rdphase = self._rdphase.storage,
wrphase = self._wrphase.storage, wrphase = self._wrphase.storage,
cl = cl, cl = cl,
cwl = cwl, cwl = cwl,
read_latency = cl_sys_latency + 6, read_latency = cl_sys_latency + 6,
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 ----------------------------------------------------------------------------

View File

@ -93,20 +93,25 @@ class USDDRPHY(Module, AutoCSR):
# PHY settings ----------------------------------------------------------------------------- # PHY settings -----------------------------------------------------------------------------
self.settings = PhySettings( self.settings = PhySettings(
phytype = phytype, phytype = phytype,
memtype = memtype, memtype = memtype,
databits = databits, databits = databits,
dfi_databits = 2*databits, dfi_databits = 2*databits,
nranks = nranks, nranks = nranks,
nphases = nphases, nphases = nphases,
rdphase = self._rdphase.storage, rdphase = self._rdphase.storage,
wrphase = self._wrphase.storage, wrphase = self._wrphase.storage,
cl = cl, cl = cl,
cwl = cwl, cwl = cwl,
read_latency = cl_sys_latency + 5, read_latency = cl_sys_latency + 5,
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:

View File

@ -1,23 +1,25 @@
#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>
#define DFII_CONTROL_SEL 0x01 #define DFII_CONTROL_SEL 0x01
#define DFII_CONTROL_CKE 0x02 #define DFII_CONTROL_CKE 0x02
#define DFII_CONTROL_ODT 0x04 #define DFII_CONTROL_ODT 0x04
#define DFII_CONTROL_RESET_N 0x08 #define DFII_CONTROL_RESET_N 0x08
#define DFII_COMMAND_CS 0x01 #define DFII_COMMAND_CS 0x01
#define DFII_COMMAND_WE 0x02 #define DFII_COMMAND_WE 0x02
#define DFII_COMMAND_CAS 0x04 #define DFII_COMMAND_CAS 0x04
#define DFII_COMMAND_RAS 0x08 #define DFII_COMMAND_RAS 0x08
#define DFII_COMMAND_WRDATA 0x10 #define DFII_COMMAND_WRDATA 0x10
#define DFII_COMMAND_RDDATA 0x20 #define DFII_COMMAND_RDDATA 0x20
#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
@ -36,47 +38,48 @@ void cdelay(int i);
__attribute__((unused)) static inline void command_p0(int cmd) __attribute__((unused)) static inline void command_p0(int cmd)
{ {
sdram_dfii_pi0_command_write(cmd); sdram_dfii_pi0_command_write(cmd);
sdram_dfii_pi0_command_issue_write(1); sdram_dfii_pi0_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p1(int cmd) __attribute__((unused)) static inline void command_p1(int cmd)
{ {
sdram_dfii_pi1_command_write(cmd); sdram_dfii_pi1_command_write(cmd);
sdram_dfii_pi1_command_issue_write(1); sdram_dfii_pi1_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p2(int cmd) __attribute__((unused)) static inline void command_p2(int cmd)
{ {
sdram_dfii_pi2_command_write(cmd); sdram_dfii_pi2_command_write(cmd);
sdram_dfii_pi2_command_issue_write(1); sdram_dfii_pi2_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p3(int cmd) __attribute__((unused)) static inline void command_p3(int cmd)
{ {
sdram_dfii_pi3_command_write(cmd); sdram_dfii_pi3_command_write(cmd);
sdram_dfii_pi3_command_issue_write(1); sdram_dfii_pi3_command_issue_write(1);
} }
#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) { {
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR; switch (phase) {
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;
case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR; case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_WRDATA_ADDR; case 3: return CSR_SDRAM_DFII_PI3_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;
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR; case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR; case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR; case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR;
default: return 0; default: return 0;
} }
} }
#define DDRX_MR_WRLVL_ADDRESS 1 #define DDRX_MR_WRLVL_ADDRESS 1
#define DDRX_MR_WRLVL_RESET 6 #define DDRX_MR_WRLVL_RESET 6
#define DDRX_MR_WRLVL_BIT 7 #define DDRX_MR_WRLVL_BIT 7
@ -123,4 +126,5 @@ static inline void init_sequence(void)
cdelay(200); cdelay(200);
} }
#endif
#endif /* __GENERATED_SDRAM_PHY_H */

View File

@ -1,23 +1,25 @@
#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>
#define DFII_CONTROL_SEL 0x01 #define DFII_CONTROL_SEL 0x01
#define DFII_CONTROL_CKE 0x02 #define DFII_CONTROL_CKE 0x02
#define DFII_CONTROL_ODT 0x04 #define DFII_CONTROL_ODT 0x04
#define DFII_CONTROL_RESET_N 0x08 #define DFII_CONTROL_RESET_N 0x08
#define DFII_COMMAND_CS 0x01 #define DFII_COMMAND_CS 0x01
#define DFII_COMMAND_WE 0x02 #define DFII_COMMAND_WE 0x02
#define DFII_COMMAND_CAS 0x04 #define DFII_COMMAND_CAS 0x04
#define DFII_COMMAND_RAS 0x08 #define DFII_COMMAND_RAS 0x08
#define DFII_COMMAND_WRDATA 0x10 #define DFII_COMMAND_WRDATA 0x10
#define DFII_COMMAND_RDDATA 0x20 #define DFII_COMMAND_RDDATA 0x20
#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
@ -35,47 +37,48 @@ void cdelay(int i);
__attribute__((unused)) static inline void command_p0(int cmd) __attribute__((unused)) static inline void command_p0(int cmd)
{ {
sdram_dfii_pi0_command_write(cmd); sdram_dfii_pi0_command_write(cmd);
sdram_dfii_pi0_command_issue_write(1); sdram_dfii_pi0_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p1(int cmd) __attribute__((unused)) static inline void command_p1(int cmd)
{ {
sdram_dfii_pi1_command_write(cmd); sdram_dfii_pi1_command_write(cmd);
sdram_dfii_pi1_command_issue_write(1); sdram_dfii_pi1_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p2(int cmd) __attribute__((unused)) static inline void command_p2(int cmd)
{ {
sdram_dfii_pi2_command_write(cmd); sdram_dfii_pi2_command_write(cmd);
sdram_dfii_pi2_command_issue_write(1); sdram_dfii_pi2_command_issue_write(1);
} }
__attribute__((unused)) static inline void command_p3(int cmd) __attribute__((unused)) static inline void command_p3(int cmd)
{ {
sdram_dfii_pi3_command_write(cmd); sdram_dfii_pi3_command_write(cmd);
sdram_dfii_pi3_command_issue_write(1); sdram_dfii_pi3_command_issue_write(1);
} }
#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) { {
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR; switch (phase) {
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;
case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR; case 2: return CSR_SDRAM_DFII_PI2_WRDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_WRDATA_ADDR; case 3: return CSR_SDRAM_DFII_PI3_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;
case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR; case 1: return CSR_SDRAM_DFII_PI1_RDDATA_ADDR;
case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR; case 2: return CSR_SDRAM_DFII_PI2_RDDATA_ADDR;
case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR; case 3: return CSR_SDRAM_DFII_PI3_RDDATA_ADDR;
default: return 0; default: return 0;
} }
} }
#define DDRX_MR_WRLVL_ADDRESS 1 #define DDRX_MR_WRLVL_ADDRESS 1
#define DDRX_MR_WRLVL_RESET 769 #define DDRX_MR_WRLVL_RESET 769
#define DDRX_MR_WRLVL_BIT 7 #define DDRX_MR_WRLVL_BIT 7
@ -137,4 +140,5 @@ static inline void init_sequence(void)
cdelay(200); cdelay(200);
} }
#endif
#endif /* __GENERATED_SDRAM_PHY_H */

View File

@ -1,54 +1,57 @@
#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>
#define DFII_CONTROL_SEL 0x01 #define DFII_CONTROL_SEL 0x01
#define DFII_CONTROL_CKE 0x02 #define DFII_CONTROL_CKE 0x02
#define DFII_CONTROL_ODT 0x04 #define DFII_CONTROL_ODT 0x04
#define DFII_CONTROL_RESET_N 0x08 #define DFII_CONTROL_RESET_N 0x08
#define DFII_COMMAND_CS 0x01 #define DFII_COMMAND_CS 0x01
#define DFII_COMMAND_WE 0x02 #define DFII_COMMAND_WE 0x02
#define DFII_COMMAND_CAS 0x04 #define DFII_COMMAND_CAS 0x04
#define DFII_COMMAND_RAS 0x08 #define DFII_COMMAND_RAS 0x08
#define DFII_COMMAND_WRDATA 0x10 #define DFII_COMMAND_WRDATA 0x10
#define DFII_COMMAND_RDDATA 0x20 #define DFII_COMMAND_RDDATA 0x20
#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);
__attribute__((unused)) static inline void command_p0(int cmd) __attribute__((unused)) static inline void command_p0(int cmd)
{ {
sdram_dfii_pi0_command_write(cmd); sdram_dfii_pi0_command_write(cmd);
sdram_dfii_pi0_command_issue_write(1); sdram_dfii_pi0_command_issue_write(1);
} }
#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) { {
case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR; switch (phase) {
default: return 0; case 0: return CSR_SDRAM_DFII_PI0_WRDATA_ADDR;
} 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;
} }
} }
static inline void init_sequence(void) static inline void init_sequence(void)
{ {
/* Bring CKE high */ /* Bring CKE high */
@ -92,4 +95,5 @@ static inline void init_sequence(void)
cdelay(200); cdelay(200);
} }
#endif
#endif /* __GENERATED_SDRAM_PHY_H */