"DDR4": 8
}
+
def get_cl_cw(memtype, tck):
f_to_cl_cwl = OrderedDict()
if memtype == "DDR2":
- f_to_cl_cwl[400e6] = (3, 2)
- f_to_cl_cwl[533e6] = (4, 3)
- f_to_cl_cwl[677e6] = (5, 4)
- f_to_cl_cwl[800e6] = (6, 5)
+ f_to_cl_cwl[400e6] = (3, 2)
+ f_to_cl_cwl[533e6] = (4, 3)
+ f_to_cl_cwl[677e6] = (5, 4)
+ f_to_cl_cwl[800e6] = (6, 5)
f_to_cl_cwl[1066e6] = (7, 5)
elif memtype == "DDR3":
- f_to_cl_cwl[800e6] = ( 6, 5)
- f_to_cl_cwl[1066e6] = ( 7, 6)
+ f_to_cl_cwl[800e6] = (6, 5)
+ f_to_cl_cwl[1066e6] = (7, 6)
f_to_cl_cwl[1333e6] = (10, 7)
f_to_cl_cwl[1600e6] = (11, 8)
elif memtype == "DDR4":
return cl, cwl
raise ValueError
+
def get_sys_latency(nphases, cas_latency):
return math.ceil(cas_latency/nphases)
+
def get_sys_phases(nphases, sys_latency, cas_latency):
dat_phase = sys_latency*nphases - cas_latency
- cmd_phase = (dat_phase - 1)%nphases
+ cmd_phase = (dat_phase - 1) % nphases
return cmd_phase, dat_phase
# PHY Pads Transformers ----------------------------------------------------------------------------
+
class PHYPadsReducer:
"""PHY Pads Reducer
For testing purposes, we often need to use only some of the DRAM modules. PHYPadsReducer allows
selecting specific modules and avoid re-definining dram pins in the Platform for this.
"""
+
def __init__(self, pads, modules):
- self.pads = pads
+ self.pads = pads
self.modules = modules
def __getattr__(self, name):
if name in ["dq"]:
return Array([getattr(self.pads, name)[8*i + j]
- for i in self.modules
- for j in range(8)])
+ for i in self.modules
+ for j in range(8)])
if name in ["dm", "dqs", "dqs_p", "dqs_n"]:
return Array([getattr(self.pads, name)[i] for i in self.modules])
else:
return getattr(self.pads, name)
+
class PHYPadsCombiner:
"""PHY Pads Combiner
and this combiner can be used to re-create a single pads structure (that will be compatible with
LiteDRAM's PHYs) to create a single DRAM controller from multiple fully dissociated DRAMs chips.
"""
+
def __init__(self, pads):
if not isinstance(pads, list):
self.groups = [pads]
def __getattr__(self, name):
if name in ["dm", "dq", "dqs", "dqs_p", "dqs_n"]:
return Array([getattr(self.groups[j], name)[i]
- for i in range(len(getattr(self.groups[0], name)))
- for j in range(len(self.groups))])
+ for i in range(len(getattr(self.groups[0], name)))
+ for j in range(len(self.groups))])
else:
return getattr(self.groups[self.sel], name)
-# BitSlip ------------------------------------------------------------------------------------------
-
-class BitSlip(Elaboratable):
- def __init__(self, dw, rst=None, slp=None, cycles=1):
- self.i = Signal(dw)
- self.o = Signal(dw)
- self.rst = Signal() if rst is None else rst
- self.slp = Signal() if slp is None else slp
- self._cycles = cycles
-
- def elaborate(self, platform):
- m = Module()
-
- value = Signal(range(self._cycles*dw))
- with m.If(self.slp):
- m.d.sync += value.eq(value+1)
- with m.Elif(self.rst):
- m.d.sync += value.eq(0)
-
- r = Signal((self._cycles+1)*dw, reset_less=True)
- m.d.sync += r.eq(Cat(r[dw:], self.i))
- cases = {}
- for i in range(self._cycles*dw):
- cases[i] = self.o.eq(r[i:dw+i])
- m.d.comb += Case(value, cases)
-
- return m
-
# DQS Pattern --------------------------------------------------------------------------------------
+
class DQSPattern(Elaboratable):
def __init__(self, preamble=None, postamble=None, wlevel_en=0, wlevel_strobe=0, register=False):
- self.preamble = Signal() if preamble is None else preamble
+ self.preamble = Signal() if preamble is None else preamble
self.postamble = Signal() if postamble is None else postamble
self.o = Signal(8)
self._wlevel_en = wlevel_en
# Settings -----------------------------------------------------------------------------------------
+
class Settings:
def set_attributes(self, attributes):
for k, v in attributes.items():
self.is_rdimm = True
self.set_attributes(locals())
+
class GeomSettings(Settings):
def __init__(self, bankbits, rowbits, colbits):
self.set_attributes(locals())
# Layouts/Interface --------------------------------------------------------------------------------
+
def cmd_layout(address_width):
return [
("valid", 1, DIR_FANOUT),
("ready", 1, DIR_FANIN),
("we", 1, DIR_FANOUT),
("addr", address_width, DIR_FANOUT),
- ("lock", 1, DIR_FANIN), # only used internally
+ ("lock", 1, DIR_FANIN), # only used internally
("wdata_ready", 1, DIR_FANIN),
("rdata_valid", 1, DIR_FANIN)
]
+
def data_layout(data_width):
return [
("wdata", data_width, DIR_FANOUT),
("rdata", data_width, DIR_FANIN)
]
+
def cmd_description(address_width):
return [
("we", 1),
("addr", address_width)
]
+
def wdata_description(data_width):
return [
("data", data_width),
("we", data_width//8)
]
+
def rdata_description(data_width):
return [("data", data_width)]
+
def cmd_request_layout(a, ba):
return [
("a", a),
("we", 1)
]
+
def cmd_request_rw_layout(a, ba):
return cmd_request_layout(a, ba) + [
("is_cmd", 1),
def __init__(self, address_align, settings):
rankbits = log2_int(settings.phy.nranks)
self.address_align = address_align
- self.address_width = settings.geom.rowbits + settings.geom.colbits + rankbits - address_align
- self.data_width = settings.phy.dfi_databits*settings.phy.nphases
- self.nbanks = settings.phy.nranks*(2**settings.geom.bankbits)
- self.nranks = settings.phy.nranks
+ self.address_width = settings.geom.rowbits + \
+ settings.geom.colbits + rankbits - address_align
+ self.data_width = settings.phy.dfi_databits*settings.phy.nphases
+ self.nbanks = settings.phy.nranks*(2**settings.geom.bankbits)
+ self.nranks = settings.phy.nranks
self.settings = settings
- layout = [("bank"+str(i), cmd_layout(self.address_width)) for i in range(self.nbanks)]
+ layout = [("bank"+str(i), cmd_layout(self.address_width))
+ for i in range(self.nbanks)]
layout += data_layout(self.data_width)
Record.__init__(self, layout)
# Ports --------------------------------------------------------------------------------------------
+
class gramNativePort(Settings):
- def __init__(self, mode, address_width, data_width, clock_domain="sys", id=0):
+ def __init__(self, mode, address_width, data_width, clock_domain="sync", id=0):
self.set_attributes(locals())
self.lock = Signal()
- self.cmd = stream.Endpoint(cmd_description(address_width))
+ self.cmd = stream.Endpoint(cmd_description(address_width))
self.wdata = stream.Endpoint(wdata_description(data_width))
self.rdata = stream.Endpoint(rdata_description(data_width))
self.flush = Signal()
- # retro-compatibility # FIXME: remove
- self.aw = self.address_width
- self.dw = self.data_width
- self.cd = self.clock_domain
-
def get_bank_address(self, bank_bits, cba_shift):
cba_upper = cba_shift + bank_bits
return self.cmd.addr[cba_shift:cba_upper]
class tXXDController(Elaboratable):
def __init__(self, txxd):
self.valid = Signal()
- self.ready = ready = Signal(reset=txxd is None)
- #ready.attr.add("no_retiming") TODO
+ self.ready = ready = Signal(reset=txxd is None, attrs={"no_retiming": True})
self._txxd = txxd
def elaborate(self, platform):
class tFAWController(Elaboratable):
def __init__(self, tfaw):
self.valid = Signal()
- self.ready = Signal(reset=1)
- #ready.attr.add("no_retiming") TODO
+ self.ready = Signal(reset=1, attrs={"no_retiming": True})
self._tfaw = tfaw
def elaborate(self, platform):
m = Module()
if self._tfaw is not None:
- count = Signal(range(max(self._tfaw, 2)))
+ count = Signal(range(max(self._tfaw, 2)))
window = Signal(self._tfaw)
m.d.sync += window.eq(Cat(self.valid, window))
- m.d.comb += count.eq(reduce(add, [window[i] for i in range(self._tfaw)]))
+ m.d.comb += count.eq(reduce(add, [window[i]
+ for i in range(self._tfaw)]))
with m.If(count < 4):
with m.If(count == 3):
m.d.sync += self.ready.eq(~self.valid)