mirror of
https://github.com/enjoy-digital/litedram.git
synced 2025-01-04 09:52:25 -05:00
phy/s7ddrphy: use our own bitslip module in fabric
we could probably reduce added latency to 2 or 1 in the future.
This commit is contained in:
parent
20d767532d
commit
8d24163a86
1 changed files with 28 additions and 16 deletions
|
@ -6,6 +6,7 @@ import math
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
from migen.genlib.misc import BitSlip
|
||||||
|
|
||||||
from litex.soc.interconnect.csr import *
|
from litex.soc.interconnect.csr import *
|
||||||
|
|
||||||
|
@ -41,9 +42,9 @@ def get_sys_phases(nphases, sys_latency, cas_latency):
|
||||||
cmd_phase = (dat_phase - 1)%nphases
|
cmd_phase = (dat_phase - 1)%nphases
|
||||||
return cmd_phase, dat_phase
|
return cmd_phase, dat_phase
|
||||||
|
|
||||||
|
|
||||||
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,
|
def __init__(self, pads, with_odelay, memtype="DDR3", nphases=4, sys_clk_freq=100e6, iodelay_clk_freq=200e6):
|
||||||
additional_read_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)
|
||||||
|
@ -52,7 +53,6 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
databits = len(pads.dq)
|
databits = len(pads.dq)
|
||||||
nphases = nphases
|
nphases = nphases
|
||||||
|
|
||||||
|
|
||||||
iodelay_tap_average = {
|
iodelay_tap_average = {
|
||||||
200e6: 78e-12,
|
200e6: 78e-12,
|
||||||
300e6: 52e-12,
|
300e6: 52e-12,
|
||||||
|
@ -97,7 +97,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
wrcmdphase=wrcmdphase,
|
wrcmdphase=wrcmdphase,
|
||||||
cl=cl,
|
cl=cl,
|
||||||
cwl=cwl,
|
cwl=cwl,
|
||||||
read_latency=2 + cl_sys_latency + 2 + additional_read_latency,
|
read_latency=2 + cl_sys_latency + 2 + 3,
|
||||||
write_latency=cwl_sys_latency
|
write_latency=cwl_sys_latency
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -318,25 +318,36 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
|
|
||||||
i_DDLY=dq_i_delayed,
|
i_DDLY=dq_i_delayed,
|
||||||
i_CE1=1,
|
i_CE1=1,
|
||||||
i_RST=ResetSignal() | (self._dly_sel.storage[i//8] & self._rdly_dq_bitslip_rst.re),
|
i_RST=ResetSignal(),
|
||||||
i_CLK=ClockSignal(ddr_clk), i_CLKB=~ClockSignal(ddr_clk), i_CLKDIV=ClockSignal(),
|
i_CLK=ClockSignal(ddr_clk), i_CLKB=~ClockSignal(ddr_clk), i_CLKDIV=ClockSignal(),
|
||||||
i_BITSLIP=self._dly_sel.storage[i//8] & self._rdly_dq_bitslip.re,
|
i_BITSLIP=0,
|
||||||
o_Q8=dq_i_data[7], o_Q7=dq_i_data[6],
|
o_Q8=dq_i_data[0], o_Q7=dq_i_data[1],
|
||||||
o_Q6=dq_i_data[5], o_Q5=dq_i_data[4],
|
o_Q6=dq_i_data[2], o_Q5=dq_i_data[3],
|
||||||
o_Q4=dq_i_data[3], o_Q3=dq_i_data[2],
|
o_Q4=dq_i_data[4], o_Q3=dq_i_data[5],
|
||||||
o_Q2=dq_i_data[1], o_Q1=dq_i_data[0]
|
o_Q2=dq_i_data[6], o_Q1=dq_i_data[7]
|
||||||
)
|
)
|
||||||
|
dq_bitslip = BitSlip(8)
|
||||||
|
self.comb += dq_bitslip.i.eq(dq_i_data)
|
||||||
|
self.sync += \
|
||||||
|
If(self._dly_sel.storage[i//8],
|
||||||
|
If(self._rdly_dq_bitslip_rst.re,
|
||||||
|
dq_bitslip.value.eq(0)
|
||||||
|
).Elif(self._rdly_dq_bitslip.re,
|
||||||
|
dq_bitslip.value.eq(dq_bitslip.value + 1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.submodules += dq_bitslip
|
||||||
if nphases == 2:
|
if nphases == 2:
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.dfi.phases[0].rddata[i].eq(dq_i_data[3]), self.dfi.phases[0].rddata[databits+i].eq(dq_i_data[2]),
|
self.dfi.phases[0].rddata[i].eq(dq_bitslip.o[7]), self.dfi.phases[0].rddata[databits+i].eq(dq_bitslip.o[5]),
|
||||||
self.dfi.phases[1].rddata[i].eq(dq_i_data[1]), self.dfi.phases[1].rddata[databits+i].eq(dq_i_data[0])
|
self.dfi.phases[1].rddata[i].eq(dq_bitslip.o[6]), self.dfi.phases[1].rddata[databits+i].eq(dq_bitslip.o[7])
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.dfi.phases[0].rddata[i].eq(dq_i_data[7]), self.dfi.phases[0].rddata[databits+i].eq(dq_i_data[6]),
|
self.dfi.phases[0].rddata[i].eq(dq_bitslip.o[0]), self.dfi.phases[0].rddata[databits+i].eq(dq_bitslip.o[1]),
|
||||||
self.dfi.phases[1].rddata[i].eq(dq_i_data[5]), self.dfi.phases[1].rddata[databits+i].eq(dq_i_data[4]),
|
self.dfi.phases[1].rddata[i].eq(dq_bitslip.o[2]), self.dfi.phases[1].rddata[databits+i].eq(dq_bitslip.o[3]),
|
||||||
self.dfi.phases[2].rddata[i].eq(dq_i_data[3]), self.dfi.phases[2].rddata[databits+i].eq(dq_i_data[2]),
|
self.dfi.phases[2].rddata[i].eq(dq_bitslip.o[4]), self.dfi.phases[2].rddata[databits+i].eq(dq_bitslip.o[5]),
|
||||||
self.dfi.phases[3].rddata[i].eq(dq_i_data[1]), self.dfi.phases[3].rddata[databits+i].eq(dq_i_data[0])
|
self.dfi.phases[3].rddata[i].eq(dq_bitslip.o[6]), self.dfi.phases[3].rddata[databits+i].eq(dq_bitslip.o[7])
|
||||||
]
|
]
|
||||||
|
|
||||||
if with_odelay:
|
if with_odelay:
|
||||||
|
@ -378,6 +389,7 @@ class S7DDRPHY(Module, AutoCSR):
|
||||||
# 2 cycles through OSERDESE2
|
# 2 cycles through OSERDESE2
|
||||||
# cl_sys_latency cycles CAS
|
# cl_sys_latency cycles CAS
|
||||||
# 2 cycles through ISERDESE2
|
# 2 cycles through ISERDESE2
|
||||||
|
# 3 cycles through Bitslip
|
||||||
rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en
|
rddata_en = self.dfi.phases[self.settings.rdphase].rddata_en
|
||||||
for i in range(self.settings.read_latency-1):
|
for i in range(self.settings.read_latency-1):
|
||||||
n_rddata_en = Signal()
|
n_rddata_en = Signal()
|
||||||
|
|
Loading…
Reference in a new issue