mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
sdram: use names that are more explicit for bank_a, row_a,...: bankbits, rowbits, .... Add databits to GeomSettings.
This commit is contained in:
parent
73c2b7ebaa
commit
7ea9e2ba89
15 changed files with 140 additions and 132 deletions
|
@ -1,11 +1,11 @@
|
|||
from collections import namedtuple
|
||||
|
||||
PhySettingsT = namedtuple("PhySettings", "memtype dfi_d nphases rdphase wrphase rdcmdphase wrcmdphase cl cwl read_latency write_latency")
|
||||
def PhySettings(memtype, dfi_d, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, read_latency, write_latency, cwl=0):
|
||||
return PhySettingsT(memtype, dfi_d, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, cwl, read_latency, write_latency)
|
||||
PhySettingsT = namedtuple("PhySettings", "memtype dfi_databits nphases rdphase wrphase rdcmdphase wrcmdphase cl cwl read_latency write_latency")
|
||||
def PhySettings(memtype, dfi_databits, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, read_latency, write_latency, cwl=0):
|
||||
return PhySettingsT(memtype, dfi_databits, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, cwl, read_latency, write_latency)
|
||||
|
||||
GeomSettingsT = namedtuple("_GeomSettings", "bank_a row_a col_a mux_a")
|
||||
def GeomSettings(bank_a, row_a, col_a):
|
||||
return GeomSettingsT(bank_a, row_a, col_a, max(row_a, col_a))
|
||||
GeomSettingsT = namedtuple("_GeomSettings", "databits bankbits rowbits colbits addressbits")
|
||||
def GeomSettings(databits, bankbits, rowbits, colbits):
|
||||
return GeomSettingsT(databits, bankbits, rowbits, colbits, max(rowbits, colbits))
|
||||
|
||||
TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC")
|
||||
|
|
|
@ -9,8 +9,8 @@ from misoclib.mem.sdram.core import lasmixbar
|
|||
class SDRAMCore(Module, AutoCSR):
|
||||
def __init__(self, phy, geom_settings, timing_settings, controller_settings, **kwargs):
|
||||
# DFI
|
||||
self.submodules.dfii = dfii.DFIInjector(geom_settings.mux_a, geom_settings.bank_a,
|
||||
phy.settings.dfi_d, phy.settings.nphases)
|
||||
self.submodules.dfii = dfii.DFIInjector(geom_settings.addressbits, geom_settings.bankbits,
|
||||
phy.settings.dfi_databits, phy.settings.nphases)
|
||||
self.comb += Record.connect(self.dfii.master, phy.dfi)
|
||||
|
||||
# LASMICON
|
||||
|
|
|
@ -28,26 +28,26 @@ class LASMIcon(Module):
|
|||
burst_length = phy_settings.nphases*2 # command multiplication*DDR
|
||||
address_align = log2_int(burst_length)
|
||||
|
||||
self.dfi = dfi.Interface(geom_settings.mux_a,
|
||||
geom_settings.bank_a,
|
||||
phy_settings.dfi_d,
|
||||
self.dfi = dfi.Interface(geom_settings.addressbits,
|
||||
geom_settings.bankbits,
|
||||
phy_settings.dfi_databits,
|
||||
phy_settings.nphases)
|
||||
self.lasmic = lasmibus.Interface(
|
||||
aw=geom_settings.row_a + geom_settings.col_a - address_align,
|
||||
dw=phy_settings.dfi_d*phy_settings.nphases,
|
||||
nbanks=2**geom_settings.bank_a,
|
||||
aw=geom_settings.rowbits + geom_settings.colbits - address_align,
|
||||
dw=phy_settings.dfi_databits*phy_settings.nphases,
|
||||
nbanks=2**geom_settings.bankbits,
|
||||
req_queue_size=controller_settings.req_queue_size,
|
||||
read_latency=phy_settings.read_latency+1,
|
||||
write_latency=phy_settings.write_latency+1)
|
||||
self.nrowbits = geom_settings.col_a - address_align
|
||||
self.nrowbits = geom_settings.colbits - address_align
|
||||
|
||||
###
|
||||
|
||||
self.submodules.refresher = Refresher(geom_settings.mux_a, geom_settings.bank_a,
|
||||
self.submodules.refresher = Refresher(geom_settings.addressbits, geom_settings.bankbits,
|
||||
timing_settings.tRP, timing_settings.tREFI, timing_settings.tRFC)
|
||||
self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, controller_settings, address_align, i,
|
||||
getattr(self.lasmic, "bank"+str(i)))
|
||||
for i in range(2**geom_settings.bank_a)]
|
||||
for i in range(2**geom_settings.bankbits)]
|
||||
self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings, controller_settings,
|
||||
self.bank_machines, self.refresher,
|
||||
self.dfi, self.lasmic,
|
||||
|
|
|
@ -7,19 +7,19 @@ from migen.genlib.fifo import SyncFIFO
|
|||
from misoclib.mem.sdram.core.lasmicon.multiplexer import *
|
||||
|
||||
class _AddressSlicer:
|
||||
def __init__(self, col_a, address_align):
|
||||
self.col_a = col_a
|
||||
def __init__(self, colbits, address_align):
|
||||
self.colbits = colbits
|
||||
self.address_align = address_align
|
||||
|
||||
def row(self, address):
|
||||
split = self.col_a - self.address_align
|
||||
split = self.colbits - self.address_align
|
||||
if isinstance(address, int):
|
||||
return address >> split
|
||||
else:
|
||||
return address[split:]
|
||||
|
||||
def col(self, address):
|
||||
split = self.col_a - self.address_align
|
||||
split = self.colbits - self.address_align
|
||||
if isinstance(address, int):
|
||||
return (address & (2**split - 1)) << self.address_align
|
||||
else:
|
||||
|
@ -29,7 +29,7 @@ class BankMachine(Module):
|
|||
def __init__(self, geom_settings, timing_settings, controller_settings, address_align, bankn, req):
|
||||
self.refresh_req = Signal()
|
||||
self.refresh_gnt = Signal()
|
||||
self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a)
|
||||
self.cmd = CommandRequestRW(geom_settings.addressbits, geom_settings.bankbits)
|
||||
|
||||
###
|
||||
|
||||
|
@ -46,11 +46,11 @@ class BankMachine(Module):
|
|||
]
|
||||
reqf = self.req_fifo.dout
|
||||
|
||||
slicer = _AddressSlicer(geom_settings.col_a, address_align)
|
||||
slicer = _AddressSlicer(geom_settings.colbits, address_align)
|
||||
|
||||
# Row tracking
|
||||
has_openrow = Signal()
|
||||
openrow = Signal(geom_settings.row_a)
|
||||
openrow = Signal(geom_settings.rowbits)
|
||||
hit = Signal()
|
||||
self.comb += hit.eq(openrow == slicer.row(reqf.adr))
|
||||
track_open = Signal()
|
||||
|
|
|
@ -108,7 +108,7 @@ class Multiplexer(Module, AutoCSR):
|
|||
]
|
||||
|
||||
# Command steering
|
||||
nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
|
||||
nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits)
|
||||
commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
|
||||
(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
|
||||
steerer = _Steerer(commands, dfi)
|
||||
|
|
|
@ -5,30 +5,30 @@ from migen.genlib.fsm import FSM, NextState
|
|||
from misoclib.mem.sdram.phy import dfi as dfibus
|
||||
|
||||
class _AddressSlicer:
|
||||
def __init__(self, col_a, bank_a, row_a, address_align):
|
||||
self.col_a = col_a
|
||||
self.bank_a = bank_a
|
||||
self.row_a = row_a
|
||||
self.max_a = col_a + row_a + bank_a
|
||||
def __init__(self, colbits, bankbits, rowbits, address_align):
|
||||
self.colbits = colbits
|
||||
self.bankbits = bankbits
|
||||
self.rowbits = rowbits
|
||||
self.max_a = colbits + rowbits + bankbits
|
||||
self.address_align = address_align
|
||||
|
||||
def row(self, address):
|
||||
split = self.bank_a + self.col_a
|
||||
split = self.bankbits + self.colbits
|
||||
if isinstance(address, int):
|
||||
return address >> split
|
||||
else:
|
||||
return address[split:self.max_a]
|
||||
|
||||
def bank(self, address):
|
||||
mask = 2**(self.bank_a + self.col_a) - 1
|
||||
shift = self.col_a
|
||||
mask = 2**(self.bankbits + self.colbits) - 1
|
||||
shift = self.colbits
|
||||
if isinstance(address, int):
|
||||
return (address & mask) >> shift
|
||||
else:
|
||||
return address[self.col_a:self.col_a+self.bank_a]
|
||||
return address[self.colbits:self.colbits+self.bankbits]
|
||||
|
||||
def col(self, address):
|
||||
split = self.col_a
|
||||
split = self.colbits
|
||||
if isinstance(address, int):
|
||||
return (address & (2**split - 1)) << self.address_align
|
||||
else:
|
||||
|
@ -46,20 +46,20 @@ class Minicon(Module):
|
|||
burst_length = phy_settings.nphases*2 # command multiplication*DDR
|
||||
address_align = log2_int(burst_length)
|
||||
|
||||
nbanks = range(2**geom_settings.bank_a)
|
||||
nbanks = range(2**geom_settings.bankbits)
|
||||
A10_ENABLED = 0
|
||||
COLUMN = 1
|
||||
ROW = 2
|
||||
rdphase = phy_settings.rdphase
|
||||
wrphase = phy_settings.wrphase
|
||||
|
||||
self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
|
||||
geom_settings.bank_a,
|
||||
phy_settings.dfi_d,
|
||||
self.dfi = dfi = dfibus.Interface(geom_settings.addressbits,
|
||||
geom_settings.bankbits,
|
||||
phy_settings.dfi_databits,
|
||||
phy_settings.nphases)
|
||||
|
||||
self.bus = bus = wishbone.Interface(data_width=phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
|
||||
slicer = _AddressSlicer(geom_settings.col_a, geom_settings.bank_a, geom_settings.row_a, address_align)
|
||||
slicer = _AddressSlicer(geom_settings.colbits, geom_settings.bankbits, geom_settings.rowbits, address_align)
|
||||
refresh_req = Signal()
|
||||
refresh_ack = Signal()
|
||||
refresh_counter = Signal(max=timing_settings.tREFI+1)
|
||||
|
@ -70,7 +70,7 @@ class Minicon(Module):
|
|||
has_curbank_openrow = Signal()
|
||||
|
||||
# Extra bit means row is active when asserted
|
||||
self.openrow = openrow = Array(Signal(geom_settings.row_a + 1) for b in nbanks)
|
||||
self.openrow = openrow = Array(Signal(geom_settings.rowbits + 1) for b in nbanks)
|
||||
|
||||
self.comb += [
|
||||
hit.eq(openrow[slicer.bank(bus.adr)] == Cat(slicer.row(bus.adr), 1)),
|
||||
|
|
|
@ -24,9 +24,10 @@ class SDRAMModule:
|
|||
def __init__(self, clk_freq, geom_settings, timing_settings):
|
||||
self.clk_freq = clk_freq
|
||||
self.geom_settings = sdram.GeomSettings(
|
||||
bank_a=log2_int(geom_settings["nbanks"]),
|
||||
row_a=log2_int(geom_settings["nrows"]),
|
||||
col_a=log2_int(geom_settings["ncols"])
|
||||
databits=geom_settings["nbits"],
|
||||
bankbits=log2_int(geom_settings["nbanks"]),
|
||||
rowbits=log2_int(geom_settings["nrows"]),
|
||||
colbits=log2_int(geom_settings["ncols"]),
|
||||
)
|
||||
self.timing_settings = sdram.TimingSettings(
|
||||
tRP=self.ns(timing_settings["tRP"]),
|
||||
|
@ -46,6 +47,7 @@ class SDRAMModule:
|
|||
# SDR
|
||||
class IS42S16160(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 16,
|
||||
"nbanks": 4,
|
||||
"nrows": 8192,
|
||||
"ncols": 512
|
||||
|
@ -65,6 +67,7 @@ class IS42S16160(SDRAMModule):
|
|||
|
||||
class MT48LC4M16(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 16,
|
||||
"nbanks": 4,
|
||||
"nrows": 4096,
|
||||
"ncols": 256
|
||||
|
@ -83,6 +86,7 @@ class MT48LC4M16(SDRAMModule):
|
|||
|
||||
class AS4C16M16(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 16,
|
||||
"nbanks": 4,
|
||||
"nrows": 8192,
|
||||
"ncols": 512
|
||||
|
@ -103,6 +107,7 @@ class AS4C16M16(SDRAMModule):
|
|||
# DDR
|
||||
class MT46V32M16(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 16,
|
||||
"nbanks": 4,
|
||||
"nrows": 8192,
|
||||
"ncols": 1024
|
||||
|
@ -122,6 +127,7 @@ class MT46V32M16(SDRAMModule):
|
|||
# LPDDR
|
||||
class MT46H32M16(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 16,
|
||||
"nbanks": 4,
|
||||
"nrows": 8192,
|
||||
"ncols": 1024
|
||||
|
@ -141,6 +147,7 @@ class MT46H32M16(SDRAMModule):
|
|||
# DDR2
|
||||
class MT47H128M8(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 8,
|
||||
"nbanks": 8,
|
||||
"nrows": 16384,
|
||||
"ncols": 1024
|
||||
|
@ -160,6 +167,7 @@ class MT47H128M8(SDRAMModule):
|
|||
# DDR3
|
||||
class MT8JTF12864(SDRAMModule):
|
||||
geom_settings = {
|
||||
"nbits": 8,
|
||||
"nbanks": 8,
|
||||
"nrows": 65536,
|
||||
"ncols": 1024
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
from migen.fhdl.std import *
|
||||
from migen.genlib.record import *
|
||||
|
||||
def phase_cmd_description(a, ba):
|
||||
def phase_cmd_description(addressbits, bankbits):
|
||||
return [
|
||||
("address", a, DIR_M_TO_S),
|
||||
("bank", ba, DIR_M_TO_S),
|
||||
("cas_n", 1, DIR_M_TO_S),
|
||||
("cs_n", 1, DIR_M_TO_S),
|
||||
("ras_n", 1, DIR_M_TO_S),
|
||||
("we_n", 1, DIR_M_TO_S),
|
||||
("cke", 1, DIR_M_TO_S),
|
||||
("odt", 1, DIR_M_TO_S),
|
||||
("reset_n", 1, DIR_M_TO_S)
|
||||
("address", addressbits, DIR_M_TO_S),
|
||||
("bank", bankbits, DIR_M_TO_S),
|
||||
("cas_n", 1, DIR_M_TO_S),
|
||||
("cs_n", 1, DIR_M_TO_S),
|
||||
("ras_n", 1, DIR_M_TO_S),
|
||||
("we_n", 1, DIR_M_TO_S),
|
||||
("cke", 1, DIR_M_TO_S),
|
||||
("odt", 1, DIR_M_TO_S),
|
||||
("reset_n", 1, DIR_M_TO_S)
|
||||
]
|
||||
|
||||
def phase_wrdata_description(d):
|
||||
def phase_wrdata_description(databits):
|
||||
return [
|
||||
("wrdata", d, DIR_M_TO_S),
|
||||
("wrdata_en", 1, DIR_M_TO_S),
|
||||
("wrdata_mask", d//8, DIR_M_TO_S)
|
||||
("wrdata", databits, DIR_M_TO_S),
|
||||
("wrdata_en", 1, DIR_M_TO_S),
|
||||
("wrdata_mask", databits//8, DIR_M_TO_S)
|
||||
]
|
||||
|
||||
def phase_rddata_description(d):
|
||||
def phase_rddata_description(databits):
|
||||
return [
|
||||
("rddata_en", 1, DIR_M_TO_S),
|
||||
("rddata", d, DIR_S_TO_M),
|
||||
("rddata_valid", 1, DIR_S_TO_M)
|
||||
("rddata_en", 1, DIR_M_TO_S),
|
||||
("rddata", databits, DIR_S_TO_M),
|
||||
("rddata_valid", 1, DIR_S_TO_M)
|
||||
]
|
||||
|
||||
def phase_description(a, ba, d):
|
||||
r = phase_cmd_description(a, ba)
|
||||
r += phase_wrdata_description(d)
|
||||
r += phase_rddata_description(d)
|
||||
def phase_description(addressbits, bankbits, databits):
|
||||
r = phase_cmd_description(addressbits, bankbits)
|
||||
r += phase_wrdata_description(databits)
|
||||
r += phase_rddata_description(databits)
|
||||
return r
|
||||
|
||||
class Interface(Record):
|
||||
def __init__(self, a, ba, d, nphases=1):
|
||||
layout = [("p"+str(i), phase_description(a, ba, d)) for i in range(nphases)]
|
||||
def __init__(self, addressbits, bankbits, databits, nphases=1):
|
||||
layout = [("p"+str(i), phase_description(addressbits, bankbits, databits)) for i in range(nphases)]
|
||||
Record.__init__(self, layout)
|
||||
self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
|
||||
for p in self.phases:
|
||||
|
|
|
@ -36,10 +36,10 @@ class PhaseInjector(Module, AutoCSR):
|
|||
self.sync += If(phase.rddata_valid, self._rddata.status.eq(phase.rddata))
|
||||
|
||||
class DFIInjector(Module, AutoCSR):
|
||||
def __init__(self, a, ba, d, nphases=1):
|
||||
inti = dfi.Interface(a, ba, d, nphases)
|
||||
self.slave = dfi.Interface(a, ba, d, nphases)
|
||||
self.master = dfi.Interface(a, ba, d, nphases)
|
||||
def __init__(self, addressbits, bankbits, databits, nphases=1):
|
||||
inti = dfi.Interface(addressbits, bankbits, databits, nphases)
|
||||
self.slave = dfi.Interface(addressbits, bankbits, databits, nphases)
|
||||
self.master = dfi.Interface(addressbits, bankbits, databits, nphases)
|
||||
|
||||
self._control = CSRStorage(4) # sel, cke, odt, reset_n
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ from misoclib.mem import sdram
|
|||
|
||||
class GENSDRPHY(Module):
|
||||
def __init__(self, pads):
|
||||
a = flen(pads.a)
|
||||
ba = flen(pads.ba)
|
||||
d = flen(pads.dq)
|
||||
addressbits = flen(pads.a)
|
||||
bankbits = flen(pads.ba)
|
||||
databits = flen(pads.dq)
|
||||
|
||||
self.settings = sdram.PhySettings(
|
||||
memtype="SDR",
|
||||
dfi_d=d,
|
||||
dfi_databits=databits,
|
||||
nphases=1,
|
||||
rdphase=0,
|
||||
wrphase=0,
|
||||
|
@ -47,7 +47,7 @@ class GENSDRPHY(Module):
|
|||
write_latency=0
|
||||
)
|
||||
|
||||
self.dfi = Interface(a, ba, d)
|
||||
self.dfi = Interface(addressbits, bankbits, databits)
|
||||
|
||||
###
|
||||
|
||||
|
@ -63,14 +63,14 @@ class GENSDRPHY(Module):
|
|||
pads.we_n.eq(self.dfi.p0.we_n)
|
||||
]
|
||||
if hasattr(pads, "cs_n"):
|
||||
self.sync += pads.cs_n.eq(self.dfi.p0.cs_n),
|
||||
self.sync += pads.cs_n.eq(self.dfi.p0.cs_n)
|
||||
|
||||
#
|
||||
# DQ/DQS/DM data
|
||||
#
|
||||
sd_dq_out = Signal(d)
|
||||
sd_dq_out = Signal(databits)
|
||||
drive_dq = Signal()
|
||||
self.sync += sd_dq_out.eq(self.dfi.p0.wrdata),
|
||||
self.sync += sd_dq_out.eq(self.dfi.p0.wrdata)
|
||||
self.specials += Tristate(pads.dq, sd_dq_out, drive_dq)
|
||||
self.sync += \
|
||||
If(self.dfi.p0.wrdata_en,
|
||||
|
@ -78,7 +78,7 @@ class GENSDRPHY(Module):
|
|||
).Else(
|
||||
pads.dm.eq(0)
|
||||
)
|
||||
sd_dq_in_ps = Signal(d)
|
||||
sd_dq_in_ps = Signal(databits)
|
||||
self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
|
||||
self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@ from misoclib.mem import sdram
|
|||
|
||||
class K7DDRPHY(Module, AutoCSR):
|
||||
def __init__(self, pads, memtype):
|
||||
a = flen(pads.a)
|
||||
ba = flen(pads.ba)
|
||||
d = flen(pads.dq)
|
||||
addressbits = flen(pads.a)
|
||||
bankbits = flen(pads.ba)
|
||||
databits = flen(pads.dq)
|
||||
nphases = 4
|
||||
|
||||
self._wlevel_en = CSRStorage()
|
||||
self._wlevel_strobe = CSR()
|
||||
self._dly_sel = CSRStorage(d//8)
|
||||
self._dly_sel = CSRStorage(databits//8)
|
||||
self._rdly_dq_rst = CSR()
|
||||
self._rdly_dq_inc = CSR()
|
||||
self._rdly_dq_bitslip = CSR()
|
||||
|
@ -26,7 +26,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
|
||||
self.settings = sdram.PhySettings(
|
||||
memtype=memtype,
|
||||
dfi_d=2*d,
|
||||
dfi_databits=2*databits,
|
||||
nphases=nphases,
|
||||
rdphase=0,
|
||||
wrphase=2,
|
||||
|
@ -38,7 +38,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
write_latency=2
|
||||
)
|
||||
|
||||
self.dfi = Interface(a, ba, self.settings.dfi_d, nphases)
|
||||
self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
|
||||
|
||||
###
|
||||
|
||||
|
@ -65,7 +65,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
]
|
||||
|
||||
# Addresses and commands
|
||||
for i in range(a):
|
||||
for i in range(addressbits):
|
||||
self.specials += \
|
||||
Instance("OSERDESE2",
|
||||
p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
|
||||
|
@ -81,7 +81,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
i_D5=self.dfi.phases[2].address[i], i_D6=self.dfi.phases[2].address[i],
|
||||
i_D7=self.dfi.phases[3].address[i], i_D8=self.dfi.phases[3].address[i]
|
||||
)
|
||||
for i in range(ba):
|
||||
for i in range(bankbits):
|
||||
self.specials += \
|
||||
Instance("OSERDESE2",
|
||||
p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
|
||||
|
@ -127,7 +127,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
).Else(
|
||||
dqs_serdes_pattern.eq(0b01010101)
|
||||
)
|
||||
for i in range(d//8):
|
||||
for i in range(databits//8):
|
||||
dm_o_nodelay = Signal()
|
||||
self.specials += \
|
||||
Instance("OSERDESE2",
|
||||
|
@ -139,10 +139,10 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
i_OCE=1,
|
||||
i_RST=ResetSignal(),
|
||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
|
||||
i_D1=self.dfi.phases[0].wrdata_mask[i], i_D2=self.dfi.phases[0].wrdata_mask[d//8+i],
|
||||
i_D3=self.dfi.phases[1].wrdata_mask[i], i_D4=self.dfi.phases[1].wrdata_mask[d//8+i],
|
||||
i_D5=self.dfi.phases[2].wrdata_mask[i], i_D6=self.dfi.phases[2].wrdata_mask[d//8+i],
|
||||
i_D7=self.dfi.phases[3].wrdata_mask[i], i_D8=self.dfi.phases[3].wrdata_mask[d//8+i]
|
||||
i_D1=self.dfi.phases[0].wrdata_mask[i], i_D2=self.dfi.phases[0].wrdata_mask[databits//8+i],
|
||||
i_D3=self.dfi.phases[1].wrdata_mask[i], i_D4=self.dfi.phases[1].wrdata_mask[databits//8+i],
|
||||
i_D5=self.dfi.phases[2].wrdata_mask[i], i_D6=self.dfi.phases[2].wrdata_mask[databits//8+i],
|
||||
i_D7=self.dfi.phases[3].wrdata_mask[i], i_D8=self.dfi.phases[3].wrdata_mask[databits//8+i]
|
||||
)
|
||||
self.specials += \
|
||||
Instance("ODELAYE2",
|
||||
|
@ -197,7 +197,7 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
|
||||
# DQ
|
||||
oe_dq = Signal()
|
||||
for i in range(d):
|
||||
for i in range(databits):
|
||||
dq_o_nodelay = Signal()
|
||||
dq_o_delayed = Signal()
|
||||
dq_i_nodelay = Signal()
|
||||
|
@ -213,10 +213,10 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
i_OCE=1, i_TCE=1,
|
||||
i_RST=ResetSignal(),
|
||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
|
||||
i_D1=self.dfi.phases[0].wrdata[i], i_D2=self.dfi.phases[0].wrdata[d+i],
|
||||
i_D3=self.dfi.phases[1].wrdata[i], i_D4=self.dfi.phases[1].wrdata[d+i],
|
||||
i_D5=self.dfi.phases[2].wrdata[i], i_D6=self.dfi.phases[2].wrdata[d+i],
|
||||
i_D7=self.dfi.phases[3].wrdata[i], i_D8=self.dfi.phases[3].wrdata[d+i],
|
||||
i_D1=self.dfi.phases[0].wrdata[i], i_D2=self.dfi.phases[0].wrdata[databits+i],
|
||||
i_D3=self.dfi.phases[1].wrdata[i], i_D4=self.dfi.phases[1].wrdata[databits+i],
|
||||
i_D5=self.dfi.phases[2].wrdata[i], i_D6=self.dfi.phases[2].wrdata[databits+i],
|
||||
i_D7=self.dfi.phases[3].wrdata[i], i_D8=self.dfi.phases[3].wrdata[databits+i],
|
||||
i_T1=~oe_dq
|
||||
),
|
||||
Instance("ISERDESE2",
|
||||
|
@ -229,10 +229,10 @@ class K7DDRPHY(Module, AutoCSR):
|
|||
i_RST=ResetSignal() | (self._dly_sel.storage[i//8] & self._wdly_dq_rst.re),
|
||||
i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
|
||||
i_BITSLIP=self._dly_sel.storage[i//8] & self._rdly_dq_bitslip.re,
|
||||
o_Q8=self.dfi.phases[0].rddata[i], o_Q7=self.dfi.phases[0].rddata[d+i],
|
||||
o_Q6=self.dfi.phases[1].rddata[i], o_Q5=self.dfi.phases[1].rddata[d+i],
|
||||
o_Q4=self.dfi.phases[2].rddata[i], o_Q3=self.dfi.phases[2].rddata[d+i],
|
||||
o_Q2=self.dfi.phases[3].rddata[i], o_Q1=self.dfi.phases[3].rddata[d+i]
|
||||
o_Q8=self.dfi.phases[0].rddata[i], o_Q7=self.dfi.phases[0].rddata[databits+i],
|
||||
o_Q6=self.dfi.phases[1].rddata[i], o_Q5=self.dfi.phases[1].rddata[databits+i],
|
||||
o_Q4=self.dfi.phases[2].rddata[i], o_Q3=self.dfi.phases[2].rddata[databits+i],
|
||||
o_Q2=self.dfi.phases[3].rddata[i], o_Q1=self.dfi.phases[3].rddata[databits+i]
|
||||
),
|
||||
Instance("ODELAYE2",
|
||||
p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
|
||||
|
|
|
@ -24,14 +24,14 @@ class S6DDRPHY(Module):
|
|||
def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
|
||||
if memtype not in ["DDR", "LPDDR", "DDR2"]:
|
||||
raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2")
|
||||
a = flen(pads.a)
|
||||
ba = flen(pads.ba)
|
||||
d = flen(pads.dq)
|
||||
addressbits = flen(pads.a)
|
||||
bankbits = flen(pads.ba)
|
||||
databits = flen(pads.dq)
|
||||
nphases = 2
|
||||
|
||||
self.settings = sdram.PhySettings(
|
||||
memtype=memtype,
|
||||
dfi_d=2*d,
|
||||
dfi_databits=2*databits,
|
||||
nphases=nphases,
|
||||
rdphase=0,
|
||||
wrphase=1,
|
||||
|
@ -42,7 +42,7 @@ class S6DDRPHY(Module):
|
|||
write_latency=0
|
||||
)
|
||||
|
||||
self.dfi = Interface(a, ba, self.settings.dfi_d, nphases)
|
||||
self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
|
||||
self.clk4x_wr_strb = Signal()
|
||||
self.clk4x_rd_strb = Signal()
|
||||
|
||||
|
@ -80,7 +80,7 @@ class S6DDRPHY(Module):
|
|||
]
|
||||
|
||||
# register dfi cmds on half_rate clk
|
||||
r_dfi = Array(Record(phase_cmd_description(a, ba)) for i in range(nphases))
|
||||
r_dfi = Array(Record(phase_cmd_description(addressbits, bankbits)) for i in range(nphases))
|
||||
for n, phase in enumerate(self.dfi.phases):
|
||||
sd_sdram_half +=[
|
||||
r_dfi[n].address.eq(phase.address),
|
||||
|
@ -130,15 +130,15 @@ class S6DDRPHY(Module):
|
|||
dqs_t_d0 = Signal()
|
||||
dqs_t_d1 = Signal()
|
||||
|
||||
dqs_o = Signal(d//8)
|
||||
dqs_t = Signal(d//8)
|
||||
dqs_o = Signal(databits//8)
|
||||
dqs_t = Signal(databits//8)
|
||||
|
||||
self.comb += [
|
||||
dqs_t_d0.eq(~(drive_dqs | postamble)),
|
||||
dqs_t_d1.eq(~drive_dqs),
|
||||
]
|
||||
|
||||
for i in range(d//8):
|
||||
for i in range(databits//8):
|
||||
# DQS output
|
||||
self.specials += Instance("ODDR2",
|
||||
p_DDR_ALIGNMENT=dqs_ddr_alignment,
|
||||
|
@ -194,7 +194,7 @@ class S6DDRPHY(Module):
|
|||
|
||||
sd_sdram_half += postamble.eq(drive_dqs)
|
||||
|
||||
d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
|
||||
d_dfi = [Record(phase_wrdata_description(nphases*databits)+phase_rddata_description(nphases*databits))
|
||||
for i in range(2*nphases)]
|
||||
|
||||
for n, phase in enumerate(self.dfi.phases):
|
||||
|
@ -215,17 +215,17 @@ class S6DDRPHY(Module):
|
|||
self.comb += drive_dq_n[0].eq(~drive_dq)
|
||||
sd_sys += drive_dq_n[1].eq(drive_dq_n[0])
|
||||
|
||||
dq_t = Signal(d)
|
||||
dq_o = Signal(d)
|
||||
dq_i = Signal(d)
|
||||
dq_t = Signal(databits)
|
||||
dq_o = Signal(databits)
|
||||
dq_i = Signal(databits)
|
||||
|
||||
dq_wrdata = []
|
||||
for i in range(2):
|
||||
for j in reversed(range(nphases)):
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[:d])
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[d:])
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[:databits])
|
||||
dq_wrdata.append(d_dfi[i*nphases+j].wrdata[databits:])
|
||||
|
||||
for i in range(d):
|
||||
for i in range(databits):
|
||||
# Data serializer
|
||||
self.specials += Instance("OSERDES2",
|
||||
p_DATA_WIDTH=4,
|
||||
|
@ -277,9 +277,9 @@ class S6DDRPHY(Module):
|
|||
i_CLKDIV=sys_clk,
|
||||
i_BITSLIP=bitslip_inc,
|
||||
|
||||
o_Q1=d_dfi[0*nphases+0].rddata[i+d],
|
||||
o_Q1=d_dfi[0*nphases+0].rddata[i+databits],
|
||||
o_Q2=d_dfi[0*nphases+0].rddata[i],
|
||||
o_Q3=d_dfi[0*nphases+1].rddata[i+d],
|
||||
o_Q3=d_dfi[0*nphases+1].rddata[i+databits],
|
||||
o_Q4=d_dfi[0*nphases+1].rddata[i],
|
||||
)
|
||||
|
||||
|
@ -294,10 +294,10 @@ class S6DDRPHY(Module):
|
|||
dq_wrdata_mask = []
|
||||
for i in range(2):
|
||||
for j in reversed(range(nphases)):
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[:d//8])
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[d//8:])
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[:databits//8])
|
||||
dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[databits//8:])
|
||||
|
||||
for i in range(d//8):
|
||||
for i in range(databits//8):
|
||||
# Mask serializer
|
||||
self.specials += Instance("OSERDES2",
|
||||
p_DATA_WIDTH=4,
|
||||
|
|
|
@ -16,7 +16,7 @@ def ns(t, margin=True):
|
|||
|
||||
sdram_phy = sdram.PhySettings(
|
||||
memtype="DDR",
|
||||
dfi_d=64,
|
||||
dfi_databits=64,
|
||||
nphases=2,
|
||||
rdphase=0,
|
||||
wrphase=1,
|
||||
|
@ -28,9 +28,9 @@ sdram_phy = sdram.PhySettings(
|
|||
)
|
||||
|
||||
sdram_geom = sdram.GeomSettings(
|
||||
bank_a=2,
|
||||
row_a=13,
|
||||
col_a=10
|
||||
bankbits=2,
|
||||
rowbits=13,
|
||||
colbits=10
|
||||
)
|
||||
sdram_timing = sdram.TimingSettings(
|
||||
tRP=ns(15),
|
||||
|
|
|
@ -154,9 +154,9 @@ if __name__ == "__main__":
|
|||
plat = board.Platform()
|
||||
|
||||
sdram_geom = sdram.GeomSettings(
|
||||
bank_a=2,
|
||||
row_a=12,
|
||||
col_a=8
|
||||
bankbits=2,
|
||||
rowbits=12,
|
||||
colbits=8
|
||||
)
|
||||
|
||||
sdram_timing = sdram.TimingSettings(
|
||||
|
|
|
@ -63,7 +63,7 @@ class SDRAMSoC(SoC):
|
|||
# MINICON frontend
|
||||
elif isinstance(self.sdram_controller_settings, MiniconSettings):
|
||||
sdram_width = flen(self.sdram.controller.bus.dat_r)
|
||||
main_ram_size = 2**(geom_settings.bank_a+geom_settings.row_a+geom_settings.col_a)*sdram_width//8
|
||||
main_ram_size = 2**(geom_settings.bankbits+geom_settings.rowbits+geom_settings.colbits)*sdram_width//8
|
||||
|
||||
if sdram_width == 32:
|
||||
self.register_mem("main_ram", self.mem_map["main_ram"], self.sdram.controller.bus, main_ram_size)
|
||||
|
|
Loading…
Reference in a new issue