from litex.gen import *
from litex.boards.platforms import de0nano
-from litex.soc.cores.sdram.settings import IS42S16160
-from litex.soc.cores.sdram.phy import GENSDRPHY
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
+from litedram.settings import IS42S16160
+from litedram.phy import GENSDRPHY
+
class _PLL(Module):
def __init__(self, period_in, name, phase_shift, operation_mode):
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
from litex.boards.platforms import kc705
-from litex.soc.cores.sdram.settings import MT8JTF12864
-from litex.soc.cores.sdram.phy import k7ddrphy
from litex.soc.cores.flash import spi_flash
from litex.soc.integration.soc_core import mem_decoder
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
+from litedram.settings import MT8JTF12864
+from litedram.phy import k7ddrphy
+
from liteeth.phy import LiteEthPHY
from liteeth.core.mac import LiteEthMAC
from litex.gen.genlib.resetsync import AsyncResetSynchronizer
from litex.boards.platforms import minispartan6
-from litex.soc.cores.sdram.settings import AS4C16M16
-from litex.soc.cores.sdram.phy import GENSDRPHY
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
+from litedram.settings import AS4C16M16
+from litedram.phy import GENSDRPHY
+
class _CRG(Module):
def __init__(self, platform, clk_freq):
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
from litex.soc.cores import uart
-from litex.soc.cores.sdram.settings import PhySettings, IS42S16160
-from litex.soc.cores.sdram.model import SDRAMPHYModel
from litex.soc.integration.soc_core import mem_decoder
+from litedram.settings import PhySettings, IS42S16160
+from litedram.model import SDRAMPHYModel
+
from liteeth.phy.model import LiteEthPHYModel
from liteeth.core.mac import LiteEthMAC
+++ /dev/null
-from litex.gen import *
-
-from litex.soc.interconnect import dfi
-from litex.soc.interconnect.csr 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(len(phase.address))
- self._baddress = CSRStorage(len(phase.bank))
- self._wrdata = CSRStorage(len(phase.wrdata))
- self._rddata = CSRStatus(len(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, addressbits, bankbits, databits, nphases=1):
- inti = dfi.Interface(addressbits, bankbits, databits, nphases)
- self.slave = dfi.Interface(addressbits, bankbits, databits, nphases)
- self.master = dfi.Interface(addressbits, bankbits, databits, nphases)
-
- self._control = CSRStorage(4) # sel, cke, odt, reset_n
-
- 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")]
+++ /dev/null
-from litex.soc.cores.sdram.lasmicon.core import ControllerSettings, LASMIcon
+++ /dev/null
-from litex.gen import *
-from litex.gen.genlib.roundrobin import *
-from litex.gen.genlib.fsm import FSM, NextState
-from litex.gen.genlib.fifo import SyncFIFO
-
-from litex.soc.cores.sdram.lasmicon.multiplexer import *
-
-
-class _AddressSlicer:
- def __init__(self, colbits, address_align):
- self.colbits = colbits
- self.address_align = address_align
-
- def row(self, address):
- split = self.colbits - self.address_align
- if isinstance(address, int):
- return address >> split
- else:
- return address[split:]
-
- def col(self, address):
- split = self.colbits - 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, controller_settings, address_align, bankn, req):
- self.refresh_req = Signal()
- self.refresh_gnt = Signal()
- self.cmd = CommandRequestRW(geom_settings.addressbits, geom_settings.bankbits)
-
- ###
-
- # Request FIFO
- layout = [("we", 1), ("adr", len(req.adr))]
- req_in = Record(layout)
- reqf = Record(layout)
- self.submodules.req_fifo = SyncFIFO(layout_len(layout),
- controller_settings.req_queue_size)
- self.comb += [
- self.req_fifo.din.eq(req_in.raw_bits()),
- reqf.raw_bits().eq(self.req_fifo.dout)
- ]
- self.comb += [
- req_in.we.eq(req.we),
- req_in.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_w_ack | req.dat_r_ack),
- req.lock.eq(self.req_fifo.readable)
- ]
-
- slicer = _AddressSlicer(geom_settings.colbits, address_align)
-
- # Row tracking
- has_openrow = Signal()
- openrow = Signal(geom_settings.rowbits)
- 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_w_ack.eq(self.cmd.ack & reqf.we),
- req.dat_r_ack.eq(self.cmd.ack & ~reqf.we),
- 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)
+++ /dev/null
-from litex.gen import *
-
-from litex.soc.interconnect import dfi, lasmi_bus
-from litex.soc.cores.sdram.lasmicon.refresher import *
-from litex.soc.cores.sdram.lasmicon.bankmachine import *
-from litex.soc.cores.sdram.lasmicon.multiplexer import *
-
-
-class ControllerSettings:
- def __init__(self, req_queue_size=8, read_time=32, write_time=16, with_bandwidth=False):
- self.req_queue_size = req_queue_size
- self.read_time = read_time
- self.write_time = write_time
- self.with_bandwidth = with_bandwidth
-
-
-class LASMIcon(Module):
- def __init__(self, phy_settings, geom_settings, timing_settings,
- controller_settings=None):
- if controller_settings is None:
- controller_settings = ControllerSettings()
- 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.addressbits,
- geom_settings.bankbits,
- phy_settings.dfi_databits,
- phy_settings.nphases)
- self.lasmic = lasmi_bus.Interface(
- aw=geom_settings.rowbits + geom_settings.colbits - address_align,
- dw=phy_settings.dfi_databits*phy_settings.nphases,
- nbanks=2**geom_settings.bankbits,
- req_queue_size=controller_settings.req_queue_size,
- read_latency=phy_settings.read_latency+1,
- write_latency=phy_settings.write_latency+1)
- self.nrowbits = geom_settings.colbits - address_align
-
- ###
-
- self.submodules.refresher = Refresher(geom_settings.addressbits, geom_settings.bankbits,
- timing_settings.tRP, timing_settings.tREFI, timing_settings.tRFC)
- self.submodules.bank_machines = [BankMachine(geom_settings, timing_settings, controller_settings, address_align, i,
- getattr(self.lasmic, "bank"+str(i)))
- for i in range(2**geom_settings.bankbits)]
- self.submodules.multiplexer = Multiplexer(phy_settings, geom_settings, timing_settings, controller_settings,
- self.bank_machines, self.refresher,
- self.dfi, self.lasmic)
-
- def get_csrs(self):
- return self.multiplexer.get_csrs()
+++ /dev/null
-from functools import reduce
-from operator import or_, and_
-
-from litex.gen import *
-from litex.gen.genlib.roundrobin import *
-from litex.gen.genlib.fsm import FSM, NextState
-
-from litex.soc.cores.sdram.lasmicon.perf import Bandwidth
-from litex.soc.interconnect.csr import AutoCSR
-
-
-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(len(requests[0].a), len(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, controller_settings, bank_machines, refresher, dfi, lasmic,
- with_bandwidth=False):
- assert(phy_settings.nphases == len(dfi.phases))
- self.phy_settings = phy_settings
-
- # Command choosing
- requests = [bm.cmd for bm in bank_machines]
- self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests)
- self.submodules.choose_req = 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)
- ]
-
- # Command steering
- nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits)
- commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
- (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
- steerer = _Steerer(commands, dfi)
- self.submodules += steerer
-
- # Read/write turnaround
- read_available = Signal()
- write_available = Signal()
- self.comb += [
- read_available.eq(reduce(or_, [req.stb & req.is_read for req in requests])),
- write_available.eq(reduce(or_, [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(controller_settings.read_time)
- write_time_en, max_write_time = anti_starvation(controller_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(reduce(and_, [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),
- refresher.ack.eq(1),
- 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)
-
- if controller_settings.with_bandwidth:
- data_width = phy_settings.dfi_databits*phy_settings.nphases
- self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width)
+++ /dev/null
-from litex.gen import *
-
-from litex.soc.interconnect.csr import *
-
-
-class Bandwidth(Module, AutoCSR):
- def __init__(self, cmd, data_width, period_bits=24):
- self._update = CSR()
- self._nreads = CSRStatus(period_bits)
- self._nwrites = CSRStatus(period_bits)
- self._data_width = CSRStatus(bits_for(data_width), reset=data_width)
-
- ###
-
- 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._update.re,
- self._nreads.status.eq(nreads_r),
- self._nwrites.status.eq(nwrites_r)
- )
- ]
+++ /dev/null
-from litex.gen import *
-from litex.gen.genlib.misc import timeline
-from litex.gen.genlib.fsm import FSM
-
-from litex.soc.cores.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"))
- )
+++ /dev/null
-from litex.soc.cores.sdram.minicon.core import Minicon
+++ /dev/null
-from functools import reduce
-from operator import or_
-
-from litex.gen import *
-from litex.gen.genlib.fsm import FSM, NextState
-from litex.gen.genlib.misc import WaitTimer
-
-from litex.soc.interconnect import dfi as dfibus
-from litex.soc.interconnect import wishbone
-
-
-class _AddressSlicer:
- def __init__(self, colbits, bankbits, rowbits, address_align):
- self.colbits = colbits
- self.bankbits = bankbits
- self.rowbits = rowbits
- self.address_align = address_align
- self.addressbits = colbits - address_align + bankbits + rowbits
-
- def row(self, address):
- split = self.bankbits + self.colbits - self.address_align
- if isinstance(address, int):
- return address >> split
- else:
- return address[split:self.addressbits]
-
- def bank(self, address):
- split = self.colbits - self.address_align
- if isinstance(address, int):
- return (address & (2**(split + self.bankbits) - 1)) >> split
- else:
- return address[split:split+self.bankbits]
-
- def col(self, address):
- split = self.colbits - 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])
-
-
-@ResetInserter()
-@CEInserter()
-class _Bank(Module):
- def __init__(self, geom_settings):
- self.open = Signal()
- self.row = Signal(geom_settings.rowbits)
-
- self.idle = Signal(reset=1)
- self.hit = Signal()
-
- # # #
-
- row = Signal(geom_settings.rowbits)
- self.sync += \
- If(self.open,
- self.idle.eq(0),
- row.eq(self.row)
- )
- self.comb += self.hit.eq(~self.idle & (self.row == row))
-
-
-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
- burst_width = phy_settings.dfi_databits*phy_settings.nphases
- address_align = log2_int(burst_length)
-
- # # #
-
- self.dfi = dfi = dfibus.Interface(geom_settings.addressbits,
- geom_settings.bankbits,
- phy_settings.dfi_databits,
- phy_settings.nphases)
-
- self.bus = bus = wishbone.Interface(burst_width)
-
- rdphase = phy_settings.rdphase
- wrphase = phy_settings.wrphase
-
- precharge_all = Signal()
- activate = Signal()
- refresh = Signal()
- write = Signal()
- read = Signal()
-
- # Compute current column, bank and row from wishbone address
- slicer = _AddressSlicer(geom_settings.colbits,
- geom_settings.bankbits,
- geom_settings.rowbits,
- address_align)
-
- # Manage banks
- bank_idle = Signal()
- bank_hit = Signal()
-
- banks = []
- for i in range(2**geom_settings.bankbits):
- bank = _Bank(geom_settings)
- self.comb += [
- bank.open.eq(activate),
- bank.reset.eq(precharge_all),
- bank.row.eq(slicer.row(bus.adr))
- ]
- banks.append(bank)
- self.submodules += banks
-
- cases = {}
- for i, bank in enumerate(banks):
- cases[i] = [bank.ce.eq(1)]
- self.comb += Case(slicer.bank(bus.adr), cases)
-
- self.comb += [
- bank_hit.eq(reduce(or_, [bank.hit & bank.ce for bank in banks])),
- bank_idle.eq(reduce(or_, [bank.idle & bank.ce for bank in banks])),
- ]
-
- # Timings
- write2precharge_timer = WaitTimer(2 + timing_settings.tWR - 1)
- self.submodules += write2precharge_timer
- self.comb += write2precharge_timer.wait.eq(~write)
-
- refresh_timer = WaitTimer(timing_settings.tREFI)
- self.submodules += refresh_timer
- self.comb += refresh_timer.wait.eq(~refresh)
-
- # Main FSM
- self.submodules.fsm = fsm = FSM()
- fsm.act("IDLE",
- If(refresh_timer.done,
- NextState("PRECHARGE-ALL")
- ).Elif(bus.stb & bus.cyc,
- If(bank_hit,
- If(bus.we,
- NextState("WRITE")
- ).Else(
- NextState("READ")
- )
- ).Elif(~bank_idle,
- If(write2precharge_timer.done,
- NextState("PRECHARGE")
- )
- ).Else(
- NextState("ACTIVATE")
- )
- )
- )
- fsm.act("READ",
- read.eq(1),
- dfi.phases[rdphase].ras_n.eq(1),
- dfi.phases[rdphase].cas_n.eq(0),
- dfi.phases[rdphase].we_n.eq(1),
- dfi.phases[rdphase].rddata_en.eq(1),
- NextState("WAIT-READ-DONE"),
- )
- fsm.act("WAIT-READ-DONE",
- If(dfi.phases[rdphase].rddata_valid,
- bus.ack.eq(1),
- NextState("IDLE")
- )
- )
- fsm.act("WRITE",
- write.eq(1),
- dfi.phases[wrphase].ras_n.eq(1),
- dfi.phases[wrphase].cas_n.eq(0),
- dfi.phases[wrphase].we_n.eq(0),
- dfi.phases[wrphase].wrdata_en.eq(1),
- NextState("WRITE-LATENCY")
- )
- fsm.act("WRITE-ACK",
- bus.ack.eq(1),
- NextState("IDLE")
- )
- fsm.act("PRECHARGE-ALL",
- precharge_all.eq(1),
- dfi.phases[rdphase].ras_n.eq(0),
- dfi.phases[rdphase].cas_n.eq(1),
- dfi.phases[rdphase].we_n.eq(0),
- NextState("PRE-REFRESH")
- )
- fsm.act("PRECHARGE",
- # do no reset bank since we are going to re-open it
- dfi.phases[0].ras_n.eq(0),
- dfi.phases[0].cas_n.eq(1),
- dfi.phases[0].we_n.eq(0),
- NextState("TRP")
- )
- fsm.act("ACTIVATE",
- activate.eq(1),
- dfi.phases[0].ras_n.eq(0),
- dfi.phases[0].cas_n.eq(1),
- dfi.phases[0].we_n.eq(1),
- NextState("TRCD"),
- )
- fsm.act("REFRESH",
- refresh.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("WRITE-LATENCY", "WRITE-ACK", phy_settings.write_latency-1)
- fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
- fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD-1)
- fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP-1)
- fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC-1)
-
- # DFI commands
- for phase in dfi.phases:
- if hasattr(phase, "reset_n"):
- self.comb += phase.reset_n.eq(1)
- if hasattr(phase, "odt"):
- self.comb += phase.odt.eq(1)
- self.comb += [
- phase.cke.eq(1),
- phase.cs_n.eq(0),
- phase.bank.eq(slicer.bank(bus.adr)),
- If(precharge_all,
- phase.address.eq(2**10)
- ).Elif(activate,
- phase.address.eq(slicer.row(bus.adr))
- ).Elif(write | read,
- phase.address.eq(slicer.col(bus.adr))
- )
- ]
-
- # DFI datapath
- self.comb += [
- 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),
- ]
+++ /dev/null
-# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
-# License: BSD
-
-# SDRAM simulation PHY at DFI level
-# tested with SDR/DDR/DDR2/LPDDR/DDR3
-# TODO:
-# - add $display support to LiteX gen and manage timing violations?
-
-from litex.gen import *
-from litex.gen.fhdl.specials import *
-from litex.soc.interconnect.dfi import *
-
-from functools import reduce
-from operator import or_
-
-
-class Bank(Module):
- def __init__(self, data_width, nrows, ncols, burst_length):
- self.activate = Signal()
- self.activate_row = Signal(max=nrows)
- self.precharge = Signal()
-
- self.write = Signal()
- self.write_col = Signal(max=ncols)
- self.write_data = Signal(data_width)
- self.write_mask = Signal(data_width//8)
-
- self.read = Signal()
- self.read_col = Signal(max=ncols)
- self.read_data = Signal(data_width)
-
- # # #
-
- active = Signal()
- row = Signal(max=nrows)
-
- self.sync += \
- If(self.precharge,
- active.eq(0),
- ).Elif(self.activate,
- active.eq(1),
- row.eq(self.activate_row)
- )
-
- self.specials.mem = mem = Memory(data_width, nrows*ncols//burst_length)
- self.specials.write_port = write_port = mem.get_port(write_capable=True,
- we_granularity=8)
- self.specials.read_port = read_port = mem.get_port(async_read=True)
- self.comb += [
- If(active,
- write_port.adr.eq(row*ncols | self.write_col),
- write_port.dat_w.eq(self.write_data),
- write_port.we.eq(Replicate(self.write, data_width//8) & ~self.write_mask),
- If(self.read,
- read_port.adr.eq(row*ncols | self.read_col),
- self.read_data.eq(read_port.dat_r)
- )
- )
- ]
-
-
-class DFIPhase(Module):
- def __init__(self, dfi, n):
- phase = getattr(dfi, "p"+str(n))
-
- self.bank = phase.bank
- self.address = phase.address
-
- self.wrdata = phase.wrdata
- self.wrdata_mask = phase.wrdata_mask
-
- self.rddata = phase.rddata
- self.rddata_valid = phase.rddata_valid
-
- self.activate = Signal()
- self.precharge = Signal()
- self.write = Signal()
- self.read = Signal()
-
- # # #
-
- self.comb += [
- If(~phase.cs_n & ~phase.ras_n & phase.cas_n,
- self.activate.eq(phase.we_n),
- self.precharge.eq(~phase.we_n)
- ),
- If(~phase.cs_n & phase.ras_n & ~phase.cas_n,
- self.write.eq(~phase.we_n),
- self.read.eq(phase.we_n)
- )
- ]
-
-
-class SDRAMPHYModel(Module):
- def __init__(self, module, settings):
- if settings.memtype in ["SDR"]:
- burst_length = settings.nphases*1 # command multiplication*SDR
- elif settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
- burst_length = settings.nphases*2 # command multiplication*DDR
-
- addressbits = module.geom_settings.addressbits
- bankbits = module.geom_settings.bankbits
- rowbits = module.geom_settings.rowbits
- colbits = module.geom_settings.colbits
-
- self.settings = settings
- self.module = module
-
- self.dfi = Interface(addressbits, bankbits, self.settings.dfi_databits, self.settings.nphases)
-
- # # #
-
- nbanks = 2**bankbits
- nrows = 2**rowbits
- ncols = 2**colbits
- data_width = self.settings.dfi_databits*self.settings.nphases
-
- # DFI phases
- phases = [DFIPhase(self.dfi, n) for n in range(self.settings.nphases)]
- self.submodules += phases
-
- # banks
- banks = [Bank(data_width, nrows, ncols, burst_length) for i in range(nbanks)]
- self.submodules += banks
-
- # connect DFI phases to banks (cmds, write datapath)
- for nb, bank in enumerate(banks):
- # bank activate
- activates = Signal(len(phases))
- cases = {}
- for np, phase in enumerate(phases):
- self.comb += activates[np].eq(phase.activate)
- cases[2**np] = [
- bank.activate.eq(phase.bank == nb),
- bank.activate_row.eq(phase.address)
- ]
- self.comb += Case(activates, cases)
-
- # bank precharge
- precharges = Signal(len(phases))
- cases = {}
- for np, phase in enumerate(phases):
- self.comb += precharges[np].eq(phase.precharge)
- cases[2**np] = [
- bank.precharge.eq((phase.bank == nb) | phase.address[10])
- ]
- self.comb += Case(precharges, cases)
-
- # bank writes
- writes = Signal(len(phases))
- cases = {}
- for np, phase in enumerate(phases):
- self.comb += writes[np].eq(phase.write)
- cases[2**np] = [
- bank.write.eq(phase.bank == nb),
- bank.write_col.eq(phase.address)
- ]
- self.comb += Case(writes, cases)
- self.comb += [
- bank.write_data.eq(Cat(*[phase.wrdata for phase in phases])),
- bank.write_mask.eq(Cat(*[phase.wrdata_mask for phase in phases]))
- ]
-
- # bank reads
- reads = Signal(len(phases))
- cases = {}
- for np, phase in enumerate(phases):
- self.comb += reads[np].eq(phase.read)
- cases[2**np] = [
- bank.read.eq(phase.bank == nb),
- bank.read_col.eq(phase.address)
- ]
- self.comb += Case(reads, cases)
-
- # connect banks to DFI phases (cmds, read datapath)
- banks_read = Signal()
- banks_read_data = Signal(data_width)
- self.comb += [
- banks_read.eq(reduce(or_, [bank.read for bank in banks])),
- banks_read_data.eq(reduce(or_, [bank.read_data for bank in banks]))
- ]
-
- # simulate read latency
- for i in range(self.settings.read_latency):
- new_banks_read = Signal()
- new_banks_read_data = Signal(data_width)
- self.sync += [
- new_banks_read.eq(banks_read),
- new_banks_read_data.eq(banks_read_data)
- ]
- banks_read = new_banks_read
- banks_read_data = new_banks_read_data
-
- self.comb += [
- Cat(*[phase.rddata_valid for phase in phases]).eq(banks_read),
- Cat(*[phase.rddata for phase in phases]).eq(banks_read_data)
- ]
+++ /dev/null
-from litex.soc.cores.sdram.phy.gensdrphy import GENSDRPHY
-from litex.soc.cores.sdram.phy.s6ddrphy import S6HalfRateDDRPHY, S6QuarterRateDDRPHY
-from litex.soc.cores.sdram.phy.k7ddrphy import K7DDRPHY
+++ /dev/null
-#
-# 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 litex.gen import *
-from litex.gen.genlib.record import *
-from litex.gen.fhdl.specials import Tristate
-
-from litex.soc.interconnect.dfi import *
-from litex.soc.cores.sdram import settings as sdram_settings
-
-
-class GENSDRPHY(Module):
- def __init__(self, pads):
- addressbits = len(pads.a)
- bankbits = len(pads.ba)
- databits = len(pads.dq)
-
- self.settings = sdram_settings.PhySettings(
- memtype="SDR",
- dfi_databits=databits,
- nphases=1,
- rdphase=0,
- wrphase=0,
- rdcmdphase=0,
- wrcmdphase=0,
- cl=2,
- read_latency=4,
- write_latency=0
- )
-
- self.dfi = Interface(addressbits, bankbits, databits)
-
- ###
-
- #
- # 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(databits)
- 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(databits)
- 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]))
+++ /dev/null
-# tCK=5ns CL=7 CWL=6
-
-from litex.gen import *
-
-from litex.soc.interconnect.dfi import *
-from litex.soc.interconnect.csr import *
-from litex.soc.cores.sdram import settings as sdram_settings
-
-
-class K7DDRPHY(Module, AutoCSR):
- def __init__(self, pads):
- addressbits = len(pads.a)
- bankbits = len(pads.ba)
- databits = len(pads.dq)
- nphases = 4
-
- self._wlevel_en = CSRStorage()
- self._wlevel_strobe = CSR()
- self._dly_sel = CSRStorage(databits//8)
- self._rdly_dq_rst = CSR()
- self._rdly_dq_inc = CSR()
- self._rdly_dq_bitslip = CSR()
- self._wdly_dq_rst = CSR()
- self._wdly_dq_inc = CSR()
- self._wdly_dqs_rst = CSR()
- self._wdly_dqs_inc = CSR()
-
- self.settings = sdram_settings.PhySettings(
- memtype="DDR3",
- dfi_databits=2*databits,
- nphases=nphases,
- rdphase=0,
- wrphase=2,
- rdcmdphase=1,
- wrcmdphase=0,
- cl=7,
- cwl=6,
- read_latency=6,
- write_latency=2
- )
-
- self.dfi = Interface(addressbits, bankbits, 2*databits, 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(addressbits):
- 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(bankbits):
- 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._wlevel_en.storage,
- If(self._wlevel_strobe.re,
- dqs_serdes_pattern.eq(0b00000001)
- ).Else(
- dqs_serdes_pattern.eq(0b00000000)
- )
- ).Else(
- dqs_serdes_pattern.eq(0b01010101)
- )
- for i in range(databits//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[databits//8+i],
- i_D3=self.dfi.phases[1].wrdata_mask[i], i_D4=self.dfi.phases[1].wrdata_mask[databits//8+i],
- i_D5=self.dfi.phases[2].wrdata_mask[i], i_D6=self.dfi.phases[2].wrdata_mask[databits//8+i],
- i_D7=self.dfi.phases[3].wrdata_mask[i], i_D8=self.dfi.phases[3].wrdata_mask[databits//8+i]
- )
- self.specials += \
- Instance("ODELAYE2",
- 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._dly_sel.storage[i] & self._wdly_dq_rst.re,
- i_CE=self._dly_sel.storage[i] & self._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._dly_sel.storage[i] & self._wdly_dqs_rst.re,
- i_CE=self._dly_sel.storage[i] & self._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(databits):
- 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[databits+i],
- i_D3=self.dfi.phases[1].wrdata[i], i_D4=self.dfi.phases[1].wrdata[databits+i],
- i_D5=self.dfi.phases[2].wrdata[i], i_D6=self.dfi.phases[2].wrdata[databits+i],
- i_D7=self.dfi.phases[3].wrdata[i], i_D8=self.dfi.phases[3].wrdata[databits+i],
- i_T1=~oe_dq
- ),
- Instance("ISERDESE2",
- 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._dly_sel.storage[i//8] & self._wdly_dq_rst.re),
- i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CLKDIV=ClockSignal(),
- i_BITSLIP=self._dly_sel.storage[i//8] & self._rdly_dq_bitslip.re,
- o_Q8=self.dfi.phases[0].rddata[i], o_Q7=self.dfi.phases[0].rddata[databits+i],
- o_Q6=self.dfi.phases[1].rddata[i], o_Q5=self.dfi.phases[1].rddata[databits+i],
- o_Q4=self.dfi.phases[2].rddata[i], o_Q3=self.dfi.phases[2].rddata[databits+i],
- o_Q2=self.dfi.phases[3].rddata[i], o_Q1=self.dfi.phases[3].rddata[databits+i]
- ),
- Instance("ODELAYE2",
- p_DELAY_SRC="ODATAIN", p_SIGNAL_PATTERN="DATA",
- 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._dly_sel.storage[i//8] & self._wdly_dq_rst.re,
- i_CE=self._dly_sel.storage[i//8] & self._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._dly_sel.storage[i//8] & self._rdly_dq_rst.re,
- i_CE=self._dly_sel.storage[i//8] & self._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.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._wlevel_en.storage)
- for phase in self.dfi.phases]
-
- oe = Signal()
- last_wrdata_en = Signal(4)
- wrphase = self.dfi.phases[self.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._wlevel_en.storage,
- oe_dqs.eq(1), oe_dq.eq(0)
- ).Else(
- oe_dqs.eq(oe), oe_dq.eq(oe)
- )
+++ /dev/null
-# 1:2 and 1:4 frequency-ratio DDR / LPDDR / DDR2 / DDR3 PHYs 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 for DDR, LPDDR, DDR2
-# and CAS latency 5/CAS write latency 6 for DDR3.
-#
-# Read commands must be sent on phase 0.
-# Write commands must be sent on phase 1.
-#
-
-from functools import reduce
-from operator import or_
-
-from litex.gen import *
-from litex.gen.genlib.record import *
-from litex.gen.fhdl.decorators import ClockDomainsRenamer
-
-from litex.soc.interconnect.dfi import *
-from litex.soc.cores.sdram import settings as sdram_settings
-
-
-class S6HalfRateDDRPHY(Module):
- def __init__(self, pads, memtype, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
- if memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
- raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
- addressbits = len(pads.a)
- bankbits = len(pads.ba)
- databits = len(pads.dq)
- nphases = 2
-
- if memtype == "DDR3":
- self.settings = sdram_settings.PhySettings(
- memtype="DDR3",
- dfi_databits=2*databits,
- nphases=nphases,
- rdphase=0,
- wrphase=1,
- rdcmdphase=1,
- wrcmdphase=0,
- cl=5,
- cwl=6,
- read_latency=6,
- write_latency=2
- )
- else:
- self.settings = sdram_settings.PhySettings(
- memtype=memtype,
- dfi_databits=2*databits,
- nphases=nphases,
- rdphase=0,
- wrphase=1,
- rdcmdphase=1,
- wrcmdphase=0,
- cl=3,
- read_latency=5,
- write_latency=0
- )
-
- self.dfi = Interface(addressbits, bankbits, 2*databits, 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))
- phase_half = Signal.like(phase_sel)
- phase_sys = Signal.like(phase_half)
-
- sd_sys += phase_sys.eq(phase_half)
-
- sd_sdram_half += [
- If(phase_half == phase_sys,
- phase_sel.eq(0),
- ).Else(
- phase_sel.eq(phase_sel+1)
- ),
- phase_half.eq(phase_half+1),
- ]
-
- # register dfi cmds on half_rate clk
- r_dfi = Array(Record(phase_cmd_description(addressbits, bankbits)) for i in range(nphases))
- for n, phase in enumerate(self.dfi.phases):
- sd_sdram_half += [
- r_dfi[n].reset_n.eq(phase.reset_n),
- r_dfi[n].odt.eq(phase.odt),
- 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)
- ]
- # optional pads
- for name in "reset_n", "cs_n", "odt":
- if hasattr(pads, name):
- sd_sdram_half += getattr(pads, name).eq(getattr(r_dfi[phase_sel], name))
-
- #
- # 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(databits//8)
- dqs_t = Signal(databits//8)
-
- self.comb += [
- dqs_t_d0.eq(~(drive_dqs | postamble)),
- dqs_t_d1.eq(~drive_dqs),
- ]
-
- for i in range(databits//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*databits)+phase_rddata_description(nphases*databits))
- 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(databits)
- dq_o = Signal(databits)
- dq_i = Signal(databits)
-
- dq_wrdata = []
- for i in range(2):
- for j in reversed(range(nphases)):
- dq_wrdata.append(d_dfi[i*nphases+j].wrdata[:databits])
- dq_wrdata.append(d_dfi[i*nphases+j].wrdata[databits:])
-
- for i in range(databits):
- # 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+databits],
- o_Q2=d_dfi[0*nphases+0].rddata[i],
- o_Q3=d_dfi[0*nphases+1].rddata[i+databits],
- 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[:databits//8])
- dq_wrdata_mask.append(d_dfi[i*nphases+j].wrdata_mask[databits//8:])
-
- for i in range(databits//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,
- )
-
-
- #
- # DQ/DQS/DM control
- #
-
- # write
- wrdata_en = Signal()
- self.comb += wrdata_en.eq(reduce(or_, [d_dfi[p].wrdata_en for p in range(nphases)]))
-
- if memtype == "DDR3":
- r_drive_dq = Signal(self.settings.cwl-1)
- sd_sdram_half += r_drive_dq.eq(Cat(wrdata_en, r_drive_dq))
- self.comb += drive_dq.eq(r_drive_dq[self.settings.cwl-2])
- else:
- self.comb += drive_dq.eq(wrdata_en)
-
- wrdata_en_d = Signal()
- sd_sys += wrdata_en_d.eq(wrdata_en)
-
- r_dfi_wrdata_en = Signal(max(self.settings.cwl, self.settings.cl))
- sd_sdram_half += r_dfi_wrdata_en.eq(Cat(wrdata_en_d, r_dfi_wrdata_en))
-
- if memtype == "DDR3":
- self.comb += drive_dqs.eq(r_dfi_wrdata_en[self.settings.cwl-1])
- else:
- self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])
-
- # read
- rddata_en = Signal()
- self.comb += rddata_en.eq(reduce(or_, [d_dfi[p].rddata_en for p in range(nphases)]))
-
- rddata_sr = Signal(self.settings.read_latency)
- sd_sys += rddata_sr.eq(Cat(rddata_sr[1:self.settings.read_latency], 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]),
- ]
-
-
-class S6QuarterRateDDRPHY(Module):
- def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
- half_rate_phy = S6HalfRateDDRPHY(pads, "DDR3", rd_bitslip, wr_bitslip, dqs_ddr_alignment)
- self.submodules += ClockDomainsRenamer("sys2x")(half_rate_phy)
-
- addressbits = len(pads.a)
- bankbits = len(pads.ba)
- databits = len(pads.dq)
- nphases = 4
-
- self.settings = sdram_settings.PhySettings(
- memtype="DDR3",
- dfi_databits=2*databits,
- nphases=nphases,
- rdphase=0,
- wrphase=1,
- rdcmdphase=1,
- wrcmdphase=0,
- cl=5,
- cwl=6,
- read_latency=6//2+1,
- write_latency=2//2
- )
-
- self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
- self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb
- self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb
-
- # sys_clk : system clk, used for dfi interface
- # sys2x_clk : 2x system clk
- sd_sys = getattr(self.sync, "sys")
- sd_sys2x = getattr(self.sync, "sys2x")
-
- # select active sys2x phase
- # sys_clk ----____----____
- # phase_sel 0 1 0 1
- phase_sel = Signal()
- phase_sys2x = Signal.like(phase_sel)
- phase_sys = Signal.like(phase_sys2x)
-
- sd_sys += phase_sys.eq(phase_sys2x)
-
- sd_sys2x += [
- If(phase_sys2x == phase_sys,
- phase_sel.eq(0),
- ).Else(
- phase_sel.eq(~phase_sel)
- ),
- phase_sys2x.eq(~phase_sel)
- ]
-
- # DFI adaptation
-
- # Commands and writes
- dfi_omit = set(["rddata", "rddata_valid", "wrdata_en"])
- self.comb += [
- If(~phase_sel,
- self.dfi.phases[0].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit),
- self.dfi.phases[1].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit),
- ).Else(
- self.dfi.phases[2].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit),
- self.dfi.phases[3].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit),
- ),
- ]
- wr_data_en = self.dfi.phases[self.settings.wrphase].wrdata_en & ~phase_sel
- wr_data_en_d = Signal()
- sd_sys2x += wr_data_en_d.eq(wr_data_en)
- self.comb += half_rate_phy.dfi.phases[half_rate_phy.settings.wrphase].wrdata_en.eq(wr_data_en | wr_data_en_d)
-
- # Reads
- rddata = Array(Signal(2*databits) for i in range(2))
- rddata_valid = Signal(2)
-
- for i in range(2):
- sd_sys2x += [
- rddata_valid[i].eq(half_rate_phy.dfi.phases[i].rddata_valid),
- rddata[i].eq(half_rate_phy.dfi.phases[i].rddata)
- ]
-
- sd_sys += [
- self.dfi.phases[0].rddata.eq(rddata[0]),
- self.dfi.phases[0].rddata_valid.eq(rddata_valid[0]),
- self.dfi.phases[1].rddata.eq(rddata[1]),
- self.dfi.phases[1].rddata_valid.eq(rddata_valid[1]),
- self.dfi.phases[2].rddata.eq(half_rate_phy.dfi.phases[0].rddata),
- self.dfi.phases[2].rddata_valid.eq(half_rate_phy.dfi.phases[0].rddata_valid),
- self.dfi.phases[3].rddata.eq(half_rate_phy.dfi.phases[1].rddata),
- self.dfi.phases[3].rddata_valid.eq(half_rate_phy.dfi.phases[1].rddata_valid)
- ]
+++ /dev/null
-from math import ceil
-from collections import namedtuple
-
-from litex.gen import *
-
-
-PhySettingsT = namedtuple("PhySettings", "memtype dfi_databits nphases rdphase wrphase rdcmdphase wrcmdphase cl cwl read_latency write_latency")
-def PhySettings(memtype, dfi_databits, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, read_latency, write_latency, cwl=0):
- return PhySettingsT(memtype, dfi_databits, nphases, rdphase, wrphase, rdcmdphase, wrcmdphase, cl, cwl, read_latency, write_latency)
-
-GeomSettingsT = namedtuple("_GeomSettings", "bankbits rowbits colbits addressbits")
-def GeomSettings(bankbits, rowbits, colbits):
- return GeomSettingsT(bankbits, rowbits, colbits, max(rowbits, colbits))
-
-TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC")
-
-
-# TODO:
-# Try to share the maximum information we can between modules:
-# - ex: MT46V32M16 and MT46H32M16 are almost identical (V=DDR, H=LPDDR)
-# - Modules can have different configuration:
-# MT8JTF12864 (1GB), MT8JTF25664 (2GB)
-# but share all others informations, try to create an unique module for all
-# configurations.
-# - Modules can have different speedgrades, add support for it (and also add
-# a check to verify clk_freq is in the supported range)
-
-
-class SDRAMModule:
- def __init__(self, clk_freq, rate):
- self.clk_freq = clk_freq
- self.rate = rate
- self.geom_settings = GeomSettings(
- bankbits=log2_int(self.nbanks),
- rowbits=log2_int(self.nrows),
- colbits=log2_int(self.ncols),
- )
- self.timing_settings = TimingSettings(
- tRP=self.ns(self.tRP),
- tRCD=self.ns(self.tRCD),
- tWR=self.ns(self.tWR),
- tWTR=self.tWTR,
- tREFI=self.ns(self.tREFI, False),
- tRFC=self.ns(self.tRFC)
- )
-
- def ns(self, t, margin=True):
- clk_period_ns = 1000000000/self.clk_freq
- if margin:
- margins = {
- "1:1" : 0,
- "1:2" : clk_period_ns/2,
- "1:4" : 3*clk_period_ns/4
- }
- t += margins[self.rate]
- return ceil(t/clk_period_ns)
-
-
-# SDR
-class IS42S16160(SDRAMModule):
- memtype = "SDR"
- # geometry
- nbanks = 4
- nrows = 8192
- ncols = 512
- # timings (-7 speedgrade)
- tRP = 20
- tRCD = 20
- tWR = 20
- tWTR = 2
- tREFI = 64*1000*1000/8192
- tRFC = 70
-
-
-class MT48LC4M16(SDRAMModule):
- memtype = "SDR"
- # geometry
- nbanks = 4
- nrows = 4096
- ncols = 256
- # timings (-7 speedgrade)
- tRP = 15
- tRCD = 15
- tWR = 14
- tWTR = 2
- tREFI = 64*1000*1000/4096
- tRFC = 66
-
-
-class AS4C16M16(SDRAMModule):
- memtype = "SDR"
- # geometry
- nbanks = 4
- nrows = 8192
- ncols = 512
- # timings (-6 speedgrade)
- tRP = 18
- tRCD = 18
- tWR = 12
- tWTR = 2
- tREFI = 64*1000*1000/8192
- tRFC = 60
-
-
-# DDR
-class MT46V32M16(SDRAMModule):
- memtype = "DDR"
- # geometry
- nbanks = 4
- nrows = 8192
- ncols = 1024
- # timings (-6 speedgrade)
- tRP = 15
- tRCD = 15
- tWR = 15
- tWTR = 2
- tREFI = 64*1000*1000/8192
- tRFC = 70
-
-
-# LPDDR
-class MT46H32M16(SDRAMModule):
- memtype = "LPDDR"
- # geometry
- nbanks = 4
- nrows = 8192
- ncols = 1024
- # timings
- tRP = 15
- tRCD = 15
- tWR = 15
- tWTR = 2
- tREFI = 64*1000*1000/8192
- tRFC = 72
-
-
-# DDR2
-class MT47H128M8(SDRAMModule):
- memtype = "DDR2"
- # geometry
- nbanks = 8
- nrows = 16384
- ncols = 1024
- # timings
- tRP = 15
- tRCD = 15
- tWR = 15
- tWTR = 2
- tREFI = 7800
- tRFC = 127.5
-
-
-class P3R1GE4JGF(SDRAMModule):
- memtype = "DDR2"
- # geometry
- nbanks = 8
- nrows = 8192
- ncols = 1024
- # timings
- tRP = 12.5
- tRCD = 12.5
- tWR = 15
- tWTR = 3
- tREFI = 7800
- tRFC = 127.5
-
-
-# DDR3
-class MT8JTF12864(SDRAMModule):
- memtype = "DDR3"
- # geometry
- nbanks = 8
- nrows = 16384
- ncols = 1024
- # timings
- tRP = 15
- tRCD = 15
- tWR = 15
- tWTR = 2
- tREFI = 7800
- tRFC = 70
-
-
-class MT41J128M16(SDRAMModule):
- memtype = "DDR3"
- # geometry
- nbanks = 8
- nrows = 16384
- ncols = 1024
- # timings
- tRP = 15
- tRCD = 15
- tWR = 15
- tWTR = 3
- tREFI = 64*1000*1000/16384
- tRFC = 260
+++ /dev/null
-from functools import reduce
-from operator import xor
-
-from litex.gen import *
-
-from litex.soc.interconnect.csr import *
-from litex.soc.interconnect import dma_lasmi
-
-# TODO: implement or replace DMAControllers in MiSoC
-
-
-@ResetInserter()
-@CEInserter()
-class LFSR(Module):
- def __init__(self, n_out, n_state=31, taps=[27, 30]):
- self.o = Signal(n_out)
-
- ###
-
- state = Signal(n_state)
- curval = [state[i] for i in range(n_state)]
- curval += [0]*(n_out - n_state)
- for i in range(n_out):
- nv = ~reduce(xor, [curval[tap] for tap in taps])
- curval.insert(0, nv)
- curval.pop()
-
- self.sync += [
- state.eq(Cat(*curval[:n_state])),
- self.o.eq(Cat(*curval))
- ]
-
-
-memtest_magic = 0x361f
-
-
-class Writer(Module):
- def __init__(self, lasmim):
- self._magic = CSRStatus(16)
- self._reset = CSR()
- self._shoot = CSR()
- self.submodules._dma = DMAWriteController(dma_lasmi.Writer(lasmim),
- MODE_EXTERNAL)
-
- ###
-
- self.comb += self._magic.status.eq(memtest_magic)
-
- lfsr = LFSR(lasmim.dw)
- self.submodules += lfsr
- self.comb += lfsr.reset.eq(self._reset.re)
-
- en = Signal()
- en_counter = Signal(lasmim.aw)
- self.comb += en.eq(en_counter != 0)
- self.sync += [
- If(self._shoot.re,
- en_counter.eq(self._dma.length)
- ).Elif(lfsr.ce,
- en_counter.eq(en_counter - 1)
- )
- ]
-
- self.comb += [
- self._dma.trigger.eq(self._shoot.re),
- self._dma.data.stb.eq(en),
- lfsr.ce.eq(en & self._dma.data.ack),
- self._dma.data.d.eq(lfsr.o)
- ]
-
- def get_csrs(self):
- return [self._magic, self._reset, self._shoot] + self._dma.get_csrs()
-
-
-class Reader(Module):
- def __init__(self, lasmim):
- self._magic = CSRStatus(16)
- self._reset = CSR()
- self._error_count = CSRStatus(lasmim.aw)
- self.submodules._dma = DMAReadController(dma_lasmi.Reader(lasmim),
- MODE_SINGLE_SHOT)
-
- ###
-
- self.comb += self._magic.status.eq(memtest_magic)
-
- lfsr = LFSR(lasmim.dw)
- self.submodules += lfsr
- self.comb += lfsr.reset.eq(self._reset.re)
-
- self.comb += [
- lfsr.ce.eq(self._dma.data.stb),
- self._dma.data.ack.eq(1)
- ]
- err_cnt = self._error_count.status
- self.sync += [
- If(self._reset.re,
- err_cnt.eq(0)
- ).Elif(self._dma.data.stb,
- If(self._dma.data.d != lfsr.o, err_cnt.eq(err_cnt + 1))
- )
- ]
-
- def get_csrs(self):
- return [self._magic, self._reset, self._error_count] + self._dma.get_csrs()
-
-
-class _LFSRTB(Module):
- def __init__(self, *args, **kwargs):
- self.submodules.dut = LFSR(*args, **kwargs)
- self.comb += self.dut.ce.eq(1)
-
- def do_simulation(self, selfp):
- print("{0:032x}".format(selfp.dut.o))
-
-if __name__ == "__main__":
- from litex.gen.fhdl import verilog
- from litex.gen.sim.generic import run_simulation
-
- lfsr = LFSR(3, 4, [3, 2])
- print(verilog.convert(lfsr, ios={lfsr.ce, lfsr.reset, lfsr.o}))
-
- run_simulation(_LFSRTB(128), ncycles=20)
from litex.gen import *
from litex.gen.genlib.record import *
-from litex.soc.interconnect import wishbone, wishbone2lasmi, lasmi_bus
+from litex.soc.interconnect import wishbone
+
+from litex.soc.interconnect import wishbone
from litex.soc.interconnect.csr import AutoCSR
-from litex.soc.cores.sdram import dfii, minicon, lasmicon
from litex.soc.integration.soc_core import *
+from litedram import lasmi_bus
+from litedram.frontend import wishbone2lasmi
+from litedram import dfii, minicon, lasmicon
+
__all__ = ["SoCSDRAM", "soc_sdram_args", "soc_sdram_argdict"]
+++ /dev/null
-from litex.gen import *
-from litex.gen.genlib.record import *
-
-
-def phase_cmd_description(addressbits, bankbits):
- return [
- ("address", addressbits, DIR_M_TO_S),
- ("bank", bankbits, DIR_M_TO_S),
- ("cas_n", 1, DIR_M_TO_S),
- ("cs_n", 1, DIR_M_TO_S),
- ("ras_n", 1, DIR_M_TO_S),
- ("we_n", 1, DIR_M_TO_S),
- ("cke", 1, DIR_M_TO_S),
- ("odt", 1, DIR_M_TO_S),
- ("reset_n", 1, DIR_M_TO_S)
- ]
-
-
-def phase_wrdata_description(databits):
- return [
- ("wrdata", databits, DIR_M_TO_S),
- ("wrdata_en", 1, DIR_M_TO_S),
- ("wrdata_mask", databits//8, DIR_M_TO_S)
- ]
-
-
-def phase_rddata_description(databits):
- return [
- ("rddata_en", 1, DIR_M_TO_S),
- ("rddata", databits, DIR_S_TO_M),
- ("rddata_valid", 1, DIR_S_TO_M)
- ]
-
-
-def phase_description(addressbits, bankbits, databits):
- r = phase_cmd_description(addressbits, bankbits)
- r += phase_wrdata_description(databits)
- r += phase_rddata_description(databits)
- return r
-
-
-class Interface(Record):
- def __init__(self, addressbits, bankbits, databits, nphases=1):
- layout = [("p"+str(i), phase_description(addressbits, bankbits, databits)) for i in range(nphases)]
- Record.__init__(self, layout)
- self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)]
- for p in self.phases:
- p.cas_n.reset = 1
- p.cs_n.reset = 1
- p.ras_n.reset = 1
- p.we_n.reset = 1
-
- # Returns pairs (DFI-mandated signal name, Migen signal object)
- def get_standard_names(self, m2s=True, s2m=True):
- r = []
- add_suffix = len(self.phases) > 1
- for n, phase in enumerate(self.phases):
- for field, size, direction in phase.layout:
- if (m2s and direction == DIR_M_TO_S) or (s2m and direction == DIR_S_TO_M):
- if add_suffix:
- if direction == DIR_M_TO_S:
- suffix = "_p" + str(n)
- else:
- suffix = "_w" + str(n)
- else:
- suffix = ""
- r.append(("dfi_" + field + suffix, getattr(phase, field)))
- return r
-
-
-class Interconnect(Module):
- def __init__(self, master, slave):
- self.comb += master.connect(slave)
+++ /dev/null
-from litex.gen import *
-from litex.gen.genlib.fifo import SyncFIFO
-
-from litex.soc.interconnect import stream
-
-class Reader(Module):
- def __init__(self, lasmim, fifo_depth=None):
- self.sink = sink = stream.Endpoint([("address", lasmim.aw)])
- self.source = source = stream.Endpoint([("data", lasmim.dw)])
- self.busy = Signal()
-
- # # #
-
- if fifo_depth is None:
- fifo_depth = lasmim.req_queue_size + lasmim.read_latency + 2
-
- # request issuance
- request_enable = Signal()
- request_issued = Signal()
-
- self.comb += [
- lasmim.we.eq(0),
- lasmim.stb.eq(sink.valid & request_enable),
- lasmim.adr.eq(sink.address),
- sink.ready.eq(lasmim.req_ack & request_enable),
- request_issued.eq(lasmim.stb & lasmim.req_ack)
- ]
-
- # FIFO reservation level counter
- # incremented when data is planned to be queued
- # decremented when data is dequeued
- data_dequeued = Signal()
- rsv_level = Signal(max=fifo_depth+1)
- self.sync += [
- If(request_issued,
- If(~data_dequeued, rsv_level.eq(rsv_level + 1))
- ).Elif(data_dequeued,
- rsv_level.eq(rsv_level - 1)
- )
- ]
- self.comb += [
- self.busy.eq(rsv_level != 0),
- request_enable.eq(rsv_level != fifo_depth)
- ]
-
- # FIFO
- fifo = SyncFIFO(lasmim.dw, fifo_depth)
- self.submodules += fifo
-
- self.comb += [
- fifo.din.eq(lasmim.dat_r),
- fifo.we.eq(lasmim.dat_r_ack),
-
- source.valid.eq(fifo.readable),
- fifo.re.eq(source.ready),
- source.data.eq(fifo.dout),
- data_dequeued.eq(source.valid & source.ready)
- ]
-
-
-class Writer(Module):
- def __init__(self, lasmim, fifo_depth=None):
- self.source = source = stream.Endpoint([("address", lasmim.aw),
- ("data", lasmim.dw)])
- self.busy = Signal()
-
- # # #
-
- if fifo_depth is None:
- fifo_depth = lasmim.req_queue_size + lasmim.write_latency + 2
-
- fifo = SyncFIFO(lasmim.dw, fifo_depth)
- self.submodules += fifo
-
- self.comb += [
- lasmim.we.eq(1),
- lasmim.stb.eq(fifo.writable & source.valid),
- lasmim.adr.eq(source.address),
- source.ready.eq(fifo.writable & lasmim.req_ack),
- fifo.we.eq(source.valid & lasmim.req_ack),
- fifo.din.eq(source.data)
- ]
-
- self.comb += [
- If(lasmim.dat_w_ack,
- fifo.re.eq(1),
- lasmim.dat_we.eq(2**(lasmim.dw//8)-1),
- lasmim.dat_w.eq(fifo.dout)
- ),
- self.busy.eq(fifo.readable)
- ]
+++ /dev/null
-from functools import reduce
-from operator import or_
-
-from litex.gen import *
-from litex.gen.genlib import roundrobin
-from litex.gen.genlib.record import *
-
-
-class Interface(Record):
- def __init__(self, aw, dw, nbanks, req_queue_size, read_latency, write_latency):
- self.aw = aw
- self.dw = dw
- self.nbanks = nbanks
- self.req_queue_size = req_queue_size
- self.read_latency = read_latency
- self.write_latency = write_latency
-
- bank_layout = [
- ("adr", aw, DIR_M_TO_S),
- ("we", 1, DIR_M_TO_S),
- ("stb", 1, DIR_M_TO_S),
- ("req_ack", 1, DIR_S_TO_M),
- ("dat_w_ack", 1, DIR_S_TO_M),
- ("dat_r_ack", 1, DIR_S_TO_M),
- ("lock", 1, DIR_S_TO_M)
- ]
- if nbanks > 1:
- layout = [("bank"+str(i), bank_layout) for i in range(nbanks)]
- else:
- layout = bank_layout
- layout += [
- ("dat_w", dw, DIR_M_TO_S),
- ("dat_we", dw//8, DIR_M_TO_S),
- ("dat_r", dw, DIR_S_TO_M)
- ]
- Record.__init__(self, layout)
-
-
-def _getattr_all(l, attr):
- it = iter(l)
- r = getattr(next(it), attr)
- for e in it:
- if getattr(e, attr) != r:
- raise ValueError
- return r
-
-
-class LASMIxbar(Module):
- def __init__(self, controllers, cba_shift):
- self._controllers = controllers
- self._cba_shift = cba_shift
-
- self._rca_bits = _getattr_all(controllers, "aw")
- self._dw = _getattr_all(controllers, "dw")
- self._nbanks = _getattr_all(controllers, "nbanks")
- self._req_queue_size = _getattr_all(controllers, "req_queue_size")
- self._read_latency = _getattr_all(controllers, "read_latency")
- self._write_latency = _getattr_all(controllers, "write_latency")
-
- self._bank_bits = log2_int(self._nbanks, False)
- self._controller_bits = log2_int(len(self._controllers), False)
-
- self._masters = []
-
- def get_master(self):
- if self.finalized:
- raise FinalizeError
- lasmi_master = Interface(self._rca_bits + self._bank_bits + self._controller_bits,
- self._dw, 1, self._req_queue_size, self._read_latency, self._write_latency)
- self._masters.append(lasmi_master)
- return lasmi_master
-
- def do_finalize(self):
- nmasters = len(self._masters)
-
- m_ca, m_ba, m_rca = self._split_master_addresses(self._controller_bits,
- self._bank_bits, self._rca_bits, self._cba_shift)
-
- for nc, controller in enumerate(self._controllers):
- if self._controller_bits:
- controller_selected = [ca == nc for ca in m_ca]
- else:
- controller_selected = [1]*nmasters
- master_req_acks = [0]*nmasters
- master_dat_w_acks = [0]*nmasters
- master_dat_r_acks = [0]*nmasters
-
- rrs = [roundrobin.RoundRobin(nmasters, roundrobin.SP_CE) for n in range(self._nbanks)]
- self.submodules += rrs
- for nb, rr in enumerate(rrs):
- bank = getattr(controller, "bank"+str(nb))
-
- # for each master, determine if another bank locks it
- master_locked = []
- for nm, master in enumerate(self._masters):
- locked = 0
- for other_nb, other_rr in enumerate(rrs):
- if other_nb != nb:
- other_bank = getattr(controller, "bank"+str(other_nb))
- locked = locked | (other_bank.lock & (other_rr.grant == nm))
- master_locked.append(locked)
-
- # arbitrate
- bank_selected = [cs & (ba == nb) & ~locked for cs, ba, locked in zip(controller_selected, m_ba, master_locked)]
- bank_requested = [bs & master.stb for bs, master in zip(bank_selected, self._masters)]
- self.comb += [
- rr.request.eq(Cat(*bank_requested)),
- rr.ce.eq(~bank.stb & ~bank.lock)
- ]
-
- # route requests
- self.comb += [
- bank.adr.eq(Array(m_rca)[rr.grant]),
- bank.we.eq(Array(self._masters)[rr.grant].we),
- bank.stb.eq(Array(bank_requested)[rr.grant])
- ]
- master_req_acks = [master_req_ack | ((rr.grant == nm) & bank_selected[nm] & bank.req_ack)
- for nm, master_req_ack in enumerate(master_req_acks)]
- master_dat_w_acks = [master_dat_w_ack | ((rr.grant == nm) & bank.dat_w_ack)
- for nm, master_dat_w_ack in enumerate(master_dat_w_acks)]
- master_dat_r_acks = [master_dat_r_ack | ((rr.grant == nm) & bank.dat_r_ack)
- for nm, master_dat_r_ack in enumerate(master_dat_r_acks)]
-
- for nm, master_dat_w_ack in enumerate(master_dat_w_acks):
- for i in range(self._write_latency):
- new_master_dat_w_ack = Signal()
- self.sync += new_master_dat_w_ack.eq(master_dat_w_ack)
- master_dat_w_ack = new_master_dat_w_ack
- master_dat_w_acks[nm] = master_dat_w_ack
-
- for nm, master_dat_r_ack in enumerate(master_dat_r_acks):
- for i in range(self._read_latency):
- new_master_dat_r_ack = Signal()
- self.sync += new_master_dat_r_ack.eq(master_dat_r_ack)
- master_dat_r_ack = new_master_dat_r_ack
- master_dat_r_acks[nm] = master_dat_r_ack
-
- self.comb += [master.req_ack.eq(master_req_ack) for master, master_req_ack in zip(self._masters, master_req_acks)]
- self.comb += [master.dat_w_ack.eq(master_dat_w_ack) for master, master_dat_w_ack in zip(self._masters, master_dat_w_acks)]
- self.comb += [master.dat_r_ack.eq(master_dat_r_ack) for master, master_dat_r_ack in zip(self._masters, master_dat_r_acks)]
-
- # route data writes
- controller_selected_wl = controller_selected
- for i in range(self._write_latency):
- n_controller_selected_wl = [Signal() for i in range(nmasters)]
- self.sync += [n.eq(o) for n, o in zip(n_controller_selected_wl, controller_selected_wl)]
- controller_selected_wl = n_controller_selected_wl
- dat_w_maskselect = []
- dat_we_maskselect = []
- for master, selected in zip(self._masters, controller_selected_wl):
- o_dat_w = Signal(self._dw)
- o_dat_we = Signal(self._dw//8)
- self.comb += If(selected,
- o_dat_w.eq(master.dat_w),
- o_dat_we.eq(master.dat_we)
- )
- dat_w_maskselect.append(o_dat_w)
- dat_we_maskselect.append(o_dat_we)
- self.comb += [
- controller.dat_w.eq(reduce(or_, dat_w_maskselect)),
- controller.dat_we.eq(reduce(or_, dat_we_maskselect))
- ]
-
- # route data reads
- if self._controller_bits:
- for master in self._masters:
- controller_sel = Signal(self._controller_bits)
- for nc, controller in enumerate(self._controllers):
- for nb in range(nbanks):
- bank = getattr(controller, "bank"+str(nb))
- self.comb += If(bank.stb & bank.ack, controller_sel.eq(nc))
- for i in range(self._read_latency):
- n_controller_sel = Signal(self._controller_bits)
- self.sync += n_controller_sel.eq(controller_sel)
- controller_sel = n_controller_sel
- self.comb += master.dat_r.eq(Array(self._controllers)[controller_sel].dat_r)
- else:
- self.comb += [master.dat_r.eq(self._controllers[0].dat_r) for master in self._masters]
-
- def _split_master_addresses(self, controller_bits, bank_bits, rca_bits, cba_shift):
- m_ca = [] # controller address
- m_ba = [] # bank address
- m_rca = [] # row and column address
- for master in self._masters:
- cba = Signal(self._controller_bits + self._bank_bits)
- rca = Signal(self._rca_bits)
- cba_upper = cba_shift + controller_bits + bank_bits
- self.comb += cba.eq(master.adr[cba_shift:cba_upper])
- if cba_shift < self._rca_bits:
- if cba_shift:
- self.comb += rca.eq(Cat(master.adr[:cba_shift], master.adr[cba_upper:]))
- else:
- self.comb += rca.eq(master.adr[cba_upper:])
- else:
- self.comb += rca.eq(master.adr[:cba_shift])
-
- if self._controller_bits:
- ca = Signal(self._controller_bits)
- ba = Signal(self._bank_bits)
- self.comb += Cat(ba, ca).eq(cba)
- else:
- ca = None
- ba = cba
-
- m_ca.append(ca)
- m_ba.append(ba)
- m_rca.append(rca)
- return m_ca, m_ba, m_rca
+++ /dev/null
-from litex.gen import *
-from litex.gen.genlib.fsm import FSM, NextState
-
-
-class WB2LASMI(Module):
- def __init__(self, wishbone, lasmim):
-
- ###
-
- # Control FSM
- self.submodules.fsm = fsm = FSM(reset_state="IDLE")
- fsm.act("IDLE",
- If(wishbone.cyc & wishbone.stb,
- NextState("REQUEST")
- )
- )
- fsm.act("REQUEST",
- lasmim.stb.eq(1),
- lasmim.we.eq(wishbone.we),
- If(lasmim.req_ack,
- If(wishbone.we,
- NextState("WRITE_DATA")
- ).Else(
- NextState("READ_DATA")
- )
- )
- )
- fsm.act("WRITE_DATA",
- If(lasmim.dat_w_ack,
- lasmim.dat_we.eq(wishbone.sel),
- wishbone.ack.eq(1),
- NextState("IDLE")
- )
- )
- fsm.act("READ_DATA",
- If(lasmim.dat_r_ack,
- wishbone.ack.eq(1),
- NextState("IDLE")
- )
- )
-
- # Address / Datapath
- self.comb += [
- lasmim.adr.eq(wishbone.adr),
- If(lasmim.dat_w_ack,
- lasmim.dat_w.eq(wishbone.dat_w),
- ),
- wishbone.dat_r.eq(lasmim.dat_r)
- ]
}
}
+#ifdef CSR_DDRPHY_BASE
int sdrlevel_generic(void)
{
int delay[DFII_PIX_DATA_SIZE/2];
return 1;
}
+#ifdef SDRAM_ISERDESE2_BITSLIP
static int sdrlevel_artix7(void)
{
int bitslip, delay, module;
}
return 1;
}
+#endif
int sdrlevel(void)
{
return 0;
#endif
}
+#endif
int sdrinit(void)
{