phys: improve presentation (add separators, better indent)
This commit is contained in:
parent
783258c97f
commit
f586aada1c
|
@ -89,6 +89,7 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = 2
|
nphases = 2
|
||||||
|
assert databits%8 == 0
|
||||||
|
|
||||||
# Init -------------------------------------------------------------------------------------
|
# Init -------------------------------------------------------------------------------------
|
||||||
self.submodules.init = ClockDomainsRenamer("init")(ECP5DDRPHYInit("sys2x"))
|
self.submodules.init = ClockDomainsRenamer("init")(ECP5DDRPHYInit("sys2x"))
|
||||||
|
@ -115,19 +116,19 @@ class ECP5DDRPHY(Module, AutoCSR):
|
||||||
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
||||||
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
memtype=memtype,
|
memtype = memtype,
|
||||||
databits=databits,
|
databits = databits,
|
||||||
dfi_databits=4*databits,
|
dfi_databits = 4*databits,
|
||||||
nranks=nranks,
|
nranks = nranks,
|
||||||
nphases=nphases,
|
nphases = nphases,
|
||||||
rdphase=rdphase,
|
rdphase = rdphase,
|
||||||
wrphase=wrphase,
|
wrphase = wrphase,
|
||||||
rdcmdphase=rdcmdphase,
|
rdcmdphase = rdcmdphase,
|
||||||
wrcmdphase=wrcmdphase,
|
wrcmdphase = wrcmdphase,
|
||||||
cl=cl,
|
cl = cl,
|
||||||
cwl=cwl,
|
cwl = cwl,
|
||||||
read_latency=2 + cl_sys_latency + 2 + log2_int(4//nphases) + 6,
|
read_latency = 2 + cl_sys_latency + 2 + log2_int(4//nphases) + 6,
|
||||||
write_latency=cwl_sys_latency
|
write_latency = cwl_sys_latency
|
||||||
)
|
)
|
||||||
|
|
||||||
# DFI Interface ----------------------------------------------------------------------------
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -21,35 +21,38 @@ from migen.fhdl.specials import Tristate
|
||||||
from litedram.common import PhySettings
|
from litedram.common import PhySettings
|
||||||
from litedram.phy.dfi import *
|
from litedram.phy.dfi import *
|
||||||
|
|
||||||
|
# Generic SDR PHY ----------------------------------------------------------------------------------
|
||||||
|
|
||||||
class GENSDRPHY(Module):
|
class GENSDRPHY(Module):
|
||||||
def __init__(self, pads, cl=2):
|
def __init__(self, pads, cl=2):
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
assert databits%8 == 0
|
assert databits%8 == 0
|
||||||
|
|
||||||
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
memtype="SDR",
|
memtype = "SDR",
|
||||||
databits=databits,
|
databits = databits,
|
||||||
dfi_databits=databits,
|
dfi_databits = databits,
|
||||||
nranks=nranks,
|
nranks = nranks,
|
||||||
nphases=1,
|
nphases = 1,
|
||||||
rdphase=0,
|
rdphase = 0,
|
||||||
wrphase=0,
|
wrphase = 0,
|
||||||
rdcmdphase=0,
|
rdcmdphase = 0,
|
||||||
wrcmdphase=0,
|
wrcmdphase = 0,
|
||||||
cl=cl,
|
cl = cl,
|
||||||
read_latency=cl + 2,
|
read_latency = cl + 2,
|
||||||
write_latency=0
|
write_latency = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
self.dfi = dfi = Interface(addressbits, bankbits, nranks, databits)
|
self.dfi = dfi = Interface(addressbits, bankbits, nranks, databits)
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Command/address
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
self.sync += [
|
self.sync += [
|
||||||
pads.a.eq(dfi.p0.address),
|
pads.a.eq(dfi.p0.address),
|
||||||
pads.ba.eq(dfi.p0.bank),
|
pads.ba.eq(dfi.p0.bank),
|
||||||
|
@ -62,7 +65,7 @@ class GENSDRPHY(Module):
|
||||||
if hasattr(pads, "cs_n"):
|
if hasattr(pads, "cs_n"):
|
||||||
self.sync += pads.cs_n.eq(dfi.p0.cs_n)
|
self.sync += pads.cs_n.eq(dfi.p0.cs_n)
|
||||||
|
|
||||||
# DQ/DQS/DM data
|
# DQ/DQS/DM Data ---------------------------------------------------------------------------
|
||||||
dq_o = Signal(databits)
|
dq_o = Signal(databits)
|
||||||
dq_oe = Signal()
|
dq_oe = Signal()
|
||||||
dq_i = Signal(databits)
|
dq_i = Signal(databits)
|
||||||
|
@ -80,7 +83,7 @@ class GENSDRPHY(Module):
|
||||||
self.sync.sys_ps += dq_in.eq(dq_i)
|
self.sync.sys_ps += dq_in.eq(dq_i)
|
||||||
self.sync += dfi.p0.rddata.eq(dq_in)
|
self.sync += dfi.p0.rddata.eq(dq_in)
|
||||||
|
|
||||||
# DQ/DM control
|
# DQ/DM Control ----------------------------------------------------------------------------
|
||||||
wrdata_en = Signal()
|
wrdata_en = Signal()
|
||||||
self.sync += wrdata_en.eq(dfi.p0.wrdata_en)
|
self.sync += wrdata_en.eq(dfi.p0.wrdata_en)
|
||||||
self.comb += dq_oe.eq(wrdata_en)
|
self.comb += dq_oe.eq(wrdata_en)
|
||||||
|
|
|
@ -36,49 +36,53 @@ class S6HalfRateDDRPHY(Module):
|
||||||
if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
||||||
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
|
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = 2
|
nphases = 2
|
||||||
|
assert databits%8 == 0
|
||||||
|
|
||||||
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
if memtype == "DDR3":
|
if memtype == "DDR3":
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
memtype="DDR3",
|
memtype = "DDR3",
|
||||||
databits=databits,
|
databits = databits,
|
||||||
dfi_databits=2*databits,
|
dfi_databits = 2*databits,
|
||||||
nranks=nranks,
|
nranks = nranks,
|
||||||
nphases=nphases,
|
nphases = nphases,
|
||||||
rdphase=0,
|
rdphase = 0,
|
||||||
wrphase=1,
|
wrphase = 1,
|
||||||
rdcmdphase=1,
|
rdcmdphase = 1,
|
||||||
wrcmdphase=0,
|
wrcmdphase = 0,
|
||||||
cl=5,
|
cl = 5,
|
||||||
cwl=6,
|
cwl = 6,
|
||||||
read_latency=6,
|
read_latency = 6,
|
||||||
write_latency=2
|
write_latency = 2
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
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=0,
|
rdphase = 0,
|
||||||
wrphase=1,
|
wrphase = 1,
|
||||||
rdcmdphase=1,
|
rdcmdphase = 1,
|
||||||
wrcmdphase=0,
|
wrcmdphase = 0,
|
||||||
cl=3,
|
cl = 3,
|
||||||
read_latency=5,
|
read_latency = 5,
|
||||||
write_latency=0
|
write_latency = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
||||||
self.clk4x_wr_strb = Signal()
|
self.clk4x_wr_strb = Signal()
|
||||||
self.clk4x_rd_strb = Signal()
|
self.clk4x_rd_strb = Signal()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
# Clock ------------------------------------------------------------------------------------
|
||||||
# sys_clk : system clk, used for dfi interface
|
# sys_clk : system clk, used for dfi interface
|
||||||
# sdram_half_clk : half rate sdram clk
|
# sdram_half_clk : half rate sdram clk
|
||||||
# sdram_full_wr_clk : full rate sdram write clk
|
# sdram_full_wr_clk : full rate sdram write clk
|
||||||
|
@ -91,9 +95,7 @@ class S6HalfRateDDRPHY(Module):
|
||||||
sdram_full_wr_clk = ClockSignal("sdram_full_wr")
|
sdram_full_wr_clk = ClockSignal("sdram_full_wr")
|
||||||
sdram_full_rd_clk = ClockSignal("sdram_full_rd")
|
sdram_full_rd_clk = ClockSignal("sdram_full_rd")
|
||||||
|
|
||||||
#
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
# Command/address
|
|
||||||
#
|
|
||||||
|
|
||||||
# select active phase
|
# select active phase
|
||||||
# sys_clk ----____----____
|
# sys_clk ----____----____
|
||||||
|
@ -142,9 +144,7 @@ class S6HalfRateDDRPHY(Module):
|
||||||
if hasattr(pads, name):
|
if hasattr(pads, name):
|
||||||
sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
|
sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
|
||||||
|
|
||||||
#
|
# Bitslip ----------------------------------------------------------------------------------
|
||||||
# Bitslip
|
|
||||||
#
|
|
||||||
bitslip_cnt = Signal(4)
|
bitslip_cnt = Signal(4)
|
||||||
bitslip_inc = Signal()
|
bitslip_inc = Signal()
|
||||||
|
|
||||||
|
@ -157,9 +157,7 @@ class S6HalfRateDDRPHY(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
#
|
# DQ/DQS/DM data ---------------------------------------------------------------------------
|
||||||
# DQ/DQS/DM data
|
|
||||||
#
|
|
||||||
sdram_half_clk_n = Signal()
|
sdram_half_clk_n = Signal()
|
||||||
self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
|
self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
|
||||||
|
|
||||||
|
@ -365,10 +363,7 @@ class S6HalfRateDDRPHY(Module):
|
||||||
i_SHIFTIN4=0,
|
i_SHIFTIN4=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# DQ/DQS/DM control ------------------------------------------------------------------------
|
||||||
#
|
|
||||||
# DQ/DQS/DM control
|
|
||||||
#
|
|
||||||
|
|
||||||
# write
|
# write
|
||||||
wrdata_en = Signal()
|
wrdata_en = Signal()
|
||||||
|
@ -411,35 +406,39 @@ class S6HalfRateDDRPHY(Module):
|
||||||
|
|
||||||
class S6QuarterRateDDRPHY(Module):
|
class S6QuarterRateDDRPHY(Module):
|
||||||
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
||||||
half_rate_phy = S6HalfRateDDRPHY(pads, "DDR3", rd_bitslip, wr_bitslip, dqs_ddr_alignment)
|
|
||||||
self.submodules += ClockDomainsRenamer("sys2x")(half_rate_phy)
|
|
||||||
|
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = 4
|
nphases = 4
|
||||||
|
|
||||||
self.settings = PhySettings(
|
# HalfRate PHY -----------------------------------------------------------------------------
|
||||||
memtype="DDR3",
|
half_rate_phy = S6HalfRateDDRPHY(pads, "DDR3", rd_bitslip, wr_bitslip, dqs_ddr_alignment)
|
||||||
databits=databits,
|
self.submodules += ClockDomainsRenamer("sys2x")(half_rate_phy)
|
||||||
dfi_databits=2*databits,
|
|
||||||
nranks=nranks,
|
|
||||||
nphases=nphases,
|
|
||||||
rdphase=0,
|
|
||||||
wrphase=1,
|
|
||||||
rdcmdphase=1,
|
|
||||||
wrcmdphase=0,
|
|
||||||
cl=5,
|
|
||||||
cwl=6,
|
|
||||||
read_latency=6//2+1,
|
|
||||||
write_latency=2//2
|
|
||||||
)
|
|
||||||
|
|
||||||
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
|
||||||
self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb
|
self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb
|
||||||
self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb
|
self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb
|
||||||
|
|
||||||
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
|
self.settings = PhySettings(
|
||||||
|
memtype = "DDR3",
|
||||||
|
databits = databits,
|
||||||
|
dfi_databits = 2*databits,
|
||||||
|
nranks = nranks,
|
||||||
|
nphases = nphases,
|
||||||
|
rdphase = 0,
|
||||||
|
wrphase = 1,
|
||||||
|
rdcmdphase = 1,
|
||||||
|
wrcmdphase = 0,
|
||||||
|
cl = 5,
|
||||||
|
cwl = 6,
|
||||||
|
read_latency = 6//2+1,
|
||||||
|
write_latency = 2//2
|
||||||
|
)
|
||||||
|
|
||||||
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
|
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
||||||
|
|
||||||
|
# Clock ------------------------------------------------------------------------------------
|
||||||
# sys_clk : system clk, used for dfi interface
|
# sys_clk : system clk, used for dfi interface
|
||||||
# sys2x_clk : 2x system clk
|
# sys2x_clk : 2x system clk
|
||||||
sd_sys = getattr(self.sync, "sys")
|
sd_sys = getattr(self.sync, "sys")
|
||||||
|
@ -463,7 +462,7 @@ class S6QuarterRateDDRPHY(Module):
|
||||||
phase_sys2x.eq(~phase_sel)
|
phase_sys2x.eq(~phase_sel)
|
||||||
]
|
]
|
||||||
|
|
||||||
# DFI adaptation
|
# DFI adaptation ---------------------------------------------------------------------------
|
||||||
|
|
||||||
# Commands and writes
|
# Commands and writes
|
||||||
dfi_omit = set(["rddata", "rddata_valid", "wrdata_en"])
|
dfi_omit = set(["rddata", "rddata_valid", "wrdata_en"])
|
||||||
|
|
|
@ -16,16 +16,18 @@ from litex.soc.interconnect.csr import *
|
||||||
from litedram.common import *
|
from litedram.common import *
|
||||||
from litedram.phy.dfi import *
|
from litedram.phy.dfi import *
|
||||||
|
|
||||||
|
# Xilinx Series7 DDR2/DDR3 PHY ---------------------------------------------------------------------
|
||||||
|
|
||||||
class S7DDRPHY(Module, AutoCSR):
|
class S7DDRPHY(Module, AutoCSR):
|
||||||
def __init__(self, pads, with_odelay, memtype="DDR3", nphases=4, sys_clk_freq=100e6, iodelay_clk_freq=200e6, cmd_latency=0):
|
def __init__(self, pads, with_odelay, memtype="DDR3", nphases=4, sys_clk_freq=100e6, iodelay_clk_freq=200e6, cmd_latency=0):
|
||||||
assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2
|
assert not (memtype == "DDR3" and nphases == 2) # FIXME: Needs BL8 support for nphases=2
|
||||||
tck = 2/(2*nphases*sys_clk_freq)
|
tck = 2/(2*nphases*sys_clk_freq)
|
||||||
addressbits = len(pads.a)
|
addressbits = len(pads.a)
|
||||||
bankbits = len(pads.ba)
|
bankbits = len(pads.ba)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = nphases
|
nphases = nphases
|
||||||
|
assert databits%8 == 0
|
||||||
|
|
||||||
iodelay_tap_average = {
|
iodelay_tap_average = {
|
||||||
200e6: 78e-12,
|
200e6: 78e-12,
|
||||||
|
@ -33,6 +35,8 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
400e6: 39e-12, # Only valid for -3 and -2/2E speed grades
|
400e6: 39e-12, # Only valid for -3 and -2/2E speed grades
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Registers --------------------------------------------------------------------------------
|
||||||
|
self._dly_sel = CSRStorage(databits//8)
|
||||||
half_sys8x_taps = math.floor(tck/(4*iodelay_tap_average[iodelay_clk_freq]))
|
half_sys8x_taps = math.floor(tck/(4*iodelay_tap_average[iodelay_clk_freq]))
|
||||||
self._half_sys8x_taps = CSRStorage(5, reset=half_sys8x_taps)
|
self._half_sys8x_taps = CSRStorage(5, reset=half_sys8x_taps)
|
||||||
|
|
||||||
|
@ -45,46 +49,47 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
self._dly_sel = CSRStorage(databits//8)
|
self._dly_sel = CSRStorage(databits//8)
|
||||||
|
|
||||||
self._rdly_dq_rst = CSR()
|
self._rdly_dq_rst = CSR()
|
||||||
self._rdly_dq_inc = CSR()
|
self._rdly_dq_inc = CSR()
|
||||||
self._rdly_dq_bitslip_rst = CSR()
|
self._rdly_dq_bitslip_rst = CSR()
|
||||||
self._rdly_dq_bitslip = CSR()
|
self._rdly_dq_bitslip = CSR()
|
||||||
|
|
||||||
if with_odelay:
|
if with_odelay:
|
||||||
self._wdly_dq_rst = CSR()
|
self._wdly_dq_rst = CSR()
|
||||||
self._wdly_dq_inc = CSR()
|
self._wdly_dq_inc = CSR()
|
||||||
self._wdly_dqs_rst = CSR()
|
self._wdly_dqs_rst = CSR()
|
||||||
self._wdly_dqs_inc = CSR()
|
self._wdly_dqs_inc = CSR()
|
||||||
|
|
||||||
# compute phy settings
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
cl, cwl = get_cl_cw(memtype, tck)
|
cl, cwl = get_cl_cw(memtype, tck)
|
||||||
cl_sys_latency = get_sys_latency(nphases, cl)
|
cl_sys_latency = get_sys_latency(nphases, cl)
|
||||||
cwl = cwl + cmd_latency
|
cwl = cwl + cmd_latency
|
||||||
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
||||||
|
|
||||||
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
||||||
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
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=rdphase,
|
rdphase = rdphase,
|
||||||
wrphase=wrphase,
|
wrphase = wrphase,
|
||||||
rdcmdphase=rdcmdphase,
|
rdcmdphase = rdcmdphase,
|
||||||
wrcmdphase=wrcmdphase,
|
wrcmdphase = wrcmdphase,
|
||||||
cl=cl,
|
cl = cl,
|
||||||
cwl=cwl - cmd_latency,
|
cwl = cwl - cmd_latency,
|
||||||
read_latency=2 + cl_sys_latency + 2 + 3,
|
read_latency = 2 + cl_sys_latency + 2 + 3,
|
||||||
write_latency=cwl_sys_latency
|
write_latency = cwl_sys_latency
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, 4)
|
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, 4)
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Clock
|
# Clock ------------------------------------------------------------------------------------
|
||||||
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
|
ddr_clk = "sys2x" if nphases == 2 else "sys4x"
|
||||||
for i in range(len(pads.clk_p)):
|
for i in range(len(pads.clk_p)):
|
||||||
sd_clk_se_nodelay = Signal()
|
sd_clk_se_nodelay = Signal()
|
||||||
|
@ -123,7 +128,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
o_OB=pads.clk_n[i]
|
o_OB=pads.clk_n[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Addresses and commands
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
for i in range(addressbits):
|
for i in range(addressbits):
|
||||||
address = Signal()
|
address = Signal()
|
||||||
self.specials += \
|
self.specials += \
|
||||||
|
@ -224,7 +229,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
o_ODATAIN=cmd, o_DATAOUT=getattr(pads, name)[i]
|
o_ODATAIN=cmd, o_DATAOUT=getattr(pads, name)[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
# DQS and DM
|
# DQS and DM -------------------------------------------------------------------------------
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
dqs_preamble = Signal()
|
dqs_preamble = Signal()
|
||||||
dqs_postamble = Signal()
|
dqs_postamble = Signal()
|
||||||
|
@ -324,7 +329,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
o_O=pads.dqs_p[i], o_OB=pads.dqs_n[i]
|
o_O=pads.dqs_p[i], o_OB=pads.dqs_n[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
# DQ
|
# DQ ---------------------------------------------------------------------------------------
|
||||||
oe_dq = Signal()
|
oe_dq = Signal()
|
||||||
for i in range(databits):
|
for i in range(databits):
|
||||||
dq_o_nodelay = Signal()
|
dq_o_nodelay = Signal()
|
||||||
|
@ -416,7 +421,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
io_IO=pads.dq[i]
|
io_IO=pads.dq[i]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Flow control
|
# Flow control -----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# total read latency:
|
# total read latency:
|
||||||
# 2 cycles through OSERDESE2
|
# 2 cycles through OSERDESE2
|
||||||
|
@ -468,16 +473,20 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
~last_wrdata_en[dqs_sys_latency]),
|
~last_wrdata_en[dqs_sys_latency]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Xilinx Virtex7 (S7DDRPHY with odelay) ------------------------------------------------------------
|
||||||
|
|
||||||
class V7DDRPHY(S7DDRPHY):
|
class V7DDRPHY(S7DDRPHY):
|
||||||
def __init__(self, pads, **kwargs):
|
def __init__(self, pads, **kwargs):
|
||||||
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
||||||
|
|
||||||
|
# Xilinx Kintex7 (S7DDRPHY with odelay) ------------------------------------------------------------
|
||||||
|
|
||||||
class K7DDRPHY(S7DDRPHY):
|
class K7DDRPHY(S7DDRPHY):
|
||||||
def __init__(self, pads, **kwargs):
|
def __init__(self, pads, **kwargs):
|
||||||
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
||||||
|
|
||||||
|
# Xilinx Artix7 (S7DDRPHY without odelay, sys2/4x_dqs generated in CRG with 90° phase vs sys2/4x) --
|
||||||
|
|
||||||
class A7DDRPHY(S7DDRPHY):
|
class A7DDRPHY(S7DDRPHY):
|
||||||
def __init__(self, pads, **kwargs):
|
def __init__(self, pads, **kwargs):
|
||||||
S7DDRPHY.__init__(self, pads, with_odelay=False, **kwargs)
|
S7DDRPHY.__init__(self, pads, with_odelay=False, **kwargs)
|
||||||
|
|
|
@ -15,6 +15,7 @@ from litex.soc.interconnect.csr import *
|
||||||
from litedram.common import *
|
from litedram.common import *
|
||||||
from litedram.phy.dfi import *
|
from litedram.phy.dfi import *
|
||||||
|
|
||||||
|
# Xilinx Ultrascale DDR3/DDR4 PHY ------------------------------------------------------------------
|
||||||
|
|
||||||
class USDDRPHY(Module, AutoCSR):
|
class USDDRPHY(Module, AutoCSR):
|
||||||
def __init__(self, pads, memtype="DDR3", sys_clk_freq=100e6, iodelay_clk_freq=200e6, cmd_latency=0):
|
def __init__(self, pads, memtype="DDR3", sys_clk_freq=100e6, iodelay_clk_freq=200e6, cmd_latency=0):
|
||||||
|
@ -23,18 +24,20 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
if memtype == "DDR4":
|
if memtype == "DDR4":
|
||||||
addressbits += 3 # cas_n/ras_n/we_n multiplexed with address
|
addressbits += 3 # cas_n/ras_n/we_n multiplexed with address
|
||||||
bankbits = len(pads.ba) if memtype == "DDR3" else len(pads.ba) + len(pads.bg)
|
bankbits = len(pads.ba) if memtype == "DDR3" else len(pads.ba) + len(pads.bg)
|
||||||
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n)
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = 4
|
nphases = 4
|
||||||
|
assert databits%8 == 0
|
||||||
|
|
||||||
if hasattr(pads, "ten"):
|
if hasattr(pads, "ten"):
|
||||||
self.comb += pads.ten.eq(0)
|
self.comb += pads.ten.eq(0)
|
||||||
|
|
||||||
|
# Registers --------------------------------------------------------------------------------
|
||||||
self._en_vtc = CSRStorage(reset=1)
|
self._en_vtc = CSRStorage(reset=1)
|
||||||
|
|
||||||
self._half_sys8x_taps = CSRStatus(9)
|
self._half_sys8x_taps = CSRStatus(9)
|
||||||
|
|
||||||
self._wlevel_en = CSRStorage()
|
self._wlevel_en = CSRStorage()
|
||||||
self._wlevel_strobe = CSR()
|
self._wlevel_strobe = CSR()
|
||||||
|
|
||||||
self._cdly_rst = CSR()
|
self._cdly_rst = CSR()
|
||||||
|
@ -42,40 +45,41 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
self._dly_sel = CSRStorage(databits//8)
|
self._dly_sel = CSRStorage(databits//8)
|
||||||
|
|
||||||
self._rdly_dq_rst = CSR()
|
self._rdly_dq_rst = CSR()
|
||||||
self._rdly_dq_inc = CSR()
|
self._rdly_dq_inc = CSR()
|
||||||
self._rdly_dq_bitslip_rst = CSR()
|
self._rdly_dq_bitslip_rst = CSR()
|
||||||
self._rdly_dq_bitslip = CSR()
|
self._rdly_dq_bitslip = CSR()
|
||||||
|
|
||||||
self._wdly_dq_rst = CSR()
|
self._wdly_dq_rst = CSR()
|
||||||
self._wdly_dq_inc = CSR()
|
self._wdly_dq_inc = CSR()
|
||||||
self._wdly_dqs_rst = CSR()
|
self._wdly_dqs_rst = CSR()
|
||||||
self._wdly_dqs_inc = CSR()
|
self._wdly_dqs_inc = CSR()
|
||||||
|
|
||||||
# compute phy settings
|
# PHY settings -----------------------------------------------------------------------------
|
||||||
cl, cwl = get_cl_cw(memtype, tck)
|
cl, cwl = get_cl_cw(memtype, tck)
|
||||||
cwl = cwl + cmd_latency
|
cwl = cwl + cmd_latency
|
||||||
cl_sys_latency = get_sys_latency(nphases, cl)
|
cl_sys_latency = get_sys_latency(nphases, cl)
|
||||||
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
cwl_sys_latency = get_sys_latency(nphases, cwl)
|
||||||
|
|
||||||
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
|
||||||
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
|
||||||
self.settings = PhySettings(
|
self.settings = PhySettings(
|
||||||
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=rdphase,
|
rdphase = rdphase,
|
||||||
wrphase=wrphase,
|
wrphase = wrphase,
|
||||||
rdcmdphase=rdcmdphase,
|
rdcmdphase = rdcmdphase,
|
||||||
wrcmdphase=wrcmdphase,
|
wrcmdphase = wrcmdphase,
|
||||||
cl=cl,
|
cl = cl,
|
||||||
cwl=cwl - cmd_latency,
|
cwl = cwl - cmd_latency,
|
||||||
read_latency=2 + cl_sys_latency + 1 + 3,
|
read_latency = 2 + cl_sys_latency + 1 + 3,
|
||||||
write_latency=cwl_sys_latency
|
write_latency = cwl_sys_latency
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# DFI Interface ----------------------------------------------------------------------------
|
||||||
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
self.dfi = dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
||||||
if memtype == "DDR4":
|
if memtype == "DDR4":
|
||||||
dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
dfi = Interface(addressbits, bankbits, nranks, 2*databits, nphases)
|
||||||
|
@ -83,7 +87,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# Clock
|
# Clock ------------------------------------------------------------------------------------
|
||||||
clk_o_nodelay = Signal()
|
clk_o_nodelay = Signal()
|
||||||
clk_o_delayed = Signal()
|
clk_o_delayed = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -114,7 +118,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Addresses and commands
|
# Addresses and Commands -------------------------------------------------------------------
|
||||||
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
|
for i in range(addressbits if memtype=="DDR3" else addressbits-3):
|
||||||
a_o_nodelay = Signal()
|
a_o_nodelay = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -212,7 +216,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# DQS and DM
|
# DQS and DM -------------------------------------------------------------------------------
|
||||||
oe_dqs = Signal()
|
oe_dqs = Signal()
|
||||||
dqs_serdes_pattern = Signal(8)
|
dqs_serdes_pattern = Signal(8)
|
||||||
self.comb += \
|
self.comb += \
|
||||||
|
@ -258,8 +262,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
dqs_delayed = Signal()
|
dqs_delayed = Signal()
|
||||||
dqs_t = Signal()
|
dqs_t = Signal()
|
||||||
if i == 0:
|
if i == 0:
|
||||||
# Store initial DQS DELAY_VALUE (in taps) to
|
# Store initial DQS DELAY_VALUE (in taps) to be able to reload DELAY_VALUE after reset.
|
||||||
# be able to reload DELAY_VALUE after reset.
|
|
||||||
dqs_taps = Signal(9)
|
dqs_taps = Signal(9)
|
||||||
dqs_taps_timer = WaitTimer(2**16)
|
dqs_taps_timer = WaitTimer(2**16)
|
||||||
self.submodules += dqs_taps_timer
|
self.submodules += dqs_taps_timer
|
||||||
|
@ -303,7 +306,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# DQ
|
# DQ ---------------------------------------------------------------------------------------
|
||||||
oe_dq = Signal()
|
oe_dq = Signal()
|
||||||
for i in range(databits):
|
for i in range(databits):
|
||||||
dq_o_nodelay = Signal()
|
dq_o_nodelay = Signal()
|
||||||
|
@ -390,7 +393,7 @@ class USDDRPHY(Module, AutoCSR):
|
||||||
dfi.phases[3].rddata[databits+i].eq(dq_bitslip.o[7]),
|
dfi.phases[3].rddata[databits+i].eq(dq_bitslip.o[7]),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Flow control
|
# Flow control -----------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# total read latency:
|
# total read latency:
|
||||||
# 2 cycles through OSERDESE2
|
# 2 cycles through OSERDESE2
|
||||||
|
|
Loading…
Reference in New Issue