355 lines
12 KiB
Python
355 lines
12 KiB
Python
from math import ceil
|
|
from collections import namedtuple
|
|
|
|
from migen import *
|
|
|
|
from litedram.common import GeomSettings, TimingSettings
|
|
|
|
|
|
_technology_timings = ["tREFI", "tWTR", "tCCD", "tRRD"]
|
|
_TechnologyTimings = namedtuple("TechnologyTimings", _technology_timings)
|
|
_speedgrade_timings = ["tRP", "tRCD", "tWR", "tRFC", "tFAW", "tRAS"]
|
|
_SpeedgradeTimings = namedtuple("SpeedgradeTimings", _speedgrade_timings)
|
|
|
|
|
|
class SDRAMModule:
|
|
"""SDRAM module geometry and timings.
|
|
|
|
SDRAM controller has to ensure that all geometry and
|
|
timings parameters are fulfilled. Timings parameters
|
|
can be expressed in ns, in SDRAM clock cycles or both
|
|
and controller needs to use the greater value.
|
|
|
|
SDRAM modules with the same geometry exist can have
|
|
various speedgrades.
|
|
"""
|
|
def __init__(self, clk_freq, rate, speedgrade=None):
|
|
self.clk_freq = clk_freq
|
|
self.rate = rate
|
|
self.speedgrade = speedgrade
|
|
self.geom_settings = GeomSettings(
|
|
bankbits=log2_int(self.nbanks),
|
|
rowbits=log2_int(self.nrows),
|
|
colbits=log2_int(self.ncols),
|
|
)
|
|
self.timing_settings = TimingSettings(
|
|
tRP=self.ns_to_cycles(self.get("tRP")),
|
|
tRCD=self.ns_to_cycles(self.get("tRCD")),
|
|
tWR=self.ns_to_cycles(self.get("tWR")),
|
|
tREFI=self.ns_to_cycles(self.get("tREFI"), False),
|
|
tRFC=self.ns_to_cycles(self.get("tRFC")),
|
|
tWTR=self.ck_ns_to_cycles(*self.get("tWTR")),
|
|
tFAW=None if self.get("tFAW") is None else self.ck_ns_to_cycles(*self.get("tFAW")),
|
|
tCCD=None if self.get("tCCD") is None else self.ck_ns_to_cycles(*self.get("tCCD")),
|
|
tRRD=None if self.get("tRRD") is None else self.ck_ns_to_cycles(*self.get("tRRD")),
|
|
tRC=None if self.get("tRAS") is None else self.ns_to_cycles(self.get("tRP") + self.get("tRAS")),
|
|
tRAS=None if self.get("tRAS") is None else self.ns_to_cycles(self.get("tRAS"))
|
|
)
|
|
|
|
def get(self, name):
|
|
if name in _speedgrade_timings:
|
|
if hasattr(self, "speedgrade_timings"):
|
|
speedgrade = "default" if self.speedgrade is None else self.speedgrade
|
|
return getattr(self.speedgrade_timings[speedgrade], name)
|
|
else:
|
|
name = name + "_" + self.speedgrade if self.speedgrade is not None else name
|
|
try:
|
|
return getattr(self, name)
|
|
except:
|
|
return None
|
|
else:
|
|
if hasattr(self, "technology_timings"):
|
|
return getattr(self.technology_timings, name)
|
|
else:
|
|
try:
|
|
return getattr(self, name)
|
|
except:
|
|
return None
|
|
|
|
def ns_to_cycles(self, t, margin=True):
|
|
clk_period_ns = 1e9/self.clk_freq
|
|
if margin:
|
|
margins = {
|
|
"1:1" : 0,
|
|
"1:2" : clk_period_ns/2,
|
|
"1:4" : 3*clk_period_ns/4
|
|
}
|
|
t += margins[self.rate]
|
|
return ceil(t/clk_period_ns)
|
|
|
|
def ck_to_cycles(self, c):
|
|
d = {
|
|
"1:1" : 1,
|
|
"1:2" : 2,
|
|
"1:4" : 4
|
|
}
|
|
return ceil(c/d[self.rate])
|
|
|
|
def ck_ns_to_cycles(self, c, t):
|
|
c = 0 if c is None else c
|
|
t = 0 if t is None else t
|
|
return max(self.ck_to_cycles(c), self.ns_to_cycles(t))
|
|
|
|
|
|
# SDR
|
|
class IS42S16160(SDRAMModule):
|
|
memtype = "SDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 512
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=20, tRCD=20, tWR=20, tRFC=70, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class MT48LC4M16(SDRAMModule):
|
|
memtype = "SDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 4096
|
|
ncols = 256
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=14, tRFC=66, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class MT48LC16M16(SDRAMModule):
|
|
memtype = "SDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 512
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=18, tRCD=18, tWR=14, tRFC=66, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class AS4C16M16(SDRAMModule):
|
|
memtype = "SDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 512
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=18, tRCD=18, tWR=12, tRFC=60, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class AS4C32M16(SDRAMModule):
|
|
memtype = "SDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=18, tRCD=18, tWR=12, tRFC=60, tFAW=None, tRAS=None)}
|
|
|
|
|
|
# DDR
|
|
class MT46V32M16(SDRAMModule):
|
|
memtype = "DDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=70, tFAW=None, tRAS=None)}
|
|
|
|
|
|
# LPDDR
|
|
class MT46H32M16(SDRAMModule):
|
|
memtype = "LPDDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=72, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class MT46H32M32(SDRAMModule):
|
|
memtype = "LPDDR"
|
|
# geometry
|
|
nbanks = 4
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(2, None), tCCD=(1, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=72, tFAW=None, tRAS=None)}
|
|
|
|
|
|
# DDR2
|
|
class MT47H128M8(SDRAMModule):
|
|
memtype = "DDR2"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 16384
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(None, 7.5), tCCD=(2, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=127.5, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class MT47H64M16(SDRAMModule):
|
|
memtype = "DDR2"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(None, 7.5), tCCD=(2, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=127.5, tFAW=None, tRAS=None)}
|
|
|
|
|
|
class P3R1GE4JGF(SDRAMModule):
|
|
memtype = "DDR2"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 8192
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(None, 7.5), tCCD=(2, None), tRRD=None)
|
|
speedgrade_timings = {"default": _SpeedgradeTimings(tRP=12.5, tRCD=12.5, tWR=15, tRFC=127.5, tFAW=None, tRAS=None)}
|
|
|
|
|
|
# DDR3 (Chips)
|
|
class MT41J128M16(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 16384
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"800": _SpeedgradeTimings(tRP=13.1, tRCD=13.1, tWR=13.1, tRFC=64, tFAW=(None, 50), tRAS=37.5),
|
|
"1066": _SpeedgradeTimings(tRP=13.1, tRCD=13.1, tWR=13.1, tRFC=86, tFAW=(None, 50), tRAS=37.5),
|
|
"1333": _SpeedgradeTimings(tRP=13.5, tRCD=13.5, tWR=13.5, tRFC=107, tFAW=(None, 45), tRAS=36),
|
|
"1600": _SpeedgradeTimings(tRP=13.75, tRCD=13.75, tWR=13.75, tRFC=128, tFAW=(None, 40), tRAS=35),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
class MT41K128M16(MT41J128M16):
|
|
pass
|
|
|
|
|
|
class MT41J256M16(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 32768
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"800": _SpeedgradeTimings(tRP=13.1, tRCD=13.1, tWR=13.1, tRFC=139, tFAW=(None, 50), tRAS=37.5),
|
|
"1066": _SpeedgradeTimings(tRP=13.1, tRCD=13.1, tWR=13.1, tRFC=138, tFAW=(None, 50), tRAS=37.5),
|
|
"1333": _SpeedgradeTimings(tRP=13.5, tRCD=13.5, tWR=13.5, tRFC=174, tFAW=(None, 45), tRAS=36),
|
|
"1600": _SpeedgradeTimings(tRP=13.75, tRCD=13.75, tWR=13.75, tRFC=208, tFAW=(None, 40), tRAS=35),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
class MT41K256M16(MT41J256M16):
|
|
pass
|
|
|
|
|
|
class K4B1G0446F(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 16384
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"800": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=120, tFAW=(None, 50), tRAS=37.5),
|
|
"1066": _SpeedgradeTimings(tRP=13.125, tRCD=13.125, tWR=15, tRFC=160, tFAW=(None, 50), tRAS=37.5),
|
|
"1333": _SpeedgradeTimings(tRP=13.5, tRCD=13.5, tWR=15, tRFC=200, tFAW=(None, 45), tRAS=36),
|
|
"1600": _SpeedgradeTimings(tRP=13.75, tRCD=13.75, tWR=15, tRFC=240, tFAW=(None, 40), tRAS=35),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
class K4B2G1646F(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 16384
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"800": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=104, tFAW=(None, 50), tRAS=37.5),
|
|
"1066": _SpeedgradeTimings(tRP=13.125, tRCD=13.125, tWR=15, tRFC=139, tFAW=(None, 50), tRAS=37.5),
|
|
"1333": _SpeedgradeTimings(tRP=13.5, tRCD=13.5, tWR=15, tRFC=174, tFAW=(None, 45), tRAS=36),
|
|
"1600": _SpeedgradeTimings(tRP=13.75, tRCD=13.75, tWR=15, tRFC=208, tFAW=(None, 40), tRAS=35),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
# DDR3 (SO-DIMM)
|
|
class MT8JTF12864(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 16384
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"1066": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=86, tFAW=(None, 50), tRAS=None),
|
|
"1333": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=107, tFAW=(None, 45), tRAS=None),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1333"]
|
|
|
|
|
|
class MT18KSF1G72HZ(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 65536
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 10))
|
|
speedgrade_timings = {
|
|
"1066": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=86, tFAW=(None, 50), tRAS=None),
|
|
"1333": _SpeedgradeTimings(tRP=15, tRCD=15, tWR=15, tRFC=107, tFAW=(None, 45), tRAS=None),
|
|
"1600": _SpeedgradeTimings(tRP=13.125, tRCD=13.125, tWR=13.125, tRFC=128, tFAW=(None, 40), tRAS=None),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
class AS4C256M16D3A(SDRAMModule):
|
|
memtype = "DDR3"
|
|
# geometry
|
|
nbanks = 8
|
|
nrows = 32768
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 7.5))
|
|
speedgrade_timings = {
|
|
"1600": _SpeedgradeTimings(tRP=13.75, tRCD=13.75, tWR=15, tRFC=260, tFAW=(None, 40), tRAS=35),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["1600"]
|
|
|
|
|
|
# DDR4 (Chips)
|
|
class EDY4016A(SDRAMModule):
|
|
memtype = "DDR4"
|
|
# geometry
|
|
nbanks = 2*4 # 2 groups of 4 banks
|
|
nrows = 32768
|
|
ncols = 1024
|
|
# timings
|
|
technology_timings = _TechnologyTimings(tREFI=64e6/8192, tWTR=(4, 7.5), tCCD=(4, None), tRRD=(4, 4.9))
|
|
speedgrade_timings = {
|
|
"2400": _SpeedgradeTimings(tRP=13.32, tRCD=13.32, tWR=15, tRFC=260, tFAW=(28, 30), tRAS=32),
|
|
}
|
|
speedgrade_timings["default"] = speedgrade_timings["2400"]
|