From 66362b128019fb2703a9a3af1a8d58b6d7f6639b Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 29 Apr 2016 07:21:42 +0200 Subject: [PATCH] move sdram code to litedram (https://github.com/enjoy-digital/litedram) --- litex/boards/targets/de0nano.py | 5 +- litex/boards/targets/kc705.py | 5 +- litex/boards/targets/minispartan6.py | 5 +- litex/boards/targets/sim.py | 5 +- litex/soc/cores/sdram/__init__.py | 0 litex/soc/cores/sdram/dfii.py | 60 --- litex/soc/cores/sdram/lasmicon/__init__.py | 1 - litex/soc/cores/sdram/lasmicon/bankmachine.py | 153 ------ litex/soc/cores/sdram/lasmicon/core.py | 53 -- litex/soc/cores/sdram/lasmicon/multiplexer.py | 222 -------- litex/soc/cores/sdram/lasmicon/perf.py | 47 -- litex/soc/cores/sdram/lasmicon/refresher.py | 69 --- litex/soc/cores/sdram/minicon/__init__.py | 1 - litex/soc/cores/sdram/minicon/core.py | 235 --------- litex/soc/cores/sdram/model.py | 197 ------- litex/soc/cores/sdram/phy/__init__.py | 3 - litex/soc/cores/sdram/phy/gensdrphy.py | 95 ---- litex/soc/cores/sdram/phy/k7ddrphy.py | 292 ----------- litex/soc/cores/sdram/phy/s6ddrphy.py | 488 ------------------ litex/soc/cores/sdram/settings.py | 196 ------- litex/soc/cores/sdram/tester.py | 123 ----- litex/soc/integration/soc_sdram.py | 9 +- litex/soc/interconnect/dfi.py | 73 --- litex/soc/interconnect/dma_lasmi.py | 91 ---- litex/soc/interconnect/lasmi_bus.py | 208 -------- litex/soc/interconnect/wishbone2lasmi.py | 49 -- litex/soc/software/bios/sdram.c | 4 + 27 files changed, 23 insertions(+), 2666 deletions(-) delete mode 100644 litex/soc/cores/sdram/__init__.py delete mode 100644 litex/soc/cores/sdram/dfii.py delete mode 100644 litex/soc/cores/sdram/lasmicon/__init__.py delete mode 100644 litex/soc/cores/sdram/lasmicon/bankmachine.py delete mode 100644 litex/soc/cores/sdram/lasmicon/core.py delete mode 100644 litex/soc/cores/sdram/lasmicon/multiplexer.py delete mode 100644 litex/soc/cores/sdram/lasmicon/perf.py delete mode 100644 litex/soc/cores/sdram/lasmicon/refresher.py delete mode 100644 litex/soc/cores/sdram/minicon/__init__.py delete mode 100644 litex/soc/cores/sdram/minicon/core.py delete mode 100644 litex/soc/cores/sdram/model.py delete mode 100644 litex/soc/cores/sdram/phy/__init__.py delete mode 100644 litex/soc/cores/sdram/phy/gensdrphy.py delete mode 100644 litex/soc/cores/sdram/phy/k7ddrphy.py delete mode 100644 litex/soc/cores/sdram/phy/s6ddrphy.py delete mode 100644 litex/soc/cores/sdram/settings.py delete mode 100644 litex/soc/cores/sdram/tester.py delete mode 100644 litex/soc/interconnect/dfi.py delete mode 100644 litex/soc/interconnect/dma_lasmi.py delete mode 100644 litex/soc/interconnect/lasmi_bus.py delete mode 100644 litex/soc/interconnect/wishbone2lasmi.py diff --git a/litex/boards/targets/de0nano.py b/litex/boards/targets/de0nano.py index c0a4c6ddb..63ac8f8fa 100755 --- a/litex/boards/targets/de0nano.py +++ b/litex/boards/targets/de0nano.py @@ -5,11 +5,12 @@ import argparse 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): diff --git a/litex/boards/targets/kc705.py b/litex/boards/targets/kc705.py index a77f6f958..14c8696c5 100755 --- a/litex/boards/targets/kc705.py +++ b/litex/boards/targets/kc705.py @@ -6,13 +6,14 @@ from litex.gen import * 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 diff --git a/litex/boards/targets/minispartan6.py b/litex/boards/targets/minispartan6.py index 19df78abf..082441db9 100755 --- a/litex/boards/targets/minispartan6.py +++ b/litex/boards/targets/minispartan6.py @@ -7,11 +7,12 @@ from litex.gen import * 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): diff --git a/litex/boards/targets/sim.py b/litex/boards/targets/sim.py index c6d972e2c..ecc5c7c1f 100755 --- a/litex/boards/targets/sim.py +++ b/litex/boards/targets/sim.py @@ -10,10 +10,11 @@ from litex.gen.genlib.io import CRG 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 diff --git a/litex/soc/cores/sdram/__init__.py b/litex/soc/cores/sdram/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/litex/soc/cores/sdram/dfii.py b/litex/soc/cores/sdram/dfii.py deleted file mode 100644 index 6051dddae..000000000 --- a/litex/soc/cores/sdram/dfii.py +++ /dev/null @@ -1,60 +0,0 @@ -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")] diff --git a/litex/soc/cores/sdram/lasmicon/__init__.py b/litex/soc/cores/sdram/lasmicon/__init__.py deleted file mode 100644 index 9242b76b5..000000000 --- a/litex/soc/cores/sdram/lasmicon/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from litex.soc.cores.sdram.lasmicon.core import ControllerSettings, LASMIcon diff --git a/litex/soc/cores/sdram/lasmicon/bankmachine.py b/litex/soc/cores/sdram/lasmicon/bankmachine.py deleted file mode 100644 index 7a9b26c87..000000000 --- a/litex/soc/cores/sdram/lasmicon/bankmachine.py +++ /dev/null @@ -1,153 +0,0 @@ -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) diff --git a/litex/soc/cores/sdram/lasmicon/core.py b/litex/soc/cores/sdram/lasmicon/core.py deleted file mode 100644 index a6625015f..000000000 --- a/litex/soc/cores/sdram/lasmicon/core.py +++ /dev/null @@ -1,53 +0,0 @@ -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() diff --git a/litex/soc/cores/sdram/lasmicon/multiplexer.py b/litex/soc/cores/sdram/lasmicon/multiplexer.py deleted file mode 100644 index af118c502..000000000 --- a/litex/soc/cores/sdram/lasmicon/multiplexer.py +++ /dev/null @@ -1,222 +0,0 @@ -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) diff --git a/litex/soc/cores/sdram/lasmicon/perf.py b/litex/soc/cores/sdram/lasmicon/perf.py deleted file mode 100644 index dbd62d3a6..000000000 --- a/litex/soc/cores/sdram/lasmicon/perf.py +++ /dev/null @@ -1,47 +0,0 @@ -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) - ) - ] diff --git a/litex/soc/cores/sdram/lasmicon/refresher.py b/litex/soc/cores/sdram/lasmicon/refresher.py deleted file mode 100644 index e4c5da92c..000000000 --- a/litex/soc/cores/sdram/lasmicon/refresher.py +++ /dev/null @@ -1,69 +0,0 @@ -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")) - ) diff --git a/litex/soc/cores/sdram/minicon/__init__.py b/litex/soc/cores/sdram/minicon/__init__.py deleted file mode 100644 index 4b265e260..000000000 --- a/litex/soc/cores/sdram/minicon/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from litex.soc.cores.sdram.minicon.core import Minicon diff --git a/litex/soc/cores/sdram/minicon/core.py b/litex/soc/cores/sdram/minicon/core.py deleted file mode 100644 index 13600b7fc..000000000 --- a/litex/soc/cores/sdram/minicon/core.py +++ /dev/null @@ -1,235 +0,0 @@ -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), - ] diff --git a/litex/soc/cores/sdram/model.py b/litex/soc/cores/sdram/model.py deleted file mode 100644 index a8792250a..000000000 --- a/litex/soc/cores/sdram/model.py +++ /dev/null @@ -1,197 +0,0 @@ -# This file is Copyright (c) 2015 Florent Kermarrec -# 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) - ] diff --git a/litex/soc/cores/sdram/phy/__init__.py b/litex/soc/cores/sdram/phy/__init__.py deleted file mode 100644 index 551c30915..000000000 --- a/litex/soc/cores/sdram/phy/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -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 diff --git a/litex/soc/cores/sdram/phy/gensdrphy.py b/litex/soc/cores/sdram/phy/gensdrphy.py deleted file mode 100644 index 303faeb0b..000000000 --- a/litex/soc/cores/sdram/phy/gensdrphy.py +++ /dev/null @@ -1,95 +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 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])) diff --git a/litex/soc/cores/sdram/phy/k7ddrphy.py b/litex/soc/cores/sdram/phy/k7ddrphy.py deleted file mode 100644 index 385bbc9bb..000000000 --- a/litex/soc/cores/sdram/phy/k7ddrphy.py +++ /dev/null @@ -1,292 +0,0 @@ -# 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) - ) diff --git a/litex/soc/cores/sdram/phy/s6ddrphy.py b/litex/soc/cores/sdram/phy/s6ddrphy.py deleted file mode 100644 index 8fe77a53c..000000000 --- a/litex/soc/cores/sdram/phy/s6ddrphy.py +++ /dev/null @@ -1,488 +0,0 @@ -# 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) - ] diff --git a/litex/soc/cores/sdram/settings.py b/litex/soc/cores/sdram/settings.py deleted file mode 100644 index 6f61d1be5..000000000 --- a/litex/soc/cores/sdram/settings.py +++ /dev/null @@ -1,196 +0,0 @@ -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 diff --git a/litex/soc/cores/sdram/tester.py b/litex/soc/cores/sdram/tester.py deleted file mode 100644 index 28b0318e4..000000000 --- a/litex/soc/cores/sdram/tester.py +++ /dev/null @@ -1,123 +0,0 @@ -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) diff --git a/litex/soc/integration/soc_sdram.py b/litex/soc/integration/soc_sdram.py index da1914143..4a6efa875 100644 --- a/litex/soc/integration/soc_sdram.py +++ b/litex/soc/integration/soc_sdram.py @@ -1,11 +1,16 @@ 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"] diff --git a/litex/soc/interconnect/dfi.py b/litex/soc/interconnect/dfi.py deleted file mode 100644 index 25812122e..000000000 --- a/litex/soc/interconnect/dfi.py +++ /dev/null @@ -1,73 +0,0 @@ -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) diff --git a/litex/soc/interconnect/dma_lasmi.py b/litex/soc/interconnect/dma_lasmi.py deleted file mode 100644 index f104ee014..000000000 --- a/litex/soc/interconnect/dma_lasmi.py +++ /dev/null @@ -1,91 +0,0 @@ -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) - ] diff --git a/litex/soc/interconnect/lasmi_bus.py b/litex/soc/interconnect/lasmi_bus.py deleted file mode 100644 index 841b72b16..000000000 --- a/litex/soc/interconnect/lasmi_bus.py +++ /dev/null @@ -1,208 +0,0 @@ -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 diff --git a/litex/soc/interconnect/wishbone2lasmi.py b/litex/soc/interconnect/wishbone2lasmi.py deleted file mode 100644 index bd139afa3..000000000 --- a/litex/soc/interconnect/wishbone2lasmi.py +++ /dev/null @@ -1,49 +0,0 @@ -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) - ] diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 8bc3bb063..3a8131400 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -556,6 +556,7 @@ int memtest(void) } } +#ifdef CSR_DDRPHY_BASE int sdrlevel_generic(void) { int delay[DFII_PIX_DATA_SIZE/2]; @@ -569,6 +570,7 @@ int sdrlevel_generic(void) return 1; } +#ifdef SDRAM_ISERDESE2_BITSLIP static int sdrlevel_artix7(void) { int bitslip, delay, module; @@ -587,6 +589,7 @@ static int sdrlevel_artix7(void) } return 1; } +#endif int sdrlevel(void) { @@ -598,6 +601,7 @@ int sdrlevel(void) return 0; #endif } +#endif int sdrinit(void) {