Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
  • 3 commits
  • 5 files changed
  • 0 commit comments
  • 2 contributors
View
230 milkymist/cif.py
@@ -67,30 +67,30 @@ def get_csr_header(csr_base, bank_array, interrupt_map):
return r
def get_sdram_phy_header(sdram_phy):
- if sdram_phy.phy_settings.type not in ["SDR", "DDR", "LPDDR", "DDR2"]:
- raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR and DDR2")
+ if sdram_phy.phy_settings.memtype not in ["SDR", "DDR", "LPDDR", "DDR2"]:
+ raise NotImplementedError("The SDRAM PHY header generator only supports SDR, DDR, LPDDR and DDR2")
- r = "#ifndef __HW_SDRAM_PHY_H\n#define __HW_SDRAM_PHY_H\n"
- r += "#include <hw/common.h>\n#include <hw/csr.h>\n#include <hw/flags.h>\n\n"
+ r = "#ifndef __HW_SDRAM_PHY_H\n#define __HW_SDRAM_PHY_H\n"
+ r += "#include <hw/common.h>\n#include <hw/csr.h>\n#include <hw/flags.h>\n\n"
- r += "static void cdelay(int i);\n"
+ r += "static void cdelay(int i);\n"
- #
- # commands_px functions
- #
- for n in range(sdram_phy.phy_settings.nphases):
- r += """
+ #
+ # commands_px functions
+ #
+ for n in range(sdram_phy.phy_settings.nphases):
+ r += """
static void command_p{n}(int cmd)
{{
dfii_pi{n}_command_write(cmd);
dfii_pi{n}_command_issue_write(1);
}}""".format(n=str(n))
- r += "\n\n"
+ r += "\n\n"
- #
- # rd/wr access macros
- #
- r += """
+ #
+ # rd/wr access macros
+ #
+ r += """
#define dfii_pird_address_write(X) dfii_pi{rdphase}_address_write(X)
#define dfii_piwr_address_write(X) dfii_pi{wrphase}_address_write(X)
@@ -100,105 +100,105 @@ def get_sdram_phy_header(sdram_phy):
#define command_prd(X) command_p{rdphase}(X)
#define command_pwr(X) command_p{wrphase}(X)
""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase))
- r +="\n"
-
- #
- # init sequence
- #
- cmds = {
- "PRECHARGE_ALL" : "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "MODE_REGISTER" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
- "AUTO_REFRESH" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
- "CKE" : "DFII_CONTROL_CKE"
- }
-
- def gen_cmd(comment, a, ba, cmd, delay):
- r = "\t/* {0} */\n".format(comment)
- r += "\tdfii_pi0_address_write({0:#x});\n".format(a)
- r += "\tdfii_pi0_baddress_write({0:d});\n".format(ba)
- if "CKE" in cmd:
- r += "\tdfii_control_write({0});\n".format(cmd)
- else:
- r += "\tcommand_p0({0});\n".format(cmd)
- r += "\tcdelay({0:d});\n".format(delay)
- r += "\n"
- return r
-
-
- r += "static void init_sequence(void)\n{\n"
-
- cl = sdram_phy.phy_settings.cl
-
- if sdram_phy.phy_settings.type == "SDR":
- bl = 1*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.type == "DDR":
- bl = 2*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.type == "LPDDR":
- bl = 2*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- elif sdram_phy.phy_settings.type == "DDR2":
- bl = 2*sdram_phy.phy_settings.nphases
- mr = log2_int(bl) + (cl << 4)
- emr = 0
- reset_dll = 1 << 8
-
- init_sequence = [
- ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
- ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
- ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
- ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
- ]
-
- for comment, a, ba, cmd, delay in init_sequence:
- r += gen_cmd(comment, a, ba, cmd, delay)
+ r +="\n"
+
+ #
+ # init sequence
+ #
+ cmds = {
+ "PRECHARGE_ALL" : "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+ "MODE_REGISTER" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+ "AUTO_REFRESH" : "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
+ "CKE" : "DFII_CONTROL_CKE"
+ }
+
+ def gen_cmd(comment, a, ba, cmd, delay):
+ r = "\t/* {0} */\n".format(comment)
+ r += "\tdfii_pi0_address_write({0:#x});\n".format(a)
+ r += "\tdfii_pi0_baddress_write({0:d});\n".format(ba)
+ if "CKE" in cmd:
+ r += "\tdfii_control_write({0});\n".format(cmd)
+ else:
+ r += "\tcommand_p0({0});\n".format(cmd)
+ r += "\tcdelay({0:d});\n".format(delay)
+ r += "\n"
+ return r
- r += "}\n"
- r += "#endif\n"
- return r
+ r += "static void init_sequence(void)\n{\n"
+
+ cl = sdram_phy.phy_settings.cl
+
+ if sdram_phy.phy_settings.memtype == "SDR":
+ bl = 1*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "DDR":
+ bl = 2*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ emr = 0
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "LPDDR":
+ bl = 2*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ emr = 0
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ elif sdram_phy.phy_settings.memtype == "DDR2":
+ bl = 2*sdram_phy.phy_settings.nphases
+ mr = log2_int(bl) + (cl << 4)
+ emr = 0
+ reset_dll = 1 << 8
+
+ init_sequence = [
+ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 2000),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+ ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+ ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+ ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+ ]
+
+ for comment, a, ba, cmd, delay in init_sequence:
+ r += gen_cmd(comment, a, ba, cmd, delay)
+
+ r += "}\n"
+ r += "#endif\n"
+
+ return r
View
7 milkymist/lasmicon/__init__.py
@@ -7,14 +7,13 @@
from milkymist.lasmicon.bankmachine import *
from milkymist.lasmicon.multiplexer import *
-PhySettings = namedtuple("PhySettings", "type dfi_d nphases rdphase wrphase cl")
+PhySettings = namedtuple("PhySettings", "memtype dfi_d nphases rdphase wrphase cl read_latency write_latency")
class GeomSettings(namedtuple("_GeomSettings", "bank_a row_a col_a")):
def __init__(self, *args, **kwargs):
self.mux_a = max(self.row_a, self.col_a)
TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC" \
- " read_latency write_latency" \
" req_queue_size read_time write_time")
class LASMIcon(Module):
@@ -31,8 +30,8 @@ def __init__(self, phy_settings, geom_settings, timing_settings):
dw=phy_settings.dfi_d*phy_settings.nphases,
nbanks=2**geom_settings.bank_a,
req_queue_size=timing_settings.req_queue_size,
- read_latency=timing_settings.read_latency+1,
- write_latency=timing_settings.write_latency+1)
+ read_latency=phy_settings.read_latency+1,
+ write_latency=phy_settings.write_latency+1)
self.nrowbits = geom_settings.col_a - address_align
###
View
2  milkymist/lasmicon/multiplexer.py
@@ -178,7 +178,7 @@ def anti_starvation(timeout):
steerer.sel[0].eq(STEER_REFRESH),
If(~refresher.req, NextState("READ"))
)
- fsm.delayed_enter("RTW", "WRITE", timing_settings.read_latency-1)
+ 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)
# FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
fsm.finalize()
View
54 milkymist/s6ddrphy/__init__.py
@@ -1,4 +1,3 @@
-#
# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for
# Spartan-6
#
@@ -8,31 +7,46 @@
#
# Assert dfi_rddata_en in the same cycle as the read
# command. The data will come back on dfi_rddata
-# CL + 2 cycles later, along with the assertion
+# 5 cycles later, along with the assertion
# of dfi_rddata_valid.
#
-# This PHY supports configurable CAS Latency.
-# Read commands must be sent on phase RDPHASE.
-# Write commands must be sent on phase WRPHASE.
-#/
+# This PHY only supports CAS Latency 3.
+# Read commands must be sent on phase 0.
+# Write commands must be sent on phase 1.
+#
# Todo:
# - use CSR for bitslip?
+# - add configurable CAS Latency
+# - automatically determines wrphase / rdphase / latencies
from migen.fhdl.std import *
from migen.bus.dfi import *
from migen.genlib.record import *
+from milkymist import lasmicon
+
class S6DDRPHY(Module):
- def __init__(self, pads, phy_settings, bitslip):
- if phy_settings.type not in ["DDR", "LPDDR", "DDR2"]:
+ def __init__(self, pads, memtype, nphases, cl, bitslip):
+ if memtype not in ["DDR", "LPDDR", "DDR2"]:
raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2")
+ if cl != 3:
+ raise NotImplementedError("S6DDRPHY only supports CAS LATENCY 3")
a = flen(pads.a)
ba = flen(pads.ba)
d = flen(pads.dq)
- nphases = phy_settings.nphases
- self.phy_settings = phy_settings
+
+ self.phy_settings = lasmicon.PhySettings(
+ memtype=memtype,
+ dfi_d=2*d,
+ nphases=nphases,
+ rdphase=0,
+ wrphase=1,
+ cl=cl,
+ read_latency=5,
+ write_latency=0
+ )
self.dfi = Interface(a, ba, nphases*d, nphases)
self.clk4x_wr_strb = Signal()
@@ -57,7 +71,7 @@ def __init__(self, pads, phy_settings, bitslip):
#
# select active phase
- # sys_clk ____----____----
+ # sys_clk ----____----____
# phase_sel(nphases=1) 0 0
# phase_sel(nphases=2) 0 1 0 1
# phase_sel(nphases=4) 0 1 2 3 0 1 2 3
@@ -102,7 +116,7 @@ def __init__(self, pads, phy_settings, bitslip):
bitslip_inc = Signal()
sd_sys += [
- If(bitslip_cnt==bitslip,
+ If(bitslip_cnt == bitslip,
bitslip_inc.eq(0)
).Else(
bitslip_cnt.eq(bitslip_cnt+1),
@@ -146,7 +160,7 @@ def __init__(self, pads, phy_settings, bitslip):
Instance.Input("S", 0),
Instance.Output("Q", dqs_o[i])
- )
+ )
# DQS tristate cmd
self.specials += Instance("ODDR2",
@@ -164,7 +178,7 @@ def __init__(self, pads, phy_settings, bitslip):
Instance.Input("S", 0),
Instance.Output("Q", dqs_t[i])
- )
+ )
# DQS tristate buffer
self.specials += Instance("OBUFT",
@@ -172,7 +186,7 @@ def __init__(self, pads, phy_settings, bitslip):
Instance.Input("T", dqs_t[i]),
Instance.Output("O", pads.dqs[i])
- )
+ )
sd_sdram_half += postamble.eq(drive_dqs)
@@ -323,23 +337,23 @@ def __init__(self, pads, phy_settings, bitslip):
Instance.Output("SHIFTOUT4"),
)
-
#
# DQ/DQS/DM control
#
- self.comb += drive_dq.eq(d_dfi[phy_settings.wrphase].wrdata_en)
+ self.comb += drive_dq.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
sd_sys += d_drive_dq.eq(drive_dq)
d_dfi_wrdata_en = Signal()
- sd_sys += d_dfi_wrdata_en.eq(d_dfi[phy_settings.wrphase].wrdata_en)
+ sd_sys += d_dfi_wrdata_en.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
r_dfi_wrdata_en = Signal(2)
sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en[0]))
self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])
- rddata_sr = Signal(phy_settings.cl+2)
- sd_sys += rddata_sr.eq(Cat(rddata_sr[1:phy_settings.cl+2], d_dfi[phy_settings.rdphase].rddata_en))
+ rddata_sr = Signal(self.phy_settings.read_latency)
+ sd_sys += rddata_sr.eq(Cat(rddata_sr[1:self.phy_settings.read_latency],
+ d_dfi[self.phy_settings.rdphase].rddata_en))
for n, phase in enumerate(self.dfi.phases):
self.comb += [
View
32 top.py
@@ -25,14 +25,6 @@ def ns(t, margin=True):
t += clk_period_ns/2
return ceil(t/clk_period_ns)
-sdram_phy = lasmicon.PhySettings(
- type="DDR",
- dfi_d=64,
- nphases=2,
- rdphase=0,
- wrphase=1,
- cl=3
-)
sdram_geom = lasmicon.GeomSettings(
bank_a=2,
row_a=13,
@@ -45,9 +37,6 @@ def ns(t, margin=True):
tWTR=2,
tREFI=ns(7800, False),
tRFC=ns(70),
-
- read_latency=5,
- write_latency=0,
req_queue_size=8,
read_time=32,
@@ -104,9 +93,19 @@ class SoC(Module):
def __init__(self, platform, platform_name, with_memtest):
#
+ # DFI
+ #
+ self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), memtype="DDR", nphases=2, cl=3, bitslip=0)
+ self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a,
+ self.ddrphy.phy_settings.dfi_d, self.ddrphy.phy_settings.nphases)
+ self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi)
+
+ #
# LASMI
#
- self.submodules.lasmicon = lasmicon.LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+ self.submodules.lasmicon = lasmicon.LASMIcon(self.ddrphy.phy_settings, sdram_geom, sdram_timing)
+ self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave)
+
n_lasmims = 7 if with_memtest else 5
self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], n_lasmims, self.lasmicon.nrowbits)
lasmims = list(self.lasmixbar.masters)
@@ -114,15 +113,6 @@ def __init__(self, platform, platform_name, with_memtest):
if with_memtest:
lasmim_mtw, lasmim_mtr = lasmims.pop(), lasmims.pop()
assert(not lasmims)
-
- #
- # DFI
- #
- self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), sdram_phy, 0)
- self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, sdram_phy.dfi_d,
- sdram_phy.nphases)
- self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi)
- self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave)
#
# WISHBONE

No commit comments for this range

Something went wrong with that request. Please try again.