sdram: pass phy_settings to LASMIcon, MiniCON and init_sequence
This commit is contained in:
parent
2f7206b386
commit
9210272356
2
make.py
2
make.py
|
@ -156,7 +156,7 @@ CPU type: {}
|
||||||
|
|
||||||
for sdram_phy in ["sdrphy", "ddrphy"]:
|
for sdram_phy in ["sdrphy", "ddrphy"]:
|
||||||
if hasattr(soc, sdram_phy):
|
if hasattr(soc, sdram_phy):
|
||||||
sdram_phy_header = initsequence.get_sdram_phy_header(getattr(soc, sdram_phy))
|
sdram_phy_header = initsequence.get_sdram_phy_header(getattr(soc, sdram_phy).settings)
|
||||||
write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header)
|
write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header)
|
||||||
mem_header = cpuif.get_mem_header(soc.memory_regions, getattr(soc, "flash_boot_address", None))
|
mem_header = cpuif.get_mem_header(soc.memory_regions, getattr(soc, "flash_boot_address", None))
|
||||||
write_to_file("software/include/generated/mem.h", boilerplate + mem_header)
|
write_to_file("software/include/generated/mem.h", boilerplate + mem_header)
|
||||||
|
|
|
@ -15,14 +15,14 @@ class SDRAMCore(Module, AutoCSR):
|
||||||
|
|
||||||
# LASMICON
|
# LASMICON
|
||||||
if ramcon_type == "lasmicon":
|
if ramcon_type == "lasmicon":
|
||||||
self.submodules.controller = controller = lasmicon.LASMIcon(phy, sdram_geom, sdram_timing, **kwargs)
|
self.submodules.controller = controller = lasmicon.LASMIcon(phy.settings, sdram_geom, sdram_timing, **kwargs)
|
||||||
self.comb += Record.connect(controller.dfi, self.dfii.slave)
|
self.comb += Record.connect(controller.dfi, self.dfii.slave)
|
||||||
|
|
||||||
self.submodules.crossbar = crossbar = Crossbar([controller.lasmic], controller.nrowbits)
|
self.submodules.crossbar = crossbar = Crossbar([controller.lasmic], controller.nrowbits)
|
||||||
|
|
||||||
# MINICON
|
# MINICON
|
||||||
elif ramcon_type == "minicon":
|
elif ramcon_type == "minicon":
|
||||||
self.submodules.controller = controller = minicon.Minicon(phy, sdram_geom, sdram_timing)
|
self.submodules.controller = controller = minicon.Minicon(phy.settings, sdram_geom, sdram_timing)
|
||||||
self.comb += Record.connect(controller.dfi, self.dfii.slave)
|
self.comb += Record.connect(controller.dfi, self.dfii.slave)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Unsupported SDRAM controller type: {}".format(self.ramcon_type))
|
raise ValueError("Unsupported SDRAM controller type: {}".format(self.ramcon_type))
|
||||||
|
|
|
@ -6,24 +6,24 @@ from misoclib.mem.sdram.core.lasmicon.bankmachine import *
|
||||||
from misoclib.mem.sdram.core.lasmicon.multiplexer import *
|
from misoclib.mem.sdram.core.lasmicon.multiplexer import *
|
||||||
|
|
||||||
class LASMIcon(Module):
|
class LASMIcon(Module):
|
||||||
def __init__(self, phy, geom_settings, timing_settings, **kwargs):
|
def __init__(self, phy_settings, geom_settings, timing_settings, **kwargs):
|
||||||
if phy.settings.memtype in ["SDR"]:
|
if phy_settings.memtype in ["SDR"]:
|
||||||
burst_length = phy.settings.nphases*1 # command multiplication*SDR
|
burst_length = phy_settings.nphases*1 # command multiplication*SDR
|
||||||
elif phy.settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
||||||
burst_length = phy.settings.nphases*2 # command multiplication*DDR
|
burst_length = phy_settings.nphases*2 # command multiplication*DDR
|
||||||
address_align = log2_int(burst_length)
|
address_align = log2_int(burst_length)
|
||||||
|
|
||||||
self.dfi = dfi.Interface(geom_settings.mux_a,
|
self.dfi = dfi.Interface(geom_settings.mux_a,
|
||||||
geom_settings.bank_a,
|
geom_settings.bank_a,
|
||||||
phy.settings.dfi_d,
|
phy_settings.dfi_d,
|
||||||
phy.settings.nphases)
|
phy_settings.nphases)
|
||||||
self.lasmic = lasmibus.Interface(
|
self.lasmic = lasmibus.Interface(
|
||||||
aw=geom_settings.row_a + geom_settings.col_a - address_align,
|
aw=geom_settings.row_a + geom_settings.col_a - address_align,
|
||||||
dw=phy.settings.dfi_d*phy.settings.nphases,
|
dw=phy_settings.dfi_d*phy_settings.nphases,
|
||||||
nbanks=2**geom_settings.bank_a,
|
nbanks=2**geom_settings.bank_a,
|
||||||
req_queue_size=timing_settings.req_queue_size,
|
req_queue_size=timing_settings.req_queue_size,
|
||||||
read_latency=phy.settings.read_latency+1,
|
read_latency=phy_settings.read_latency+1,
|
||||||
write_latency=phy.settings.write_latency+1)
|
write_latency=phy_settings.write_latency+1)
|
||||||
self.nrowbits = geom_settings.col_a - address_align
|
self.nrowbits = geom_settings.col_a - address_align
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -33,7 +33,7 @@ class LASMIcon(Module):
|
||||||
self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, address_align, i,
|
self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, address_align, i,
|
||||||
getattr(self.lasmic, "bank"+str(i)))
|
getattr(self.lasmic, "bank"+str(i)))
|
||||||
for i in range(2**geom_settings.bank_a)]
|
for i in range(2**geom_settings.bank_a)]
|
||||||
self.submodules.multiplexer = Multiplexer(phy, geom_settings, timing_settings,
|
self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings,
|
||||||
self.bank_machines, self.refresher,
|
self.bank_machines, self.refresher,
|
||||||
self.dfi, self.lasmic,
|
self.dfi, self.lasmic,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
|
@ -89,9 +89,9 @@ class _Steerer(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
class Multiplexer(Module, AutoCSR):
|
class Multiplexer(Module, AutoCSR):
|
||||||
def __init__(self, phy, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic,
|
def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic,
|
||||||
with_bandwidth=False):
|
with_bandwidth=False):
|
||||||
assert(phy.settings.nphases == len(dfi.phases))
|
assert(phy_settings.nphases == len(dfi.phases))
|
||||||
|
|
||||||
# Command choosing
|
# Command choosing
|
||||||
requests = [bm.cmd for bm in bank_machines]
|
requests = [bm.cmd for bm in bank_machines]
|
||||||
|
@ -101,7 +101,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
choose_cmd.want_reads.eq(0),
|
choose_cmd.want_reads.eq(0),
|
||||||
choose_cmd.want_writes.eq(0)
|
choose_cmd.want_writes.eq(0)
|
||||||
]
|
]
|
||||||
if phy.settings.nphases == 1:
|
if phy_settings.nphases == 1:
|
||||||
self.comb += [
|
self.comb += [
|
||||||
choose_cmd.want_cmds.eq(1),
|
choose_cmd.want_cmds.eq(1),
|
||||||
choose_req.want_cmds.eq(1)
|
choose_req.want_cmds.eq(1)
|
||||||
|
@ -159,19 +159,19 @@ class Multiplexer(Module, AutoCSR):
|
||||||
fsm = FSM()
|
fsm = FSM()
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
def steerer_sel(steerer, phy, r_w_n):
|
def steerer_sel(steerer, phy_settings, r_w_n):
|
||||||
r = []
|
r = []
|
||||||
for i in range(phy.settings.nphases):
|
for i in range(phy_settings.nphases):
|
||||||
s = steerer.sel[i].eq(STEER_NOP)
|
s = steerer.sel[i].eq(STEER_NOP)
|
||||||
if r_w_n == "read":
|
if r_w_n == "read":
|
||||||
if i == phy.settings.rdphase:
|
if i == phy_settings.rdphase:
|
||||||
s = steerer.sel[i].eq(STEER_REQ)
|
s = steerer.sel[i].eq(STEER_REQ)
|
||||||
elif i == phy.settings.rdcmdphase:
|
elif i == phy_settings.rdcmdphase:
|
||||||
s = steerer.sel[i].eq(STEER_CMD)
|
s = steerer.sel[i].eq(STEER_CMD)
|
||||||
elif r_w_n == "write":
|
elif r_w_n == "write":
|
||||||
if i == phy.settings.wrphase:
|
if i == phy_settings.wrphase:
|
||||||
s = steerer.sel[i].eq(STEER_REQ)
|
s = steerer.sel[i].eq(STEER_REQ)
|
||||||
elif i == phy.settings.wrcmdphase:
|
elif i == phy_settings.wrcmdphase:
|
||||||
s = steerer.sel[i].eq(STEER_CMD)
|
s = steerer.sel[i].eq(STEER_CMD)
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
@ -183,7 +183,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
choose_req.want_reads.eq(1),
|
choose_req.want_reads.eq(1),
|
||||||
choose_cmd.cmd.ack.eq(1),
|
choose_cmd.cmd.ack.eq(1),
|
||||||
choose_req.cmd.ack.eq(1),
|
choose_req.cmd.ack.eq(1),
|
||||||
steerer_sel(steerer, phy, "read"),
|
steerer_sel(steerer, phy_settings, "read"),
|
||||||
If(write_available,
|
If(write_available,
|
||||||
# TODO: switch only after several cycles of ~read_available?
|
# TODO: switch only after several cycles of ~read_available?
|
||||||
If(~read_available | max_read_time, NextState("RTW"))
|
If(~read_available | max_read_time, NextState("RTW"))
|
||||||
|
@ -195,7 +195,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
choose_req.want_writes.eq(1),
|
choose_req.want_writes.eq(1),
|
||||||
choose_cmd.cmd.ack.eq(1),
|
choose_cmd.cmd.ack.eq(1),
|
||||||
choose_req.cmd.ack.eq(1),
|
choose_req.cmd.ack.eq(1),
|
||||||
steerer_sel(steerer, phy, "write"),
|
steerer_sel(steerer, phy_settings, "write"),
|
||||||
If(read_available,
|
If(read_available,
|
||||||
If(~write_available | max_write_time, NextState("WTR"))
|
If(~write_available | max_write_time, NextState("WTR"))
|
||||||
),
|
),
|
||||||
|
@ -205,7 +205,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
steerer.sel[0].eq(STEER_REFRESH),
|
steerer.sel[0].eq(STEER_REFRESH),
|
||||||
If(~refresher.req, NextState("READ"))
|
If(~refresher.req, NextState("READ"))
|
||||||
)
|
)
|
||||||
fsm.delayed_enter("RTW", "WRITE", phy.settings.read_latency-1) # FIXME: reduce this, actual limit is around (cl+1)/nphases
|
fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1) # FIXME: reduce this, actual limit is around (cl+1)/nphases
|
||||||
fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
|
fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
|
||||||
# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
|
# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
|
||||||
fsm.finalize()
|
fsm.finalize()
|
||||||
|
|
|
@ -35,26 +35,26 @@ class _AddressSlicer:
|
||||||
return Cat(Replicate(0, self.address_align), address[:split])
|
return Cat(Replicate(0, self.address_align), address[:split])
|
||||||
|
|
||||||
class Minicon(Module):
|
class Minicon(Module):
|
||||||
def __init__(self, phy, geom_settings, timing_settings):
|
def __init__(self, phy_settings, geom_settings, timing_settings):
|
||||||
if phy.settings.memtype in ["SDR"]:
|
if phy_settings.memtype in ["SDR"]:
|
||||||
burst_length = phy.settings.nphases*1 # command multiplication*SDR
|
burst_length = phy_settings.nphases*1 # command multiplication*SDR
|
||||||
elif phy.settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
|
||||||
burst_length = phy.settings.nphases*2 # command multiplication*DDR
|
burst_length = phy_settings.nphases*2 # command multiplication*DDR
|
||||||
address_align = log2_int(burst_length)
|
address_align = log2_int(burst_length)
|
||||||
|
|
||||||
nbanks = range(2**geom_settings.bank_a)
|
nbanks = range(2**geom_settings.bank_a)
|
||||||
A10_ENABLED = 0
|
A10_ENABLED = 0
|
||||||
COLUMN = 1
|
COLUMN = 1
|
||||||
ROW = 2
|
ROW = 2
|
||||||
rdphase = phy.settings.rdphase
|
rdphase = phy_settings.rdphase
|
||||||
wrphase = phy.settings.wrphase
|
wrphase = phy_settings.wrphase
|
||||||
|
|
||||||
self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
|
self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
|
||||||
geom_settings.bank_a,
|
geom_settings.bank_a,
|
||||||
phy.settings.dfi_d,
|
phy_settings.dfi_d,
|
||||||
phy.settings.nphases)
|
phy_settings.nphases)
|
||||||
|
|
||||||
self.bus = bus = wishbone.Interface(data_width=phy.settings.nphases*flen(dfi.phases[rdphase].rddata))
|
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.col_a, geom_settings.bank_a, geom_settings.row_a, address_align)
|
||||||
refresh_req = Signal()
|
refresh_req = Signal()
|
||||||
refresh_ack = Signal()
|
refresh_ack = Signal()
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from migen.fhdl.std import log2_int
|
from migen.fhdl.std import log2_int
|
||||||
|
|
||||||
def get_sdram_phy_header(sdram_phy):
|
def get_sdram_phy_header(sdram_phy_settings):
|
||||||
r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
|
r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
|
||||||
r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
|
r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
|
||||||
|
|
||||||
nphases = sdram_phy.settings.nphases
|
nphases = sdram_phy_settings.nphases
|
||||||
r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
|
r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
|
||||||
|
|
||||||
r += "static void cdelay(int i);\n"
|
r += "static void cdelay(int i);\n"
|
||||||
|
@ -29,7 +29,7 @@ static void command_p{n}(int cmd)
|
||||||
|
|
||||||
#define command_prd(X) command_p{rdphase}(X)
|
#define command_prd(X) command_p{rdphase}(X)
|
||||||
#define command_pwr(X) command_p{wrphase}(X)
|
#define command_pwr(X) command_p{wrphase}(X)
|
||||||
""".format(rdphase=str(sdram_phy.settings.rdphase), wrphase=str(sdram_phy.settings.wrphase))
|
""".format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase))
|
||||||
r +="\n"
|
r +="\n"
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -64,10 +64,10 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
"CKE" : "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
|
"CKE" : "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
|
||||||
}
|
}
|
||||||
|
|
||||||
cl = sdram_phy.settings.cl
|
cl = sdram_phy_settings.cl
|
||||||
|
|
||||||
if sdram_phy.settings.memtype == "SDR":
|
if sdram_phy_settings.memtype == "SDR":
|
||||||
bl = sdram_phy.settings.nphases
|
bl = sdram_phy_settings.nphases
|
||||||
mr = log2_int(bl) + (cl << 4)
|
mr = log2_int(bl) + (cl << 4)
|
||||||
reset_dll = 1 << 8
|
reset_dll = 1 << 8
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
||||||
]
|
]
|
||||||
|
|
||||||
elif sdram_phy.settings.memtype == "DDR":
|
elif sdram_phy_settings.memtype == "DDR":
|
||||||
bl = 2*sdram_phy.settings.nphases
|
bl = 2*sdram_phy_settings.nphases
|
||||||
mr = log2_int(bl) + (cl << 4)
|
mr = log2_int(bl) + (cl << 4)
|
||||||
emr = 0
|
emr = 0
|
||||||
reset_dll = 1 << 8
|
reset_dll = 1 << 8
|
||||||
|
@ -98,8 +98,8 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
||||||
]
|
]
|
||||||
|
|
||||||
elif sdram_phy.settings.memtype == "LPDDR":
|
elif sdram_phy_settings.memtype == "LPDDR":
|
||||||
bl = 2*sdram_phy.settings.nphases
|
bl = 2*sdram_phy_settings.nphases
|
||||||
mr = log2_int(bl) + (cl << 4)
|
mr = log2_int(bl) + (cl << 4)
|
||||||
emr = 0
|
emr = 0
|
||||||
reset_dll = 1 << 8
|
reset_dll = 1 << 8
|
||||||
|
@ -115,8 +115,8 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
|
||||||
]
|
]
|
||||||
|
|
||||||
elif sdram_phy.settings.memtype == "DDR2":
|
elif sdram_phy_settings.memtype == "DDR2":
|
||||||
bl = 2*sdram_phy.settings.nphases
|
bl = 2*sdram_phy_settings.nphases
|
||||||
wr = 2
|
wr = 2
|
||||||
mr = log2_int(bl) + (cl << 4) + (wr << 9)
|
mr = log2_int(bl) + (cl << 4) + (wr << 9)
|
||||||
emr = 0
|
emr = 0
|
||||||
|
@ -139,8 +139,8 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
|
("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
|
||||||
("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
|
("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
|
||||||
]
|
]
|
||||||
elif sdram_phy.settings.memtype == "DDR3":
|
elif sdram_phy_settings.memtype == "DDR3":
|
||||||
bl = 2*sdram_phy.settings.nphases
|
bl = 2*sdram_phy_settings.nphases
|
||||||
if bl != 8:
|
if bl != 8:
|
||||||
raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
|
raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
|
|
||||||
mr0 = format_mr0(cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK)
|
mr0 = format_mr0(cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK)
|
||||||
mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm)
|
mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm)
|
||||||
mr2 = format_mr2(sdram_phy.settings.cwl, 2) # Rtt(WR) RZQ/4
|
mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4
|
||||||
mr3 = 0
|
mr3 = 0
|
||||||
|
|
||||||
init_sequence = [
|
init_sequence = [
|
||||||
|
@ -204,7 +204,7 @@ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
|
||||||
# the value of MR1 needs to be modified during write leveling
|
# the value of MR1 needs to be modified during write leveling
|
||||||
r += "#define DDR3_MR1 {}\n\n".format(mr1)
|
r += "#define DDR3_MR1 {}\n\n".format(mr1)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Unsupported memory type: "+sdram_phy.settings.memtype)
|
raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype)
|
||||||
|
|
||||||
r += "static void init_sequence(void)\n{\n"
|
r += "static void init_sequence(void)\n{\n"
|
||||||
for comment, a, ba, cmd, delay in init_sequence:
|
for comment, a, ba, cmd, delay in init_sequence:
|
||||||
|
|
Loading…
Reference in New Issue