diff --git a/litedram/phy/s7ddrphy.py b/litedram/phy/s7ddrphy.py index 3b19e70..d898f2d 100644 --- a/litedram/phy/s7ddrphy.py +++ b/litedram/phy/s7ddrphy.py @@ -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)