phys: improve presentation (add separators, better indent)

This commit is contained in:
Florent Kermarrec 2019-09-11 09:50:46 +02:00
parent 783258c97f
commit f586aada1c
5 changed files with 173 additions and 158 deletions

View File

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

View File

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

View File

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

View File

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

View File

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