phy/s7ddrphy: compute phy settings automatically (based on tck) and add DDR3-1066/1333/1600 support.
This commit is contained in:
parent
ba16ebfb22
commit
d9da7c54ee
|
@ -1,5 +1,6 @@
|
|||
# 1:4 frequency-ratio DDR3 PHYs for Series7
|
||||
# tCK=2.5ns CL=7 CWL=6
|
||||
# 1:4 frequency-ratio DDR3 PHY for Xilinx's Series7
|
||||
|
||||
import math
|
||||
|
||||
from migen import *
|
||||
|
||||
|
@ -9,13 +10,37 @@ from litedram.common import PhySettings
|
|||
from litedram.phy.dfi import *
|
||||
|
||||
|
||||
def get_sys_latency(cas_latency):
|
||||
return math.ceil(cas_latency/4)
|
||||
|
||||
|
||||
def get_sys_phases(sys_latency, cas_latency, write=False):
|
||||
cmd_phase = 0
|
||||
dat_phase = 0
|
||||
diff_phase = 0
|
||||
while (diff_phase + cas_latency) != sys_latency*4:
|
||||
dat_phase += 1
|
||||
if dat_phase == 4:
|
||||
dat_phase = 0
|
||||
cmd_phase += 1
|
||||
if write:
|
||||
diff_phase = dat_phase - cmd_phase
|
||||
else:
|
||||
diff_phase = cmd_phase - dat_phase
|
||||
return cmd_phase, dat_phase
|
||||
|
||||
|
||||
class S7DDRPHY(Module, AutoCSR):
|
||||
def __init__(self, pads, with_odelay):
|
||||
def __init__(self, pads, with_odelay, sys_clk_freq=100e6):
|
||||
tck = 2/(8*sys_clk_freq)
|
||||
addressbits = len(pads.a)
|
||||
bankbits = len(pads.ba)
|
||||
databits = len(pads.dq)
|
||||
nphases = 4
|
||||
|
||||
half_sys8x_taps = math.floor(tck/(4*78e-12))
|
||||
self._half_sys8x_taps = CSRStorage(4, reset=half_sys8x_taps)
|
||||
|
||||
if with_odelay:
|
||||
self._wlevel_en = CSRStorage()
|
||||
self._wlevel_strobe = CSR()
|
||||
|
@ -32,18 +57,35 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
self._wdly_dqs_rst = CSR()
|
||||
self._wdly_dqs_inc = CSR()
|
||||
|
||||
# compute phy settings
|
||||
if tck >= 1.875e-9: # ddr3-1066
|
||||
cl = 7
|
||||
cwl = 6
|
||||
elif tck >= 1.5e-9: # ddr3-1333
|
||||
cl = 10
|
||||
cwl = 7
|
||||
elif tck >= 1.25e-9: # ddr3-1600
|
||||
cl = 11
|
||||
cwl = 8
|
||||
|
||||
cl_sys_latency = get_sys_latency(cl)
|
||||
cwl_sys_latency = get_sys_latency(cwl)
|
||||
|
||||
rdcmdphase, rdphase = get_sys_phases(cl_sys_latency, cl)
|
||||
wrcmdphase, wrphase = get_sys_phases(cwl_sys_latency, cwl, write=True)
|
||||
|
||||
self.settings = PhySettings(
|
||||
memtype="DDR3",
|
||||
dfi_databits=2*databits,
|
||||
nphases=nphases,
|
||||
rdphase=0,
|
||||
wrphase=2,
|
||||
rdcmdphase=1,
|
||||
wrcmdphase=0,
|
||||
cl=7,
|
||||
cwl=6,
|
||||
read_latency=6,
|
||||
write_latency=2
|
||||
rdphase=rdphase,
|
||||
wrphase=wrphase,
|
||||
rdcmdphase=rdcmdphase,
|
||||
wrcmdphase=wrcmdphase,
|
||||
cl=cl,
|
||||
cwl=cwl,
|
||||
read_latency=2 + cl_sys_latency + 2,
|
||||
write_latency=cwl_sys_latency
|
||||
)
|
||||
|
||||
self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
|
||||
|
@ -183,7 +225,7 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
|
||||
p_SERDES_MODE="MASTER",
|
||||
|
||||
o_OFB=dqs_nodelay if with_odelay else Signal(),
|
||||
o_OFB=dqs_nodelay if with_odelay else Signal(),
|
||||
o_OQ=Signal() if with_odelay else dqs_nodelay,
|
||||
o_TQ=dqs_t,
|
||||
i_OCE=1, i_TCE=1,
|
||||
|
@ -200,7 +242,7 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
Instance("ODELAYE2",
|
||||
p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
|
||||
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
|
||||
p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=6,
|
||||
p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=half_sys8x_taps,
|
||||
|
||||
i_C=ClockSignal(),
|
||||
i_LD=self._dly_sel.storage[i] & self._wdly_dqs_rst.re,
|
||||
|
@ -278,7 +320,7 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
Instance("IDELAYE2",
|
||||
p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
|
||||
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
|
||||
p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=6,
|
||||
p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=0,
|
||||
|
||||
i_C=ClockSignal(),
|
||||
i_LD=self._dly_sel.storage[i//8] & self._rdly_dq_rst.re,
|
||||
|
@ -295,12 +337,12 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
|
||||
# Flow control
|
||||
#
|
||||
# total read latency = 6:
|
||||
# total read latency:
|
||||
# 2 cycles through OSERDESE2
|
||||
# 2 cycles CAS
|
||||
# cl_sys_latency cycles CAS
|
||||
# 2 cycles through ISERDESE2
|
||||
rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en
|
||||
for i in range(6-1):
|
||||
for i in range(self.settings.read_latency-1):
|
||||
n_rddata_en = Signal()
|
||||
self.sync += n_rddata_en.eq(rddata_en)
|
||||
rddata_en = n_rddata_en
|
||||
|
@ -312,10 +354,13 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
for phase in self.dfi.phases]
|
||||
|
||||
oe = Signal()
|
||||
last_wrdata_en = Signal(4)
|
||||
last_wrdata_en = Signal(cwl_sys_latency+2)
|
||||
wrphase = self.dfi.phases[self.settings.wrphase]
|
||||
self.sync += last_wrdata_en.eq(Cat(wrphase.wrdata_en, last_wrdata_en[:3]))
|
||||
self.comb += oe.eq(last_wrdata_en[1] | last_wrdata_en[2] | last_wrdata_en[3])
|
||||
self.sync += last_wrdata_en.eq(Cat(wrphase.wrdata_en, last_wrdata_en[:-1]))
|
||||
self.comb += oe.eq(
|
||||
last_wrdata_en[cwl_sys_latency-1] |
|
||||
last_wrdata_en[cwl_sys_latency] |
|
||||
last_wrdata_en[cwl_sys_latency+1])
|
||||
if with_odelay:
|
||||
self.sync += \
|
||||
If(self._wlevel_en.storage,
|
||||
|
@ -331,14 +376,14 @@ class S7DDRPHY(Module, AutoCSR):
|
|||
|
||||
|
||||
class V7DDRPHY(S7DDRPHY):
|
||||
def __init__(self, pads):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=True)
|
||||
def __init__(self, pads, **kwargs):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
||||
|
||||
|
||||
class K7DDRPHY(S7DDRPHY):
|
||||
def __init__(self, pads):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=True)
|
||||
def __init__(self, pads, **kwargs):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=True, **kwargs)
|
||||
|
||||
class A7DDRPHY(S7DDRPHY):
|
||||
def __init__(self, pads):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=False)
|
||||
def __init__(self, pads, **kwargs):
|
||||
S7DDRPHY.__init__(self, pads, with_odelay=False, **kwargs)
|
||||
|
|
Loading…
Reference in New Issue