Refactor directory hierarchy of sdram phys and controllers
authorYann Sionneau <ys@m-labs.hk>
Wed, 26 Nov 2014 09:37:50 +0000 (10:37 +0100)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Thu, 27 Nov 2014 14:09:10 +0000 (22:09 +0800)
42 files changed:
make.py
misoclib/dfii/__init__.py [deleted file]
misoclib/gensoc/__init__.py
misoclib/lasmicon/__init__.py [deleted file]
misoclib/lasmicon/bankmachine.py [deleted file]
misoclib/lasmicon/minicon.py [deleted file]
misoclib/lasmicon/minicontb.py [deleted file]
misoclib/lasmicon/multiplexer.py [deleted file]
misoclib/lasmicon/perf.py [deleted file]
misoclib/lasmicon/refresher.py [deleted file]
misoclib/lasmicon/test/bankmachine.py [deleted file]
misoclib/lasmicon/test/common.py [deleted file]
misoclib/lasmicon/test/lasmicon.py [deleted file]
misoclib/lasmicon/test/lasmicon_df.py [deleted file]
misoclib/lasmicon/test/lasmicon_wb.py [deleted file]
misoclib/lasmicon/test/refresher.py [deleted file]
misoclib/sdram/__init__.py [new file with mode: 0644]
misoclib/sdram/dfii/__init__.py [new file with mode: 0644]
misoclib/sdram/lasmicon/__init__.py [new file with mode: 0644]
misoclib/sdram/lasmicon/bankmachine.py [new file with mode: 0644]
misoclib/sdram/lasmicon/multiplexer.py [new file with mode: 0644]
misoclib/sdram/lasmicon/perf.py [new file with mode: 0644]
misoclib/sdram/lasmicon/refresher.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/bankmachine.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/common.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/lasmicon.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/lasmicon_df.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/lasmicon_wb.py [new file with mode: 0644]
misoclib/sdram/lasmicon/test/refresher.py [new file with mode: 0644]
misoclib/sdram/minicon/__init__.py [new file with mode: 0755]
misoclib/sdram/minicon/tb/minicontb.py [new file with mode: 0755]
misoclib/sdram/phy/gensdrphy.py [new file with mode: 0644]
misoclib/sdram/phy/initsequence.py [new file with mode: 0644]
misoclib/sdram/phy/k7ddrphy.py [new file with mode: 0644]
misoclib/sdram/phy/s6ddrphy.py [new file with mode: 0644]
misoclib/sdramphy/gensdrphy.py [deleted file]
misoclib/sdramphy/initsequence.py [deleted file]
misoclib/sdramphy/k7ddrphy.py [deleted file]
misoclib/sdramphy/s6ddrphy.py [deleted file]
targets/kc705.py
targets/mlabs_video.py
targets/ppro.py

diff --git a/make.py b/make.py
index 8de6e09e280c75d0e9694e4069a74223bc2c1cb0..99a12bb6fc938e4e0731777f3f9d322f7adf48b9 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -7,7 +7,7 @@ from migen.util.misc import autotype
 from migen.fhdl import simplify
 
 from misoclib.gensoc import cpuif
-from misoclib.sdramphy import initsequence
+from misoclib.sdram.phy import initsequence
 
 from misoc_import import misoc_import
 
diff --git a/misoclib/dfii/__init__.py b/misoclib/dfii/__init__.py
deleted file mode 100644 (file)
index ba53d37..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import dfi
-from migen.bank.description import *
-
-class PhaseInjector(Module, AutoCSR):
-       def __init__(self, phase):
-               self._command = CSRStorage(6) # cs, we, cas, ras, wren, rden
-               self._command_issue = CSR()
-               self._address = CSRStorage(flen(phase.address))
-               self._baddress = CSRStorage(flen(phase.bank))
-               self._wrdata = CSRStorage(flen(phase.wrdata))
-               self._rddata = CSRStatus(flen(phase.rddata))
-
-               ###
-
-               self.comb += [
-                       If(self._command_issue.re,
-                               phase.cs_n.eq(~self._command.storage[0]),
-                               phase.we_n.eq(~self._command.storage[1]),
-                               phase.cas_n.eq(~self._command.storage[2]),
-                               phase.ras_n.eq(~self._command.storage[3])
-                       ).Else(
-                               phase.cs_n.eq(1),
-                               phase.we_n.eq(1),
-                               phase.cas_n.eq(1),
-                               phase.ras_n.eq(1)
-                       ),
-                       phase.address.eq(self._address.storage),
-                       phase.bank.eq(self._baddress.storage),
-                       phase.wrdata_en.eq(self._command_issue.re & self._command.storage[4]),
-                       phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]),
-                       phase.wrdata.eq(self._wrdata.storage),
-                       phase.wrdata_mask.eq(0)
-               ]
-               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)
-
-               self._control = CSRStorage(4) # sel, cke, odt, reset_n
-
-               for n, phase in enumerate(inti.phases):
-                       setattr(self.submodules, "pi" + str(n), PhaseInjector(phase))
-
-               ###
-
-               self.comb += If(self._control.storage[0],
-                               self.slave.connect(self.master)
-                       ).Else(
-                               inti.connect(self.master)
-                       )
-               self.comb += [phase.cke.eq(self._control.storage[1]) for phase in inti.phases]
-               self.comb += [phase.odt.eq(self._control.storage[2]) for phase in inti.phases if hasattr(phase, "odt")]
-               self.comb += [phase.reset_n.eq(self._control.storage[3]) for phase in inti.phases if hasattr(phase, "reset_n")]
index 661b1d109a619f65c6b3137b7228480ae9c361ed..d605a1a6d829bdb971ff1b0ebd9280d885ee506d 100644 (file)
@@ -8,8 +8,10 @@ from migen.bank import csrgen
 from migen.bus import wishbone, csr, lasmibus, dfi
 from migen.bus import wishbone2lasmi, wishbone2csr
 
-from misoclib import lm32, mor1kx, uart, dfii, lasmicon, identifier, timer, memtest
-from misoclib.lasmicon.minicon import Minicon
+from misoclib import lm32, mor1kx, uart, identifier, timer, memtest
+from misoclib.sdram import lasmicon
+from misoclib.sdram import dfii
+from misoclib.sdram.minicon import Minicon
 
 class GenSoC(Module):
        csr_base = 0xe0000000
diff --git a/misoclib/lasmicon/__init__.py b/misoclib/lasmicon/__init__.py
deleted file mode 100644 (file)
index 7dbf313..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-from collections import namedtuple
-
-from migen.fhdl.std import *
-from migen.bus import dfi, lasmibus
-
-from misoclib.lasmicon.refresher import *
-from misoclib.lasmicon.bankmachine import *
-from misoclib.lasmicon.multiplexer import *
-
-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)
-
-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))
-
-TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC" \
-       " req_queue_size read_time write_time")
-
-class LASMIcon(Module):
-       def __init__(self, phy_settings, geom_settings, timing_settings):
-               if phy_settings.memtype in ["SDR"]:
-                       burst_length = phy_settings.nphases*1 # command multiplication*SDR
-               elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
-                       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,
-                       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,
-                       req_queue_size=timing_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.submodules.refresher = Refresher(geom_settings.mux_a, geom_settings.bank_a,
-                       timing_settings.tRP, timing_settings.tREFI, timing_settings.tRFC)
-               self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, address_align, i,
-                               getattr(self.lasmic, "bank"+str(i)))
-                       for i in range(2**geom_settings.bank_a)]
-               self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings,
-                       self.bank_machines, self.refresher,
-                       self.dfi, self.lasmic)
-
-       def get_csrs(self):
-               return self.multiplexer.get_csrs()
diff --git a/misoclib/lasmicon/bankmachine.py b/misoclib/lasmicon/bankmachine.py
deleted file mode 100644 (file)
index 9b08d28..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.roundrobin import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import optree
-from migen.genlib.fifo import SyncFIFO
-
-from misoclib.lasmicon.multiplexer import *
-
-class _AddressSlicer:
-       def __init__(self, col_a, address_align):
-               self.col_a = col_a
-               self.address_align = address_align
-
-       def row(self, address):
-               split = self.col_a - 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
-               if isinstance(address, int):
-                       return (address & (2**split - 1)) << self.address_align
-               else:
-                       return Cat(Replicate(0, self.address_align), address[:split])
-
-class BankMachine(Module):
-       def __init__(self, geom_settings, timing_settings, address_align, bankn, req):
-               self.refresh_req = Signal()
-               self.refresh_gnt = Signal()
-               self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a)
-
-               ###
-
-               # Request FIFO
-               self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))], timing_settings.req_queue_size)
-               self.comb += [
-                       self.req_fifo.din.we.eq(req.we),
-                       self.req_fifo.din.adr.eq(req.adr),
-                       self.req_fifo.we.eq(req.stb),
-                       req.req_ack.eq(self.req_fifo.writable),
-
-                       self.req_fifo.re.eq(req.dat_ack),
-                       req.lock.eq(self.req_fifo.readable)
-               ]
-               reqf = self.req_fifo.dout
-
-               slicer = _AddressSlicer(geom_settings.col_a, address_align)
-
-               # Row tracking
-               has_openrow = Signal()
-               openrow = Signal(geom_settings.row_a)
-               hit = Signal()
-               self.comb += hit.eq(openrow == slicer.row(reqf.adr))
-               track_open = Signal()
-               track_close = Signal()
-               self.sync += [
-                       If(track_open,
-                               has_openrow.eq(1),
-                               openrow.eq(slicer.row(reqf.adr))
-                       ),
-                       If(track_close,
-                               has_openrow.eq(0)
-                       )
-               ]
-
-               # Address generation
-               s_row_adr = Signal()
-               self.comb += [
-                       self.cmd.ba.eq(bankn),
-                       If(s_row_adr,
-                               self.cmd.a.eq(slicer.row(reqf.adr))
-                       ).Else(
-                               self.cmd.a.eq(slicer.col(reqf.adr))
-                       )
-               ]
-
-               # Respect write-to-precharge specification
-               precharge_ok = Signal()
-               t_unsafe_precharge = 2 + timing_settings.tWR - 1
-               unsafe_precharge_count = Signal(max=t_unsafe_precharge+1)
-               self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
-               self.sync += [
-                       If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
-                               unsafe_precharge_count.eq(t_unsafe_precharge)
-                       ).Elif(~precharge_ok,
-                               unsafe_precharge_count.eq(unsafe_precharge_count-1)
-                       )
-               ]
-
-               # Control and command generation FSM
-               fsm = FSM()
-               self.submodules += fsm
-               fsm.act("REGULAR",
-                       If(self.refresh_req,
-                               NextState("REFRESH")
-                       ).Elif(self.req_fifo.readable,
-                               If(has_openrow,
-                                       If(hit,
-                                               # NB: write-to-read specification is enforced by multiplexer
-                                               self.cmd.stb.eq(1),
-                                               req.dat_ack.eq(self.cmd.ack),
-                                               self.cmd.is_read.eq(~reqf.we),
-                                               self.cmd.is_write.eq(reqf.we),
-                                               self.cmd.cas_n.eq(0),
-                                               self.cmd.we_n.eq(~reqf.we)
-                                       ).Else(
-                                               NextState("PRECHARGE")
-                                       )
-                               ).Else(
-                                       NextState("ACTIVATE")
-                               )
-                       )
-               )
-               fsm.act("PRECHARGE",
-                       # Notes:
-                       # 1. we are presenting the column address, A10 is always low
-                       # 2. since we always go to the ACTIVATE state, we do not need
-                       # to assert track_close.
-                       If(precharge_ok,
-                               self.cmd.stb.eq(1),
-                               If(self.cmd.ack, NextState("TRP")),
-                               self.cmd.ras_n.eq(0),
-                               self.cmd.we_n.eq(0),
-                               self.cmd.is_cmd.eq(1)
-                       )
-               )
-               fsm.act("ACTIVATE",
-                       s_row_adr.eq(1),
-                       track_open.eq(1),
-                       self.cmd.stb.eq(1),
-                       self.cmd.is_cmd.eq(1),
-                       If(self.cmd.ack, NextState("TRCD")),
-                       self.cmd.ras_n.eq(0)
-               )
-               fsm.act("REFRESH",
-                       self.refresh_gnt.eq(precharge_ok),
-                       track_close.eq(1),
-                       self.cmd.is_cmd.eq(1),
-                       If(~self.refresh_req, NextState("REGULAR"))
-               )
-               fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
-               fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD-1)
diff --git a/misoclib/lasmicon/minicon.py b/misoclib/lasmicon/minicon.py
deleted file mode 100755 (executable)
index 6cd3674..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.bus import dfi as dfibus
-from migen.genlib.fsm import FSM, NextState
-
-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
-               self.address_align = address_align
-
-       def row(self, address):
-               split = self.bank_a + self.col_a
-               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
-               if isinstance(address, int):
-                       return (address & mask) >> shift
-               else:
-                       return address[self.col_a:self.col_a+self.bank_a]
-
-       def col(self, address):
-               split = self.col_a
-               if isinstance(address, int):
-                       return (address & (2**split - 1)) << self.address_align
-               else:
-                       return Cat(Replicate(0, self.address_align), address[:split])
-
-class Minicon(Module):
-       def __init__(self, phy_settings, geom_settings, timing_settings):
-               if phy_settings.memtype in ["SDR"]:
-                       burst_length = phy_settings.nphases*1 # command multiplication*SDR
-               elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
-                       burst_length = phy_settings.nphases*2 # command multiplication*DDR
-               address_align = log2_int(burst_length)
-
-               nbanks = range(2**geom_settings.bank_a)
-               A10_ENABLED = 0
-               COLUMN      = 1
-               ROW         = 2
-               rdphase = phy_settings.rdphase
-               wrphase = phy_settings.wrphase
-               rdcmdphase = phy_settings.rdcmdphase
-               wrcmdphase = phy_settings.wrcmdphase
-
-               self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
-                               geom_settings.bank_a,
-                               phy_settings.dfi_d,
-                               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)
-               req_addr = Signal(geom_settings.col_a + geom_settings.bank_a + geom_settings.row_a)
-               refresh_req = Signal()
-               refresh_ack = Signal()
-               wb_access = Signal()
-               refresh_counter = Signal(max=timing_settings.tREFI+1)
-               hit = Signal()
-               row_open = Signal()
-               row_closeall = Signal()
-               addr_sel = Signal(max=3, reset=A10_ENABLED)
-               has_curbank_openrow = Signal()
-               cl_counter = Signal(max=phy_settings.cl+1)
-
-               # Extra bit means row is active when asserted
-               self.openrow = openrow = Array(Signal(geom_settings.row_a + 1) for b in nbanks)
-
-               self.comb += [
-                       hit.eq(openrow[slicer.bank(bus.adr)] == Cat(slicer.row(bus.adr), 1)),
-                       has_curbank_openrow.eq(openrow[slicer.bank(bus.adr)][-1]),
-                       wb_access.eq(bus.stb & bus.cyc),
-                       bus.dat_r.eq(Cat([phase.rddata for phase in dfi.phases])),
-                       Cat([phase.wrdata for phase in dfi.phases]).eq(bus.dat_w),
-                       Cat([phase.wrdata_mask for phase in dfi.phases]).eq(~bus.sel),
-               ]
-
-               for phase in dfi.phases:
-                       self.comb += [
-                               phase.cke.eq(1),
-                               phase.address.eq(Array([2**10, slicer.col(bus.adr), slicer.row(bus.adr)])[addr_sel]),
-                               If(wb_access,
-                                       phase.bank.eq(slicer.bank(bus.adr))
-                               )
-                       ]
-                       phase.cs_n.reset = 0
-                       phase.ras_n.reset = 1
-                       phase.cas_n.reset = 1
-                       phase.we_n.reset = 1
-
-               for b in nbanks:
-                       self.sync += [
-                               If(row_open & (b == slicer.bank(bus.adr)),
-                                       openrow[b].eq(Cat(slicer.row(bus.adr), 1)),
-                               ),
-                               If(row_closeall,
-                                       openrow[b][-1].eq(0)
-                               )
-                       ]
-
-               self.sync += [
-                       If(refresh_ack,
-                               refresh_req.eq(0)
-                       ),
-                       If(refresh_counter == 0,
-                               refresh_counter.eq(timing_settings.tREFI),
-                               refresh_req.eq(1)
-                       ).Else(
-                               refresh_counter.eq(refresh_counter - 1)
-                       )
-               ]
-
-               fsm = FSM()
-               self.submodules += fsm
-               fsm.act("IDLE",
-                       If(refresh_req,
-                               NextState("PRECHARGEALL")
-                       ).Elif(wb_access,
-                                If(hit & bus.we,
-                                        NextState("WRITE"),
-                                ),
-                                If(hit & ~bus.we,
-                                        NextState("READ"),
-                                ),
-                                If(has_curbank_openrow & ~hit,
-                                        NextState("PRECHARGE")
-                                ),
-                                If(~has_curbank_openrow,
-                                        NextState("ACTIVATE")
-                                ),
-                        )
-               )
-               fsm.act("READ",
-                       # We output Column bits at address pins so that A10 is 0
-                       # to disable row Auto-Precharge
-                       dfi.phases[rdcmdphase].ras_n.eq(1),
-                       dfi.phases[rdcmdphase].cas_n.eq(0),
-                       dfi.phases[rdcmdphase].we_n.eq(1),
-                       dfi.phases[rdphase].rddata_en.eq(1),
-                       addr_sel.eq(COLUMN),
-                       NextState("READ-WAIT-ACK"),
-               )
-               fsm.act("READ-WAIT-ACK",
-                       If(dfi.phases[rdphase].rddata_valid,
-                               NextState("IDLE"),
-                               bus.ack.eq(1)
-                       ).Else(
-                               NextState("READ-WAIT-ACK")
-                       )
-               )
-               fsm.act("WRITE",
-                       dfi.phases[wrcmdphase].ras_n.eq(1),
-                       dfi.phases[wrcmdphase].cas_n.eq(0),
-                       dfi.phases[wrcmdphase].we_n.eq(0),
-                       dfi.phases[wrphase].wrdata_en.eq(1),
-                       addr_sel.eq(COLUMN),
-                       bus.ack.eq(1),
-                       NextState("IDLE")
-               )
-               fsm.act("PRECHARGEALL",
-                       row_closeall.eq(1),
-                       dfi.phases[rdphase].ras_n.eq(0),
-                       dfi.phases[rdphase].cas_n.eq(1),
-                       dfi.phases[rdphase].we_n.eq(0),
-                       addr_sel.eq(A10_ENABLED),
-                       NextState("PRE-REFRESH")
-               )
-               fsm.act("PRECHARGE",
-                       # Notes:
-                       # 1. we are presenting the column address so that A10 is low
-                       # 2. since we always go to the ACTIVATE state, we do not need
-                       # to assert row_close because it will be reopen right after.
-                       NextState("TRP"),
-                       addr_sel.eq(COLUMN),
-                       dfi.phases[rdphase].ras_n.eq(0),
-                       dfi.phases[rdphase].cas_n.eq(1),
-                       dfi.phases[rdphase].we_n.eq(0)
-               )
-               fsm.act("ACTIVATE",
-                       row_open.eq(1),
-                       NextState("TRCD"),
-                       dfi.phases[rdphase].ras_n.eq(0),
-                       dfi.phases[rdphase].cas_n.eq(1),
-                       dfi.phases[rdphase].we_n.eq(1),
-                       addr_sel.eq(ROW)
-               )
-               fsm.act("REFRESH",
-                       refresh_ack.eq(1),
-                       dfi.phases[rdphase].ras_n.eq(0),
-                       dfi.phases[rdphase].cas_n.eq(0),
-                       dfi.phases[rdphase].we_n.eq(1),
-                       NextState("POST-REFRESH")
-               )
-               fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
-               fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP-1)
-               fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD-1)
-               fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC-1)
diff --git a/misoclib/lasmicon/minicontb.py b/misoclib/lasmicon/minicontb.py
deleted file mode 100755 (executable)
index 8fb982b..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import TRead, TWrite
-from migen.bus import wishbone
-from migen.sim.generic import Simulator
-from migen.sim import icarus
-from mibuild.platforms import papilio_pro as board
-from misoclib import lasmicon
-from misoclib.lasmicon.minicon import Minicon
-from misoclib.sdramphy import gensdrphy
-from itertools import chain
-from os.path import isfile
-import sys
-
-clk_freq = 80000000
-
-from math import ceil
-
-def ns(t, margin=True):
-       clk_period_ns = 1000000000/clk_freq
-       if margin:
-               t += clk_period_ns/2
-       return ceil(t/clk_period_ns)
-
-class MiniconTB(Module):
-       def __init__(self, sdrphy, dfi, sdram_geom, sdram_timing, pads, sdram_clk):
-
-               self.clk_freq = 80000000
-               phy_settings = sdrphy.phy_settings
-               rdphase = phy_settings.rdphase
-               self.submodules.slave = Minicon(phy_settings, sdram_geom, sdram_timing)
-
-               self.submodules.tap = wishbone.Tap(self.slave.bus)
-               self.submodules.dc = dc = wishbone.DownConverter(32, phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
-               self.submodules.master = wishbone.Initiator(self.genxfers(), bus=dc.wishbone_i)
-               self.submodules.intercon = wishbone.InterconnectPointToPoint(dc.wishbone_o, self.slave.bus)
-
-               self.submodules.sdrphy = self.sdrphy = sdrphy
-               self.dfi = dfi
-               self.pads = pads
-
-               self.specials += Instance("mt48lc4m16a2",
-                       io_Dq=pads.dq,
-                       i_Addr=pads.a,
-                       i_Ba=pads.ba,
-                       i_Clk=ClockSignal(),
-                       i_Cke=pads.cke,
-                       i_Cs_n=pads.cs_n,
-                       i_Ras_n=pads.ras_n,
-                       i_Cas_n=pads.cas_n,
-                       i_We_n=pads.we_n,
-                       i_Dqm=pads.dm
-               )
-
-       def genxfers(self):
-               cycle = 0
-               for a in chain(range(4),range(256,260),range(1024,1028)):
-                       t = TRead(a)
-                       yield t
-                       print("read {} in {} cycles".format(t.data, t.latency))
-               for a in chain(range(4),range(256,260),range(1024,1028),range(4096,4100)):
-                       t = TWrite(a, 0xaa55aa55+cycle)
-                       cycle += 1
-                       yield t
-                       print("read {} in {} cycles".format(t.data, t.latency))
-               for a in chain(range(4),range(256,260),range(1024,1028),range(4096,4100)):
-                       t = TRead(a)
-                       yield t
-                       print("read {} in {} cycles".format(t.data, t.latency))
-
-       def gen_simulation(self, selfp):
-               dfi = selfp.dfi
-               phy = self.sdrphy
-               rdphase = phy.phy_settings.rdphase
-               cycle = 0
-
-               while True:
-                       yield
-
-class MyTopLevel:
-       def __init__(self, vcd_name=None, vcd_level=1,
-         top_name="top", dut_type="dut", dut_name="dut",
-         cd_name="sys", clk_period=10):
-               self.vcd_name = vcd_name
-               self.vcd_level = vcd_level
-               self.top_name = top_name
-               self.dut_type = dut_type
-               self.dut_name = dut_name
-
-               self._cd_name = cd_name
-               self._clk_period = clk_period
-
-               cd = ClockDomain(self._cd_name)
-               cd_ps = ClockDomain("sys_ps")
-               self.clock_domains = [cd, cd_ps]
-               self.ios = {cd.clk, cd.rst, cd_ps.clk}
-
-       def get(self, sockaddr):
-               template1 = """`timescale 1ns / 1ps
-
-module {top_name}();
-
-reg {clk_name};
-reg {rst_name};
-reg sys_ps_clk;
-
-initial begin
-       {rst_name} <= 1'b1;
-       @(posedge {clk_name});
-       {rst_name} <= 1'b0;
-end
-
-always begin
-       {clk_name} <= 1'b0;
-       #{hclk_period};
-       {clk_name} <= 1'b1;
-       #{hclk_period};
-end
-
-always @(posedge {clk_name} or negedge {clk_name})
-       sys_ps_clk <= #({hclk_period}*2-3) {clk_name};
-
-{dut_type} {dut_name}(
-       .{rst_name}({rst_name}),
-       .{clk_name}({clk_name}),
-       .sys_ps_clk(sys_ps_clk)
-);
-
-initial $migensim_connect("{sockaddr}");
-always @(posedge {clk_name}) $migensim_tick;
-"""
-               template2 = """
-initial begin
-       $dumpfile("{vcd_name}");
-       $dumpvars({vcd_level}, {dut_name});
-end
-"""
-               r = template1.format(top_name=self.top_name,
-                       dut_type=self.dut_type,
-                       dut_name=self.dut_name,
-                       clk_name=self._cd_name + "_clk",
-                       rst_name=self._cd_name + "_rst",
-                       hclk_period=str(self._clk_period/2),
-                       sockaddr=sockaddr)
-               if self.vcd_name is not None:
-                       r += template2.format(vcd_name=self.vcd_name,
-                               vcd_level=str(self.vcd_level),
-                               dut_name=self.dut_name)
-               r += "\nendmodule"
-               return r
-               
-
-if __name__ == "__main__":
-
-       plat = board.Platform()
-
-       sdram_geom = lasmicon.GeomSettings(
-               bank_a=2,
-               row_a=12,
-               col_a=8
-       )
-
-       sdram_timing = lasmicon.TimingSettings(
-               tRP=ns(15),
-               tRCD=ns(15),
-               tWR=ns(14),
-               tWTR=2,
-               tREFI=ns(64*1000*1000/4096, False),
-               tRFC=ns(66),
-               req_queue_size=8,
-               read_time=32,
-               write_time=16
-       )
-
-       sdram_pads = plat.request("sdram")
-       sdram_clk = plat.request("sdram_clock")
-
-       sdrphy = gensdrphy.GENSDRPHY(sdram_pads)
-
-# This sets CL to 2 during LMR done on 1st cycle
-       sdram_pads.a.reset = 1<<5
-
-       s = MiniconTB(sdrphy, sdrphy.dfi, sdram_geom, sdram_timing, pads=sdram_pads, sdram_clk=sdram_clk)
-
-       extra_files = [ "sdram_model/mt48lc4m16a2.v" ]
-
-       if not isfile(extra_files[0]):
-               print("ERROR: You need to download Micron Verilog simulation model for MT48LC4M16A2 and put it in sdram_model/mt48lc4m16a2.v")
-               print("File can be downloaded from this URL: http://www.micron.com/-/media/documents/products/sim%20model/dram/dram/4054mt48lc4m16a2.zip")
-               sys.exit(1)
-
-       with Simulator(s, MyTopLevel("top.vcd", clk_period=int(1/0.08)), icarus.Runner(extra_files=extra_files, keep_files=True)) as sim:
-               sim.run(5000)
diff --git a/misoclib/lasmicon/multiplexer.py b/misoclib/lasmicon/multiplexer.py
deleted file mode 100644 (file)
index f72bf86..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.roundrobin import *
-from migen.genlib.misc import optree
-from migen.genlib.fsm import FSM, NextState
-from migen.bank.description import AutoCSR
-
-from misoclib.lasmicon.perf import Bandwidth
-
-class CommandRequest:
-       def __init__(self, a, ba):
-               self.a = Signal(a)
-               self.ba = Signal(ba)
-               self.cas_n = Signal(reset=1)
-               self.ras_n = Signal(reset=1)
-               self.we_n = Signal(reset=1)
-
-class CommandRequestRW(CommandRequest):
-       def __init__(self, a, ba):
-               CommandRequest.__init__(self, a, ba)
-               self.stb = Signal()
-               self.ack = Signal()
-               self.is_cmd = Signal()
-               self.is_read = Signal()
-               self.is_write = Signal()
-
-class _CommandChooser(Module):
-       def __init__(self, requests):
-               self.want_reads = Signal()
-               self.want_writes = Signal()
-               self.want_cmds = Signal()
-               # NB: cas_n/ras_n/we_n are 1 when stb is inactive
-               self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
-
-               ###
-
-               rr = RoundRobin(len(requests), SP_CE)
-               self.submodules += rr
-
-               self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
-                       for i, req in enumerate(requests)]
-
-               stb = Signal()
-               self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
-               for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
-                       choices = Array(getattr(req, name) for req in requests)
-                       self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
-               for name in ["cas_n", "ras_n", "we_n"]:
-                       # we should only assert those signals when stb is 1
-                       choices = Array(getattr(req, name) for req in requests)
-                       self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
-               self.comb += self.cmd.stb.eq(stb \
-                       & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
-                       & (self.cmd.is_write == self.want_writes))))
-
-               self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
-                       for i, req in enumerate(requests)]
-               self.comb += rr.ce.eq(self.cmd.ack)
-
-class _Steerer(Module):
-       def __init__(self, commands, dfi):
-               ncmd = len(commands)
-               nph = len(dfi.phases)
-               self.sel = [Signal(max=ncmd) for i in range(nph)]
-
-               ###
-
-               def stb_and(cmd, attr):
-                       if not hasattr(cmd, "stb"):
-                               return 0
-                       else:
-                               return cmd.stb & getattr(cmd, attr)
-               for phase, sel in zip(dfi.phases, self.sel):
-                       self.comb += [
-                               phase.cke.eq(1),
-                               phase.cs_n.eq(0)
-                       ]
-                       if hasattr(phase, "odt"):
-                               self.comb += phase.odt.eq(1)
-                       if hasattr(phase, "reset_n"):
-                               self.comb += phase.reset_n.eq(1)
-                       self.sync += [
-                               phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
-                               phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
-                               phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
-                               phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
-                               phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
-                               phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
-                               phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
-                       ]
-
-class Multiplexer(Module, AutoCSR):
-       def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
-               assert(phy_settings.nphases == len(dfi.phases))
-
-               # Command choosing
-               requests = [bm.cmd for bm in bank_machines]
-               choose_cmd = _CommandChooser(requests)
-               choose_req = _CommandChooser(requests)
-               self.comb += [
-                       choose_cmd.want_reads.eq(0),
-                       choose_cmd.want_writes.eq(0)
-               ]
-               if phy_settings.nphases == 1:
-                       self.comb += [
-                               choose_cmd.want_cmds.eq(1),
-                               choose_req.want_cmds.eq(1)
-                       ]
-               self.submodules += choose_cmd, choose_req
-
-               # Command steering
-               nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
-               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)
-               self.submodules += steerer
-
-               # Read/write turnaround
-               read_available = Signal()
-               write_available = Signal()
-               self.comb += [
-                       read_available.eq(optree("|", [req.stb & req.is_read for req in requests])),
-                       write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
-               ]
-
-               def anti_starvation(timeout):
-                       en = Signal()
-                       max_time = Signal()
-                       if timeout:
-                               t = timeout - 1
-                               time = Signal(max=t+1)
-                               self.comb += max_time.eq(time == 0)
-                               self.sync += If(~en,
-                                               time.eq(t)
-                                       ).Elif(~max_time,
-                                               time.eq(time - 1)
-                                       )
-                       else:
-                               self.comb += max_time.eq(0)
-                       return en, max_time
-               read_time_en, max_read_time = anti_starvation(timing_settings.read_time)
-               write_time_en, max_write_time = anti_starvation(timing_settings.write_time)
-
-               # Refresh
-               self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
-               go_to_refresh = Signal()
-               self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
-
-               # Datapath
-               all_rddata = [p.rddata for p in dfi.phases]
-               all_wrdata = [p.wrdata for p in dfi.phases]
-               all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
-               self.comb += [
-                       lasmic.dat_r.eq(Cat(*all_rddata)),
-                       Cat(*all_wrdata).eq(lasmic.dat_w),
-                       Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
-               ]
-
-               # Control FSM
-               fsm = FSM()
-               self.submodules += fsm
-
-               def steerer_sel(steerer, phy_settings, r_w_n):
-                       r = []
-                       for i in range(phy_settings.nphases):
-                               s = steerer.sel[i].eq(STEER_NOP)
-                               if r_w_n == "read":
-                                       if i == phy_settings.rdphase:
-                                               s = steerer.sel[i].eq(STEER_REQ)
-                                       elif i == phy_settings.rdcmdphase:
-                                               s = steerer.sel[i].eq(STEER_CMD)
-                               elif r_w_n == "write":
-                                       if i == phy_settings.wrphase:
-                                               s = steerer.sel[i].eq(STEER_REQ)
-                                       elif i == phy_settings.wrcmdphase:
-                                               s = steerer.sel[i].eq(STEER_CMD)
-                               else:
-                                       raise ValueError
-                               r.append(s)
-                       return r
-
-               fsm.act("READ",
-                       read_time_en.eq(1),
-                       choose_req.want_reads.eq(1),
-                       choose_cmd.cmd.ack.eq(1),
-                       choose_req.cmd.ack.eq(1),
-                       steerer_sel(steerer, phy_settings, "read"),
-                       If(write_available,
-                               # TODO: switch only after several cycles of ~read_available?
-                               If(~read_available | max_read_time, NextState("RTW"))
-                       ),
-                       If(go_to_refresh, NextState("REFRESH"))
-               )
-               fsm.act("WRITE",
-                       write_time_en.eq(1),
-                       choose_req.want_writes.eq(1),
-                       choose_cmd.cmd.ack.eq(1),
-                       choose_req.cmd.ack.eq(1),
-                       steerer_sel(steerer, phy_settings, "write"),
-                       If(read_available,
-                               If(~write_available | max_write_time, NextState("WTR"))
-                       ),
-                       If(go_to_refresh, NextState("REFRESH"))
-               )
-               fsm.act("REFRESH",
-                       steerer.sel[0].eq(STEER_REFRESH),
-                       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("WTR", "READ", timing_settings.tWTR-1)
-               # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
-               fsm.finalize()
-               self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])
-
-               self.submodules.bandwidth = Bandwidth(choose_req.cmd)
diff --git a/misoclib/lasmicon/perf.py b/misoclib/lasmicon/perf.py
deleted file mode 100644 (file)
index ec09c79..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-class Bandwidth(Module, AutoCSR):
-       def __init__(self, cmd, period_bits=24):
-               self._r_update = CSR()
-               self._r_nreads = CSRStatus(period_bits)
-               self._r_nwrites = CSRStatus(period_bits)
-
-               ###
-
-               cmd_stb = Signal()
-               cmd_ack = Signal()
-               cmd_is_read = Signal()
-               cmd_is_write = Signal()
-               self.sync += [
-                       cmd_stb.eq(cmd.stb),
-                       cmd_ack.eq(cmd.ack),
-                       cmd_is_read.eq(cmd.is_read),
-                       cmd_is_write.eq(cmd.is_write)
-               ]
-
-               counter = Signal(period_bits)
-               period = Signal()
-               nreads = Signal(period_bits)
-               nwrites = Signal(period_bits)
-               nreads_r = Signal(period_bits)
-               nwrites_r = Signal(period_bits)
-               self.sync += [
-                       Cat(counter, period).eq(counter + 1),
-                       If(period,
-                               nreads_r.eq(nreads),
-                               nwrites_r.eq(nwrites),
-                               nreads.eq(0),
-                               nwrites.eq(0)
-                       ).Elif(cmd_stb & cmd_ack,
-                               If(cmd_is_read, nreads.eq(nreads + 1)),
-                               If(cmd_is_write, nwrites.eq(nwrites + 1)),
-                       ),
-                       If(self._r_update.re,
-                               self._r_nreads.status.eq(nreads_r),
-                               self._r_nwrites.status.eq(nwrites_r)
-                       )
-               ]
diff --git a/misoclib/lasmicon/refresher.py b/misoclib/lasmicon/refresher.py
deleted file mode 100644 (file)
index 76482bd..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.misc import timeline
-from migen.genlib.fsm import FSM
-
-from misoclib.lasmicon.multiplexer import *
-
-class Refresher(Module):
-       def __init__(self, a, ba, tRP, tREFI, tRFC):
-               self.req = Signal()
-               self.ack = Signal() # 1st command 1 cycle after assertion of ack
-               self.cmd = CommandRequest(a, ba)
-
-               ###
-
-               # Refresh sequence generator:
-               # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
-               seq_start = Signal()
-               seq_done = Signal()
-               self.sync += [
-                       self.cmd.a.eq(2**10),
-                       self.cmd.ba.eq(0),
-                       self.cmd.cas_n.eq(1),
-                       self.cmd.ras_n.eq(1),
-                       self.cmd.we_n.eq(1),
-                       seq_done.eq(0)
-               ]
-               self.sync += timeline(seq_start, [
-                       (1, [
-                               self.cmd.ras_n.eq(0),
-                               self.cmd.we_n.eq(0)
-                       ]),
-                       (1+tRP, [
-                               self.cmd.cas_n.eq(0),
-                               self.cmd.ras_n.eq(0)
-                       ]),
-                       (1+tRP+tRFC, [
-                               seq_done.eq(1)
-                       ])
-               ])
-
-               # Periodic refresh counter
-               counter = Signal(max=tREFI)
-               start = Signal()
-               self.sync += [
-                       start.eq(0),
-                       If(counter == 0,
-                               start.eq(1),
-                               counter.eq(tREFI - 1)
-                       ).Else(
-                               counter.eq(counter - 1)
-                       )
-               ]
-
-               # Control FSM
-               fsm = FSM()
-               self.submodules += fsm
-               fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
-               fsm.act("WAIT_GRANT",
-                       self.req.eq(1),
-                       If(self.ack,
-                               seq_start.eq(1),
-                               NextState("WAIT_SEQ")
-                       )
-               )
-               fsm.act("WAIT_SEQ",
-                       self.req.eq(1),
-                       If(seq_done, NextState("IDLE"))
-               )
diff --git a/misoclib/lasmicon/test/bankmachine.py b/misoclib/lasmicon/test/bankmachine.py
deleted file mode 100644 (file)
index d446fb0..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.lasmibus import *
-from migen.sim.generic import run_simulation
-
-from misoclib.lasmicon.bankmachine import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger
-
-def my_generator():
-       for x in range(10):
-               yield True, x
-       for x in range(10):
-               yield False, 128*x
-
-class TB(Module):
-       def __init__(self):
-               self.req = Interface(32, 32, 1,
-                       sdram_timing.req_queue_size, sdram_phy.read_latency, sdram_phy.write_latency)
-               self.submodules.dut = BankMachine(sdram_geom, sdram_timing, 2, 0, self.req)
-               self.submodules.logger = CommandLogger(self.dut.cmd, True)
-               self.generator = my_generator()
-               self.dat_ack_cnt = 0
-
-       def do_simulation(self, selfp):
-               if selfp.req.dat_ack:
-                       self.dat_ack_cnt += 1
-               if selfp.req.req_ack:
-                       try:
-                               we, adr = next(self.generator)
-                       except StopIteration:
-                               selfp.req.stb = 0
-                               if not selfp.req.lock:
-                                       print("data ack count: {0}".format(self.dat_ack_cnt))
-                                       raise StopSimulation
-                               return
-                       selfp.req.adr = adr
-                       selfp.req.we = we
-                       selfp.req.stb = 1
-
-if __name__ == "__main__":
-       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/lasmicon/test/common.py b/misoclib/lasmicon/test/common.py
deleted file mode 100644 (file)
index c463297..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-from fractions import Fraction
-from math import ceil
-
-from migen.fhdl.std import *
-
-from misoclib import lasmicon
-
-MHz = 1000000
-clk_freq = (83 + Fraction(1, 3))*MHz
-
-clk_period_ns = 1000000000/clk_freq
-def ns(t, margin=True):
-       if margin:
-               t += clk_period_ns/2
-       return ceil(t/clk_period_ns)
-
-sdram_phy = lasmicon.PhySettings(
-       memtype="DDR",
-       dfi_d=64,
-       nphases=2,
-       rdphase=0,
-       wrphase=1,
-       rdcmdphase=1,
-       wrcmdphase=0,
-       cl=3,
-       read_latency=5,
-       write_latency=0
-)
-
-sdram_geom = lasmicon.GeomSettings(
-       bank_a=2,
-       row_a=13,
-       col_a=10
-)
-sdram_timing = lasmicon.TimingSettings(
-       tRP=ns(15),
-       tRCD=ns(15),
-       tWR=ns(15),
-       tWTR=2,
-       tREFI=ns(7800, False),
-       tRFC=ns(70),
-
-       req_queue_size=8,
-       read_time=32,
-       write_time=16
-)
-
-def decode_sdram(ras_n, cas_n, we_n, bank, address):
-       elts = []
-       if not ras_n and cas_n and we_n:
-               elts.append("ACTIVATE")
-               elts.append("BANK " + str(bank))
-               elts.append("ROW " + str(address))
-       elif ras_n and not cas_n and we_n:
-               elts.append("READ\t")
-               elts.append("BANK " + str(bank))
-               elts.append("COL " + str(address))
-       elif ras_n and not cas_n and not we_n:
-               elts.append("WRITE\t")
-               elts.append("BANK " + str(bank))
-               elts.append("COL " + str(address))
-       elif ras_n and cas_n and not we_n:
-               elts.append("BST")
-       elif not ras_n and not cas_n and we_n:
-               elts.append("AUTO REFRESH")
-       elif not ras_n and cas_n and not we_n:
-               elts.append("PRECHARGE")
-               if address & 2**10:
-                       elts.append("ALL")
-               else:
-                       elts.append("BANK " + str(bank))
-       elif not ras_n and not cas_n and not we_n:
-               elts.append("LMR")
-       return elts
-
-class CommandLogger(Module):
-       def __init__(self, cmd, rw=False):
-               self.cmd = cmd
-               if rw:
-                       self.comb += self.cmd.ack.eq(1)
-
-       def do_simulation(self, selfp):
-               elts = ["@" + str(selfp.simulator.cycle_counter)]
-               cmdp = selfp.cmd
-               elts += decode_sdram(cmdp.ras_n, cmdp.cas_n, cmdp.we_n, cmdp.ba, cmdp.a)
-               if len(elts) > 1:
-                       print("\t".join(elts))
-       do_simulation.passive = True
-
-class DFILogger(Module):
-       def __init__(self, dfi):
-               self.dfi = dfi
-
-       def do_simulation(self, selfp):
-               dfip = selfp.dfi
-               for i, p in enumerate(dfip.phases):
-                       elts = ["@" + str(selfp.simulator.cycle_counter) + ":" + str(i)]
-                       elts += decode_sdram(p.ras_n, p.cas_n, p.we_n, p.bank, p.address)
-                       if len(elts) > 1:
-                               print("\t".join(elts))
-       do_simulation.passive = True
diff --git a/misoclib/lasmicon/test/lasmicon.py b/misoclib/lasmicon/test/lasmicon.py
deleted file mode 100644 (file)
index 05466d4..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.lasmibus import *
-from migen.sim.generic import run_simulation
-
-from misoclib.lasmicon import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-def my_generator_r(n):
-       for x in range(10):
-               t = TRead(128*n + 48*n*x)
-               yield t
-       print("{0:3}: reads done".format(n))
-
-def my_generator_w(n):
-       for x in range(10):
-               t = TWrite(128*n + 48*n*x, x)
-               yield t
-       print("{0:3}: writes done".format(n))
-
-def my_generator(n):
-       if n % 2:
-               return my_generator_w(n // 2)
-       else:
-               return my_generator_r(n // 2)
-
-class TB(Module):
-       def __init__(self):
-               self.submodules.dut = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-               self.submodules.xbar = lasmibus.Crossbar([self.dut.lasmic], self.dut.nrowbits)
-               self.submodules.logger = DFILogger(self.dut.dfi)
-
-               masters = [self.xbar.get_master() for i in range(6)]
-               self.initiators = [Initiator(my_generator(n), master)
-                       for n, master in enumerate(masters)]
-               self.submodules += self.initiators
-
-if __name__ == "__main__":
-       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/lasmicon/test/lasmicon_df.py b/misoclib/lasmicon/test/lasmicon_df.py
deleted file mode 100644 (file)
index b5380df..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import lasmibus
-from migen.actorlib import dma_lasmi
-from migen.sim.generic import run_simulation
-
-from misoclib.lasmicon import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-class TB(Module):
-       def __init__(self):
-               self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-               self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
-               self.submodules.logger = DFILogger(self.ctler.dfi)
-               self.submodules.writer = dma_lasmi.Writer(self.xbar.get_master())
-
-               self.comb += self.writer.address_data.stb.eq(1)
-               pl = self.writer.address_data.payload
-               pl.a.reset = 255
-               pl.d.reset = pl.a.reset*2
-               self.sync += If(self.writer.address_data.ack,
-                       pl.a.eq(pl.a + 1),
-                       pl.d.eq(pl.d + 2)
-               )
-               self.open_row = None
-
-       def do_simulation(self, selfp):
-               dfip = selfp.ctler.dfi
-               for p in dfip.phases:
-                       if p.ras_n and not p.cas_n and not p.we_n: # write
-                               d = dfip.phases[0].wrdata | (dfip.phases[1].wrdata << 64)
-                               print(d)
-                               if d != p.address//2 + p.bank*512 + self.open_row*2048:
-                                       print("**** ERROR ****")
-                       elif not p.ras_n and p.cas_n and p.we_n: # activate
-                               self.open_row = p.address
-
-if __name__ == "__main__":
-       run_simulation(TB(), ncycles=3500, vcd_name="my.vcd")
diff --git a/misoclib/lasmicon/test/lasmicon_wb.py b/misoclib/lasmicon/test/lasmicon_wb.py
deleted file mode 100644 (file)
index 1a385ed..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone, wishbone2lasmi, lasmibus
-from migen.bus.transactions import *
-from migen.sim.generic import run_simulation
-
-from misoclib.lasmicon import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-l2_size = 8192 # in bytes
-
-def my_generator():
-       for x in range(20):
-               t = TWrite(x, x)
-               yield t
-               print(str(t) + " delay=" + str(t.latency))
-       for x in range(20):
-               t = TRead(x)
-               yield t
-               print(str(t) + " delay=" + str(t.latency))
-       for x in range(20):
-               t = TRead(x+l2_size//4)
-               yield t
-               print(str(t) + " delay=" + str(t.latency))
-
-class TB(Module):
-       def __init__(self):
-               self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-               self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
-               self.submodules.logger = DFILogger(self.ctler.dfi)
-               self.submodules.bridge = wishbone2lasmi.WB2LASMI(l2_size//4, self.xbar.get_master())
-               self.submodules.initiator = wishbone.Initiator(my_generator())
-               self.submodules.conn = wishbone.InterconnectPointToPoint(self.initiator.bus, self.bridge.wishbone)
-
-if __name__ == "__main__":
-       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/lasmicon/test/refresher.py b/misoclib/lasmicon/test/refresher.py
deleted file mode 100644 (file)
index 040b42d..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-from random import Random
-
-from migen.fhdl.std import *
-from migen.sim.generic import run_simulation
-
-from misoclib.lasmicon.refresher import *
-
-from common import CommandLogger
-
-class Granter(Module):
-       def __init__(self, req, ack):
-               self.req = req
-               self.ack = ack
-               self.state = 0
-               self.prng = Random(92837)
-
-       def do_simulation(self, selfp):
-               elts = ["@" + str(selfp.simulator.cycle_counter)]
-
-               if self.state == 0:
-                       if selfp.req:
-                               elts.append("Refresher requested access")
-                               self.state = 1
-               elif self.state == 1:
-                       if self.prng.randrange(0, 5) == 0:
-                               elts.append("Granted access to refresher")
-                               selfp.ack = 1
-                               self.state = 2
-               elif self.state == 2:
-                       if not selfp.req:
-                               elts.append("Refresher released access")
-                               selfp.ack = 0
-                               self.state = 0
-
-               if len(elts) > 1:
-                       print("\t".join(elts))
-
-class TB(Module):
-       def __init__(self):
-               self.submodules.dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5)
-               self.submodules.logger = CommandLogger(self.dut.cmd)
-               self.submodules.granter = Granter(self.dut.req, self.dut.ack)
-
-if __name__ == "__main__":
-       run_simulation(TB(), ncycles=400)
diff --git a/misoclib/sdram/__init__.py b/misoclib/sdram/__init__.py
new file mode 100644 (file)
index 0000000..f861d63
--- /dev/null
@@ -0,0 +1,12 @@
+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)
+
+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))
+
+TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC" \
+       " req_queue_size read_time write_time")
diff --git a/misoclib/sdram/dfii/__init__.py b/misoclib/sdram/dfii/__init__.py
new file mode 100644 (file)
index 0000000..ba53d37
--- /dev/null
@@ -0,0 +1,57 @@
+from migen.fhdl.std import *
+from migen.bus import dfi
+from migen.bank.description import *
+
+class PhaseInjector(Module, AutoCSR):
+       def __init__(self, phase):
+               self._command = CSRStorage(6) # cs, we, cas, ras, wren, rden
+               self._command_issue = CSR()
+               self._address = CSRStorage(flen(phase.address))
+               self._baddress = CSRStorage(flen(phase.bank))
+               self._wrdata = CSRStorage(flen(phase.wrdata))
+               self._rddata = CSRStatus(flen(phase.rddata))
+
+               ###
+
+               self.comb += [
+                       If(self._command_issue.re,
+                               phase.cs_n.eq(~self._command.storage[0]),
+                               phase.we_n.eq(~self._command.storage[1]),
+                               phase.cas_n.eq(~self._command.storage[2]),
+                               phase.ras_n.eq(~self._command.storage[3])
+                       ).Else(
+                               phase.cs_n.eq(1),
+                               phase.we_n.eq(1),
+                               phase.cas_n.eq(1),
+                               phase.ras_n.eq(1)
+                       ),
+                       phase.address.eq(self._address.storage),
+                       phase.bank.eq(self._baddress.storage),
+                       phase.wrdata_en.eq(self._command_issue.re & self._command.storage[4]),
+                       phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]),
+                       phase.wrdata.eq(self._wrdata.storage),
+                       phase.wrdata_mask.eq(0)
+               ]
+               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)
+
+               self._control = CSRStorage(4) # sel, cke, odt, reset_n
+
+               for n, phase in enumerate(inti.phases):
+                       setattr(self.submodules, "pi" + str(n), PhaseInjector(phase))
+
+               ###
+
+               self.comb += If(self._control.storage[0],
+                               self.slave.connect(self.master)
+                       ).Else(
+                               inti.connect(self.master)
+                       )
+               self.comb += [phase.cke.eq(self._control.storage[1]) for phase in inti.phases]
+               self.comb += [phase.odt.eq(self._control.storage[2]) for phase in inti.phases if hasattr(phase, "odt")]
+               self.comb += [phase.reset_n.eq(self._control.storage[3]) for phase in inti.phases if hasattr(phase, "reset_n")]
diff --git a/misoclib/sdram/lasmicon/__init__.py b/misoclib/sdram/lasmicon/__init__.py
new file mode 100644 (file)
index 0000000..1136bcf
--- /dev/null
@@ -0,0 +1,41 @@
+from migen.fhdl.std import *
+from migen.bus import dfi, lasmibus
+
+from misoclib.sdram.lasmicon.refresher import *
+from misoclib.sdram.lasmicon.bankmachine import *
+from misoclib.sdram.lasmicon.multiplexer import *
+
+class LASMIcon(Module):
+       def __init__(self, phy_settings, geom_settings, timing_settings):
+               if phy_settings.memtype in ["SDR"]:
+                       burst_length = phy_settings.nphases*1 # command multiplication*SDR
+               elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
+                       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,
+                       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,
+                       req_queue_size=timing_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.submodules.refresher = Refresher(geom_settings.mux_a, geom_settings.bank_a,
+                       timing_settings.tRP, timing_settings.tREFI, timing_settings.tRFC)
+               self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, address_align, i,
+                               getattr(self.lasmic, "bank"+str(i)))
+                       for i in range(2**geom_settings.bank_a)]
+               self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings,
+                       self.bank_machines, self.refresher,
+                       self.dfi, self.lasmic)
+
+       def get_csrs(self):
+               return self.multiplexer.get_csrs()
diff --git a/misoclib/sdram/lasmicon/bankmachine.py b/misoclib/sdram/lasmicon/bankmachine.py
new file mode 100644 (file)
index 0000000..53c43f0
--- /dev/null
@@ -0,0 +1,144 @@
+from migen.fhdl.std import *
+from migen.genlib.roundrobin import *
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import optree
+from migen.genlib.fifo import SyncFIFO
+
+from misoclib.sdram.lasmicon.multiplexer import *
+
+class _AddressSlicer:
+       def __init__(self, col_a, address_align):
+               self.col_a = col_a
+               self.address_align = address_align
+
+       def row(self, address):
+               split = self.col_a - 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
+               if isinstance(address, int):
+                       return (address & (2**split - 1)) << self.address_align
+               else:
+                       return Cat(Replicate(0, self.address_align), address[:split])
+
+class BankMachine(Module):
+       def __init__(self, geom_settings, timing_settings, address_align, bankn, req):
+               self.refresh_req = Signal()
+               self.refresh_gnt = Signal()
+               self.cmd = CommandRequestRW(geom_settings.mux_a, geom_settings.bank_a)
+
+               ###
+
+               # Request FIFO
+               self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))], timing_settings.req_queue_size)
+               self.comb += [
+                       self.req_fifo.din.we.eq(req.we),
+                       self.req_fifo.din.adr.eq(req.adr),
+                       self.req_fifo.we.eq(req.stb),
+                       req.req_ack.eq(self.req_fifo.writable),
+
+                       self.req_fifo.re.eq(req.dat_ack),
+                       req.lock.eq(self.req_fifo.readable)
+               ]
+               reqf = self.req_fifo.dout
+
+               slicer = _AddressSlicer(geom_settings.col_a, address_align)
+
+               # Row tracking
+               has_openrow = Signal()
+               openrow = Signal(geom_settings.row_a)
+               hit = Signal()
+               self.comb += hit.eq(openrow == slicer.row(reqf.adr))
+               track_open = Signal()
+               track_close = Signal()
+               self.sync += [
+                       If(track_open,
+                               has_openrow.eq(1),
+                               openrow.eq(slicer.row(reqf.adr))
+                       ),
+                       If(track_close,
+                               has_openrow.eq(0)
+                       )
+               ]
+
+               # Address generation
+               s_row_adr = Signal()
+               self.comb += [
+                       self.cmd.ba.eq(bankn),
+                       If(s_row_adr,
+                               self.cmd.a.eq(slicer.row(reqf.adr))
+                       ).Else(
+                               self.cmd.a.eq(slicer.col(reqf.adr))
+                       )
+               ]
+
+               # Respect write-to-precharge specification
+               precharge_ok = Signal()
+               t_unsafe_precharge = 2 + timing_settings.tWR - 1
+               unsafe_precharge_count = Signal(max=t_unsafe_precharge+1)
+               self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
+               self.sync += [
+                       If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
+                               unsafe_precharge_count.eq(t_unsafe_precharge)
+                       ).Elif(~precharge_ok,
+                               unsafe_precharge_count.eq(unsafe_precharge_count-1)
+                       )
+               ]
+
+               # Control and command generation FSM
+               fsm = FSM()
+               self.submodules += fsm
+               fsm.act("REGULAR",
+                       If(self.refresh_req,
+                               NextState("REFRESH")
+                       ).Elif(self.req_fifo.readable,
+                               If(has_openrow,
+                                       If(hit,
+                                               # NB: write-to-read specification is enforced by multiplexer
+                                               self.cmd.stb.eq(1),
+                                               req.dat_ack.eq(self.cmd.ack),
+                                               self.cmd.is_read.eq(~reqf.we),
+                                               self.cmd.is_write.eq(reqf.we),
+                                               self.cmd.cas_n.eq(0),
+                                               self.cmd.we_n.eq(~reqf.we)
+                                       ).Else(
+                                               NextState("PRECHARGE")
+                                       )
+                               ).Else(
+                                       NextState("ACTIVATE")
+                               )
+                       )
+               )
+               fsm.act("PRECHARGE",
+                       # Notes:
+                       # 1. we are presenting the column address, A10 is always low
+                       # 2. since we always go to the ACTIVATE state, we do not need
+                       # to assert track_close.
+                       If(precharge_ok,
+                               self.cmd.stb.eq(1),
+                               If(self.cmd.ack, NextState("TRP")),
+                               self.cmd.ras_n.eq(0),
+                               self.cmd.we_n.eq(0),
+                               self.cmd.is_cmd.eq(1)
+                       )
+               )
+               fsm.act("ACTIVATE",
+                       s_row_adr.eq(1),
+                       track_open.eq(1),
+                       self.cmd.stb.eq(1),
+                       self.cmd.is_cmd.eq(1),
+                       If(self.cmd.ack, NextState("TRCD")),
+                       self.cmd.ras_n.eq(0)
+               )
+               fsm.act("REFRESH",
+                       self.refresh_gnt.eq(precharge_ok),
+                       track_close.eq(1),
+                       self.cmd.is_cmd.eq(1),
+                       If(~self.refresh_req, NextState("REGULAR"))
+               )
+               fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
+               fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD-1)
diff --git a/misoclib/sdram/lasmicon/multiplexer.py b/misoclib/sdram/lasmicon/multiplexer.py
new file mode 100644 (file)
index 0000000..cee6f1f
--- /dev/null
@@ -0,0 +1,214 @@
+from migen.fhdl.std import *
+from migen.genlib.roundrobin import *
+from migen.genlib.misc import optree
+from migen.genlib.fsm import FSM, NextState
+from migen.bank.description import AutoCSR
+
+from misoclib.sdram.lasmicon.perf import Bandwidth
+
+class CommandRequest:
+       def __init__(self, a, ba):
+               self.a = Signal(a)
+               self.ba = Signal(ba)
+               self.cas_n = Signal(reset=1)
+               self.ras_n = Signal(reset=1)
+               self.we_n = Signal(reset=1)
+
+class CommandRequestRW(CommandRequest):
+       def __init__(self, a, ba):
+               CommandRequest.__init__(self, a, ba)
+               self.stb = Signal()
+               self.ack = Signal()
+               self.is_cmd = Signal()
+               self.is_read = Signal()
+               self.is_write = Signal()
+
+class _CommandChooser(Module):
+       def __init__(self, requests):
+               self.want_reads = Signal()
+               self.want_writes = Signal()
+               self.want_cmds = Signal()
+               # NB: cas_n/ras_n/we_n are 1 when stb is inactive
+               self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
+
+               ###
+
+               rr = RoundRobin(len(requests), SP_CE)
+               self.submodules += rr
+
+               self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
+                       for i, req in enumerate(requests)]
+
+               stb = Signal()
+               self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
+               for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
+                       choices = Array(getattr(req, name) for req in requests)
+                       self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
+               for name in ["cas_n", "ras_n", "we_n"]:
+                       # we should only assert those signals when stb is 1
+                       choices = Array(getattr(req, name) for req in requests)
+                       self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
+               self.comb += self.cmd.stb.eq(stb \
+                       & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
+                       & (self.cmd.is_write == self.want_writes))))
+
+               self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
+                       for i, req in enumerate(requests)]
+               self.comb += rr.ce.eq(self.cmd.ack)
+
+class _Steerer(Module):
+       def __init__(self, commands, dfi):
+               ncmd = len(commands)
+               nph = len(dfi.phases)
+               self.sel = [Signal(max=ncmd) for i in range(nph)]
+
+               ###
+
+               def stb_and(cmd, attr):
+                       if not hasattr(cmd, "stb"):
+                               return 0
+                       else:
+                               return cmd.stb & getattr(cmd, attr)
+               for phase, sel in zip(dfi.phases, self.sel):
+                       self.comb += [
+                               phase.cke.eq(1),
+                               phase.cs_n.eq(0)
+                       ]
+                       if hasattr(phase, "odt"):
+                               self.comb += phase.odt.eq(1)
+                       if hasattr(phase, "reset_n"):
+                               self.comb += phase.reset_n.eq(1)
+                       self.sync += [
+                               phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
+                               phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
+                               phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
+                               phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
+                               phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
+                               phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
+                               phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
+                       ]
+
+class Multiplexer(Module, AutoCSR):
+       def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
+               assert(phy_settings.nphases == len(dfi.phases))
+
+               # Command choosing
+               requests = [bm.cmd for bm in bank_machines]
+               choose_cmd = _CommandChooser(requests)
+               choose_req = _CommandChooser(requests)
+               self.comb += [
+                       choose_cmd.want_reads.eq(0),
+                       choose_cmd.want_writes.eq(0)
+               ]
+               if phy_settings.nphases == 1:
+                       self.comb += [
+                               choose_cmd.want_cmds.eq(1),
+                               choose_req.want_cmds.eq(1)
+                       ]
+               self.submodules += choose_cmd, choose_req
+
+               # Command steering
+               nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
+               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)
+               self.submodules += steerer
+
+               # Read/write turnaround
+               read_available = Signal()
+               write_available = Signal()
+               self.comb += [
+                       read_available.eq(optree("|", [req.stb & req.is_read for req in requests])),
+                       write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
+               ]
+
+               def anti_starvation(timeout):
+                       en = Signal()
+                       max_time = Signal()
+                       if timeout:
+                               t = timeout - 1
+                               time = Signal(max=t+1)
+                               self.comb += max_time.eq(time == 0)
+                               self.sync += If(~en,
+                                               time.eq(t)
+                                       ).Elif(~max_time,
+                                               time.eq(time - 1)
+                                       )
+                       else:
+                               self.comb += max_time.eq(0)
+                       return en, max_time
+               read_time_en, max_read_time = anti_starvation(timing_settings.read_time)
+               write_time_en, max_write_time = anti_starvation(timing_settings.write_time)
+
+               # Refresh
+               self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
+               go_to_refresh = Signal()
+               self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
+
+               # Datapath
+               all_rddata = [p.rddata for p in dfi.phases]
+               all_wrdata = [p.wrdata for p in dfi.phases]
+               all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
+               self.comb += [
+                       lasmic.dat_r.eq(Cat(*all_rddata)),
+                       Cat(*all_wrdata).eq(lasmic.dat_w),
+                       Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
+               ]
+
+               # Control FSM
+               fsm = FSM()
+               self.submodules += fsm
+
+               def steerer_sel(steerer, phy_settings, r_w_n):
+                       r = []
+                       for i in range(phy_settings.nphases):
+                               s = steerer.sel[i].eq(STEER_NOP)
+                               if r_w_n == "read":
+                                       if i == phy_settings.rdphase:
+                                               s = steerer.sel[i].eq(STEER_REQ)
+                                       elif i == phy_settings.rdcmdphase:
+                                               s = steerer.sel[i].eq(STEER_CMD)
+                               elif r_w_n == "write":
+                                       if i == phy_settings.wrphase:
+                                               s = steerer.sel[i].eq(STEER_REQ)
+                                       elif i == phy_settings.wrcmdphase:
+                                               s = steerer.sel[i].eq(STEER_CMD)
+                               else:
+                                       raise ValueError
+                               r.append(s)
+                       return r
+
+               fsm.act("READ",
+                       read_time_en.eq(1),
+                       choose_req.want_reads.eq(1),
+                       choose_cmd.cmd.ack.eq(1),
+                       choose_req.cmd.ack.eq(1),
+                       steerer_sel(steerer, phy_settings, "read"),
+                       If(write_available,
+                               # TODO: switch only after several cycles of ~read_available?
+                               If(~read_available | max_read_time, NextState("RTW"))
+                       ),
+                       If(go_to_refresh, NextState("REFRESH"))
+               )
+               fsm.act("WRITE",
+                       write_time_en.eq(1),
+                       choose_req.want_writes.eq(1),
+                       choose_cmd.cmd.ack.eq(1),
+                       choose_req.cmd.ack.eq(1),
+                       steerer_sel(steerer, phy_settings, "write"),
+                       If(read_available,
+                               If(~write_available | max_write_time, NextState("WTR"))
+                       ),
+                       If(go_to_refresh, NextState("REFRESH"))
+               )
+               fsm.act("REFRESH",
+                       steerer.sel[0].eq(STEER_REFRESH),
+                       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("WTR", "READ", timing_settings.tWTR-1)
+               # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
+               fsm.finalize()
+               self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])
+
+               self.submodules.bandwidth = Bandwidth(choose_req.cmd)
diff --git a/misoclib/sdram/lasmicon/perf.py b/misoclib/sdram/lasmicon/perf.py
new file mode 100644 (file)
index 0000000..ec09c79
--- /dev/null
@@ -0,0 +1,44 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+class Bandwidth(Module, AutoCSR):
+       def __init__(self, cmd, period_bits=24):
+               self._r_update = CSR()
+               self._r_nreads = CSRStatus(period_bits)
+               self._r_nwrites = CSRStatus(period_bits)
+
+               ###
+
+               cmd_stb = Signal()
+               cmd_ack = Signal()
+               cmd_is_read = Signal()
+               cmd_is_write = Signal()
+               self.sync += [
+                       cmd_stb.eq(cmd.stb),
+                       cmd_ack.eq(cmd.ack),
+                       cmd_is_read.eq(cmd.is_read),
+                       cmd_is_write.eq(cmd.is_write)
+               ]
+
+               counter = Signal(period_bits)
+               period = Signal()
+               nreads = Signal(period_bits)
+               nwrites = Signal(period_bits)
+               nreads_r = Signal(period_bits)
+               nwrites_r = Signal(period_bits)
+               self.sync += [
+                       Cat(counter, period).eq(counter + 1),
+                       If(period,
+                               nreads_r.eq(nreads),
+                               nwrites_r.eq(nwrites),
+                               nreads.eq(0),
+                               nwrites.eq(0)
+                       ).Elif(cmd_stb & cmd_ack,
+                               If(cmd_is_read, nreads.eq(nreads + 1)),
+                               If(cmd_is_write, nwrites.eq(nwrites + 1)),
+                       ),
+                       If(self._r_update.re,
+                               self._r_nreads.status.eq(nreads_r),
+                               self._r_nwrites.status.eq(nwrites_r)
+                       )
+               ]
diff --git a/misoclib/sdram/lasmicon/refresher.py b/misoclib/sdram/lasmicon/refresher.py
new file mode 100644 (file)
index 0000000..cb59fb8
--- /dev/null
@@ -0,0 +1,68 @@
+from migen.fhdl.std import *
+from migen.genlib.misc import timeline
+from migen.genlib.fsm import FSM
+
+from misoclib.sdram.lasmicon.multiplexer import *
+
+class Refresher(Module):
+       def __init__(self, a, ba, tRP, tREFI, tRFC):
+               self.req = Signal()
+               self.ack = Signal() # 1st command 1 cycle after assertion of ack
+               self.cmd = CommandRequest(a, ba)
+
+               ###
+
+               # Refresh sequence generator:
+               # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
+               seq_start = Signal()
+               seq_done = Signal()
+               self.sync += [
+                       self.cmd.a.eq(2**10),
+                       self.cmd.ba.eq(0),
+                       self.cmd.cas_n.eq(1),
+                       self.cmd.ras_n.eq(1),
+                       self.cmd.we_n.eq(1),
+                       seq_done.eq(0)
+               ]
+               self.sync += timeline(seq_start, [
+                       (1, [
+                               self.cmd.ras_n.eq(0),
+                               self.cmd.we_n.eq(0)
+                       ]),
+                       (1+tRP, [
+                               self.cmd.cas_n.eq(0),
+                               self.cmd.ras_n.eq(0)
+                       ]),
+                       (1+tRP+tRFC, [
+                               seq_done.eq(1)
+                       ])
+               ])
+
+               # Periodic refresh counter
+               counter = Signal(max=tREFI)
+               start = Signal()
+               self.sync += [
+                       start.eq(0),
+                       If(counter == 0,
+                               start.eq(1),
+                               counter.eq(tREFI - 1)
+                       ).Else(
+                               counter.eq(counter - 1)
+                       )
+               ]
+
+               # Control FSM
+               fsm = FSM()
+               self.submodules += fsm
+               fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
+               fsm.act("WAIT_GRANT",
+                       self.req.eq(1),
+                       If(self.ack,
+                               seq_start.eq(1),
+                               NextState("WAIT_SEQ")
+                       )
+               )
+               fsm.act("WAIT_SEQ",
+                       self.req.eq(1),
+                       If(seq_done, NextState("IDLE"))
+               )
diff --git a/misoclib/sdram/lasmicon/test/bankmachine.py b/misoclib/sdram/lasmicon/test/bankmachine.py
new file mode 100644 (file)
index 0000000..a6719cf
--- /dev/null
@@ -0,0 +1,41 @@
+from migen.fhdl.std import *
+from migen.bus.lasmibus import *
+from migen.sim.generic import run_simulation
+
+from misoclib.sdram.lasmicon.bankmachine import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger
+
+def my_generator():
+       for x in range(10):
+               yield True, x
+       for x in range(10):
+               yield False, 128*x
+
+class TB(Module):
+       def __init__(self):
+               self.req = Interface(32, 32, 1,
+                       sdram_timing.req_queue_size, sdram_phy.read_latency, sdram_phy.write_latency)
+               self.submodules.dut = BankMachine(sdram_geom, sdram_timing, 2, 0, self.req)
+               self.submodules.logger = CommandLogger(self.dut.cmd, True)
+               self.generator = my_generator()
+               self.dat_ack_cnt = 0
+
+       def do_simulation(self, selfp):
+               if selfp.req.dat_ack:
+                       self.dat_ack_cnt += 1
+               if selfp.req.req_ack:
+                       try:
+                               we, adr = next(self.generator)
+                       except StopIteration:
+                               selfp.req.stb = 0
+                               if not selfp.req.lock:
+                                       print("data ack count: {0}".format(self.dat_ack_cnt))
+                                       raise StopSimulation
+                               return
+                       selfp.req.adr = adr
+                       selfp.req.we = we
+                       selfp.req.stb = 1
+
+if __name__ == "__main__":
+       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/sdram/lasmicon/test/common.py b/misoclib/sdram/lasmicon/test/common.py
new file mode 100644 (file)
index 0000000..3d60d70
--- /dev/null
@@ -0,0 +1,101 @@
+from fractions import Fraction
+from math import ceil
+
+from migen.fhdl.std import *
+
+from misoclib import sdram
+
+MHz = 1000000
+clk_freq = (83 + Fraction(1, 3))*MHz
+
+clk_period_ns = 1000000000/clk_freq
+def ns(t, margin=True):
+       if margin:
+               t += clk_period_ns/2
+       return ceil(t/clk_period_ns)
+
+sdram_phy = sdram.PhySettings(
+       memtype="DDR",
+       dfi_d=64,
+       nphases=2,
+       rdphase=0,
+       wrphase=1,
+       rdcmdphase=1,
+       wrcmdphase=0,
+       cl=3,
+       read_latency=5,
+       write_latency=0
+)
+
+sdram_geom = sdram.GeomSettings(
+       bank_a=2,
+       row_a=13,
+       col_a=10
+)
+sdram_timing = sdram.TimingSettings(
+       tRP=ns(15),
+       tRCD=ns(15),
+       tWR=ns(15),
+       tWTR=2,
+       tREFI=ns(7800, False),
+       tRFC=ns(70),
+
+       req_queue_size=8,
+       read_time=32,
+       write_time=16
+)
+
+def decode_sdram(ras_n, cas_n, we_n, bank, address):
+       elts = []
+       if not ras_n and cas_n and we_n:
+               elts.append("ACTIVATE")
+               elts.append("BANK " + str(bank))
+               elts.append("ROW " + str(address))
+       elif ras_n and not cas_n and we_n:
+               elts.append("READ\t")
+               elts.append("BANK " + str(bank))
+               elts.append("COL " + str(address))
+       elif ras_n and not cas_n and not we_n:
+               elts.append("WRITE\t")
+               elts.append("BANK " + str(bank))
+               elts.append("COL " + str(address))
+       elif ras_n and cas_n and not we_n:
+               elts.append("BST")
+       elif not ras_n and not cas_n and we_n:
+               elts.append("AUTO REFRESH")
+       elif not ras_n and cas_n and not we_n:
+               elts.append("PRECHARGE")
+               if address & 2**10:
+                       elts.append("ALL")
+               else:
+                       elts.append("BANK " + str(bank))
+       elif not ras_n and not cas_n and not we_n:
+               elts.append("LMR")
+       return elts
+
+class CommandLogger(Module):
+       def __init__(self, cmd, rw=False):
+               self.cmd = cmd
+               if rw:
+                       self.comb += self.cmd.ack.eq(1)
+
+       def do_simulation(self, selfp):
+               elts = ["@" + str(selfp.simulator.cycle_counter)]
+               cmdp = selfp.cmd
+               elts += decode_sdram(cmdp.ras_n, cmdp.cas_n, cmdp.we_n, cmdp.ba, cmdp.a)
+               if len(elts) > 1:
+                       print("\t".join(elts))
+       do_simulation.passive = True
+
+class DFILogger(Module):
+       def __init__(self, dfi):
+               self.dfi = dfi
+
+       def do_simulation(self, selfp):
+               dfip = selfp.dfi
+               for i, p in enumerate(dfip.phases):
+                       elts = ["@" + str(selfp.simulator.cycle_counter) + ":" + str(i)]
+                       elts += decode_sdram(p.ras_n, p.cas_n, p.we_n, p.bank, p.address)
+                       if len(elts) > 1:
+                               print("\t".join(elts))
+       do_simulation.passive = True
diff --git a/misoclib/sdram/lasmicon/test/lasmicon.py b/misoclib/sdram/lasmicon/test/lasmicon.py
new file mode 100644 (file)
index 0000000..e4cd045
--- /dev/null
@@ -0,0 +1,39 @@
+from migen.fhdl.std import *
+from migen.bus.lasmibus import *
+from migen.sim.generic import run_simulation
+
+from misoclib.sdram.lasmicon import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+def my_generator_r(n):
+       for x in range(10):
+               t = TRead(128*n + 48*n*x)
+               yield t
+       print("{0:3}: reads done".format(n))
+
+def my_generator_w(n):
+       for x in range(10):
+               t = TWrite(128*n + 48*n*x, x)
+               yield t
+       print("{0:3}: writes done".format(n))
+
+def my_generator(n):
+       if n % 2:
+               return my_generator_w(n // 2)
+       else:
+               return my_generator_r(n // 2)
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.dut = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+               self.submodules.xbar = lasmibus.Crossbar([self.dut.lasmic], self.dut.nrowbits)
+               self.submodules.logger = DFILogger(self.dut.dfi)
+
+               masters = [self.xbar.get_master() for i in range(6)]
+               self.initiators = [Initiator(my_generator(n), master)
+                       for n, master in enumerate(masters)]
+               self.submodules += self.initiators
+
+if __name__ == "__main__":
+       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/sdram/lasmicon/test/lasmicon_df.py b/misoclib/sdram/lasmicon/test/lasmicon_df.py
new file mode 100644 (file)
index 0000000..d2a4add
--- /dev/null
@@ -0,0 +1,39 @@
+from migen.fhdl.std import *
+from migen.bus import lasmibus
+from migen.actorlib import dma_lasmi
+from migen.sim.generic import run_simulation
+
+from misoclib.sdram.lasmicon import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+               self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
+               self.submodules.logger = DFILogger(self.ctler.dfi)
+               self.submodules.writer = dma_lasmi.Writer(self.xbar.get_master())
+
+               self.comb += self.writer.address_data.stb.eq(1)
+               pl = self.writer.address_data.payload
+               pl.a.reset = 255
+               pl.d.reset = pl.a.reset*2
+               self.sync += If(self.writer.address_data.ack,
+                       pl.a.eq(pl.a + 1),
+                       pl.d.eq(pl.d + 2)
+               )
+               self.open_row = None
+
+       def do_simulation(self, selfp):
+               dfip = selfp.ctler.dfi
+               for p in dfip.phases:
+                       if p.ras_n and not p.cas_n and not p.we_n: # write
+                               d = dfip.phases[0].wrdata | (dfip.phases[1].wrdata << 64)
+                               print(d)
+                               if d != p.address//2 + p.bank*512 + self.open_row*2048:
+                                       print("**** ERROR ****")
+                       elif not p.ras_n and p.cas_n and p.we_n: # activate
+                               self.open_row = p.address
+
+if __name__ == "__main__":
+       run_simulation(TB(), ncycles=3500, vcd_name="my.vcd")
diff --git a/misoclib/sdram/lasmicon/test/lasmicon_wb.py b/misoclib/sdram/lasmicon/test/lasmicon_wb.py
new file mode 100644 (file)
index 0000000..35d18d9
--- /dev/null
@@ -0,0 +1,36 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone, wishbone2lasmi, lasmibus
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from misoclib.sdram.lasmicon import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+l2_size = 8192 # in bytes
+
+def my_generator():
+       for x in range(20):
+               t = TWrite(x, x)
+               yield t
+               print(str(t) + " delay=" + str(t.latency))
+       for x in range(20):
+               t = TRead(x)
+               yield t
+               print(str(t) + " delay=" + str(t.latency))
+       for x in range(20):
+               t = TRead(x+l2_size//4)
+               yield t
+               print(str(t) + " delay=" + str(t.latency))
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+               self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
+               self.submodules.logger = DFILogger(self.ctler.dfi)
+               self.submodules.bridge = wishbone2lasmi.WB2LASMI(l2_size//4, self.xbar.get_master())
+               self.submodules.initiator = wishbone.Initiator(my_generator())
+               self.submodules.conn = wishbone.InterconnectPointToPoint(self.initiator.bus, self.bridge.wishbone)
+
+if __name__ == "__main__":
+       run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/sdram/lasmicon/test/refresher.py b/misoclib/sdram/lasmicon/test/refresher.py
new file mode 100644 (file)
index 0000000..6437a78
--- /dev/null
@@ -0,0 +1,45 @@
+from random import Random
+
+from migen.fhdl.std import *
+from migen.sim.generic import run_simulation
+
+from misoclib.sdram.lasmicon.refresher import *
+
+from common import CommandLogger
+
+class Granter(Module):
+       def __init__(self, req, ack):
+               self.req = req
+               self.ack = ack
+               self.state = 0
+               self.prng = Random(92837)
+
+       def do_simulation(self, selfp):
+               elts = ["@" + str(selfp.simulator.cycle_counter)]
+
+               if self.state == 0:
+                       if selfp.req:
+                               elts.append("Refresher requested access")
+                               self.state = 1
+               elif self.state == 1:
+                       if self.prng.randrange(0, 5) == 0:
+                               elts.append("Granted access to refresher")
+                               selfp.ack = 1
+                               self.state = 2
+               elif self.state == 2:
+                       if not selfp.req:
+                               elts.append("Refresher released access")
+                               selfp.ack = 0
+                               self.state = 0
+
+               if len(elts) > 1:
+                       print("\t".join(elts))
+
+class TB(Module):
+       def __init__(self):
+               self.submodules.dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5)
+               self.submodules.logger = CommandLogger(self.dut.cmd)
+               self.submodules.granter = Granter(self.dut.req, self.dut.ack)
+
+if __name__ == "__main__":
+       run_simulation(TB(), ncycles=400)
diff --git a/misoclib/sdram/minicon/__init__.py b/misoclib/sdram/minicon/__init__.py
new file mode 100755 (executable)
index 0000000..6cd3674
--- /dev/null
@@ -0,0 +1,203 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.bus import dfi as dfibus
+from migen.genlib.fsm import FSM, NextState
+
+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
+               self.address_align = address_align
+
+       def row(self, address):
+               split = self.bank_a + self.col_a
+               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
+               if isinstance(address, int):
+                       return (address & mask) >> shift
+               else:
+                       return address[self.col_a:self.col_a+self.bank_a]
+
+       def col(self, address):
+               split = self.col_a
+               if isinstance(address, int):
+                       return (address & (2**split - 1)) << self.address_align
+               else:
+                       return Cat(Replicate(0, self.address_align), address[:split])
+
+class Minicon(Module):
+       def __init__(self, phy_settings, geom_settings, timing_settings):
+               if phy_settings.memtype in ["SDR"]:
+                       burst_length = phy_settings.nphases*1 # command multiplication*SDR
+               elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
+                       burst_length = phy_settings.nphases*2 # command multiplication*DDR
+               address_align = log2_int(burst_length)
+
+               nbanks = range(2**geom_settings.bank_a)
+               A10_ENABLED = 0
+               COLUMN      = 1
+               ROW         = 2
+               rdphase = phy_settings.rdphase
+               wrphase = phy_settings.wrphase
+               rdcmdphase = phy_settings.rdcmdphase
+               wrcmdphase = phy_settings.wrcmdphase
+
+               self.dfi = dfi = dfibus.Interface(geom_settings.mux_a,
+                               geom_settings.bank_a,
+                               phy_settings.dfi_d,
+                               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)
+               req_addr = Signal(geom_settings.col_a + geom_settings.bank_a + geom_settings.row_a)
+               refresh_req = Signal()
+               refresh_ack = Signal()
+               wb_access = Signal()
+               refresh_counter = Signal(max=timing_settings.tREFI+1)
+               hit = Signal()
+               row_open = Signal()
+               row_closeall = Signal()
+               addr_sel = Signal(max=3, reset=A10_ENABLED)
+               has_curbank_openrow = Signal()
+               cl_counter = Signal(max=phy_settings.cl+1)
+
+               # Extra bit means row is active when asserted
+               self.openrow = openrow = Array(Signal(geom_settings.row_a + 1) for b in nbanks)
+
+               self.comb += [
+                       hit.eq(openrow[slicer.bank(bus.adr)] == Cat(slicer.row(bus.adr), 1)),
+                       has_curbank_openrow.eq(openrow[slicer.bank(bus.adr)][-1]),
+                       wb_access.eq(bus.stb & bus.cyc),
+                       bus.dat_r.eq(Cat([phase.rddata for phase in dfi.phases])),
+                       Cat([phase.wrdata for phase in dfi.phases]).eq(bus.dat_w),
+                       Cat([phase.wrdata_mask for phase in dfi.phases]).eq(~bus.sel),
+               ]
+
+               for phase in dfi.phases:
+                       self.comb += [
+                               phase.cke.eq(1),
+                               phase.address.eq(Array([2**10, slicer.col(bus.adr), slicer.row(bus.adr)])[addr_sel]),
+                               If(wb_access,
+                                       phase.bank.eq(slicer.bank(bus.adr))
+                               )
+                       ]
+                       phase.cs_n.reset = 0
+                       phase.ras_n.reset = 1
+                       phase.cas_n.reset = 1
+                       phase.we_n.reset = 1
+
+               for b in nbanks:
+                       self.sync += [
+                               If(row_open & (b == slicer.bank(bus.adr)),
+                                       openrow[b].eq(Cat(slicer.row(bus.adr), 1)),
+                               ),
+                               If(row_closeall,
+                                       openrow[b][-1].eq(0)
+                               )
+                       ]
+
+               self.sync += [
+                       If(refresh_ack,
+                               refresh_req.eq(0)
+                       ),
+                       If(refresh_counter == 0,
+                               refresh_counter.eq(timing_settings.tREFI),
+                               refresh_req.eq(1)
+                       ).Else(
+                               refresh_counter.eq(refresh_counter - 1)
+                       )
+               ]
+
+               fsm = FSM()
+               self.submodules += fsm
+               fsm.act("IDLE",
+                       If(refresh_req,
+                               NextState("PRECHARGEALL")
+                       ).Elif(wb_access,
+                                If(hit & bus.we,
+                                        NextState("WRITE"),
+                                ),
+                                If(hit & ~bus.we,
+                                        NextState("READ"),
+                                ),
+                                If(has_curbank_openrow & ~hit,
+                                        NextState("PRECHARGE")
+                                ),
+                                If(~has_curbank_openrow,
+                                        NextState("ACTIVATE")
+                                ),
+                        )
+               )
+               fsm.act("READ",
+                       # We output Column bits at address pins so that A10 is 0
+                       # to disable row Auto-Precharge
+                       dfi.phases[rdcmdphase].ras_n.eq(1),
+                       dfi.phases[rdcmdphase].cas_n.eq(0),
+                       dfi.phases[rdcmdphase].we_n.eq(1),
+                       dfi.phases[rdphase].rddata_en.eq(1),
+                       addr_sel.eq(COLUMN),
+                       NextState("READ-WAIT-ACK"),
+               )
+               fsm.act("READ-WAIT-ACK",
+                       If(dfi.phases[rdphase].rddata_valid,
+                               NextState("IDLE"),
+                               bus.ack.eq(1)
+                       ).Else(
+                               NextState("READ-WAIT-ACK")
+                       )
+               )
+               fsm.act("WRITE",
+                       dfi.phases[wrcmdphase].ras_n.eq(1),
+                       dfi.phases[wrcmdphase].cas_n.eq(0),
+                       dfi.phases[wrcmdphase].we_n.eq(0),
+                       dfi.phases[wrphase].wrdata_en.eq(1),
+                       addr_sel.eq(COLUMN),
+                       bus.ack.eq(1),
+                       NextState("IDLE")
+               )
+               fsm.act("PRECHARGEALL",
+                       row_closeall.eq(1),
+                       dfi.phases[rdphase].ras_n.eq(0),
+                       dfi.phases[rdphase].cas_n.eq(1),
+                       dfi.phases[rdphase].we_n.eq(0),
+                       addr_sel.eq(A10_ENABLED),
+                       NextState("PRE-REFRESH")
+               )
+               fsm.act("PRECHARGE",
+                       # Notes:
+                       # 1. we are presenting the column address so that A10 is low
+                       # 2. since we always go to the ACTIVATE state, we do not need
+                       # to assert row_close because it will be reopen right after.
+                       NextState("TRP"),
+                       addr_sel.eq(COLUMN),
+                       dfi.phases[rdphase].ras_n.eq(0),
+                       dfi.phases[rdphase].cas_n.eq(1),
+                       dfi.phases[rdphase].we_n.eq(0)
+               )
+               fsm.act("ACTIVATE",
+                       row_open.eq(1),
+                       NextState("TRCD"),
+                       dfi.phases[rdphase].ras_n.eq(0),
+                       dfi.phases[rdphase].cas_n.eq(1),
+                       dfi.phases[rdphase].we_n.eq(1),
+                       addr_sel.eq(ROW)
+               )
+               fsm.act("REFRESH",
+                       refresh_ack.eq(1),
+                       dfi.phases[rdphase].ras_n.eq(0),
+                       dfi.phases[rdphase].cas_n.eq(0),
+                       dfi.phases[rdphase].we_n.eq(1),
+                       NextState("POST-REFRESH")
+               )
+               fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
+               fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP-1)
+               fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD-1)
+               fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC-1)
diff --git a/misoclib/sdram/minicon/tb/minicontb.py b/misoclib/sdram/minicon/tb/minicontb.py
new file mode 100755 (executable)
index 0000000..325da01
--- /dev/null
@@ -0,0 +1,192 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import TRead, TWrite
+from migen.bus import wishbone
+from migen.sim.generic import Simulator
+from migen.sim import icarus
+from mibuild.platforms import papilio_pro as board
+from misoclib import sdram
+from misoclib.sdram.minicon import Minicon
+from misoclib.sdram.phy import gensdrphy
+from itertools import chain
+from os.path import isfile
+import sys
+
+clk_freq = 80000000
+
+from math import ceil
+
+def ns(t, margin=True):
+       clk_period_ns = 1000000000/clk_freq
+       if margin:
+               t += clk_period_ns/2
+       return ceil(t/clk_period_ns)
+
+class MiniconTB(Module):
+       def __init__(self, sdrphy, dfi, sdram_geom, sdram_timing, pads, sdram_clk):
+
+               self.clk_freq = 80000000
+               phy_settings = sdrphy.phy_settings
+               rdphase = phy_settings.rdphase
+               self.submodules.slave = Minicon(phy_settings, sdram_geom, sdram_timing)
+
+               self.submodules.tap = wishbone.Tap(self.slave.bus)
+               self.submodules.dc = dc = wishbone.DownConverter(32, phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
+               self.submodules.master = wishbone.Initiator(self.genxfers(), bus=dc.wishbone_i)
+               self.submodules.intercon = wishbone.InterconnectPointToPoint(dc.wishbone_o, self.slave.bus)
+
+               self.submodules.sdrphy = self.sdrphy = sdrphy
+               self.dfi = dfi
+               self.pads = pads
+
+               self.specials += Instance("mt48lc4m16a2",
+                       io_Dq=pads.dq,
+                       i_Addr=pads.a,
+                       i_Ba=pads.ba,
+                       i_Clk=ClockSignal(),
+                       i_Cke=pads.cke,
+                       i_Cs_n=pads.cs_n,
+                       i_Ras_n=pads.ras_n,
+                       i_Cas_n=pads.cas_n,
+                       i_We_n=pads.we_n,
+                       i_Dqm=pads.dm
+               )
+
+       def genxfers(self):
+               cycle = 0
+               for a in chain(range(4),range(256,260),range(1024,1028)):
+                       t = TRead(a)
+                       yield t
+                       print("read {} in {} cycles".format(t.data, t.latency))
+               for a in chain(range(4),range(256,260),range(1024,1028),range(4096,4100)):
+                       t = TWrite(a, 0xaa55aa55+cycle)
+                       cycle += 1
+                       yield t
+                       print("read {} in {} cycles".format(t.data, t.latency))
+               for a in chain(range(4),range(256,260),range(1024,1028),range(4096,4100)):
+                       t = TRead(a)
+                       yield t
+                       print("read {} in {} cycles".format(t.data, t.latency))
+
+       def gen_simulation(self, selfp):
+               dfi = selfp.dfi
+               phy = self.sdrphy
+               rdphase = phy.phy_settings.rdphase
+               cycle = 0
+
+               while True:
+                       yield
+
+class MyTopLevel:
+       def __init__(self, vcd_name=None, vcd_level=1,
+         top_name="top", dut_type="dut", dut_name="dut",
+         cd_name="sys", clk_period=10):
+               self.vcd_name = vcd_name
+               self.vcd_level = vcd_level
+               self.top_name = top_name
+               self.dut_type = dut_type
+               self.dut_name = dut_name
+
+               self._cd_name = cd_name
+               self._clk_period = clk_period
+
+               cd = ClockDomain(self._cd_name)
+               cd_ps = ClockDomain("sys_ps")
+               self.clock_domains = [cd, cd_ps]
+               self.ios = {cd.clk, cd.rst, cd_ps.clk}
+
+       def get(self, sockaddr):
+               template1 = """`timescale 1ns / 1ps
+
+module {top_name}();
+
+reg {clk_name};
+reg {rst_name};
+reg sys_ps_clk;
+
+initial begin
+       {rst_name} <= 1'b1;
+       @(posedge {clk_name});
+       {rst_name} <= 1'b0;
+end
+
+always begin
+       {clk_name} <= 1'b0;
+       #{hclk_period};
+       {clk_name} <= 1'b1;
+       #{hclk_period};
+end
+
+always @(posedge {clk_name} or negedge {clk_name})
+       sys_ps_clk <= #({hclk_period}*2-3) {clk_name};
+
+{dut_type} {dut_name}(
+       .{rst_name}({rst_name}),
+       .{clk_name}({clk_name}),
+       .sys_ps_clk(sys_ps_clk)
+);
+
+initial $migensim_connect("{sockaddr}");
+always @(posedge {clk_name}) $migensim_tick;
+"""
+               template2 = """
+initial begin
+       $dumpfile("{vcd_name}");
+       $dumpvars({vcd_level}, {dut_name});
+end
+"""
+               r = template1.format(top_name=self.top_name,
+                       dut_type=self.dut_type,
+                       dut_name=self.dut_name,
+                       clk_name=self._cd_name + "_clk",
+                       rst_name=self._cd_name + "_rst",
+                       hclk_period=str(self._clk_period/2),
+                       sockaddr=sockaddr)
+               if self.vcd_name is not None:
+                       r += template2.format(vcd_name=self.vcd_name,
+                               vcd_level=str(self.vcd_level),
+                               dut_name=self.dut_name)
+               r += "\nendmodule"
+               return r
+               
+
+if __name__ == "__main__":
+
+       plat = board.Platform()
+
+       sdram_geom = sdram.GeomSettings(
+               bank_a=2,
+               row_a=12,
+               col_a=8
+       )
+
+       sdram_timing = sdram.TimingSettings(
+               tRP=ns(15),
+               tRCD=ns(15),
+               tWR=ns(14),
+               tWTR=2,
+               tREFI=ns(64*1000*1000/4096, False),
+               tRFC=ns(66),
+               req_queue_size=8,
+               read_time=32,
+               write_time=16
+       )
+
+       sdram_pads = plat.request("sdram")
+       sdram_clk = plat.request("sdram_clock")
+
+       sdrphy = gensdrphy.GENSDRPHY(sdram_pads)
+
+# This sets CL to 2 during LMR done on 1st cycle
+       sdram_pads.a.reset = 1<<5
+
+       s = MiniconTB(sdrphy, sdrphy.dfi, sdram_geom, sdram_timing, pads=sdram_pads, sdram_clk=sdram_clk)
+
+       extra_files = [ "sdram_model/mt48lc4m16a2.v" ]
+
+       if not isfile(extra_files[0]):
+               print("ERROR: You need to download Micron Verilog simulation model for MT48LC4M16A2 and put it in sdram_model/mt48lc4m16a2.v")
+               print("File can be downloaded from this URL: http://www.micron.com/-/media/documents/products/sim%20model/dram/dram/4054mt48lc4m16a2.zip")
+               sys.exit(1)
+
+       with Simulator(s, MyTopLevel("top.vcd", clk_period=int(1/0.08)), icarus.Runner(extra_files=extra_files, keep_files=True)) as sim:
+               sim.run(5000)
diff --git a/misoclib/sdram/phy/gensdrphy.py b/misoclib/sdram/phy/gensdrphy.py
new file mode 100644 (file)
index 0000000..9abd1d0
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# 1:1 frequency-ratio Generic SDR PHY
+#
+# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
+# not use vendor-dependent code, it can also be used on other architectures.
+#
+# The PHY needs 2 Clock domains:
+#  - sys_clk    : The System Clock domain
+#  - sys_clk_ps : The System Clock domain with its phase shifted
+#                 (-3ns on C4@100MHz)
+#
+# Assert dfi_wrdata_en and present the data
+# on dfi_wrdata_mask/dfi_wrdata in the same
+# cycle as the write command.
+#
+# Assert dfi_rddata_en in the same cycle as the read
+# command. The data will come back on dfi_rddata
+# 4 cycles later, along with the assertion of
+# dfi_rddata_valid.
+#
+# This PHY only supports CAS Latency 2.
+#
+
+from migen.fhdl.std import *
+from migen.bus.dfi import *
+from migen.genlib.record import *
+from migen.fhdl.specials import *
+
+from misoclib import sdram
+
+class GENSDRPHY(Module):
+       def __init__(self, pads):
+               a = flen(pads.a)
+               ba = flen(pads.ba)
+               d = flen(pads.dq)
+
+               self.phy_settings = sdram.PhySettings(
+                       memtype="SDR",
+                       dfi_d=d,
+                       nphases=1,
+                       rdphase=0,
+                       wrphase=0,
+                       rdcmdphase=0,
+                       wrcmdphase=0,
+                       cl=2,
+                       read_latency=4,
+                       write_latency=0
+               )
+
+               self.dfi = Interface(a, ba, d)
+
+               ###
+
+               #
+               # Command/address
+               #
+               self.sync += [
+                       pads.a.eq(self.dfi.p0.address),
+                       pads.ba.eq(self.dfi.p0.bank),
+                       pads.cke.eq(self.dfi.p0.cke),
+                       pads.cas_n.eq(self.dfi.p0.cas_n),
+                       pads.ras_n.eq(self.dfi.p0.ras_n),
+                       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),
+
+               #
+               # DQ/DQS/DM data
+               #
+               sd_dq_out = Signal(d)
+               drive_dq = Signal()
+               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,
+                               pads.dm.eq(self.dfi.p0.wrdata_mask)
+                       ).Else(
+                               pads.dm.eq(0)
+                       )
+               sd_dq_in_ps = Signal(d)
+               self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
+               self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)
+
+               #
+               # DQ/DM control
+               #
+               d_dfi_wrdata_en = Signal()
+               self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en)
+               self.comb += drive_dq.eq(d_dfi_wrdata_en)
+
+               rddata_sr = Signal(4)
+               self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3])
+               self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))
diff --git a/misoclib/sdram/phy/initsequence.py b/misoclib/sdram/phy/initsequence.py
new file mode 100644 (file)
index 0000000..32ccd77
--- /dev/null
@@ -0,0 +1,225 @@
+from migen.fhdl.std import log2_int
+
+def get_sdram_phy_header(sdram_phy):
+       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"
+
+       nphases = sdram_phy.phy_settings.nphases
+       r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
+
+       r += "static void cdelay(int i);\n"
+
+       # commands_px functions
+       for n in range(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"
+
+       # 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)
+
+#define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X)
+#define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X)
+
+#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"
+
+       #
+       # sdrrd/sdrwr functions utilities
+       #
+       r += "#define DFII_PIX_DATA_SIZE CSR_DFII_PI0_WRDATA_SIZE\n"
+       dfii_pix_wrdata_addr = []
+       for n in range(nphases):
+               dfii_pix_wrdata_addr.append("CSR_DFII_PI{n}_WRDATA_ADDR".format(n=n))
+       r += """
+const unsigned int dfii_pix_wrdata_addr[{n}] = {{
+       {dfii_pix_wrdata_addr}
+}};
+""".format(n=nphases, dfii_pix_wrdata_addr=",\n\t".join(dfii_pix_wrdata_addr))
+
+       dfii_pix_rddata_addr = []
+       for n in range(nphases):
+               dfii_pix_rddata_addr.append("CSR_DFII_PI{n}_RDDATA_ADDR".format(n=n))
+       r += """
+const unsigned int dfii_pix_rddata_addr[{n}] = {{
+       {dfii_pix_rddata_addr}
+}};
+""".format(n=nphases, dfii_pix_rddata_addr=",\n\t".join(dfii_pix_rddata_addr))
+       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",
+               "UNRESET"       : "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
+               "CKE"           : "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
+       }
+
+       cl = sdram_phy.phy_settings.cl
+
+       if sdram_phy.phy_settings.memtype == "SDR":
+               bl = sdram_phy.phy_settings.nphases
+               mr = log2_int(bl) + (cl << 4)
+               reset_dll = 1 << 8
+
+               init_sequence = [
+                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+                       ("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"], 20000),
+                       ("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"], 20000),
+                       ("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
+               wr = 2
+               mr = log2_int(bl) + (cl << 4) + (wr << 9)
+               emr = 0
+               emr2 = 0
+               emr3 = 0
+               reset_dll = 1 << 8
+               ocd = 7 << 7
+
+               init_sequence = [
+                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+                       ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+                       ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
+                       ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 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),
+                       ("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),
+               ]
+       elif sdram_phy.phy_settings.memtype == "DDR3":
+               bl = 2*sdram_phy.phy_settings.nphases
+               if bl != 8:
+                       raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
+
+               def format_mr0(cl, wr, dll_reset):
+                       cl_to_mr0 = {
+                               5 : 0b0010,
+                               6 : 0b0100,
+                               7 : 0b0110,
+                               8 : 0b1000,
+                               9 : 0b1010,
+                               10: 0b1100,
+                               11: 0b1110,
+                               12: 0b0001,
+                               13: 0b0011,
+                               14: 0b0101
+                       }
+                       wr_to_mr0 = {
+                               16: 0b000,
+                               5 : 0b001,
+                               6 : 0b010,
+                               7 : 0b011,
+                               8 : 0b100,
+                               10: 0b101,
+                               12: 0b110,
+                               14: 0b111
+                       }
+                       mr0 = (cl_to_mr0[cl] & 1) << 2
+                       mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
+                       mr0 |= dll_reset << 8
+                       mr0 |= wr_to_mr0[wr] << 9
+                       return mr0
+
+               def format_mr1(output_drive_strength, rtt_nom):
+                       mr1 = ((output_drive_strength >> 0) & 1) << 1
+                       mr1 |= ((output_drive_strength >> 1) & 1) << 5
+                       mr1 |= ((rtt_nom >> 0) & 1) << 2
+                       mr1 |= ((rtt_nom >> 1) & 1) << 6
+                       mr1 |= ((rtt_nom >> 2) & 1) << 9
+                       return mr1
+
+               def format_mr2(cwl, rtt_wr):
+                       mr2 = (cwl-5) << 3
+                       mr2 |= rtt_wr << 9
+                       return mr2
+
+               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)
+               mr2 = format_mr2(sdram_phy.phy_settings.cwl, 2) # Rtt(WR) RZQ/4
+               mr3 = 0
+
+               init_sequence = [
+                       ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
+                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
+                       ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0),
+                       ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
+                       ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
+                       ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
+                       ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
+               ]
+
+               # the value of MR1 needs to be modified during write leveling
+               r += "#define DDR3_MR1 {}\n\n".format(mr1)
+       else:
+               raise NotImplementedError("Unsupported memory type: "+sdram_phy.phy_settings.memtype)
+
+       r += "static void init_sequence(void)\n{\n"
+       for comment, a, ba, cmd, delay in init_sequence:
+               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 cmd[:12] == "DFII_CONTROL":
+                       r += "\tdfii_control_write({0});\n".format(cmd)
+               else:
+                       r += "\tcommand_p0({0});\n".format(cmd)
+               if delay:
+                       r += "\tcdelay({0:d});\n".format(delay)
+               r += "\n"
+       r += "}\n"
+
+       r += "#endif\n"
+
+       return r
diff --git a/misoclib/sdram/phy/k7ddrphy.py b/misoclib/sdram/phy/k7ddrphy.py
new file mode 100644 (file)
index 0000000..5e83f16
--- /dev/null
@@ -0,0 +1,291 @@
+# tCK=5ns CL=7 CWL=6
+
+from migen.fhdl.std import *
+from migen.bus.dfi import *
+from migen.bank.description import *
+
+from misoclib import sdram
+
+class K7DDRPHY(Module, AutoCSR):
+       def __init__(self, pads, memtype):
+               a = flen(pads.a)
+               ba = flen(pads.ba)
+               d = flen(pads.dq)
+               nphases = 4
+
+               self._r_wlevel_en = CSRStorage()
+               self._r_wlevel_strobe = CSR()
+               self._r_dly_sel = CSRStorage(d//8)
+               self._r_rdly_dq_rst = CSR()
+               self._r_rdly_dq_inc = CSR()
+               self._r_rdly_dq_bitslip = CSR()
+               self._r_wdly_dq_rst = CSR()
+               self._r_wdly_dq_inc = CSR()
+               self._r_wdly_dqs_rst = CSR()
+               self._r_wdly_dqs_inc = CSR()
+
+               self.phy_settings = sdram.PhySettings(
+                       memtype=memtype,
+                       dfi_d=2*d,
+                       nphases=nphases,
+                       rdphase=0,
+                       wrphase=2,
+                       rdcmdphase=1,
+                       wrcmdphase=0,
+                       cl=7,
+                       cwl=6,
+                       read_latency=6,
+                       write_latency=2
+               )
+
+               self.dfi = Interface(a, ba, self.phy_settings.dfi_d, nphases)
+
+               ###
+
+               # Clock
+               sd_clk_se = Signal()
+               self.specials += [
+                       Instance("OSERDESE2",
+                               p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                               p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                               p_SERDES_MODE="MASTER",
+
+                               o_OQ=sd_clk_se,
+                               i_OCE=1,
+                               i_RST=ResetSignal(),
+                               i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                               i_D1=0, i_D2=1, i_D3=0, i_D4=1,
+                               i_D5=0, i_D6=1, i_D7=0, i_D8=1
+                       ),
+                       Instance("OBUFDS",
+                               i_I=sd_clk_se,
+                               o_O=pads.clk_p,
+                               o_OB=pads.clk_n
+                       )
+               ]
+
+               # Addresses and commands
+               for i in range(a):
+                       self.specials += \
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OQ=pads.a[i],
+                                       i_OCE=1,
+                                       i_RST=ResetSignal(),
+                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                                       i_D1=self.dfi.phases[0].address[i], i_D2=self.dfi.phases[0].address[i],
+                                       i_D3=self.dfi.phases[1].address[i], i_D4=self.dfi.phases[1].address[i],
+                                       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):
+                       self.specials += \
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OQ=pads.ba[i],
+                                       i_OCE=1,
+                                       i_RST=ResetSignal(),
+                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                                       i_D1=self.dfi.phases[0].bank[i], i_D2=self.dfi.phases[0].bank[i],
+                                       i_D3=self.dfi.phases[1].bank[i], i_D4=self.dfi.phases[1].bank[i],
+                                       i_D5=self.dfi.phases[2].bank[i], i_D6=self.dfi.phases[2].bank[i],
+                                       i_D7=self.dfi.phases[3].bank[i], i_D8=self.dfi.phases[3].bank[i]
+                               )
+               for name in "ras_n", "cas_n", "we_n", "cs_n", "cke", "odt", "reset_n":
+                       self.specials += \
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OQ=getattr(pads, name),
+                                       i_OCE=1,
+                                       i_RST=ResetSignal(),
+                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                                       i_D1=getattr(self.dfi.phases[0], name), i_D2=getattr(self.dfi.phases[0], name),
+                                       i_D3=getattr(self.dfi.phases[1], name), i_D4=getattr(self.dfi.phases[1], name),
+                                       i_D5=getattr(self.dfi.phases[2], name), i_D6=getattr(self.dfi.phases[2], name),
+                                       i_D7=getattr(self.dfi.phases[3], name), i_D8=getattr(self.dfi.phases[3], name)
+                               )
+
+               # DQS and DM
+               oe_dqs = Signal()
+               dqs_serdes_pattern = Signal(8)
+               self.comb += \
+                       If(self._r_wlevel_en.storage,
+                               If(self._r_wlevel_strobe.re,
+                                       dqs_serdes_pattern.eq(0b00000001)
+                               ).Else(
+                                       dqs_serdes_pattern.eq(0b00000000)
+                               )
+                       ).Else(
+                               dqs_serdes_pattern.eq(0b01010101)
+                       )
+               for i in range(d//8):
+                       dm_o_nodelay = Signal()
+                       self.specials += \
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OQ=dm_o_nodelay,
+                                       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]
+                               )
+                       self.specials += \
+                               Instance("ODELAYE2",
+                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
+                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
+                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0,
+
+                                       i_C=ClockSignal(),
+                                       i_LD=self._r_dly_sel.storage[i] & self._r_wdly_dq_rst.re,
+                                       i_CE=self._r_dly_sel.storage[i] & self._r_wdly_dq_inc.re,
+                                       i_LDPIPEEN=0, i_INC=1,
+
+                                       o_ODATAIN=dm_o_nodelay, o_DATAOUT=pads.dm[i]
+                               )
+
+                       dqs_nodelay = Signal()
+                       dqs_delayed = Signal()
+                       dqs_t = Signal()
+                       self.specials += [
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OFB=dqs_nodelay, o_TQ=dqs_t,
+                                       i_OCE=1, i_TCE=1,
+                                       i_RST=ResetSignal(),
+                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                                       i_D1=dqs_serdes_pattern[0], i_D2=dqs_serdes_pattern[1],
+                                       i_D3=dqs_serdes_pattern[2], i_D4=dqs_serdes_pattern[3],
+                                       i_D5=dqs_serdes_pattern[4], i_D6=dqs_serdes_pattern[5],
+                                       i_D7=dqs_serdes_pattern[6], i_D8=dqs_serdes_pattern[7],
+                                       i_T1=~oe_dqs
+                               ),
+                               Instance("ODELAYE2",
+                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
+                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
+                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=6,
+
+                                       i_C=ClockSignal(),
+                                       i_LD=self._r_dly_sel.storage[i] & self._r_wdly_dqs_rst.re,
+                                       i_CE=self._r_dly_sel.storage[i] & self._r_wdly_dqs_inc.re,
+                                       i_LDPIPEEN=0, i_INC=1,
+
+                                       o_ODATAIN=dqs_nodelay, o_DATAOUT=dqs_delayed
+                               ),
+                               Instance("OBUFTDS",
+                                       i_I=dqs_delayed, i_T=dqs_t,
+                                       o_O=pads.dqs_p[i], o_OB=pads.dqs_n[i]
+                               )
+                       ]
+
+               # DQ
+               oe_dq = Signal()
+               for i in range(d):
+                       dq_o_nodelay = Signal()
+                       dq_o_delayed = Signal()
+                       dq_i_nodelay = Signal()
+                       dq_i_delayed = Signal()
+                       dq_t = Signal()
+                       self.specials += [
+                               Instance("OSERDESE2",
+                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
+                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
+                                       p_SERDES_MODE="MASTER",
+
+                                       o_OQ=dq_o_nodelay, o_TQ=dq_t,
+                                       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_T1=~oe_dq
+                               ),
+                               Instance("ISERDESE2",
+                                       p_DATA_WIDTH=8, p_DATA_RATE="DDR",
+                                       p_SERDES_MODE="MASTER", p_INTERFACE_TYPE="NETWORKING",
+                                       p_NUM_CE=1, p_IOBDELAY="IFD",
+
+                                       i_DDLY=dq_i_delayed,
+                                       i_CE1=1,
+                                       i_RST=ResetSignal() | (self._r_dly_sel.storage[i//8] & self._r_wdly_dq_rst.re),
+                                       i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
+                                       i_BITSLIP=self._r_dly_sel.storage[i//8] & self._r_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]
+                               ),
+                               Instance("ODELAYE2",
+                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
+                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
+                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0,
+
+                                       i_C=ClockSignal(),
+                                       i_LD=self._r_dly_sel.storage[i//8] & self._r_wdly_dq_rst.re,
+                                       i_CE=self._r_dly_sel.storage[i//8] & self._r_wdly_dq_inc.re,
+                                       i_LDPIPEEN=0, i_INC=1,
+
+                                       o_ODATAIN=dq_o_nodelay, o_DATAOUT=dq_o_delayed
+                               ),
+                               Instance("IDELAYE2",
+                                       p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
+                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
+                                       p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=6,
+
+                                       i_C=ClockSignal(),
+                                       i_LD=self._r_dly_sel.storage[i//8] & self._r_rdly_dq_rst.re,
+                                       i_CE=self._r_dly_sel.storage[i//8] & self._r_rdly_dq_inc.re,
+                                       i_LDPIPEEN=0, i_INC=1,
+
+                                       i_IDATAIN=dq_i_nodelay, o_DATAOUT=dq_i_delayed
+                               ),
+                               Instance("IOBUF",
+                                       i_I=dq_o_delayed, o_O=dq_i_nodelay, i_T=dq_t,
+                                       io_IO=pads.dq[i]
+                               )
+                       ]
+
+               # Flow control
+               #
+               # total read latency = 6:
+               #  2 cycles through OSERDESE2
+               #  2 cycles CAS
+               #  2 cycles through ISERDESE2
+               rddata_en = self.dfi.phases[self.phy_settings.rdphase].rddata_en
+               for i in range(5):
+                       n_rddata_en = Signal()
+                       self.sync += n_rddata_en.eq(rddata_en)
+                       rddata_en = n_rddata_en
+               self.sync += [phase.rddata_valid.eq(rddata_en | self._r_wlevel_en.storage)
+                       for phase in self.dfi.phases]
+
+               oe = Signal()
+               last_wrdata_en = Signal(4)
+               wrphase = self.dfi.phases[self.phy_settings.wrphase]
+               self.sync += last_wrdata_en.eq(Cat(wrphase.wrdata_en, last_wrdata_en[:3]))
+               self.comb += oe.eq(last_wrdata_en[1] | last_wrdata_en[2] | last_wrdata_en[3])
+               self.sync += \
+                       If(self._r_wlevel_en.storage,
+                               oe_dqs.eq(1), oe_dq.eq(0)
+                       ).Else(
+                               oe_dqs.eq(oe), oe_dq.eq(oe)
+                       )
diff --git a/misoclib/sdram/phy/s6ddrphy.py b/misoclib/sdram/phy/s6ddrphy.py
new file mode 100644 (file)
index 0000000..0dd3837
--- /dev/null
@@ -0,0 +1,358 @@
+# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for Spartan-6
+#
+# Assert dfi_wrdata_en and present the data
+# on dfi_wrdata_mask/dfi_wrdata in the same
+# cycle as the write command.
+#
+# Assert dfi_rddata_en in the same cycle as the read
+# command. The data will come back on dfi_rddata
+# 5 cycles later, along with the assertion
+# of dfi_rddata_valid.
+#
+# This PHY only supports CAS Latency 3.
+# Read commands must be sent on phase 0.
+# Write commands must be sent on phase 1.
+#
+
+from migen.fhdl.std import *
+from migen.bus.dfi import *
+from migen.genlib.record import *
+
+from misoclib import sdram
+
+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)
+               nphases = 2
+
+               self.phy_settings = sdram.PhySettings(
+                       memtype=memtype,
+                       dfi_d=2*d,
+                       nphases=nphases,
+                       rdphase=0,
+                       wrphase=1,
+                       rdcmdphase=1,
+                       wrcmdphase=0,
+                       cl=3,
+                       read_latency=5,
+                       write_latency=0
+               )
+
+               self.dfi = Interface(a, ba, self.phy_settings.dfi_d, nphases)
+               self.clk4x_wr_strb = Signal()
+               self.clk4x_rd_strb = Signal()
+
+               ###
+
+               # sys_clk           : system clk, used for dfi interface
+               # sdram_half_clk    : half rate sdram clk
+               # sdram_full_wr_clk : full rate sdram write clk
+               # sdram_full_rd_clk : full rate sdram read clk
+               sd_sys = getattr(self.sync, "sys")
+               sd_sdram_half = getattr(self.sync, "sdram_half")
+
+               sys_clk = ClockSignal("sys")
+               sdram_half_clk = ClockSignal("sdram_half")
+               sdram_full_wr_clk = ClockSignal("sdram_full_wr")
+               sdram_full_rd_clk = ClockSignal("sdram_full_rd")
+
+               #
+               # Command/address
+               #
+
+               # select active phase
+               #             sys_clk   ----____----____
+               #  phase_sel(nphases=2) 0   1   0   1     Half Rate
+               phase_sel = Signal(log2_int(nphases))
+               sys_clk_d = Signal()
+
+               sd_sdram_half += [
+                       If(sys_clk & ~sys_clk_d,
+                               phase_sel.eq(0)
+                       ).Else(
+                               phase_sel.eq(phase_sel+1)
+                       ),
+                       sys_clk_d.eq(sys_clk)
+               ]
+
+               # register dfi cmds on half_rate clk
+               r_dfi = Array(Record(phase_cmd_description(a, ba)) for i in range(nphases))
+               for n, phase in enumerate(self.dfi.phases):
+                       sd_sdram_half +=[
+                               r_dfi[n].address.eq(phase.address),
+                               r_dfi[n].bank.eq(phase.bank),
+                               r_dfi[n].cs_n.eq(phase.cs_n),
+                               r_dfi[n].cke.eq(phase.cke),
+                               r_dfi[n].cas_n.eq(phase.cas_n),
+                               r_dfi[n].ras_n.eq(phase.ras_n),
+                               r_dfi[n].we_n.eq(phase.we_n)
+                       ]
+
+               # output cmds
+               sd_sdram_half += [
+                       pads.a.eq(r_dfi[phase_sel].address),
+                       pads.ba.eq(r_dfi[phase_sel].bank),
+                       pads.cke.eq(r_dfi[phase_sel].cke),
+                       pads.ras_n.eq(r_dfi[phase_sel].ras_n),
+                       pads.cas_n.eq(r_dfi[phase_sel].cas_n),
+                       pads.we_n.eq(r_dfi[phase_sel].we_n)
+               ]
+               if hasattr(pads, "cs_n"):
+                       sd_sdram_half += pads.cs_n.eq(r_dfi[phase_sel].cs_n)
+
+               #
+               # Bitslip
+               #
+               bitslip_cnt = Signal(4)
+               bitslip_inc = Signal()
+
+               sd_sys += [
+                       If(bitslip_cnt == rd_bitslip,
+                               bitslip_inc.eq(0)
+                       ).Else(
+                               bitslip_cnt.eq(bitslip_cnt+1),
+                               bitslip_inc.eq(1)
+                       )
+               ]
+
+               #
+               # DQ/DQS/DM data
+               #
+               sdram_half_clk_n = Signal()
+               self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
+
+               postamble = Signal()
+               drive_dqs = Signal()
+               dqs_t_d0 = Signal()
+               dqs_t_d1 = Signal()
+
+               dqs_o = Signal(d//8)
+               dqs_t = Signal(d//8)
+
+               self.comb += [
+                       dqs_t_d0.eq(~(drive_dqs | postamble)),
+                       dqs_t_d1.eq(~drive_dqs),
+               ]
+
+               for i in range(d//8):
+                       # DQS output
+                       self.specials += Instance("ODDR2",
+                               p_DDR_ALIGNMENT=dqs_ddr_alignment,
+                               p_INIT=0,
+                               p_SRTYPE="ASYNC",
+
+                               i_C0=sdram_half_clk,
+                               i_C1=sdram_half_clk_n,
+
+                               i_CE=1,
+                               i_D0=0,
+                               i_D1=1,
+                               i_R=0,
+                               i_S=0,
+
+                               o_Q=dqs_o[i]
+                       )
+
+                       # DQS tristate cmd
+                       self.specials += Instance("ODDR2",
+                               p_DDR_ALIGNMENT=dqs_ddr_alignment,
+                               p_INIT=0,
+                               p_SRTYPE="ASYNC",
+
+                               i_C0=sdram_half_clk,
+                               i_C1=sdram_half_clk_n,
+
+                               i_CE=1,
+                               i_D0=dqs_t_d0,
+                               i_D1=dqs_t_d1,
+                               i_R=0,
+                               i_S=0,
+
+                               o_Q=dqs_t[i]
+                       )
+
+                       # DQS tristate buffer
+                       if hasattr(pads, "dqs_n"):
+                               self.specials += Instance("OBUFTDS",
+                                       i_I=dqs_o[i],
+                                       i_T=dqs_t[i],
+
+                                       o_O=pads.dqs[i],
+                                       o_OB=pads.dqs_n[i],
+                               )
+                       else:
+                               self.specials += Instance("OBUFT",
+                                       i_I=dqs_o[i],
+                                       i_T=dqs_t[i],
+
+                                       o_O=pads.dqs[i]
+                               )
+
+               sd_sdram_half += postamble.eq(drive_dqs)
+
+               d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
+                       for i in range(2*nphases)]
+
+               for n, phase in enumerate(self.dfi.phases):
+                       self.comb += [
+                               d_dfi[n].wrdata.eq(phase.wrdata),
+                               d_dfi[n].wrdata_mask.eq(phase.wrdata_mask),
+                               d_dfi[n].wrdata_en.eq(phase.wrdata_en),
+                               d_dfi[n].rddata_en.eq(phase.rddata_en),
+                       ]
+                       sd_sys += [
+                               d_dfi[nphases+n].wrdata.eq(phase.wrdata),
+                               d_dfi[nphases+n].wrdata_mask.eq(phase.wrdata_mask)
+                       ]
+
+
+               drive_dq = Signal()
+               drive_dq_n = [Signal() for i in range(2)]
+               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_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:])
+
+               for i in range(d):
+                       # Data serializer
+                       self.specials += Instance("OSERDES2",
+                               p_DATA_WIDTH=4,
+                               p_DATA_RATE_OQ="SDR",
+                               p_DATA_RATE_OT="SDR",
+                               p_SERDES_MODE="NONE",
+                               p_OUTPUT_MODE="SINGLE_ENDED",
+
+                               o_OQ=dq_o[i],
+                               i_OCE=1,
+                               i_CLK0=sdram_full_wr_clk,
+                               i_CLK1=0,
+                               i_IOCE=self.clk4x_wr_strb,
+                               i_RST=0,
+                               i_CLKDIV=sys_clk,
+
+                               i_D1=dq_wrdata[wr_bitslip+3][i],
+                               i_D2=dq_wrdata[wr_bitslip+2][i],
+                               i_D3=dq_wrdata[wr_bitslip+1][i],
+                               i_D4=dq_wrdata[wr_bitslip+0][i],
+
+                               o_TQ=dq_t[i],
+                               i_T1=drive_dq_n[(wr_bitslip+3)//4],
+                               i_T2=drive_dq_n[(wr_bitslip+2)//4],
+                               i_T3=drive_dq_n[(wr_bitslip+1)//4],
+                               i_T4=drive_dq_n[(wr_bitslip+0)//4],
+                               i_TRAIN=0,
+                               i_TCE=1,
+                               i_SHIFTIN1=0,
+                               i_SHIFTIN2=0,
+                               i_SHIFTIN3=0,
+                               i_SHIFTIN4=0,
+                       )
+
+                       # Data deserializer
+                       self.specials += Instance("ISERDES2",
+                               p_DATA_WIDTH=4,
+                               p_DATA_RATE="SDR",
+                               p_BITSLIP_ENABLE="TRUE",
+                               p_SERDES_MODE="NONE",
+                               p_INTERFACE_TYPE="RETIMED",
+
+                               i_D=dq_i[i],
+                               i_CE0=1,
+                               i_CLK0=sdram_full_rd_clk,
+                               i_CLK1=0,
+                               i_IOCE=self.clk4x_rd_strb,
+                               i_RST=ResetSignal(),
+                               i_CLKDIV=sys_clk,
+                               i_BITSLIP=bitslip_inc,
+
+                               o_Q1=d_dfi[0*nphases+0].rddata[i+d],
+                               o_Q2=d_dfi[0*nphases+0].rddata[i],
+                               o_Q3=d_dfi[0*nphases+1].rddata[i+d],
+                               o_Q4=d_dfi[0*nphases+1].rddata[i],
+                       )
+
+                       # Data buffer
+                       self.specials += Instance("IOBUF",
+                               i_I=dq_o[i],
+                               o_O=dq_i[i],
+                               i_T=dq_t[i],
+                               io_IO=pads.dq[i]
+                       )
+
+               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:])
+
+               for i in range(d//8):
+                       # Mask serializer
+                       self.specials += Instance("OSERDES2",
+                               p_DATA_WIDTH=4,
+                               p_DATA_RATE_OQ="SDR",
+                               p_DATA_RATE_OT="SDR",
+                               p_SERDES_MODE="NONE",
+                               p_OUTPUT_MODE="SINGLE_ENDED",
+
+                               o_OQ=pads.dm[i],
+                               i_OCE=1,
+                               i_CLK0=sdram_full_wr_clk,
+                               i_CLK1=0,
+                               i_IOCE=self.clk4x_wr_strb,
+                               i_RST=0,
+                               i_CLKDIV=sys_clk,
+
+                               i_D1=dq_wrdata_mask[wr_bitslip+3][i],
+                               i_D2=dq_wrdata_mask[wr_bitslip+2][i],
+                               i_D3=dq_wrdata_mask[wr_bitslip+1][i],
+                               i_D4=dq_wrdata_mask[wr_bitslip+0][i],
+
+                               i_TRAIN=0,
+                               i_TCE=0,
+                               i_SHIFTIN1=0,
+                               i_SHIFTIN2=0,
+                               i_SHIFTIN3=0,
+                               i_SHIFTIN4=0,
+                       )
+
+               #
+               # ODT
+               #
+               # ODT not yet supported
+               if hasattr(pads, "odt"):
+                       self.comb += pads.odt.eq(0)
+
+               #
+               # DQ/DQS/DM control
+               #
+               self.comb += drive_dq.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
+
+               d_dfi_wrdata_en = Signal()
+               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(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 += [
+                               phase.rddata.eq(d_dfi[n].rddata),
+                               phase.rddata_valid.eq(rddata_sr[0]),
+                       ]
diff --git a/misoclib/sdramphy/gensdrphy.py b/misoclib/sdramphy/gensdrphy.py
deleted file mode 100644 (file)
index a065a93..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# 1:1 frequency-ratio Generic SDR PHY
-#
-# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
-# not use vendor-dependent code, it can also be used on other architectures.
-#
-# The PHY needs 2 Clock domains:
-#  - sys_clk    : The System Clock domain
-#  - sys_clk_ps : The System Clock domain with its phase shifted
-#                 (-3ns on C4@100MHz)
-#
-# Assert dfi_wrdata_en and present the data
-# on dfi_wrdata_mask/dfi_wrdata in the same
-# cycle as the write command.
-#
-# Assert dfi_rddata_en in the same cycle as the read
-# command. The data will come back on dfi_rddata
-# 4 cycles later, along with the assertion of
-# dfi_rddata_valid.
-#
-# This PHY only supports CAS Latency 2.
-#
-
-from migen.fhdl.std import *
-from migen.bus.dfi import *
-from migen.genlib.record import *
-from migen.fhdl.specials import *
-
-from misoclib import lasmicon
-
-class GENSDRPHY(Module):
-       def __init__(self, pads):
-               a = flen(pads.a)
-               ba = flen(pads.ba)
-               d = flen(pads.dq)
-
-               self.phy_settings = lasmicon.PhySettings(
-                       memtype="SDR",
-                       dfi_d=d,
-                       nphases=1,
-                       rdphase=0,
-                       wrphase=0,
-                       rdcmdphase=0,
-                       wrcmdphase=0,
-                       cl=2,
-                       read_latency=4,
-                       write_latency=0
-               )
-
-               self.dfi = Interface(a, ba, d)
-
-               ###
-
-               #
-               # Command/address
-               #
-               self.sync += [
-                       pads.a.eq(self.dfi.p0.address),
-                       pads.ba.eq(self.dfi.p0.bank),
-                       pads.cke.eq(self.dfi.p0.cke),
-                       pads.cas_n.eq(self.dfi.p0.cas_n),
-                       pads.ras_n.eq(self.dfi.p0.ras_n),
-                       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),
-
-               #
-               # DQ/DQS/DM data
-               #
-               sd_dq_out = Signal(d)
-               drive_dq = Signal()
-               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,
-                               pads.dm.eq(self.dfi.p0.wrdata_mask)
-                       ).Else(
-                               pads.dm.eq(0)
-                       )
-               sd_dq_in_ps = Signal(d)
-               self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
-               self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)
-
-               #
-               # DQ/DM control
-               #
-               d_dfi_wrdata_en = Signal()
-               self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en)
-               self.comb += drive_dq.eq(d_dfi_wrdata_en)
-
-               rddata_sr = Signal(4)
-               self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3])
-               self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))
diff --git a/misoclib/sdramphy/initsequence.py b/misoclib/sdramphy/initsequence.py
deleted file mode 100644 (file)
index 32ccd77..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-from migen.fhdl.std import log2_int
-
-def get_sdram_phy_header(sdram_phy):
-       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"
-
-       nphases = sdram_phy.phy_settings.nphases
-       r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
-
-       r += "static void cdelay(int i);\n"
-
-       # commands_px functions
-       for n in range(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"
-
-       # 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)
-
-#define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X)
-#define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X)
-
-#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"
-
-       #
-       # sdrrd/sdrwr functions utilities
-       #
-       r += "#define DFII_PIX_DATA_SIZE CSR_DFII_PI0_WRDATA_SIZE\n"
-       dfii_pix_wrdata_addr = []
-       for n in range(nphases):
-               dfii_pix_wrdata_addr.append("CSR_DFII_PI{n}_WRDATA_ADDR".format(n=n))
-       r += """
-const unsigned int dfii_pix_wrdata_addr[{n}] = {{
-       {dfii_pix_wrdata_addr}
-}};
-""".format(n=nphases, dfii_pix_wrdata_addr=",\n\t".join(dfii_pix_wrdata_addr))
-
-       dfii_pix_rddata_addr = []
-       for n in range(nphases):
-               dfii_pix_rddata_addr.append("CSR_DFII_PI{n}_RDDATA_ADDR".format(n=n))
-       r += """
-const unsigned int dfii_pix_rddata_addr[{n}] = {{
-       {dfii_pix_rddata_addr}
-}};
-""".format(n=nphases, dfii_pix_rddata_addr=",\n\t".join(dfii_pix_rddata_addr))
-       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",
-               "UNRESET"       : "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
-               "CKE"           : "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
-       }
-
-       cl = sdram_phy.phy_settings.cl
-
-       if sdram_phy.phy_settings.memtype == "SDR":
-               bl = sdram_phy.phy_settings.nphases
-               mr = log2_int(bl) + (cl << 4)
-               reset_dll = 1 << 8
-
-               init_sequence = [
-                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-                       ("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"], 20000),
-                       ("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"], 20000),
-                       ("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
-               wr = 2
-               mr = log2_int(bl) + (cl << 4) + (wr << 9)
-               emr = 0
-               emr2 = 0
-               emr3 = 0
-               reset_dll = 1 << 8
-               ocd = 7 << 7
-
-               init_sequence = [
-                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-                       ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-                       ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
-                       ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 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),
-                       ("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),
-               ]
-       elif sdram_phy.phy_settings.memtype == "DDR3":
-               bl = 2*sdram_phy.phy_settings.nphases
-               if bl != 8:
-                       raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
-
-               def format_mr0(cl, wr, dll_reset):
-                       cl_to_mr0 = {
-                               5 : 0b0010,
-                               6 : 0b0100,
-                               7 : 0b0110,
-                               8 : 0b1000,
-                               9 : 0b1010,
-                               10: 0b1100,
-                               11: 0b1110,
-                               12: 0b0001,
-                               13: 0b0011,
-                               14: 0b0101
-                       }
-                       wr_to_mr0 = {
-                               16: 0b000,
-                               5 : 0b001,
-                               6 : 0b010,
-                               7 : 0b011,
-                               8 : 0b100,
-                               10: 0b101,
-                               12: 0b110,
-                               14: 0b111
-                       }
-                       mr0 = (cl_to_mr0[cl] & 1) << 2
-                       mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
-                       mr0 |= dll_reset << 8
-                       mr0 |= wr_to_mr0[wr] << 9
-                       return mr0
-
-               def format_mr1(output_drive_strength, rtt_nom):
-                       mr1 = ((output_drive_strength >> 0) & 1) << 1
-                       mr1 |= ((output_drive_strength >> 1) & 1) << 5
-                       mr1 |= ((rtt_nom >> 0) & 1) << 2
-                       mr1 |= ((rtt_nom >> 1) & 1) << 6
-                       mr1 |= ((rtt_nom >> 2) & 1) << 9
-                       return mr1
-
-               def format_mr2(cwl, rtt_wr):
-                       mr2 = (cwl-5) << 3
-                       mr2 |= rtt_wr << 9
-                       return mr2
-
-               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)
-               mr2 = format_mr2(sdram_phy.phy_settings.cwl, 2) # Rtt(WR) RZQ/4
-               mr3 = 0
-
-               init_sequence = [
-                       ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
-                       ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
-                       ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0),
-                       ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
-                       ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
-                       ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
-                       ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
-               ]
-
-               # the value of MR1 needs to be modified during write leveling
-               r += "#define DDR3_MR1 {}\n\n".format(mr1)
-       else:
-               raise NotImplementedError("Unsupported memory type: "+sdram_phy.phy_settings.memtype)
-
-       r += "static void init_sequence(void)\n{\n"
-       for comment, a, ba, cmd, delay in init_sequence:
-               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 cmd[:12] == "DFII_CONTROL":
-                       r += "\tdfii_control_write({0});\n".format(cmd)
-               else:
-                       r += "\tcommand_p0({0});\n".format(cmd)
-               if delay:
-                       r += "\tcdelay({0:d});\n".format(delay)
-               r += "\n"
-       r += "}\n"
-
-       r += "#endif\n"
-
-       return r
diff --git a/misoclib/sdramphy/k7ddrphy.py b/misoclib/sdramphy/k7ddrphy.py
deleted file mode 100644 (file)
index f601294..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-# tCK=5ns CL=7 CWL=6
-
-from migen.fhdl.std import *
-from migen.bus.dfi import *
-from migen.bank.description import *
-
-from misoclib import lasmicon
-
-class K7DDRPHY(Module, AutoCSR):
-       def __init__(self, pads, memtype):
-               a = flen(pads.a)
-               ba = flen(pads.ba)
-               d = flen(pads.dq)
-               nphases = 4
-
-               self._r_wlevel_en = CSRStorage()
-               self._r_wlevel_strobe = CSR()
-               self._r_dly_sel = CSRStorage(d//8)
-               self._r_rdly_dq_rst = CSR()
-               self._r_rdly_dq_inc = CSR()
-               self._r_rdly_dq_bitslip = CSR()
-               self._r_wdly_dq_rst = CSR()
-               self._r_wdly_dq_inc = CSR()
-               self._r_wdly_dqs_rst = CSR()
-               self._r_wdly_dqs_inc = CSR()
-
-               self.phy_settings = lasmicon.PhySettings(
-                       memtype=memtype,
-                       dfi_d=2*d,
-                       nphases=nphases,
-                       rdphase=0,
-                       wrphase=2,
-                       rdcmdphase=1,
-                       wrcmdphase=0,
-                       cl=7,
-                       cwl=6,
-                       read_latency=6,
-                       write_latency=2
-               )
-
-               self.dfi = Interface(a, ba, self.phy_settings.dfi_d, nphases)
-
-               ###
-
-               # Clock
-               sd_clk_se = Signal()
-               self.specials += [
-                       Instance("OSERDESE2",
-                               p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                               p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                               p_SERDES_MODE="MASTER",
-
-                               o_OQ=sd_clk_se,
-                               i_OCE=1,
-                               i_RST=ResetSignal(),
-                               i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                               i_D1=0, i_D2=1, i_D3=0, i_D4=1,
-                               i_D5=0, i_D6=1, i_D7=0, i_D8=1
-                       ),
-                       Instance("OBUFDS",
-                               i_I=sd_clk_se,
-                               o_O=pads.clk_p,
-                               o_OB=pads.clk_n
-                       )
-               ]
-
-               # Addresses and commands
-               for i in range(a):
-                       self.specials += \
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OQ=pads.a[i],
-                                       i_OCE=1,
-                                       i_RST=ResetSignal(),
-                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                                       i_D1=self.dfi.phases[0].address[i], i_D2=self.dfi.phases[0].address[i],
-                                       i_D3=self.dfi.phases[1].address[i], i_D4=self.dfi.phases[1].address[i],
-                                       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):
-                       self.specials += \
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OQ=pads.ba[i],
-                                       i_OCE=1,
-                                       i_RST=ResetSignal(),
-                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                                       i_D1=self.dfi.phases[0].bank[i], i_D2=self.dfi.phases[0].bank[i],
-                                       i_D3=self.dfi.phases[1].bank[i], i_D4=self.dfi.phases[1].bank[i],
-                                       i_D5=self.dfi.phases[2].bank[i], i_D6=self.dfi.phases[2].bank[i],
-                                       i_D7=self.dfi.phases[3].bank[i], i_D8=self.dfi.phases[3].bank[i]
-                               )
-               for name in "ras_n", "cas_n", "we_n", "cs_n", "cke", "odt", "reset_n":
-                       self.specials += \
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OQ=getattr(pads, name),
-                                       i_OCE=1,
-                                       i_RST=ResetSignal(),
-                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                                       i_D1=getattr(self.dfi.phases[0], name), i_D2=getattr(self.dfi.phases[0], name),
-                                       i_D3=getattr(self.dfi.phases[1], name), i_D4=getattr(self.dfi.phases[1], name),
-                                       i_D5=getattr(self.dfi.phases[2], name), i_D6=getattr(self.dfi.phases[2], name),
-                                       i_D7=getattr(self.dfi.phases[3], name), i_D8=getattr(self.dfi.phases[3], name)
-                               )
-
-               # DQS and DM
-               oe_dqs = Signal()
-               dqs_serdes_pattern = Signal(8)
-               self.comb += \
-                       If(self._r_wlevel_en.storage,
-                               If(self._r_wlevel_strobe.re,
-                                       dqs_serdes_pattern.eq(0b00000001)
-                               ).Else(
-                                       dqs_serdes_pattern.eq(0b00000000)
-                               )
-                       ).Else(
-                               dqs_serdes_pattern.eq(0b01010101)
-                       )
-               for i in range(d//8):
-                       dm_o_nodelay = Signal()
-                       self.specials += \
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OQ=dm_o_nodelay,
-                                       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]
-                               )
-                       self.specials += \
-                               Instance("ODELAYE2",
-                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
-                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
-                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0,
-
-                                       i_C=ClockSignal(),
-                                       i_LD=self._r_dly_sel.storage[i] & self._r_wdly_dq_rst.re,
-                                       i_CE=self._r_dly_sel.storage[i] & self._r_wdly_dq_inc.re,
-                                       i_LDPIPEEN=0, i_INC=1,
-
-                                       o_ODATAIN=dm_o_nodelay, o_DATAOUT=pads.dm[i]
-                               )
-
-                       dqs_nodelay = Signal()
-                       dqs_delayed = Signal()
-                       dqs_t = Signal()
-                       self.specials += [
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OFB=dqs_nodelay, o_TQ=dqs_t,
-                                       i_OCE=1, i_TCE=1,
-                                       i_RST=ResetSignal(),
-                                       i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                                       i_D1=dqs_serdes_pattern[0], i_D2=dqs_serdes_pattern[1],
-                                       i_D3=dqs_serdes_pattern[2], i_D4=dqs_serdes_pattern[3],
-                                       i_D5=dqs_serdes_pattern[4], i_D6=dqs_serdes_pattern[5],
-                                       i_D7=dqs_serdes_pattern[6], i_D8=dqs_serdes_pattern[7],
-                                       i_T1=~oe_dqs
-                               ),
-                               Instance("ODELAYE2",
-                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
-                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
-                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=6,
-
-                                       i_C=ClockSignal(),
-                                       i_LD=self._r_dly_sel.storage[i] & self._r_wdly_dqs_rst.re,
-                                       i_CE=self._r_dly_sel.storage[i] & self._r_wdly_dqs_inc.re,
-                                       i_LDPIPEEN=0, i_INC=1,
-
-                                       o_ODATAIN=dqs_nodelay, o_DATAOUT=dqs_delayed
-                               ),
-                               Instance("OBUFTDS",
-                                       i_I=dqs_delayed, i_T=dqs_t,
-                                       o_O=pads.dqs_p[i], o_OB=pads.dqs_n[i]
-                               )
-                       ]
-
-               # DQ
-               oe_dq = Signal()
-               for i in range(d):
-                       dq_o_nodelay = Signal()
-                       dq_o_delayed = Signal()
-                       dq_i_nodelay = Signal()
-                       dq_i_delayed = Signal()
-                       dq_t = Signal()
-                       self.specials += [
-                               Instance("OSERDESE2",
-                                       p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
-                                       p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
-                                       p_SERDES_MODE="MASTER",
-
-                                       o_OQ=dq_o_nodelay, o_TQ=dq_t,
-                                       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_T1=~oe_dq
-                               ),
-                               Instance("ISERDESE2",
-                                       p_DATA_WIDTH=8, p_DATA_RATE="DDR",
-                                       p_SERDES_MODE="MASTER", p_INTERFACE_TYPE="NETWORKING",
-                                       p_NUM_CE=1, p_IOBDELAY="IFD",
-
-                                       i_DDLY=dq_i_delayed,
-                                       i_CE1=1,
-                                       i_RST=ResetSignal() | (self._r_dly_sel.storage[i//8] & self._r_wdly_dq_rst.re),
-                                       i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
-                                       i_BITSLIP=self._r_dly_sel.storage[i//8] & self._r_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]
-                               ),
-                               Instance("ODELAYE2",
-                                       p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
-                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
-                                       p_PIPE_SEL="FALSE", p_ODELAY_TYPE="VARIABLE", p_ODELAY_VALUE=0,
-
-                                       i_C=ClockSignal(),
-                                       i_LD=self._r_dly_sel.storage[i//8] & self._r_wdly_dq_rst.re,
-                                       i_CE=self._r_dly_sel.storage[i//8] & self._r_wdly_dq_inc.re,
-                                       i_LDPIPEEN=0, i_INC=1,
-
-                                       o_ODATAIN=dq_o_nodelay, o_DATAOUT=dq_o_delayed
-                               ),
-                               Instance("IDELAYE2",
-                                       p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
-                                       p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0,
-                                       p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=6,
-
-                                       i_C=ClockSignal(),
-                                       i_LD=self._r_dly_sel.storage[i//8] & self._r_rdly_dq_rst.re,
-                                       i_CE=self._r_dly_sel.storage[i//8] & self._r_rdly_dq_inc.re,
-                                       i_LDPIPEEN=0, i_INC=1,
-
-                                       i_IDATAIN=dq_i_nodelay, o_DATAOUT=dq_i_delayed
-                               ),
-                               Instance("IOBUF",
-                                       i_I=dq_o_delayed, o_O=dq_i_nodelay, i_T=dq_t,
-                                       io_IO=pads.dq[i]
-                               )
-                       ]
-
-               # Flow control
-               #
-               # total read latency = 6:
-               #  2 cycles through OSERDESE2
-               #  2 cycles CAS
-               #  2 cycles through ISERDESE2
-               rddata_en = self.dfi.phases[self.phy_settings.rdphase].rddata_en
-               for i in range(5):
-                       n_rddata_en = Signal()
-                       self.sync += n_rddata_en.eq(rddata_en)
-                       rddata_en = n_rddata_en
-               self.sync += [phase.rddata_valid.eq(rddata_en | self._r_wlevel_en.storage)
-                       for phase in self.dfi.phases]
-
-               oe = Signal()
-               last_wrdata_en = Signal(4)
-               wrphase = self.dfi.phases[self.phy_settings.wrphase]
-               self.sync += last_wrdata_en.eq(Cat(wrphase.wrdata_en, last_wrdata_en[:3]))
-               self.comb += oe.eq(last_wrdata_en[1] | last_wrdata_en[2] | last_wrdata_en[3])
-               self.sync += \
-                       If(self._r_wlevel_en.storage,
-                               oe_dqs.eq(1), oe_dq.eq(0)
-                       ).Else(
-                               oe_dqs.eq(oe), oe_dq.eq(oe)
-                       )
diff --git a/misoclib/sdramphy/s6ddrphy.py b/misoclib/sdramphy/s6ddrphy.py
deleted file mode 100644 (file)
index 9c5c925..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for Spartan-6
-#
-# Assert dfi_wrdata_en and present the data
-# on dfi_wrdata_mask/dfi_wrdata in the same
-# cycle as the write command.
-#
-# Assert dfi_rddata_en in the same cycle as the read
-# command. The data will come back on dfi_rddata
-# 5 cycles later, along with the assertion
-# of dfi_rddata_valid.
-#
-# This PHY only supports CAS Latency 3.
-# Read commands must be sent on phase 0.
-# Write commands must be sent on phase 1.
-#
-
-from migen.fhdl.std import *
-from migen.bus.dfi import *
-from migen.genlib.record import *
-
-from misoclib import lasmicon
-
-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)
-               nphases = 2
-
-               self.phy_settings = lasmicon.PhySettings(
-                       memtype=memtype,
-                       dfi_d=2*d,
-                       nphases=nphases,
-                       rdphase=0,
-                       wrphase=1,
-                       rdcmdphase=1,
-                       wrcmdphase=0,
-                       cl=3,
-                       read_latency=5,
-                       write_latency=0
-               )
-
-               self.dfi = Interface(a, ba, self.phy_settings.dfi_d, nphases)
-               self.clk4x_wr_strb = Signal()
-               self.clk4x_rd_strb = Signal()
-
-               ###
-
-               # sys_clk           : system clk, used for dfi interface
-               # sdram_half_clk    : half rate sdram clk
-               # sdram_full_wr_clk : full rate sdram write clk
-               # sdram_full_rd_clk : full rate sdram read clk
-               sd_sys = getattr(self.sync, "sys")
-               sd_sdram_half = getattr(self.sync, "sdram_half")
-
-               sys_clk = ClockSignal("sys")
-               sdram_half_clk = ClockSignal("sdram_half")
-               sdram_full_wr_clk = ClockSignal("sdram_full_wr")
-               sdram_full_rd_clk = ClockSignal("sdram_full_rd")
-
-               #
-               # Command/address
-               #
-
-               # select active phase
-               #             sys_clk   ----____----____
-               #  phase_sel(nphases=2) 0   1   0   1     Half Rate
-               phase_sel = Signal(log2_int(nphases))
-               sys_clk_d = Signal()
-
-               sd_sdram_half += [
-                       If(sys_clk & ~sys_clk_d,
-                               phase_sel.eq(0)
-                       ).Else(
-                               phase_sel.eq(phase_sel+1)
-                       ),
-                       sys_clk_d.eq(sys_clk)
-               ]
-
-               # register dfi cmds on half_rate clk
-               r_dfi = Array(Record(phase_cmd_description(a, ba)) for i in range(nphases))
-               for n, phase in enumerate(self.dfi.phases):
-                       sd_sdram_half +=[
-                               r_dfi[n].address.eq(phase.address),
-                               r_dfi[n].bank.eq(phase.bank),
-                               r_dfi[n].cs_n.eq(phase.cs_n),
-                               r_dfi[n].cke.eq(phase.cke),
-                               r_dfi[n].cas_n.eq(phase.cas_n),
-                               r_dfi[n].ras_n.eq(phase.ras_n),
-                               r_dfi[n].we_n.eq(phase.we_n)
-                       ]
-
-               # output cmds
-               sd_sdram_half += [
-                       pads.a.eq(r_dfi[phase_sel].address),
-                       pads.ba.eq(r_dfi[phase_sel].bank),
-                       pads.cke.eq(r_dfi[phase_sel].cke),
-                       pads.ras_n.eq(r_dfi[phase_sel].ras_n),
-                       pads.cas_n.eq(r_dfi[phase_sel].cas_n),
-                       pads.we_n.eq(r_dfi[phase_sel].we_n)
-               ]
-               if hasattr(pads, "cs_n"):
-                       sd_sdram_half += pads.cs_n.eq(r_dfi[phase_sel].cs_n)
-
-               #
-               # Bitslip
-               #
-               bitslip_cnt = Signal(4)
-               bitslip_inc = Signal()
-
-               sd_sys += [
-                       If(bitslip_cnt == rd_bitslip,
-                               bitslip_inc.eq(0)
-                       ).Else(
-                               bitslip_cnt.eq(bitslip_cnt+1),
-                               bitslip_inc.eq(1)
-                       )
-               ]
-
-               #
-               # DQ/DQS/DM data
-               #
-               sdram_half_clk_n = Signal()
-               self.comb += sdram_half_clk_n.eq(~sdram_half_clk)
-
-               postamble = Signal()
-               drive_dqs = Signal()
-               dqs_t_d0 = Signal()
-               dqs_t_d1 = Signal()
-
-               dqs_o = Signal(d//8)
-               dqs_t = Signal(d//8)
-
-               self.comb += [
-                       dqs_t_d0.eq(~(drive_dqs | postamble)),
-                       dqs_t_d1.eq(~drive_dqs),
-               ]
-
-               for i in range(d//8):
-                       # DQS output
-                       self.specials += Instance("ODDR2",
-                               p_DDR_ALIGNMENT=dqs_ddr_alignment,
-                               p_INIT=0,
-                               p_SRTYPE="ASYNC",
-
-                               i_C0=sdram_half_clk,
-                               i_C1=sdram_half_clk_n,
-
-                               i_CE=1,
-                               i_D0=0,
-                               i_D1=1,
-                               i_R=0,
-                               i_S=0,
-
-                               o_Q=dqs_o[i]
-                       )
-
-                       # DQS tristate cmd
-                       self.specials += Instance("ODDR2",
-                               p_DDR_ALIGNMENT=dqs_ddr_alignment,
-                               p_INIT=0,
-                               p_SRTYPE="ASYNC",
-
-                               i_C0=sdram_half_clk,
-                               i_C1=sdram_half_clk_n,
-
-                               i_CE=1,
-                               i_D0=dqs_t_d0,
-                               i_D1=dqs_t_d1,
-                               i_R=0,
-                               i_S=0,
-
-                               o_Q=dqs_t[i]
-                       )
-
-                       # DQS tristate buffer
-                       if hasattr(pads, "dqs_n"):
-                               self.specials += Instance("OBUFTDS",
-                                       i_I=dqs_o[i],
-                                       i_T=dqs_t[i],
-
-                                       o_O=pads.dqs[i],
-                                       o_OB=pads.dqs_n[i],
-                               )
-                       else:
-                               self.specials += Instance("OBUFT",
-                                       i_I=dqs_o[i],
-                                       i_T=dqs_t[i],
-
-                                       o_O=pads.dqs[i]
-                               )
-
-               sd_sdram_half += postamble.eq(drive_dqs)
-
-               d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
-                       for i in range(2*nphases)]
-
-               for n, phase in enumerate(self.dfi.phases):
-                       self.comb += [
-                               d_dfi[n].wrdata.eq(phase.wrdata),
-                               d_dfi[n].wrdata_mask.eq(phase.wrdata_mask),
-                               d_dfi[n].wrdata_en.eq(phase.wrdata_en),
-                               d_dfi[n].rddata_en.eq(phase.rddata_en),
-                       ]
-                       sd_sys += [
-                               d_dfi[nphases+n].wrdata.eq(phase.wrdata),
-                               d_dfi[nphases+n].wrdata_mask.eq(phase.wrdata_mask)
-                       ]
-
-
-               drive_dq = Signal()
-               drive_dq_n = [Signal() for i in range(2)]
-               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_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:])
-
-               for i in range(d):
-                       # Data serializer
-                       self.specials += Instance("OSERDES2",
-                               p_DATA_WIDTH=4,
-                               p_DATA_RATE_OQ="SDR",
-                               p_DATA_RATE_OT="SDR",
-                               p_SERDES_MODE="NONE",
-                               p_OUTPUT_MODE="SINGLE_ENDED",
-
-                               o_OQ=dq_o[i],
-                               i_OCE=1,
-                               i_CLK0=sdram_full_wr_clk,
-                               i_CLK1=0,
-                               i_IOCE=self.clk4x_wr_strb,
-                               i_RST=0,
-                               i_CLKDIV=sys_clk,
-
-                               i_D1=dq_wrdata[wr_bitslip+3][i],
-                               i_D2=dq_wrdata[wr_bitslip+2][i],
-                               i_D3=dq_wrdata[wr_bitslip+1][i],
-                               i_D4=dq_wrdata[wr_bitslip+0][i],
-
-                               o_TQ=dq_t[i],
-                               i_T1=drive_dq_n[(wr_bitslip+3)//4],
-                               i_T2=drive_dq_n[(wr_bitslip+2)//4],
-                               i_T3=drive_dq_n[(wr_bitslip+1)//4],
-                               i_T4=drive_dq_n[(wr_bitslip+0)//4],
-                               i_TRAIN=0,
-                               i_TCE=1,
-                               i_SHIFTIN1=0,
-                               i_SHIFTIN2=0,
-                               i_SHIFTIN3=0,
-                               i_SHIFTIN4=0,
-                       )
-
-                       # Data deserializer
-                       self.specials += Instance("ISERDES2",
-                               p_DATA_WIDTH=4,
-                               p_DATA_RATE="SDR",
-                               p_BITSLIP_ENABLE="TRUE",
-                               p_SERDES_MODE="NONE",
-                               p_INTERFACE_TYPE="RETIMED",
-
-                               i_D=dq_i[i],
-                               i_CE0=1,
-                               i_CLK0=sdram_full_rd_clk,
-                               i_CLK1=0,
-                               i_IOCE=self.clk4x_rd_strb,
-                               i_RST=ResetSignal(),
-                               i_CLKDIV=sys_clk,
-                               i_BITSLIP=bitslip_inc,
-
-                               o_Q1=d_dfi[0*nphases+0].rddata[i+d],
-                               o_Q2=d_dfi[0*nphases+0].rddata[i],
-                               o_Q3=d_dfi[0*nphases+1].rddata[i+d],
-                               o_Q4=d_dfi[0*nphases+1].rddata[i],
-                       )
-
-                       # Data buffer
-                       self.specials += Instance("IOBUF",
-                               i_I=dq_o[i],
-                               o_O=dq_i[i],
-                               i_T=dq_t[i],
-                               io_IO=pads.dq[i]
-                       )
-
-               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:])
-
-               for i in range(d//8):
-                       # Mask serializer
-                       self.specials += Instance("OSERDES2",
-                               p_DATA_WIDTH=4,
-                               p_DATA_RATE_OQ="SDR",
-                               p_DATA_RATE_OT="SDR",
-                               p_SERDES_MODE="NONE",
-                               p_OUTPUT_MODE="SINGLE_ENDED",
-
-                               o_OQ=pads.dm[i],
-                               i_OCE=1,
-                               i_CLK0=sdram_full_wr_clk,
-                               i_CLK1=0,
-                               i_IOCE=self.clk4x_wr_strb,
-                               i_RST=0,
-                               i_CLKDIV=sys_clk,
-
-                               i_D1=dq_wrdata_mask[wr_bitslip+3][i],
-                               i_D2=dq_wrdata_mask[wr_bitslip+2][i],
-                               i_D3=dq_wrdata_mask[wr_bitslip+1][i],
-                               i_D4=dq_wrdata_mask[wr_bitslip+0][i],
-
-                               i_TRAIN=0,
-                               i_TCE=0,
-                               i_SHIFTIN1=0,
-                               i_SHIFTIN2=0,
-                               i_SHIFTIN3=0,
-                               i_SHIFTIN4=0,
-                       )
-
-               #
-               # ODT
-               #
-               # ODT not yet supported
-               if hasattr(pads, "odt"):
-                       self.comb += pads.odt.eq(0)
-
-               #
-               # DQ/DQS/DM control
-               #
-               self.comb += drive_dq.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
-
-               d_dfi_wrdata_en = Signal()
-               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(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 += [
-                               phase.rddata.eq(d_dfi[n].rddata),
-                               phase.rddata_valid.eq(rddata_sr[0]),
-                       ]
index cd0df76960832e324f1831674a1b7d57878629a6..2bab721ecdb642cef95c5b8cb9fe60023be3fa4b 100644 (file)
@@ -1,8 +1,8 @@
 from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 
-from misoclib import lasmicon, spiflash, ethmac
-from misoclib.sdramphy import k7ddrphy
+from misoclib import sdram, spiflash, ethmac
+from misoclib.sdram.phy import k7ddrphy
 from misoclib.gensoc import SDRAMSoC
 from misoclib.ethmac.phy import gmii
 
@@ -75,12 +75,12 @@ class BaseSoC(SDRAMSoC):
 
                self.submodules.crg = _CRG(platform)
 
-               sdram_geom = lasmicon.GeomSettings(
+               sdram_geom = sdram.GeomSettings(
                        bank_a=3,
                        row_a=16,
                        col_a=10
                )
-               sdram_timing = lasmicon.TimingSettings(
+               sdram_timing = sdram.TimingSettings(
                        tRP=self.ns(15),
                        tRCD=self.ns(15),
                        tWR=self.ns(15),
index 869f232cd581fdf2ec6ca8c71712a4a1cc3e5168..fcc219a288d527adc5032e3d658f3c207d81e102 100644 (file)
@@ -4,8 +4,8 @@ from fractions import Fraction
 from migen.fhdl.std import *
 from mibuild.generic_platform import ConstraintError
 
-from misoclib import lasmicon, mxcrg, norflash16, ethmac, framebuffer, gpio
-from misoclib.sdramphy import s6ddrphy
+from misoclib import sdram, mxcrg, norflash16, minimac3, framebuffer, gpio
+from misoclib.sdram.phy import s6ddrphy
 from misoclib.gensoc import SDRAMSoC
 from misoclib.ethmac.phy import mii
 
@@ -31,12 +31,12 @@ class BaseSoC(SDRAMSoC):
                        cpu_reset_address=0x00180000,
                        **kwargs)
 
-               sdram_geom = lasmicon.GeomSettings(
+               sdram_geom = sdram.GeomSettings(
                        bank_a=2,
                        row_a=13,
                        col_a=10
                )
-               sdram_timing = lasmicon.TimingSettings(
+               sdram_timing = sdram.TimingSettings(
                        tRP=self.ns(15),
                        tRCD=self.ns(15),
                        tWR=self.ns(15),
index 05bfea3bb92623cf262ec7b9b2e9977c6edcb779..34b1a6381a9f337b7b3c1508aa114898a320ad75 100644 (file)
@@ -3,8 +3,8 @@ from fractions import Fraction
 from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 
-from misoclib import lasmicon, spiflash
-from misoclib.sdramphy import gensdrphy
+from misoclib import spiflash, sdram
+from misoclib.sdram.phy import gensdrphy
 from misoclib.gensoc import SDRAMSoC
 
 class _CRG(Module):
@@ -67,12 +67,12 @@ class BaseSoC(SDRAMSoC):
 
                self.submodules.crg = _CRG(platform, clk_freq)
 
-               sdram_geom = lasmicon.GeomSettings(
+               sdram_geom = sdram.GeomSettings(
                        bank_a=2,
                        row_a=12,
                        col_a=8
                )
-               sdram_timing = lasmicon.TimingSettings(
+               sdram_timing = sdram.TimingSettings(
                        tRP=self.ns(15),
                        tRCD=self.ns(15),
                        tWR=self.ns(14),