misoclib -> misoc
authorSebastien Bourdeauducq <sb@m-labs.hk>
Tue, 22 Sep 2015 16:35:02 +0000 (00:35 +0800)
committerSebastien Bourdeauducq <sb@m-labs.hk>
Tue, 22 Sep 2015 16:35:02 +0000 (00:35 +0800)
207 files changed:
make.py
misoc/__init__.py [new file with mode: 0644]
misoc/com/__init__.py [new file with mode: 0644]
misoc/com/gpio.py [new file with mode: 0644]
misoc/com/liteethmini/LICENSE [new file with mode: 0644]
misoc/com/liteethmini/README [new file with mode: 0644]
misoc/com/liteethmini/__init__.py [new file with mode: 0644]
misoc/com/liteethmini/common.py [new file with mode: 0644]
misoc/com/liteethmini/mac/__init__.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/__init__.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/crc.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/gap.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/last_be.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/padding.py [new file with mode: 0644]
misoc/com/liteethmini/mac/core/preamble.py [new file with mode: 0644]
misoc/com/liteethmini/mac/frontend/__init__.py [new file with mode: 0644]
misoc/com/liteethmini/mac/frontend/sram.py [new file with mode: 0644]
misoc/com/liteethmini/mac/frontend/wishbone.py [new file with mode: 0644]
misoc/com/liteethmini/phy/__init__.py [new file with mode: 0644]
misoc/com/liteethmini/phy/gmii.py [new file with mode: 0644]
misoc/com/liteethmini/phy/gmii_mii.py [new file with mode: 0644]
misoc/com/liteethmini/phy/loopback.py [new file with mode: 0644]
misoc/com/liteethmini/phy/mii.py [new file with mode: 0644]
misoc/com/liteethmini/phy/s6rgmii.py [new file with mode: 0644]
misoc/com/liteethmini/phy/sim.py [new file with mode: 0644]
misoc/com/spi/__init__.py [new file with mode: 0644]
misoc/com/spi/test/spi_master_tb.py [new file with mode: 0644]
misoc/com/uart/__init__.py [new file with mode: 0644]
misoc/com/uart/bridge.py [new file with mode: 0644]
misoc/com/uart/phy/__init__.py [new file with mode: 0644]
misoc/com/uart/phy/serial.py [new file with mode: 0644]
misoc/com/uart/phy/sim.py [new file with mode: 0644]
misoc/com/uart/software/__init__.py [new file with mode: 0644]
misoc/com/uart/software/reg.py [new file with mode: 0644]
misoc/com/uart/software/wishbone.py [new file with mode: 0644]
misoc/com/uart/test/test_serial_phy.py [new file with mode: 0644]
misoc/cpu/__init__.py [new file with mode: 0644]
misoc/cpu/identifier.py [new file with mode: 0644]
misoc/cpu/lm32.py [new file with mode: 0644]
misoc/cpu/mor1kx.py [new file with mode: 0644]
misoc/cpu/timer.py [new file with mode: 0644]
misoc/mem/__init__.py [new file with mode: 0644]
misoc/mem/flash/__init__.py [new file with mode: 0644]
misoc/mem/flash/norflash16.py [new file with mode: 0644]
misoc/mem/flash/spiflash.py [new file with mode: 0644]
misoc/mem/sdram/__init__.py [new file with mode: 0644]
misoc/mem/sdram/core/__init__.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmibus.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmicon/__init__.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmicon/bankmachine.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmicon/multiplexer.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmicon/perf.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmicon/refresher.py [new file with mode: 0644]
misoc/mem/sdram/core/lasmixbar.py [new file with mode: 0644]
misoc/mem/sdram/core/minicon/__init__.py [new file with mode: 0644]
misoc/mem/sdram/frontend/__init__.py [new file with mode: 0644]
misoc/mem/sdram/frontend/dma_lasmi.py [new file with mode: 0644]
misoc/mem/sdram/frontend/memtest.py [new file with mode: 0644]
misoc/mem/sdram/frontend/wishbone2lasmi.py [new file with mode: 0644]
misoc/mem/sdram/module.py [new file with mode: 0644]
misoc/mem/sdram/phy/__init__.py [new file with mode: 0644]
misoc/mem/sdram/phy/dfi.py [new file with mode: 0644]
misoc/mem/sdram/phy/dfii.py [new file with mode: 0644]
misoc/mem/sdram/phy/gensdrphy.py [new file with mode: 0644]
misoc/mem/sdram/phy/initsequence.py [new file with mode: 0644]
misoc/mem/sdram/phy/k7ddrphy.py [new file with mode: 0644]
misoc/mem/sdram/phy/s6ddrphy.py [new file with mode: 0644]
misoc/mem/sdram/phy/simphy.py [new file with mode: 0644]
misoc/mem/sdram/test/abstract_transactions_lasmi.py [new file with mode: 0644]
misoc/mem/sdram/test/bankmachine_tb.py [new file with mode: 0644]
misoc/mem/sdram/test/common.py [new file with mode: 0644]
misoc/mem/sdram/test/lasmicon_df_tb.py [new file with mode: 0644]
misoc/mem/sdram/test/lasmicon_tb.py [new file with mode: 0644]
misoc/mem/sdram/test/lasmicon_wb.py [new file with mode: 0644]
misoc/mem/sdram/test/minicon_tb.py [new file with mode: 0644]
misoc/mem/sdram/test/refresher.py [new file with mode: 0644]
misoc/mxcrg.v [new file with mode: 0644]
misoc/soc/__init__.py [new file with mode: 0644]
misoc/soc/cpuif.py [new file with mode: 0644]
misoc/soc/sdram.py [new file with mode: 0644]
misoc/tools/__init__.py [new file with mode: 0644]
misoc/tools/wishbone.py [new file with mode: 0644]
misoc/video/__init__.py [new file with mode: 0644]
misoc/video/dvisampler/__init__.py [new file with mode: 0644]
misoc/video/dvisampler/analysis.py [new file with mode: 0644]
misoc/video/dvisampler/chansync.py [new file with mode: 0644]
misoc/video/dvisampler/charsync.py [new file with mode: 0644]
misoc/video/dvisampler/clocking.py [new file with mode: 0644]
misoc/video/dvisampler/common.py [new file with mode: 0644]
misoc/video/dvisampler/datacapture.py [new file with mode: 0644]
misoc/video/dvisampler/debug.py [new file with mode: 0644]
misoc/video/dvisampler/decoding.py [new file with mode: 0644]
misoc/video/dvisampler/dma.py [new file with mode: 0644]
misoc/video/dvisampler/edid.py [new file with mode: 0644]
misoc/video/dvisampler/wer.py [new file with mode: 0644]
misoc/video/framebuffer/__init__.py [new file with mode: 0644]
misoc/video/framebuffer/dvi.py [new file with mode: 0644]
misoc/video/framebuffer/format.py [new file with mode: 0644]
misoc/video/framebuffer/phy.py [new file with mode: 0644]
misoclib/__init__.py [deleted file]
misoclib/com/__init__.py [deleted file]
misoclib/com/gpio.py [deleted file]
misoclib/com/liteethmini/LICENSE [deleted file]
misoclib/com/liteethmini/README [deleted file]
misoclib/com/liteethmini/__init__.py [deleted file]
misoclib/com/liteethmini/common.py [deleted file]
misoclib/com/liteethmini/mac/__init__.py [deleted file]
misoclib/com/liteethmini/mac/core/__init__.py [deleted file]
misoclib/com/liteethmini/mac/core/crc.py [deleted file]
misoclib/com/liteethmini/mac/core/gap.py [deleted file]
misoclib/com/liteethmini/mac/core/last_be.py [deleted file]
misoclib/com/liteethmini/mac/core/padding.py [deleted file]
misoclib/com/liteethmini/mac/core/preamble.py [deleted file]
misoclib/com/liteethmini/mac/frontend/__init__.py [deleted file]
misoclib/com/liteethmini/mac/frontend/sram.py [deleted file]
misoclib/com/liteethmini/mac/frontend/wishbone.py [deleted file]
misoclib/com/liteethmini/phy/__init__.py [deleted file]
misoclib/com/liteethmini/phy/gmii.py [deleted file]
misoclib/com/liteethmini/phy/gmii_mii.py [deleted file]
misoclib/com/liteethmini/phy/loopback.py [deleted file]
misoclib/com/liteethmini/phy/mii.py [deleted file]
misoclib/com/liteethmini/phy/s6rgmii.py [deleted file]
misoclib/com/liteethmini/phy/sim.py [deleted file]
misoclib/com/spi/__init__.py [deleted file]
misoclib/com/spi/test/spi_master_tb.py [deleted file]
misoclib/com/uart/__init__.py [deleted file]
misoclib/com/uart/bridge.py [deleted file]
misoclib/com/uart/phy/__init__.py [deleted file]
misoclib/com/uart/phy/serial.py [deleted file]
misoclib/com/uart/phy/sim.py [deleted file]
misoclib/com/uart/software/__init__.py [deleted file]
misoclib/com/uart/software/reg.py [deleted file]
misoclib/com/uart/software/wishbone.py [deleted file]
misoclib/com/uart/test/test_serial_phy.py [deleted file]
misoclib/cpu/__init__.py [deleted file]
misoclib/cpu/identifier.py [deleted file]
misoclib/cpu/lm32.py [deleted file]
misoclib/cpu/mor1kx.py [deleted file]
misoclib/cpu/timer.py [deleted file]
misoclib/mem/__init__.py [deleted file]
misoclib/mem/flash/__init__.py [deleted file]
misoclib/mem/flash/norflash16.py [deleted file]
misoclib/mem/flash/spiflash.py [deleted file]
misoclib/mem/sdram/__init__.py [deleted file]
misoclib/mem/sdram/core/__init__.py [deleted file]
misoclib/mem/sdram/core/lasmibus.py [deleted file]
misoclib/mem/sdram/core/lasmicon/__init__.py [deleted file]
misoclib/mem/sdram/core/lasmicon/bankmachine.py [deleted file]
misoclib/mem/sdram/core/lasmicon/multiplexer.py [deleted file]
misoclib/mem/sdram/core/lasmicon/perf.py [deleted file]
misoclib/mem/sdram/core/lasmicon/refresher.py [deleted file]
misoclib/mem/sdram/core/lasmixbar.py [deleted file]
misoclib/mem/sdram/core/minicon/__init__.py [deleted file]
misoclib/mem/sdram/frontend/__init__.py [deleted file]
misoclib/mem/sdram/frontend/dma_lasmi.py [deleted file]
misoclib/mem/sdram/frontend/memtest.py [deleted file]
misoclib/mem/sdram/frontend/wishbone2lasmi.py [deleted file]
misoclib/mem/sdram/module.py [deleted file]
misoclib/mem/sdram/phy/__init__.py [deleted file]
misoclib/mem/sdram/phy/dfi.py [deleted file]
misoclib/mem/sdram/phy/dfii.py [deleted file]
misoclib/mem/sdram/phy/gensdrphy.py [deleted file]
misoclib/mem/sdram/phy/initsequence.py [deleted file]
misoclib/mem/sdram/phy/k7ddrphy.py [deleted file]
misoclib/mem/sdram/phy/s6ddrphy.py [deleted file]
misoclib/mem/sdram/phy/simphy.py [deleted file]
misoclib/mem/sdram/test/abstract_transactions_lasmi.py [deleted file]
misoclib/mem/sdram/test/bankmachine_tb.py [deleted file]
misoclib/mem/sdram/test/common.py [deleted file]
misoclib/mem/sdram/test/lasmicon_df_tb.py [deleted file]
misoclib/mem/sdram/test/lasmicon_tb.py [deleted file]
misoclib/mem/sdram/test/lasmicon_wb.py [deleted file]
misoclib/mem/sdram/test/minicon_tb.py [deleted file]
misoclib/mem/sdram/test/refresher.py [deleted file]
misoclib/mxcrg.v [deleted file]
misoclib/soc/__init__.py [deleted file]
misoclib/soc/cpuif.py [deleted file]
misoclib/soc/sdram.py [deleted file]
misoclib/tools/__init__.py [deleted file]
misoclib/tools/wishbone.py [deleted file]
misoclib/video/__init__.py [deleted file]
misoclib/video/dvisampler/__init__.py [deleted file]
misoclib/video/dvisampler/analysis.py [deleted file]
misoclib/video/dvisampler/chansync.py [deleted file]
misoclib/video/dvisampler/charsync.py [deleted file]
misoclib/video/dvisampler/clocking.py [deleted file]
misoclib/video/dvisampler/common.py [deleted file]
misoclib/video/dvisampler/datacapture.py [deleted file]
misoclib/video/dvisampler/debug.py [deleted file]
misoclib/video/dvisampler/decoding.py [deleted file]
misoclib/video/dvisampler/dma.py [deleted file]
misoclib/video/dvisampler/edid.py [deleted file]
misoclib/video/dvisampler/wer.py [deleted file]
misoclib/video/framebuffer/__init__.py [deleted file]
misoclib/video/framebuffer/dvi.py [deleted file]
misoclib/video/framebuffer/format.py [deleted file]
misoclib/video/framebuffer/phy.py [deleted file]
setup.py
software/common.mak
targets/de0nano.py
targets/kc705.py
targets/minispartan6.py
targets/mlabs_video.py
targets/pipistrello.py
targets/ppro.py
targets/simple.py
targets/versa.py

diff --git a/make.py b/make.py
index 2d1c51b3ffaf28ebf6e816232faf40fadcc052a6..28b3722344cb7c6261cebde78eb6c7b0f20a15d7 100755 (executable)
--- a/make.py
+++ b/make.py
@@ -11,8 +11,8 @@ from mibuild.tools import write_to_file
 from migen.util.misc import autotype
 from migen.fhdl import simplify
 
-from misoclib.soc import cpuif
-from misoclib.mem.sdram.phy import initsequence
+from misoc.soc import cpuif
+from misoc.mem.sdram.phy import initsequence
 
 from misoc_import import misoc_import
 
diff --git a/misoc/__init__.py b/misoc/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/com/__init__.py b/misoc/com/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/com/gpio.py b/misoc/com/gpio.py
new file mode 100644 (file)
index 0000000..88a4904
--- /dev/null
@@ -0,0 +1,31 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.bank.description import *
+
+
+class GPIOIn(Module, AutoCSR):
+    def __init__(self, signal):
+        self._in = CSRStatus(flen(signal))
+        self.specials += MultiReg(signal, self._in.status)
+
+
+class GPIOOut(Module, AutoCSR):
+    def __init__(self, signal):
+        self._out = CSRStorage(flen(signal))
+        self.comb += signal.eq(self._out.storage)
+
+
+class GPIOInOut(Module):
+    def __init__(self, in_signal, out_signal):
+        self.submodules.gpio_in = GPIOIn(in_signal)
+        self.submodules.gpio_out = GPIOOut(out_signal)
+
+    def get_csrs(self):
+        return self.gpio_in.get_csrs() + self.gpio_out.get_csrs()
+
+
+class Blinker(Module):
+    def __init__(self, signal, divbits=26):
+        counter = Signal(divbits)
+        self.comb += signal.eq(counter[divbits-1])
+        self.sync += counter.eq(counter + 1)
diff --git a/misoc/com/liteethmini/LICENSE b/misoc/com/liteethmini/LICENSE
new file mode 100644 (file)
index 0000000..cbbfe8b
--- /dev/null
@@ -0,0 +1,28 @@
+Unless otherwise noted, LiteEth is copyright (C) 2015 Florent Kermarrec.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Other authors retain ownership of their contributions. If a submission can
+reasonably be considered independently copyrightable, it's yours and we
+encourage you to claim it with appropriate copyright notices. This submission
+then falls under the "otherwise noted" category. All submissions are strongly
+encouraged to use the two-clause BSD license reproduced above.
diff --git a/misoc/com/liteethmini/README b/misoc/com/liteethmini/README
new file mode 100644 (file)
index 0000000..595d2fc
--- /dev/null
@@ -0,0 +1,58 @@
+         __   _ __      ______  __   __  ____      _
+        / /  (_) /____ / __/ /_/ /  /  |/  (_)__  (_)
+       / /__/ / __/ -_) _// __/ _ \/ /|_/ / / _ \/ /
+      /____/_/\__/\__/___/\__/_//_/_/  /_/_/_//_/_/
+
+        Copyright 2012-2015 / EnjoyDigital / M-Labs Ltd
+
+   A small footprint and configurable minimal Ethernet core
+                  powered by Migen
+
+[> Intro
+---------
+LiteEthMini is a subset of LiteEth (https://github.com/enjoy-digital/liteeth)
+intended to be used with a CPU and a software stack.
+
+[> Features
+-----------
+- Ethernet MAC with various various PHYs (GMII, MII, RGMII, Loopback)
+- SRAM storage and wishbone interface
+
+[> Possible improvements
+-------------------------
+- add DMA interface to MAC
+- add SGMII PHY
+- ... See below Support and consulting :)
+
+If you want to support these features, please contact us at florent [AT]
+enjoy-digital.fr. You can also contact our partner on the public mailing list
+devel [AT] lists.m-labs.hk.
+
+[> License
+-----------
+LiteEthMini is released under the very permissive two-clause BSD license. Under
+the terms of this license, you are authorized to use LiteEthMini for closed-source
+proprietary designs.
+Even though we do not require you to do so, those things are awesome, so please
+do them if possible:
+ - tell us that you are using LiteEthMini
+ - cite LiteEthMini in publications related to research it has helped
+ - send us feedback and suggestions for improvements
+ - send us bug reports when something goes wrong
+ - send us the modifications and improvements you have done to LiteEthMini.
+
+[> Support and consulting
+--------------------------
+We love open-source hardware and like sharing our designs with others.
+
+LiteEthMini is mainly developed and maintained by EnjoyDigital.
+
+If you would like to know more about LiteEthMini or if you are already a happy
+user and would like to extend it for your needs, EnjoyDigital can provide standard
+commercial support as well as consulting services.
+
+So feel free to contact us, we'd love to work with you! (and eventually shorten
+the list of the possible improvements :)
+
+[> Contact
+E-mail: florent [AT] enjoy-digital.fr
\ No newline at end of file
diff --git a/misoc/com/liteethmini/__init__.py b/misoc/com/liteethmini/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/com/liteethmini/common.py b/misoc/com/liteethmini/common.py
new file mode 100644 (file)
index 0000000..a5f0b3f
--- /dev/null
@@ -0,0 +1,44 @@
+import math
+from collections import OrderedDict
+
+from migen.fhdl.std import *
+from migen.genlib.resetsync import AsyncResetSynchronizer
+from migen.genlib.record import *
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import chooser, reverse_bytes, FlipFlop, Counter, WaitTimer
+from migen.flow.actor import *
+from migen.actorlib.structuring import Converter, Pipeline
+from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
+from migen.actorlib.packet import *
+from migen.bank.description import *
+
+class Port:
+    def connect(self, port):
+        r = [
+            Record.connect(self.source, port.sink),
+            Record.connect(port.source, self.sink)
+        ]
+        return r
+
+eth_mtu = 1532
+eth_min_len = 46
+eth_interpacket_gap = 12
+eth_preamble = 0xD555555555555555
+buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
+
+def eth_phy_description(dw):
+    payload_layout = [
+        ("data", dw),
+        ("last_be", dw//8),
+        ("error", dw//8)
+    ]
+    return EndpointDescription(payload_layout, packetized=True)
+
+
+def eth_mac_description(dw):
+    payload_layout = mac_header.get_layout() + [
+        ("data", dw),
+        ("last_be", dw//8),
+        ("error", dw//8)
+    ]
+    return EndpointDescription(payload_layout, packetized=True)
diff --git a/misoc/com/liteethmini/mac/__init__.py b/misoc/com/liteethmini/mac/__init__.py
new file mode 100644 (file)
index 0000000..6844c42
--- /dev/null
@@ -0,0 +1,22 @@
+from misoc.com.liteethmini.common import *
+from misoc.com.liteethmini.mac.core import LiteEthMACCore
+from misoc.com.liteethmini.mac.frontend.wishbone import LiteEthMACWishboneInterface
+
+
+class LiteEthMAC(Module, AutoCSR):
+    def __init__(self, phy, dw,
+                 interface="wishbone",
+                 endianness="big",
+                 with_preamble_crc=True):
+        self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_preamble_crc)
+        self.csrs = []
+        if interface == "wishbone":
+            self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2)
+            self.comb += Port.connect(self.interface, self.core)
+            self.ev, self.bus = self.interface.sram.ev, self.interface.bus
+            self.csrs = self.interface.get_csrs() + self.core.get_csrs()
+        else:
+            raise NotImplementedError
+
+    def get_csrs(self):
+        return self.csrs
diff --git a/misoc/com/liteethmini/mac/core/__init__.py b/misoc/com/liteethmini/mac/core/__init__.py
new file mode 100644 (file)
index 0000000..2551f5e
--- /dev/null
@@ -0,0 +1,100 @@
+from misoc.com.liteethmini.common import *
+from misoc.com.liteethmini.mac.core import gap, preamble, crc, padding, last_be
+from misoc.com.liteethmini.phy.sim import LiteEthPHYSim
+from misoc.com.liteethmini.phy.mii import LiteEthPHYMII
+
+
+class LiteEthMACCore(Module, AutoCSR):
+    def __init__(self, phy, dw, endianness="big",
+            with_preamble_crc=True,
+            with_padding=True):
+        if dw < phy.dw:
+            raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
+
+        rx_pipeline = [phy]
+        tx_pipeline = [phy]
+
+        # Interpacket gap
+        tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
+        rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
+        self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx")
+        self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx")
+
+        tx_pipeline += [tx_gap_inserter]
+        rx_pipeline += [rx_gap_checker]
+
+        # Preamble / CRC
+        if isinstance(phy, LiteEthPHYSim):
+            # In simulation, avoid CRC/Preamble to enable direct connection
+            # to the Ethernet tap.
+            self._preamble_crc = CSRStatus(reset=1)
+        elif with_preamble_crc:
+            self._preamble_crc = CSRStatus(reset=1)
+            # Preamble insert/check
+            preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
+            preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
+            self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
+            self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
+
+            # CRC insert/check
+            crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
+            crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
+            self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
+            self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
+
+            tx_pipeline += [preamble_inserter, crc32_inserter]
+            rx_pipeline += [preamble_checker, crc32_checker]
+
+        # Padding
+        if with_padding:
+            padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60)
+            padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60)
+            self.submodules += RenameClockDomains(padding_inserter, "eth_tx")
+            self.submodules += RenameClockDomains(padding_checker, "eth_rx")
+
+            tx_pipeline += [padding_inserter]
+            rx_pipeline += [padding_checker]
+
+        # Delimiters
+        if dw != 8:
+            tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
+            rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
+            self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
+            self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
+
+            tx_pipeline += [tx_last_be]
+            rx_pipeline += [rx_last_be]
+
+        # Converters
+        if dw != phy.dw:
+            reverse = endianness == "big"
+            tx_converter = Converter(eth_phy_description(dw),
+                                     eth_phy_description(phy.dw),
+                                     reverse=reverse)
+            rx_converter = Converter(eth_phy_description(phy.dw),
+                                     eth_phy_description(dw),
+                                     reverse=reverse)
+            self.submodules += RenameClockDomains(tx_converter, "eth_tx")
+            self.submodules += RenameClockDomains(rx_converter, "eth_rx")
+
+            tx_pipeline += [tx_converter]
+            rx_pipeline += [rx_converter]
+
+        # Cross Domain Crossing
+        if isinstance(phy, LiteEthPHYMII):
+            fifo_depth = 8
+        else:
+            fifo_depth = 64
+        tx_cdc = AsyncFIFO(eth_phy_description(dw), fifo_depth)
+        rx_cdc = AsyncFIFO(eth_phy_description(dw), fifo_depth)
+        self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
+        self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
+
+        tx_pipeline += [tx_cdc]
+        rx_pipeline += [rx_cdc]
+
+        # Graph
+        self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
+        self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
+
+        self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
diff --git a/misoc/com/liteethmini/mac/core/crc.py b/misoc/com/liteethmini/mac/core/crc.py
new file mode 100644 (file)
index 0000000..01b88f7
--- /dev/null
@@ -0,0 +1,281 @@
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthMACCRCEngine(Module):
+    """Cyclic Redundancy Check Engine
+
+    Compute next CRC value from last CRC value and data input using
+    an optimized asynchronous LFSR.
+
+    Parameters
+    ----------
+    data_width : int
+        Width of the data bus.
+    width : int
+        Width of the CRC.
+    polynom : int
+        Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
+
+    Attributes
+    ----------
+    data : in
+        Data input.
+    last : in
+        last CRC value.
+    next :
+        next CRC value.
+    """
+    def __init__(self, data_width, width, polynom):
+        self.data = Signal(data_width)
+        self.last = Signal(width)
+        self.next = Signal(width)
+
+        # # #
+
+        def _optimize_eq(l):
+            """
+            Replace even numbers of XORs in the equation
+            with an equivalent XOR
+            """
+            d = OrderedDict()
+            for e in l:
+                if e in d:
+                    d[e] += 1
+                else:
+                    d[e] = 1
+            r = []
+            for key, value in d.items():
+                if value%2 != 0:
+                    r.append(key)
+            return r
+
+        # compute and optimize CRC's LFSR
+        curval = [[("state", i)] for i in range(width)]
+        for i in range(data_width):
+            feedback = curval.pop() + [("din", i)]
+            for j in range(width-1):
+                if (polynom & (1<<(j+1))):
+                    curval[j] += feedback
+                curval[j] = _optimize_eq(curval[j])
+            curval.insert(0, feedback)
+
+        # implement logic
+        for i in range(width):
+            xors = []
+            for t, n in curval[i]:
+                if t == "state":
+                    xors += [self.last[n]]
+                elif t == "din":
+                    xors += [self.data[n]]
+            self.comb += self.next[i].eq(optree("^", xors))
+
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+class LiteEthMACCRC32(Module):
+    """IEEE 802.3 CRC
+
+    Implement an IEEE 802.3 CRC generator/checker.
+
+    Parameters
+    ----------
+    data_width : int
+        Width of the data bus.
+
+    Attributes
+    ----------
+    d : in
+        Data input.
+    value : out
+        CRC value (used for generator).
+    error : out
+        CRC error (used for checker).
+    """
+    width = 32
+    polynom = 0x04C11DB7
+    init = 2**width-1
+    check = 0xC704DD7B
+    def __init__(self, data_width):
+        self.data = Signal(data_width)
+        self.value = Signal(self.width)
+        self.error = Signal()
+
+        # # #
+
+        self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
+        reg = Signal(self.width, reset=self.init)
+        self.sync += reg.eq(self.engine.next)
+        self.comb += [
+            self.engine.data.eq(self.data),
+            self.engine.last.eq(reg),
+
+            self.value.eq(~reg[::-1]),
+            self.error.eq(self.engine.next != self.check)
+        ]
+
+
+class LiteEthMACCRCInserter(Module):
+    """CRC Inserter
+
+    Append a CRC at the end of each packet.
+
+    Parameters
+    ----------
+    description : description
+        description of the dataflow.
+
+    Attributes
+    ----------
+    sink : in
+        Packets input without CRC.
+    source : out
+        Packets output with CRC.
+    """
+    def __init__(self, crc_class, description):
+        self.sink = sink = Sink(description)
+        self.source = source = Source(description)
+        self.busy = Signal()
+
+        # # #
+
+        dw = flen(sink.data)
+        crc = crc_class(dw)
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += crc, fsm
+
+        fsm.act("IDLE",
+            crc.reset.eq(1),
+            sink.ack.eq(1),
+            If(sink.stb & sink.sop,
+                sink.ack.eq(0),
+                NextState("COPY"),
+            )
+        )
+        fsm.act("COPY",
+            crc.ce.eq(sink.stb & source.ack),
+            crc.data.eq(sink.data),
+            Record.connect(sink, source),
+            source.eop.eq(0),
+            If(sink.stb & sink.eop & source.ack,
+                NextState("INSERT"),
+            )
+        )
+        ratio = crc.width//dw
+        if ratio > 1:
+            cnt = Signal(max=ratio, reset=ratio-1)
+            cnt_done = Signal()
+            fsm.act("INSERT",
+                source.stb.eq(1),
+                chooser(crc.value, cnt, source.data, reverse=True),
+                If(cnt_done,
+                    source.eop.eq(1),
+                    If(source.ack, NextState("IDLE"))
+                )
+            )
+            self.comb += cnt_done.eq(cnt == 0)
+            self.sync += \
+                If(fsm.ongoing("IDLE"),
+                    cnt.eq(cnt.reset)
+                ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
+                    cnt.eq(cnt - source.ack)
+                )
+        else:
+            fsm.act("INSERT",
+                source.stb.eq(1),
+                source.eop.eq(1),
+                source.data.eq(crc.value),
+                If(source.ack, NextState("IDLE"))
+            )
+        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+
+
+class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter):
+    def __init__(self, description):
+        LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description)
+
+
+class LiteEthMACCRCChecker(Module):
+    """CRC Checker
+
+    Check CRC at the end of each packet.
+
+    Parameters
+    ----------
+    description : description
+        description of the dataflow.
+
+    Attributes
+    ----------
+    sink : in
+        Packets input with CRC.
+    source : out
+        Packets output without CRC and "error" set to 0
+        on eop when CRC OK / set to 1 when CRC KO.
+    """
+    def __init__(self, crc_class, description):
+        self.sink = sink = Sink(description)
+        self.source = source = Source(description)
+        self.busy = Signal()
+
+        # # #
+
+        dw = flen(sink.data)
+        crc = crc_class(dw)
+        self.submodules += crc
+        ratio = crc.width//dw
+
+        error = Signal()
+        fifo = InsertReset(SyncFIFO(description, ratio + 1))
+        self.submodules += fifo
+
+        fsm = FSM(reset_state="RESET")
+        self.submodules += fsm
+
+        fifo_in = Signal()
+        fifo_out = Signal()
+        fifo_full = Signal()
+
+        self.comb += [
+            fifo_full.eq(fifo.fifo.level == ratio),
+            fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
+            fifo_out.eq(source.stb & source.ack),
+
+            Record.connect(sink, fifo.sink),
+            fifo.sink.stb.eq(fifo_in),
+            self.sink.ack.eq(fifo_in),
+
+            source.stb.eq(sink.stb & fifo_full),
+            source.sop.eq(fifo.source.sop),
+            source.eop.eq(sink.eop),
+            fifo.source.ack.eq(fifo_out),
+            source.payload.eq(fifo.source.payload),
+
+            source.error.eq(sink.error | crc.error),
+        ]
+
+        fsm.act("RESET",
+            crc.reset.eq(1),
+            fifo.reset.eq(1),
+            NextState("IDLE"),
+        )
+        self.comb += crc.data.eq(sink.data)
+        fsm.act("IDLE",
+            If(sink.stb & sink.sop & sink.ack,
+                crc.ce.eq(1),
+                NextState("COPY")
+            )
+        )
+        fsm.act("COPY",
+            If(sink.stb & sink.ack,
+                crc.ce.eq(1),
+                If(sink.eop,
+                    NextState("RESET")
+                )
+            )
+        )
+        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
+
+
+class LiteEthMACCRC32Checker(LiteEthMACCRCChecker):
+    def __init__(self, description):
+        LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description)
diff --git a/misoc/com/liteethmini/mac/core/gap.py b/misoc/com/liteethmini/mac/core/gap.py
new file mode 100644 (file)
index 0000000..ce4ad1b
--- /dev/null
@@ -0,0 +1,27 @@
+from misoc.com.liteethmini.common import *
+
+class LiteEthMACGap(Module):
+    def __init__(self, dw, ack_on_gap=False):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.source = source = Source(eth_phy_description(dw))
+
+        # # #
+
+        gap = math.ceil(eth_interpacket_gap/(dw//8))
+        self.submodules.counter = counter = Counter(max=gap)
+
+        self.submodules.fsm = fsm = FSM(reset_state="COPY")
+        fsm.act("COPY",
+            counter.reset.eq(1),
+            Record.connect(sink, source),
+            If(sink.stb & sink.eop & sink.ack,
+                NextState("GAP")
+            )
+        )
+        fsm.act("GAP",
+            counter.ce.eq(1),
+            sink.ack.eq(int(ack_on_gap)),
+            If(counter.value == (gap-1),
+                NextState("COPY")
+            )
+        )
diff --git a/misoc/com/liteethmini/mac/core/last_be.py b/misoc/com/liteethmini/mac/core/last_be.py
new file mode 100644 (file)
index 0000000..14d8a30
--- /dev/null
@@ -0,0 +1,43 @@
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthMACTXLastBE(Module):
+    def __init__(self, dw):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.source = source = Source(eth_phy_description(dw))
+
+        # # #
+
+        ongoing = Signal()
+        self.sync += \
+            If(sink.stb & sink.ack,
+                If(sink.sop,
+                    ongoing.eq(1)
+                ).Elif(sink.last_be,
+                    ongoing.eq(0)
+                )
+            )
+        self.comb += [
+            source.stb.eq(sink.stb & (sink.sop | ongoing)),
+            source.sop.eq(sink.sop),
+            source.eop.eq(sink.last_be),
+            source.data.eq(sink.data),
+            sink.ack.eq(source.ack)
+        ]
+
+
+class LiteEthMACRXLastBE(Module):
+    def __init__(self, dw):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.source = source = Source(eth_phy_description(dw))
+
+        # # #
+
+        self.comb += [
+            source.stb.eq(sink.stb),
+            source.sop.eq(sink.sop),
+            source.eop.eq(sink.eop),
+            source.data.eq(sink.data),
+            source.last_be.eq(sink.eop),
+            sink.ack.eq(source.ack)
+        ]
diff --git a/misoc/com/liteethmini/mac/core/padding.py b/misoc/com/liteethmini/mac/core/padding.py
new file mode 100644 (file)
index 0000000..fa4aa92
--- /dev/null
@@ -0,0 +1,56 @@
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthMACPaddingInserter(Module):
+    def __init__(self, dw, padding):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.source = source = Source(eth_phy_description(dw))
+
+        # # #
+
+        padding_limit = math.ceil(padding/(dw/8))-1
+
+        self.submodules.counter = counter = Counter(16, reset=1)
+        counter_done = Signal()
+        self.comb += [
+            counter.reset.eq(sink.stb & sink.sop & sink.ack),
+            counter.ce.eq(source.stb & source.ack),
+            counter_done.eq(counter.value >= padding_limit),
+        ]
+
+        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
+        fsm.act("IDLE",
+            Record.connect(sink, source),
+            If(source.stb & source.ack,
+                counter.ce.eq(1),
+                If(sink.eop,
+                    If(~counter_done,
+                        source.eop.eq(0),
+                        NextState("PADDING")
+                    )
+                )
+            )
+        )
+        fsm.act("PADDING",
+            source.stb.eq(1),
+            source.eop.eq(counter_done),
+            source.data.eq(0),
+            If(source.ack,
+                If(counter_done,
+                    NextState("IDLE")
+                )
+            )
+        )
+
+
+class LiteEthMACPaddingChecker(Module):
+    def __init__(self, dw, packet_min_length):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.source = source = Source(eth_phy_description(dw))
+
+        # # #
+
+        # XXX see if we should drop the packet when
+        # payload size < minimum ethernet payload size
+        self.comb += Record.connect(sink, source)
+
diff --git a/misoc/com/liteethmini/mac/core/preamble.py b/misoc/com/liteethmini/mac/core/preamble.py
new file mode 100644 (file)
index 0000000..52078f9
--- /dev/null
@@ -0,0 +1,150 @@
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthMACPreambleInserter(Module):
+    def __init__(self, dw):
+        self.sink = Sink(eth_phy_description(dw))
+        self.source = Source(eth_phy_description(dw))
+
+        # # #
+
+        preamble = Signal(64, reset=eth_preamble)
+        cnt_max = (64//dw)-1
+        cnt = Signal(max=cnt_max+1)
+        clr_cnt = Signal()
+        inc_cnt = Signal()
+
+        self.sync += \
+            If(clr_cnt,
+                cnt.eq(0)
+            ).Elif(inc_cnt,
+                cnt.eq(cnt+1)
+            )
+
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+        fsm.act("IDLE",
+            self.sink.ack.eq(1),
+            clr_cnt.eq(1),
+            If(self.sink.stb & self.sink.sop,
+                self.sink.ack.eq(0),
+                NextState("INSERT"),
+            )
+        )
+        fsm.act("INSERT",
+            self.source.stb.eq(1),
+            self.source.sop.eq(cnt == 0),
+            chooser(preamble, cnt, self.source.data),
+            If(cnt == cnt_max,
+                If(self.source.ack, NextState("COPY"))
+            ).Else(
+                inc_cnt.eq(self.source.ack)
+            )
+        )
+
+        self.comb += [
+            self.source.data.eq(self.sink.data),
+            self.source.last_be.eq(self.sink.last_be)
+        ]
+        fsm.act("COPY",
+            Record.connect(self.sink, self.source, leave_out=set(["data", "last_be"])),
+            self.source.sop.eq(0),
+
+            If(self.sink.stb & self.sink.eop & self.source.ack,
+                NextState("IDLE"),
+            )
+        )
+
+
+class LiteEthMACPreambleChecker(Module):
+    def __init__(self, dw):
+        self.sink = Sink(eth_phy_description(dw))
+        self.source = Source(eth_phy_description(dw))
+
+        # # #
+
+        preamble = Signal(64, reset=eth_preamble)
+        cnt_max = (64//dw) - 1
+        cnt = Signal(max=cnt_max+1)
+        clr_cnt = Signal()
+        inc_cnt = Signal()
+
+        self.sync += \
+            If(clr_cnt,
+                cnt.eq(0)
+            ).Elif(inc_cnt,
+                cnt.eq(cnt+1)
+            )
+
+        discard = Signal()
+        clr_discard = Signal()
+        set_discard = Signal()
+
+        self.sync += \
+            If(clr_discard,
+                discard.eq(0)
+            ).Elif(set_discard,
+                discard.eq(1)
+            )
+
+        sop = Signal()
+        clr_sop = Signal()
+        set_sop = Signal()
+        self.sync += \
+            If(clr_sop,
+                sop.eq(0)
+            ).Elif(set_sop,
+                sop.eq(1)
+            )
+
+        ref = Signal(dw)
+        match = Signal()
+        self.comb += [
+            chooser(preamble, cnt, ref),
+            match.eq(self.sink.data == ref)
+        ]
+
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+
+        fsm.act("IDLE",
+            self.sink.ack.eq(1),
+            clr_cnt.eq(1),
+            clr_discard.eq(1),
+            If(self.sink.stb & self.sink.sop,
+                clr_cnt.eq(0),
+                inc_cnt.eq(1),
+                clr_discard.eq(0),
+                set_discard.eq(~match),
+                NextState("CHECK"),
+            )
+        )
+        fsm.act("CHECK",
+            self.sink.ack.eq(1),
+            If(self.sink.stb,
+                set_discard.eq(~match),
+                If(cnt == cnt_max,
+                    If(discard | (~match),
+                        NextState("IDLE")
+                    ).Else(
+                        set_sop.eq(1),
+                        NextState("COPY")
+                    )
+                ).Else(
+                    inc_cnt.eq(1)
+                )
+            )
+        )
+        self.comb += [
+            self.source.data.eq(self.sink.data),
+            self.source.last_be.eq(self.sink.last_be)
+        ]
+        fsm.act("COPY",
+            Record.connect(self.sink, self.source, leave_out=set(["data", "last_be"])),
+            self.source.sop.eq(sop),
+            clr_sop.eq(self.source.stb & self.source.ack),
+
+            If(self.source.stb & self.source.eop & self.source.ack,
+                NextState("IDLE"),
+            )
+        )
diff --git a/misoc/com/liteethmini/mac/frontend/__init__.py b/misoc/com/liteethmini/mac/frontend/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/com/liteethmini/mac/frontend/sram.py b/misoc/com/liteethmini/mac/frontend/sram.py
new file mode 100644 (file)
index 0000000..1495e08
--- /dev/null
@@ -0,0 +1,234 @@
+from misoc.com.liteethmini.common import *
+
+from migen.bank.description import *
+from migen.bank.eventmanager import *
+
+
+class LiteEthMACSRAMWriter(Module, AutoCSR):
+    def __init__(self, dw, depth, nslots=2):
+        self.sink = sink = Sink(eth_phy_description(dw))
+        self.crc_error = Signal()
+
+        slotbits = max(log2_int(nslots), 1)
+        lengthbits = log2_int(depth*4)  # length in bytes
+
+        self._slot = CSRStatus(slotbits)
+        self._length = CSRStatus(lengthbits)
+
+        self.submodules.ev = EventManager()
+        self.ev.available = EventSourceLevel()
+        self.ev.finalize()
+
+        # # #
+
+        # packet dropped if no slot available
+        sink.ack.reset = 1
+
+        # length computation
+        increment = Signal(3)
+        self.comb += \
+            If(sink.last_be[3],
+                increment.eq(1)
+            ).Elif(sink.last_be[2],
+                increment.eq(2)
+            ).Elif(sink.last_be[1],
+                increment.eq(3)
+            ).Else(
+                increment.eq(4)
+            )
+        counter = Counter(lengthbits, increment=increment)
+        self.submodules += counter
+
+        # slot computation
+        slot = Counter(slotbits)
+        self.submodules += slot
+
+        ongoing = Signal()
+
+        # status fifo
+        fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
+        self.submodules += fifo
+
+        # fsm
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+
+        fsm.act("IDLE",
+            If(sink.stb & sink.sop,
+                If(fifo.sink.ack,
+                    ongoing.eq(1),
+                    counter.ce.eq(1),
+                    NextState("WRITE")
+                )
+            )
+        )
+        fsm.act("WRITE",
+            counter.ce.eq(sink.stb),
+            ongoing.eq(1),
+            If(sink.stb & sink.eop,
+                If((sink.error & sink.last_be) != 0,
+                    NextState("DISCARD")
+                ).Else(
+                    NextState("TERMINATE")
+                )
+            )
+        )
+        fsm.act("DISCARD",
+            counter.reset.eq(1),
+            NextState("IDLE")
+        )
+        self.comb += [
+            fifo.sink.slot.eq(slot.value),
+            fifo.sink.length.eq(counter.value)
+        ]
+        fsm.act("TERMINATE",
+            counter.reset.eq(1),
+            slot.ce.eq(1),
+            fifo.sink.stb.eq(1),
+            NextState("IDLE")
+        )
+        self.comb += [
+            fifo.source.ack.eq(self.ev.available.clear),
+            self.ev.available.trigger.eq(fifo.source.stb),
+            self._slot.status.eq(fifo.source.slot),
+            self._length.status.eq(fifo.source.length),
+        ]
+
+        # memory
+        mems = [None]*nslots
+        ports = [None]*nslots
+        for n in range(nslots):
+            mems[n] = Memory(dw, depth)
+            ports[n] = mems[n].get_port(write_capable=True)
+            self.specials += ports[n]
+        self.mems = mems
+
+        cases = {}
+        for n, port in enumerate(ports):
+            cases[n] = [
+                ports[n].adr.eq(counter.value[2:]),
+                ports[n].dat_w.eq(sink.data),
+                If(sink.stb & ongoing,
+                    ports[n].we.eq(0xf)
+                )
+            ]
+        self.comb += Case(slot.value, cases)
+
+
+class LiteEthMACSRAMReader(Module, AutoCSR):
+    def __init__(self, dw, depth, nslots=2):
+        self.source = source = Source(eth_phy_description(dw))
+
+        slotbits = max(log2_int(nslots), 1)
+        lengthbits = log2_int(depth*4)  # length in bytes
+        self.lengthbits = lengthbits
+
+        self._start = CSR()
+        self._ready = CSRStatus()
+        self._slot = CSRStorage(slotbits)
+        self._length = CSRStorage(lengthbits)
+
+        self.submodules.ev = EventManager()
+        self.ev.done = EventSourcePulse()
+        self.ev.finalize()
+
+        # # #
+
+        # command fifo
+        fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
+        self.submodules += fifo
+        self.comb += [
+            fifo.sink.stb.eq(self._start.re),
+            fifo.sink.slot.eq(self._slot.storage),
+            fifo.sink.length.eq(self._length.storage),
+            self._ready.status.eq(fifo.sink.ack)
+        ]
+
+        # length computation
+        self.submodules.counter = counter = Counter(lengthbits, increment=4)
+
+        # fsm
+        first = Signal()
+        last  = Signal()
+        last_d = Signal()
+
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+
+        fsm.act("IDLE",
+            counter.reset.eq(1),
+            If(fifo.source.stb,
+                NextState("CHECK")
+            )
+        )
+        fsm.act("CHECK",
+            If(~last_d,
+                NextState("SEND"),
+            ).Else(
+                NextState("END"),
+            )
+        )
+        length_lsb = fifo.source.length[0:2]
+        self.comb += [
+            If(last,
+                If(length_lsb == 3,
+                    source.last_be.eq(0b0010)
+                ).Elif(length_lsb == 2,
+                    source.last_be.eq(0b0100)
+                ).Elif(length_lsb == 1,
+                    source.last_be.eq(0b1000)
+                ).Else(
+                    source.last_be.eq(0b0001)
+                )
+            )
+        ]
+        fsm.act("SEND",
+            source.stb.eq(1),
+            source.sop.eq(first),
+            source.eop.eq(last),
+            If(source.ack,
+                counter.ce.eq(~last),
+                NextState("CHECK")
+            )
+        )
+        fsm.act("END",
+            fifo.source.ack.eq(1),
+            self.ev.done.trigger.eq(1),
+            NextState("IDLE")
+        )
+
+        # first/last computation
+        self.sync += [
+            If(fsm.ongoing("IDLE"),
+                first.eq(1)
+            ).Elif(source.stb & source.ack,
+                first.eq(0)
+            )
+        ]
+        self.comb += last.eq((counter.value + 4) >= fifo.source.length)
+        self.sync += last_d.eq(last)
+
+        # memory
+        rd_slot = fifo.source.slot
+
+        mems = [None]*nslots
+        ports = [None]*nslots
+        for n in range(nslots):
+            mems[n] = Memory(dw, depth)
+            ports[n] = mems[n].get_port()
+            self.specials += ports[n]
+        self.mems = mems
+
+        cases = {}
+        for n, port in enumerate(ports):
+            self.comb += ports[n].adr.eq(counter.value[2:])
+            cases[n] = [source.data.eq(port.dat_r)]
+        self.comb += Case(rd_slot, cases)
+
+
+class LiteEthMACSRAM(Module, AutoCSR):
+    def __init__(self, dw, depth, nrxslots, ntxslots):
+        self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots)
+        self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots)
+        self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
+        self.sink, self.source = self.writer.sink, self.reader.source
diff --git a/misoc/com/liteethmini/mac/frontend/wishbone.py b/misoc/com/liteethmini/mac/frontend/wishbone.py
new file mode 100644 (file)
index 0000000..e45f744
--- /dev/null
@@ -0,0 +1,41 @@
+from misoc.com.liteethmini.common import *
+from misoc.com.liteethmini.mac.frontend import sram
+
+from migen.bus import wishbone
+from migen.fhdl.simplify import FullMemoryWE
+
+
+class LiteEthMACWishboneInterface(Module, AutoCSR):
+    def __init__(self, dw, nrxslots=2, ntxslots=2):
+        self.sink = Sink(eth_phy_description(dw))
+        self.source = Source(eth_phy_description(dw))
+        self.bus = wishbone.Interface()
+
+        # # #
+
+        # storage in SRAM
+        sram_depth = buffer_depth//(dw//8)
+        self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
+        self.comb += [
+            Record.connect(self.sink, self.sram.sink),
+            Record.connect(self.sram.source, self.source)
+        ]
+
+        # Wishbone interface
+        wb_rx_sram_ifs = [wishbone.SRAM(self.sram.writer.mems[n], read_only=True)
+            for n in range(nrxslots)]
+        # TODO: FullMemoryWE should move to Mibuild
+        wb_tx_sram_ifs = [FullMemoryWE()(wishbone.SRAM(self.sram.reader.mems[n], read_only=False))
+            for n in range(ntxslots)]
+        wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs
+
+        wb_slaves = []
+        decoderoffset = log2_int(sram_depth)
+        decoderbits = log2_int(len(wb_sram_ifs))
+        for n, wb_sram_if in enumerate(wb_sram_ifs):
+            def slave_filter(a, v=n):
+                return a[decoderoffset:decoderoffset+decoderbits] == v
+            wb_slaves.append((slave_filter, wb_sram_if.bus))
+            self.submodules += wb_sram_if
+        wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True)
+        self.submodules += wb_con
diff --git a/misoc/com/liteethmini/phy/__init__.py b/misoc/com/liteethmini/phy/__init__.py
new file mode 100644 (file)
index 0000000..c17124d
--- /dev/null
@@ -0,0 +1,27 @@
+from misoc.com.liteethmini.common import *
+
+
+def LiteEthPHY(clock_pads, pads, clk_freq=None, **kwargs):
+    # Autodetect PHY
+    if hasattr(pads, "source_stb"):
+        # This is a simulation PHY
+        from misoc.com.liteethmini.phy.sim import LiteEthPHYSim
+        return LiteEthPHYSim(pads)
+    elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8:
+        if hasattr(clock_pads, "tx"):
+            # This is a 10/100/1G PHY
+            from misoc.com.liteethmini.phy.gmii_mii import LiteEthPHYGMIIMII
+            return LiteEthPHYGMIIMII(clock_pads, pads, clk_freq=clk_freq, **kwargs)
+        else:
+            # This is a pure 1G PHY
+            from misoc.com.liteethmini.phy.gmii import LiteEthPHYGMII
+            return LiteEthPHYGMII(clock_pads, pads, **kwargs)
+    elif hasattr(pads, "rx_ctl"):
+        # This is a 10/100/1G RGMII PHY
+        raise ValueError("RGMII PHYs are specific to vendors (for now), use direct instantiation")
+    elif flen(pads.tx_data) == 4:
+        # This is a MII PHY
+        from misoc.com.liteethmini.phy.mii import LiteEthPHYMII
+        return LiteEthPHYMII(clock_pads, pads, **kwargs)
+    else:
+        raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation")
diff --git a/misoc/com/liteethmini/phy/gmii.py b/misoc/com/liteethmini/phy/gmii.py
new file mode 100644 (file)
index 0000000..24f4dc8
--- /dev/null
@@ -0,0 +1,98 @@
+from migen.genlib.io import DDROutput
+
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthPHYGMIITX(Module):
+    def __init__(self, pads, pads_register=True):
+        self.sink = sink = Sink(eth_phy_description(8))
+
+        # # #
+
+        if hasattr(pads, "tx_er"):
+            self.sync += pads.tx_er.eq(0)
+        pads_eq = [
+            pads.tx_en.eq(sink.stb),
+            pads.tx_data.eq(sink.data)
+        ]
+        if pads_register:
+            self.sync += pads_eq
+        else:
+            self.comb += pads_eq
+        self.comb += sink.ack.eq(1)
+
+
+class LiteEthPHYGMIIRX(Module):
+    def __init__(self, pads):
+        self.source = source = Source(eth_phy_description(8))
+
+        # # #
+
+        dv_d = Signal()
+        self.sync += dv_d.eq(pads.dv)
+
+        sop = Signal()
+        eop = Signal()
+        self.comb += [
+            sop.eq(pads.dv & ~dv_d),
+            eop.eq(~pads.dv & dv_d)
+        ]
+        self.sync += [
+            source.stb.eq(pads.dv),
+            source.sop.eq(sop),
+            source.data.eq(pads.rx_data)
+        ]
+        self.comb += source.eop.eq(eop)
+
+
+class LiteEthPHYGMIICRG(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
+        self._reset = CSRStorage()
+
+        # # #
+
+        self.clock_domains.cd_eth_rx = ClockDomain()
+        self.clock_domains.cd_eth_tx = ClockDomain()
+
+        # RX : Let the synthesis tool insert the appropriate clock buffer
+        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
+
+        # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
+        #      MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
+        self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx"))
+        # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
+        self.specials += Instance("BUFGMUX",
+                                  i_I0=self.cd_eth_rx.clk,
+                                  i_I1=clock_pads.tx,
+                                  i_S=mii_mode,
+                                  o_O=self.cd_eth_tx.clk)
+
+        if with_hw_init_reset:
+            reset = Signal()
+            counter_done = Signal()
+            self.submodules.counter = counter = Counter(max=512)
+            self.comb += [
+                counter_done.eq(counter.value == 256),
+                counter.ce.eq(~counter_done),
+                reset.eq(~counter_done | self._reset.storage)
+            ]
+        else:
+            reset = self._reset.storage
+        self.comb += pads.rst_n.eq(~reset)
+        self.specials += [
+            AsyncResetSynchronizer(self.cd_eth_tx, reset),
+            AsyncResetSynchronizer(self.cd_eth_rx, reset),
+        ]
+
+
+class LiteEthPHYGMII(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+        self.dw = 8
+        self.submodules.crg = LiteEthPHYGMIICRG(clock_pads,
+                                                pads,
+                                                with_hw_init_reset)
+        self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads),
+                                                "eth_tx")
+        self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads),
+                                                "eth_rx")
+        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoc/com/liteethmini/phy/gmii_mii.py b/misoc/com/liteethmini/phy/gmii_mii.py
new file mode 100644 (file)
index 0000000..8ed4741
--- /dev/null
@@ -0,0 +1,161 @@
+from migen.genlib.io import DDROutput
+from migen.flow.plumbing import Multiplexer, Demultiplexer
+from migen.genlib.cdc import PulseSynchronizer
+
+from misoc.com.liteethmini.common import *
+
+from misoc.com.liteethmini.phy.gmii import LiteEthPHYGMIICRG
+from misoc.com.liteethmini.phy.mii import LiteEthPHYMIITX, LiteEthPHYMIIRX
+from misoc.com.liteethmini.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX
+
+modes = {
+    "GMII": 0,
+    "MII": 1
+}
+
+tx_pads_layout = [("tx_er", 1), ("tx_en", 1), ("tx_data", 8)]
+rx_pads_layout = [("rx_er", 1), ("dv", 1), ("rx_data", 8)]
+
+
+class LiteEthPHYGMIIMIITX(Module):
+    def __init__(self, pads, mode):
+        self.sink = sink = Sink(eth_phy_description(8))
+
+        # # #
+
+        gmii_tx_pads = Record(tx_pads_layout)
+        gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False)
+        self.submodules += gmii_tx
+
+        mii_tx_pads = Record(tx_pads_layout)
+        mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False)
+        self.submodules += mii_tx
+
+        demux = Demultiplexer(eth_phy_description(8), 2)
+        self.submodules += demux
+        self.comb += [
+            demux.sel.eq(mode == modes["MII"]),
+            Record.connect(sink, demux.sink),
+            Record.connect(demux.source0, gmii_tx.sink),
+            Record.connect(demux.source1, mii_tx.sink),
+        ]
+
+        if hasattr(pads, "tx_er"):
+            self.comb += pads.tx_er.eq(0)
+        self.sync += [
+            If(mode == modes["MII"],
+                pads.tx_en.eq(mii_tx_pads.tx_en),
+                pads.tx_data.eq(mii_tx_pads.tx_data),
+            ).Else(
+                pads.tx_en.eq(gmii_tx_pads.tx_en),
+                pads.tx_data.eq(gmii_tx_pads.tx_data),
+            )
+        ]
+
+
+class LiteEthPHYGMIIMIIRX(Module):
+    def __init__(self, pads, mode):
+        self.source = source = Source(eth_phy_description(8))
+
+        # # #
+
+        pads_d = Record(rx_pads_layout)
+        self.sync += [
+            pads_d.dv.eq(pads.dv),
+            pads_d.rx_data.eq(pads.rx_data)
+        ]
+
+        gmii_rx = LiteEthPHYGMIIRX(pads_d)
+        self.submodules += gmii_rx
+
+        mii_rx = LiteEthPHYMIIRX(pads_d)
+        self.submodules += mii_rx
+
+        mux = Multiplexer(eth_phy_description(8), 2)
+        self.submodules += mux
+        self.comb += [
+            mux.sel.eq(mode == modes["MII"]),
+            Record.connect(gmii_rx.source, mux.sink0),
+            Record.connect(mii_rx.source, mux.sink1),
+            Record.connect(mux.source, source)
+        ]
+
+
+class LiteEthGMIIMIIModeDetection(Module, AutoCSR):
+    def __init__(self, clk_freq):
+        self.mode = Signal()
+        self._mode = CSRStatus()
+
+        # # #
+
+        mode = Signal()
+        update_mode = Signal()
+        self.sync += \
+            If(update_mode,
+                self.mode.eq(mode)
+            )
+        self.comb += self._mode.status.eq(self.mode)
+
+        # Principle:
+        #  sys_clk >= 125MHz
+        #  eth_rx <= 125Mhz
+        # We generate ticks every 1024 clock cycles in eth_rx domain
+        # and measure ticks period in sys_clk domain.
+
+        # Generate a tick every 1024 clock cycles (eth_rx clock domain)
+        eth_tick = Signal()
+        eth_counter = Signal(10)
+        self.sync.eth_rx += eth_counter.eq(eth_counter + 1)
+        self.comb += eth_tick.eq(eth_counter == 0)
+
+        # Synchronize tick (sys clock domain)
+        sys_tick = Signal()
+        eth_ps = PulseSynchronizer("eth_rx", "sys")
+        self.comb += [
+            eth_ps.i.eq(eth_tick),
+            sys_tick.eq(eth_ps.o)
+        ]
+        self.submodules += eth_ps
+
+        # sys_clk domain counter
+        sys_counter = Counter(24)
+        self.submodules += sys_counter
+
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+
+        fsm.act("IDLE",
+            sys_counter.reset.eq(1),
+            If(sys_tick,
+                NextState("COUNT")
+            )
+        )
+        fsm.act("COUNT",
+            sys_counter.ce.eq(1),
+            If(sys_tick,
+                NextState("DETECTION")
+            )
+        )
+        fsm.act("DETECTION",
+            update_mode.eq(1),
+            # if freq < 125MHz-5% use MII mode
+            If(sys_counter.value > int((clk_freq/125000000)*1024*1.05),
+                mode.eq(1)
+            # if freq >= 125MHz-5% use GMII mode
+            ).Else(
+                mode.eq(0)
+            ),
+            NextState("IDLE")
+        )
+
+
+class LiteEthPHYGMIIMII(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, clk_freq, with_hw_init_reset=True):
+        self.dw = 8
+        # Note: we can use GMII CRG since it also handles tx clock pad used for MII
+        self.submodules.mode_detection = LiteEthGMIIMIIModeDetection(clk_freq)
+        mode = self.mode_detection.mode
+        self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode == modes["MII"])
+        self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
+        self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
+        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoc/com/liteethmini/phy/loopback.py b/misoc/com/liteethmini/phy/loopback.py
new file mode 100644 (file)
index 0000000..c9e5cf1
--- /dev/null
@@ -0,0 +1,31 @@
+from misoc.com.liteethmini.common import *
+from misoc.com.liteethmini.generic import *
+
+
+class LiteEthPHYLoopbackCRG(Module, AutoCSR):
+    def __init__(self):
+        self._reset = CSRStorage()
+
+        # # #
+
+        self.clock_domains.cd_eth_rx = ClockDomain()
+        self.clock_domains.cd_eth_tx = ClockDomain()
+        self.comb += [
+            self.cd_eth_rx.clk.eq(ClockSignal()),
+            self.cd_eth_tx.clk.eq(ClockSignal())
+        ]
+
+        reset = self._reset.storage
+        self.comb += [
+            self.cd_eth_rx.rst.eq(reset),
+            self.cd_eth_tx.rst.eq(reset)
+        ]
+
+
+class LiteEthPHYLoopback(Module, AutoCSR):
+    def __init__(self):
+        self.dw = 8
+        self.submodules.crg = LiteEthLoopbackPHYCRG()
+        self.sink = sink = Sink(eth_phy_description(8))
+        self.source = source = Source(eth_phy_description(8))
+        self.comb += Record.connect(self.sink, self.source)
diff --git a/misoc/com/liteethmini/phy/mii.py b/misoc/com/liteethmini/phy/mii.py
new file mode 100644 (file)
index 0000000..6956524
--- /dev/null
@@ -0,0 +1,102 @@
+from misoc.com.liteethmini.common import *
+
+
+def converter_description(dw):
+    payload_layout = [("data", dw)]
+    return EndpointDescription(payload_layout, packetized=True)
+
+
+class LiteEthPHYMIITX(Module):
+    def __init__(self, pads, pads_register=True):
+        self.sink = sink = Sink(eth_phy_description(8))
+
+        # # #
+
+        if hasattr(pads, "tx_er"):
+            self.sync += pads.tx_er.eq(0)
+        converter = Converter(converter_description(8),
+                              converter_description(4))
+        self.submodules += converter
+        self.comb += [
+            converter.sink.stb.eq(sink.stb),
+            converter.sink.data.eq(sink.data),
+            sink.ack.eq(converter.sink.ack),
+            converter.source.ack.eq(1)
+        ]
+        pads_eq = [
+            pads.tx_en.eq(converter.source.stb),
+            pads.tx_data.eq(converter.source.data)
+        ]
+        if pads_register:
+            self.sync += pads_eq
+        else:
+            self.comb += pads_eq
+
+
+class LiteEthPHYMIIRX(Module):
+    def __init__(self, pads):
+        self.source = source = Source(eth_phy_description(8))
+
+        # # #
+
+        sop = FlipFlop(reset=1)
+        self.submodules += sop
+
+        converter = Converter(converter_description(4),
+                              converter_description(8))
+        converter = InsertReset(converter)
+        self.submodules += converter
+
+        self.sync += [
+            converter.reset.eq(~pads.dv),
+            converter.sink.stb.eq(1),
+            converter.sink.data.eq(pads.rx_data)
+        ]
+        self.comb += [
+            sop.reset.eq(~pads.dv),
+            sop.ce.eq(pads.dv),
+            converter.sink.sop.eq(sop.q),
+            converter.sink.eop.eq(~pads.dv)
+        ]
+        self.comb += Record.connect(converter.source, source)
+
+
+class LiteEthPHYMIICRG(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset):
+        self._reset = CSRStorage()
+
+        # # #
+
+        if hasattr(clock_pads, "phy"):
+            self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy)
+
+        self.clock_domains.cd_eth_rx = ClockDomain()
+        self.clock_domains.cd_eth_tx = ClockDomain()
+        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
+        self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx)
+
+        if with_hw_init_reset:
+            reset = Signal()
+            counter_done = Signal()
+            self.submodules.counter = counter = Counter(max=512)
+            self.comb += [
+                counter_done.eq(counter.value == 256),
+                counter.ce.eq(~counter_done),
+                reset.eq(~counter_done | self._reset.storage)
+            ]
+        else:
+            reset = self._reset.storage
+        self.comb += pads.rst_n.eq(~reset)
+        self.specials += [
+            AsyncResetSynchronizer(self.cd_eth_tx, reset),
+            AsyncResetSynchronizer(self.cd_eth_rx, reset),
+        ]
+
+
+class LiteEthPHYMII(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+        self.dw = 8
+        self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset)
+        self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
+        self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
+        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoc/com/liteethmini/phy/s6rgmii.py b/misoc/com/liteethmini/phy/s6rgmii.py
new file mode 100644 (file)
index 0000000..8f7da75
--- /dev/null
@@ -0,0 +1,162 @@
+# RGMII PHY for Spartan-6
+
+from migen.genlib.io import DDROutput
+from migen.genlib.misc import WaitTimer
+from migen.genlib.fsm import FSM, NextState
+
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthPHYRGMIITX(Module):
+    def __init__(self, pads, pads_register=True):
+        self.sink = sink = Sink(eth_phy_description(8))
+
+        # # #
+
+        self.specials += Instance("ODDR2",
+                p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
+                i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
+                i_CE=1, i_S=0, i_R=0,
+                i_D0=sink.stb, i_D1=sink.stb, o_Q=pads.tx_ctl,
+        )
+        for i in range(4):
+            self.specials += Instance("ODDR2",
+                    p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
+                    i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
+                    i_CE=1, i_S=0, i_R=0,
+                    i_D0=sink.data[i], i_D1=sink.data[4+i], o_Q=pads.tx_data[i],
+            )
+        self.comb += sink.ack.eq(1)
+
+
+class LiteEthPHYRGMIIRX(Module):
+    def __init__(self, pads):
+        self.source = source = Source(eth_phy_description(8))
+
+        # # #
+
+        rx_ctl = Signal()
+        rx_data = Signal(8)
+
+        self.specials += Instance("IDDR2",
+                p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
+                i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
+                i_CE=1, i_S=0, i_R=0,
+                i_D=pads.rx_ctl, o_Q1=rx_ctl,
+        )
+        for i in range(4):
+            self.specials += Instance("IDDR2",
+                    p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
+                    i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
+                    i_CE=1, i_S=0, i_R=0,
+                    i_D=pads.rx_data[i], o_Q0=rx_data[4+i], o_Q1=rx_data[i],
+            )
+
+
+        rx_ctl_d = Signal()
+        self.sync += rx_ctl_d.eq(rx_ctl)
+
+        sop = Signal()
+        eop = Signal()
+        self.comb += [
+            sop.eq(rx_ctl & ~rx_ctl_d),
+            eop.eq(~rx_ctl & rx_ctl_d)
+        ]
+        self.sync += [
+            source.stb.eq(rx_ctl),
+            source.sop.eq(sop),
+            source.data.eq(rx_data)
+        ]
+        self.comb += source.eop.eq(eop)
+
+
+class LiteEthPHYRGMIICRG(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset):
+        self._reset = CSRStorage()
+
+        # # #
+
+        self.clock_domains.cd_eth_rx = ClockDomain()
+        self.clock_domains.cd_eth_tx = ClockDomain()
+
+
+        # RX
+        dcm_reset = Signal()
+        dcm_locked = Signal()
+
+        timer = WaitTimer(1024)
+        fsm = FSM(reset_state="DCM_RESET")
+        self.submodules += timer, fsm
+
+        fsm.act("DCM_RESET",
+            dcm_reset.eq(1),
+            timer.wait.eq(1),
+            If(timer.done,
+                timer.wait.eq(0),
+                NextState("DCM_WAIT")
+            )
+        )
+        fsm.act("DCM_WAIT",
+            timer.wait.eq(1),
+            If(timer.done,
+                NextState("DCM_CHECK_LOCK")
+            )
+        )
+        fsm.act("DCM_CHECK_LOCK",
+            If(~dcm_locked,
+                NextState("DCM_RESET")
+            )
+        )
+
+        clk90_rx = Signal()
+        clk0_rx = Signal()
+        clk0_rx_bufg = Signal()
+        self.specials += Instance("DCM",
+                i_CLKIN=clock_pads.rx,
+                i_CLKFB=clk0_rx_bufg,
+                o_CLK0=clk0_rx,
+                o_CLK90=clk90_rx,
+                o_LOCKED=dcm_locked,
+                i_PSEN=0,
+                i_PSCLK=0,
+                i_PSINCDEC=0,
+                i_RST=dcm_reset
+        )
+
+        self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg)
+        self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk)
+
+        # TX
+        self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx"))
+        self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk)
+
+        # Reset
+        if with_hw_init_reset:
+            reset = Signal()
+            counter_done = Signal()
+            self.submodules.counter = counter = Counter(max=512)
+            self.comb += [
+                counter_done.eq(counter.value == 256),
+                counter.ce.eq(~counter_done),
+                reset.eq(~counter_done | self._reset.storage)
+            ]
+        else:
+            reset = self._reset.storage
+        self.comb += pads.rst_n.eq(~reset)
+        self.specials += [
+            AsyncResetSynchronizer(self.cd_eth_tx, reset),
+            AsyncResetSynchronizer(self.cd_eth_rx, reset),
+        ]
+
+
+class LiteEthPHYRGMII(Module, AutoCSR):
+    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
+        self.dw = 8
+        self.submodules.crg = LiteEthPHYRGMIICRG(clock_pads,
+                                                 pads,
+                                                 with_hw_init_reset)
+        self.submodules.tx = RenameClockDomains(LiteEthPHYRGMIITX(pads),
+                                                "eth_tx")
+        self.submodules.rx = RenameClockDomains(LiteEthPHYRGMIIRX(pads),
+                                                "eth_rx")
+        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoc/com/liteethmini/phy/sim.py b/misoc/com/liteethmini/phy/sim.py
new file mode 100644 (file)
index 0000000..d6d1778
--- /dev/null
@@ -0,0 +1,58 @@
+import os
+
+from misoc.com.liteethmini.common import *
+
+
+class LiteEthPHYSimCRG(Module, AutoCSR):
+    def __init__(self):
+        self._reset = CSRStorage()
+
+        # # #
+
+        self.clock_domains.cd_eth_rx = ClockDomain()
+        self.clock_domains.cd_eth_tx = ClockDomain()
+        self.comb += [
+            self.cd_eth_rx.clk.eq(ClockSignal()),
+            self.cd_eth_tx.clk.eq(ClockSignal())
+        ]
+
+        reset = self._reset.storage
+        self.comb += [
+            self.cd_eth_rx.rst.eq(reset),
+            self.cd_eth_tx.rst.eq(reset)
+        ]
+
+
+class LiteEthPHYSim(Module, AutoCSR):
+    def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"):
+        self.dw = 8
+        self.submodules.crg = LiteEthPHYSimCRG()
+        self.sink = sink = Sink(eth_phy_description(8))
+        self.source = source = Source(eth_phy_description(8))
+        self.tap = tap
+        self.ip_address = ip_address
+
+        self.comb += [
+            pads.source_stb.eq(self.sink.stb),
+            pads.source_data.eq(self.sink.data),
+            self.sink.ack.eq(1)
+        ]
+
+        self.sync += [
+            self.source.stb.eq(pads.sink_stb),
+            self.source.sop.eq(pads.sink_stb & ~self.source.stb),
+            self.source.data.eq(pads.sink_data),
+        ]
+        self.comb += [
+            self.source.eop.eq(~pads.sink_stb & self.source.stb),
+        ]
+
+        # XXX avoid use of os.system
+        os.system("openvpn --mktun --dev {}".format(self.tap))
+        os.system("ifconfig {} {} up".format(self.tap, self.ip_address))
+        os.system("mknod /dev/net/{} c 10 200".format(self.tap))
+
+    def do_exit(self, *args, **kwargs):
+        # XXX avoid use of os.system
+        os.system("rm -f /dev/net/{}".format(self.tap))
+        os.system("openvpn --rmtun --dev {}".format(self.tap))
diff --git a/misoc/com/spi/__init__.py b/misoc/com/spi/__init__.py
new file mode 100644 (file)
index 0000000..a78a6db
--- /dev/null
@@ -0,0 +1,154 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+from migen.genlib.fsm import FSM, NextState
+
+
+class SPIMaster(Module, AutoCSR):
+    def __init__(self, pads, width=24, div=2, cpha=1):
+        self.pads = pads
+
+        self._ctrl = CSR()
+        self._length = CSRStorage(8)
+        self._status = CSRStatus()
+        if hasattr(pads, "mosi"):
+            self._mosi = CSRStorage(width)
+        if hasattr(pads, "miso"):
+            self._miso = CSRStatus(width)
+
+        self.irq = Signal()
+
+    ###
+
+        # ctrl
+        start = Signal()
+        length = self._length.storage
+        enable_cs = Signal()
+        enable_shift = Signal()
+        done = Signal()
+
+        self.comb += [
+            start.eq(self._ctrl.re & self._ctrl.r[0]),
+            self._status.status.eq(done)
+        ]
+
+        # clk
+        i = Signal(max=div)
+        clk_en = Signal()
+        set_clk = Signal()
+        clr_clk = Signal()
+        self.sync += [
+            If(set_clk,
+                pads.clk.eq(enable_cs)
+            ),
+            If(clr_clk,
+                pads.clk.eq(0),
+                i.eq(0)
+            ).Else(
+                i.eq(i + 1),
+            )
+        ]
+
+        self.comb += [
+            set_clk.eq(i == (div//2-1)),
+            clr_clk.eq(i == (div-1))
+        ]
+
+        # fsm
+        cnt = Signal(8)
+        clr_cnt = Signal()
+        inc_cnt = Signal()
+        self.sync += \
+            If(clr_cnt,
+                cnt.eq(0)
+            ).Elif(inc_cnt,
+                cnt.eq(cnt+1)
+            )
+
+        fsm = FSM(reset_state="IDLE")
+        self.submodules += fsm
+        fsm.act("IDLE",
+            If(start,
+                NextState("WAIT_CLK")
+            ),
+            done.eq(1),
+            clr_cnt.eq(1)
+        )
+        fsm.act("WAIT_CLK",
+            If(clr_clk,
+                NextState("SHIFT")
+            ),
+        )
+        fsm.act("SHIFT",
+            If(cnt == length,
+                NextState("END")
+            ).Else(
+                inc_cnt.eq(clr_clk),
+            ),
+            enable_cs.eq(1),
+            enable_shift.eq(1),
+        )
+        fsm.act("END",
+            If(set_clk,
+                NextState("IDLE")
+            ),
+            enable_shift.eq(1),
+            self.irq.eq(1)
+        )
+
+        # miso
+        if hasattr(pads, "miso"):
+            miso = Signal()
+            sr_miso = Signal(width)
+
+            # (cpha = 1: capture on clk falling edge)
+            if cpha:
+                self.sync += \
+                    If(enable_shift,
+                        If(clr_clk,
+                            miso.eq(pads.miso),
+                        ).Elif(set_clk,
+                            sr_miso.eq(Cat(miso, sr_miso[:-1]))
+                        )
+                    )
+            # (cpha = 0: capture on clk rising edge)
+            else:
+                self.sync += \
+                    If(enable_shift,
+                        If(set_clk,
+                            miso.eq(pads.miso),
+                        ).Elif(clr_clk,
+                            sr_miso.eq(Cat(miso, sr_miso[:-1]))
+                        )
+                    )
+            self.comb += self._miso.status.eq(sr_miso)
+
+        # mosi
+        if hasattr(pads, "mosi"):
+            mosi = Signal()
+            sr_mosi = Signal(width)
+
+            # (cpha = 1: propagated on clk rising edge)
+            if cpha:
+                self.sync += \
+                    If(start,
+                        sr_mosi.eq(self._mosi.storage)
+                    ).Elif(clr_clk & enable_shift,
+                        sr_mosi.eq(Cat(Signal(), sr_mosi[:-1]))
+                    ).Elif(set_clk,
+                        pads.mosi.eq(sr_mosi[-1])
+                    )
+
+            # (cpha = 0: propagated on clk falling edge)
+            else:
+                self.sync += [
+                    If(start,
+                        sr_mosi.eq(self._mosi.storage)
+                    ).Elif(set_clk & enable_shift,
+                        sr_mosi.eq(Cat(Signal(), sr_mosi[:-1]))
+                    ).Elif(clr_clk,
+                        pads.mosi.eq(sr_mosi[-1])
+                    )
+                ]
+
+        # cs_n
+        self.comb += pads.cs_n.eq(~enable_cs)
diff --git a/misoc/com/spi/test/spi_master_tb.py b/misoc/com/spi/test/spi_master_tb.py
new file mode 100644 (file)
index 0000000..51a30c6
--- /dev/null
@@ -0,0 +1,86 @@
+from migen.fhdl.std import *
+from migen.genlib.record import *
+from migen.sim.generic import run_simulation
+
+from misoc.com.spi import SPIMaster
+
+
+class SPISlave(Module):
+    def __init__(self, pads, width):
+        self.pads = pads
+        self.width = width
+
+        ###
+
+        self.mosi = 0
+        self.miso = 0
+
+        self.last_cs_n = 1
+        self.last_clk = 0
+
+
+    def get_mosi(self):
+        return self.mosi
+
+    def set_miso(self, value):
+        self.miso = value
+
+    def do_simulation(self, selfp):
+        # detect edges
+        cs_n_rising = 0
+        cs_n_falling = 0
+        clk_rising = 0
+        clk_falling = 0
+        if selfp.pads.cs_n and not self.last_cs_n:
+            cs_n_rising = 1
+        if not selfp.pads.cs_n and self.last_cs_n:
+            cs_n_falling = 1
+        if selfp.pads.clk and not self.last_clk:
+            clk_rising = 1
+        if not selfp.pads.clk and self.last_clk:
+            clk_falling = 1
+
+        # input mosi
+        if clk_falling and not selfp.pads.cs_n:
+            self.mosi = self.mosi << 1
+            self.mosi |= selfp.pads.mosi
+
+        # output miso
+        if (clk_rising and not selfp.pads.cs_n):
+            selfp.pads.miso = (self.miso >> (self.width-1)) & 0x1
+            self.miso = self.miso << 1
+
+        # save signal states
+        self.last_cs_n = selfp.pads.cs_n
+        self.last_clk = selfp.pads.clk
+
+
+def spi_access(selfp, length, mosi):
+    selfp.spi_master._mosi.storage = mosi
+    yield
+    selfp.spi_master._ctrl.r = (length << 8) | 1
+    selfp.spi_master._ctrl.re = 1
+    yield
+    selfp.spi_master._ctrl.r = 0
+    selfp.spi_master._ctrl.re = 0
+    yield
+    while not (selfp.spi_master._status.status & 0x1):
+        yield
+
+
+class TB(Module):
+    def __init__(self):
+        pads = Record([("cs_n", 1), ("clk", 1), ("mosi", 1), ("miso", 1)])
+        self.submodules.spi_master = SPIMaster(pads, 24, 4)
+        self.submodules.spi_slave = SPISlave(pads, 24)
+
+    def gen_simulation(self, selfp):
+        for i in range(16):
+            yield
+        self.spi_slave.set_miso(0x123457)
+        yield from spi_access(selfp, 8, 0x123457)
+        print("{:08x}".format(self.spi_slave.get_mosi()))
+        print("{:08x}".format(selfp.spi_master._miso.status))
+
+if __name__ == "__main__":
+    run_simulation(TB(), ncycles=1000, vcd_name="my.vcd", keep_files=True)
diff --git a/misoc/com/uart/__init__.py b/misoc/com/uart/__init__.py
new file mode 100644 (file)
index 0000000..ffc39b4
--- /dev/null
@@ -0,0 +1,58 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+from migen.bank.eventmanager import *
+from migen.genlib.record import Record
+from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
+
+
+def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
+    if sink_cd != source_cd:
+        fifo = AsyncFIFO([("data", 8)], depth)
+        return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
+    else:
+        return SyncFIFO([("data", 8)], depth)
+
+
+class UART(Module, AutoCSR):
+    def __init__(self, phy,
+                 tx_fifo_depth=16,
+                 rx_fifo_depth=16,
+                 phy_cd="sys"):
+        self._rxtx = CSR(8)
+        self._txfull = CSRStatus()
+        self._rxempty = CSRStatus()
+
+        self.submodules.ev = EventManager()
+        self.ev.tx = EventSourceProcess()
+        self.ev.rx = EventSourceProcess()
+        self.ev.finalize()
+
+        # # #
+
+        # TX
+        tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
+        self.submodules += tx_fifo
+
+        self.comb += [
+            tx_fifo.sink.stb.eq(self._rxtx.re),
+            tx_fifo.sink.data.eq(self._rxtx.r),
+            self._txfull.status.eq(~tx_fifo.sink.ack),
+            Record.connect(tx_fifo.source, phy.sink),
+            # Generate TX IRQ when tx_fifo becomes non-full
+            self.ev.tx.trigger.eq(~tx_fifo.sink.ack)
+        ]
+
+
+        # RX
+        rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
+        self.submodules += rx_fifo
+
+
+        self.comb += [
+            Record.connect(phy.source, rx_fifo.sink),
+            self._rxempty.status.eq(~rx_fifo.source.stb),
+            self._rxtx.w.eq(rx_fifo.source.data),
+            rx_fifo.source.ack.eq(self.ev.rx.clear),
+            # Generate RX IRQ when tx_fifo becomes non-empty
+            self.ev.rx.trigger.eq(~rx_fifo.source.stb)
+        ]
diff --git a/misoc/com/uart/bridge.py b/misoc/com/uart/bridge.py
new file mode 100644 (file)
index 0000000..6917f35
--- /dev/null
@@ -0,0 +1,9 @@
+from migen.fhdl.std import *
+
+from misoc.tools.wishbone import WishboneStreamingBridge
+from misoc.com.uart.phy.serial import UARTPHYSerial
+
+class UARTWishboneBridge(WishboneStreamingBridge):
+    def __init__(self, pads, clk_freq, baudrate=115200):
+        self.submodules.phy = UARTPHYSerial(pads, clk_freq, baudrate)
+        WishboneStreamingBridge.__init__(self, self.phy, clk_freq)
diff --git a/misoc/com/uart/phy/__init__.py b/misoc/com/uart/phy/__init__.py
new file mode 100644 (file)
index 0000000..76ebd80
--- /dev/null
@@ -0,0 +1,8 @@
+def UARTPHY(pads, *args, **kwargs):
+    # Autodetect PHY
+    if hasattr(pads, "source_stb"):
+        from misoc.com.uart.phy.sim import UARTPHYSim
+        return UARTPHYSim(pads, *args, **kwargs)
+    else:
+        from misoc.com.uart.phy.serial import UARTPHYSerial
+        return UARTPHYSerial(pads, *args, **kwargs)
diff --git a/misoc/com/uart/phy/serial.py b/misoc/com/uart/phy/serial.py
new file mode 100644 (file)
index 0000000..747dbd2
--- /dev/null
@@ -0,0 +1,104 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.bank.description import *
+from migen.flow.actor import Sink, Source
+
+
+class UARTPHYSerialRX(Module):
+    def __init__(self, pads, tuning_word):
+        self.source = Source([("data", 8)])
+        ###
+        uart_clk_rxen = Signal()
+        phase_accumulator_rx = Signal(32)
+
+        rx = Signal()
+        self.specials += MultiReg(pads.rx, rx)
+        rx_r = Signal()
+        rx_reg = Signal(8)
+        rx_bitcount = Signal(4)
+        rx_busy = Signal()
+        rx_done = self.source.stb
+        rx_data = self.source.data
+        self.sync += [
+            rx_done.eq(0),
+            rx_r.eq(rx),
+            If(~rx_busy,
+                If(~rx & rx_r,  # look for start bit
+                    rx_busy.eq(1),
+                    rx_bitcount.eq(0),
+                )
+            ).Else(
+                If(uart_clk_rxen,
+                    rx_bitcount.eq(rx_bitcount + 1),
+                    If(rx_bitcount == 0,
+                        If(rx,  # verify start bit
+                            rx_busy.eq(0)
+                        )
+                    ).Elif(rx_bitcount == 9,
+                        rx_busy.eq(0),
+                        If(rx,  # verify stop bit
+                            rx_data.eq(rx_reg),
+                            rx_done.eq(1)
+                        )
+                    ).Else(
+                        rx_reg.eq(Cat(rx_reg[1:], rx))
+                    )
+                )
+            )
+        ]
+        self.sync += \
+                If(rx_busy,
+                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
+                ).Else(
+                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
+                )
+
+
+class UARTPHYSerialTX(Module):
+    def __init__(self, pads, tuning_word):
+        self.sink = Sink([("data", 8)])
+        ###
+        uart_clk_txen = Signal()
+        phase_accumulator_tx = Signal(32)
+
+        pads.tx.reset = 1
+
+        tx_reg = Signal(8)
+        tx_bitcount = Signal(4)
+        tx_busy = Signal()
+        self.sync += [
+            self.sink.ack.eq(0),
+            If(self.sink.stb & ~tx_busy & ~self.sink.ack,
+                tx_reg.eq(self.sink.data),
+                tx_bitcount.eq(0),
+                tx_busy.eq(1),
+                pads.tx.eq(0)
+            ).Elif(uart_clk_txen & tx_busy,
+                tx_bitcount.eq(tx_bitcount + 1),
+                If(tx_bitcount == 8,
+                    pads.tx.eq(1)
+                ).Elif(tx_bitcount == 9,
+                    pads.tx.eq(1),
+                    tx_busy.eq(0),
+                    self.sink.ack.eq(1),
+                ).Else(
+                    pads.tx.eq(tx_reg[0]),
+                    tx_reg.eq(Cat(tx_reg[1:], 0))
+                )
+            )
+        ]
+        self.sync += [
+                If(tx_busy,
+                    Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
+                ).Else(
+                    Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
+                )
+        ]
+
+
+class UARTPHYSerial(Module, AutoCSR):
+    def __init__(self, pads, clk_freq, baudrate=115200):
+        self._tuning_word = CSRStorage(32, reset=int((baudrate/clk_freq)*2**32))
+        self.submodules.tx = UARTPHYSerialTX(pads, self._tuning_word.storage)
+        self.submodules.rx = UARTPHYSerialRX(pads, self._tuning_word.storage)
+        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoc/com/uart/phy/sim.py b/misoc/com/uart/phy/sim.py
new file mode 100644 (file)
index 0000000..a7348e0
--- /dev/null
@@ -0,0 +1,33 @@
+import os
+import pty
+import time
+
+from migen.fhdl.std import *
+from migen.flow.actor import Sink, Source
+
+
+class UARTPHYSim(Module):
+    def __init__(self, pads, *args, **kwargs):
+        self.sink = Sink([("data", 8)])
+        self.source = Source([("data", 8)])
+
+        self.comb += [
+            pads.source_stb.eq(self.sink.stb),
+            pads.source_data.eq(self.sink.data),
+            self.sink.ack.eq(pads.source_ack),
+
+            self.source.stb.eq(pads.sink_stb),
+            self.source.data.eq(pads.sink_data),
+            pads.sink_ack.eq(self.source.ack)
+        ]
+
+        m, s = pty.openpty()
+        name = os.ttyname(s)
+        print("UART tty: "+name)
+        time.sleep(0.5)  # pause for user
+        f = open("/tmp/simserial", "w")
+        f.write(os.ttyname(s))
+        f.close()
+
+    def do_exit(self, *args, **kwargs):
+        os.remove("/tmp/simserial")
diff --git a/misoc/com/uart/software/__init__.py b/misoc/com/uart/software/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/com/uart/software/reg.py b/misoc/com/uart/software/reg.py
new file mode 100644 (file)
index 0000000..204a626
--- /dev/null
@@ -0,0 +1,55 @@
+import csv
+
+
+class MappedReg:
+    def __init__(self, readfn, writefn, name, addr, length, busword, mode):
+        self.readfn = readfn
+        self.writefn = writefn
+        self.addr = addr
+        self.length = length
+        self.busword = busword
+        self.mode = mode
+
+    def read(self):
+        if self.mode not in ["rw", "ro"]:
+            raise KeyError(name + "register not readable")
+        datas = self.readfn(self.addr, burst_length=self.length)
+        if isinstance(datas, int):
+            return datas
+        else:
+            data = 0
+            for i in range(self.length):
+                data = data << self.busword
+                data |= datas[i]
+            return data
+    def write(self, value):
+        if self.mode not in ["rw", "wo"]:
+            raise KeyError(name + "register not writable")
+        datas = []
+        for i in range(self.length):
+            datas.append((value >> ((self.length-1-i)*self.busword)) & (2**self.busword-1))
+        self.writefn(self.addr, datas)
+
+
+class MappedRegs:
+    def __init__(self, d):
+        self.d = d
+
+    def __getattr__(self, attr):
+        try:
+            return self.__dict__['d'][attr]
+        except KeyError:
+            pass
+        raise KeyError("No such register " + attr)
+
+
+def build_map(addrmap, busword, readfn, writefn):
+    csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#')
+    d = {}
+    for item in csv_reader:
+        name, addr, length, mode = item
+        addr = int(addr.replace("0x", ""), 16)
+        length = int(length)
+        d[name] = MappedReg(readfn, writefn, name, addr, length, busword, mode)
+    return MappedRegs(d)
diff --git a/misoc/com/uart/software/wishbone.py b/misoc/com/uart/software/wishbone.py
new file mode 100644 (file)
index 0000000..608ccf2
--- /dev/null
@@ -0,0 +1,75 @@
+import serial
+from struct import *
+from misoc.com.uart.software.reg import *
+
+
+def write_b(uart, data):
+    uart.write(pack('B', data))
+
+
+class UARTWishboneBridgeDriver:
+    cmds = {
+        "write": 0x01,
+        "read":  0x02
+    }
+    def __init__(self, port, baudrate=115200, addrmap=None, busword=8, debug=False):
+        self.port = port
+        self.baudrate = str(baudrate)
+        self.debug = debug
+        self.uart = serial.Serial(port, baudrate, timeout=0.25)
+        if addrmap is not None:
+            self.regs = build_map(addrmap, busword, self.read, self.write)
+
+    def open(self):
+        self.uart.flushOutput()
+        self.uart.close()
+        self.uart.open()
+        self.uart.flushInput()
+
+    def close(self):
+        self.uart.flushOutput()
+        self.uart.close()
+
+    def read(self, addr, burst_length=1):
+        datas = []
+        self.uart.flushInput()
+        write_b(self.uart, self.cmds["read"])
+        write_b(self.uart, burst_length)
+        word_addr = addr//4
+        write_b(self.uart, (word_addr >> 24) & 0xff)
+        write_b(self.uart, (word_addr >> 16) & 0xff)
+        write_b(self.uart, (word_addr >>  8) & 0xff)
+        write_b(self.uart, (word_addr >>  0) & 0xff)
+        for i in range(burst_length):
+            data = 0
+            for k in range(4):
+                data = data << 8
+                data |= ord(self.uart.read())
+            if self.debug:
+                print("RD {:08X} @ {:08X}".format(data, addr + 4*i))
+            datas.append(data)
+        if burst_length == 1:
+            return datas[0]
+        else:
+            return datas
+
+    def write(self, addr, data):
+        if isinstance(data, list):
+            burst_length = len(data)
+        else:
+            burst_length = 1
+            data = [data]
+        write_b(self.uart, self.cmds["write"])
+        write_b(self.uart, burst_length)
+        word_addr = addr//4
+        write_b(self.uart, (word_addr >> 24) & 0xff)
+        write_b(self.uart, (word_addr >> 16) & 0xff)
+        write_b(self.uart, (word_addr >>  8) & 0xff)
+        write_b(self.uart, (word_addr >>  0) & 0xff)
+        for i in range(len(data)):
+            dat = data[i]
+            for j in range(4):
+                write_b(self.uart, (dat >> 24) & 0xff)
+                dat = dat << 8
+            if self.debug:
+                print("WR {:08X} @ {:08X}".format(data[i], addr + 4*i))
diff --git a/misoc/com/uart/test/test_serial_phy.py b/misoc/com/uart/test/test_serial_phy.py
new file mode 100644 (file)
index 0000000..71318c7
--- /dev/null
@@ -0,0 +1,97 @@
+# XXX Adapt test to new architecture
+class UARTTB(Module):
+    def __init__(self):
+        self.clk_freq = 83333333
+        self.baud = 3000000
+        self.pads = Record([("rx", 1), ("tx", 1)])
+        self.submodules.slave = UART(self.pads, self.clk_freq, self.baud)
+
+    def wait_for(self, ns_time):
+        freq_in_ghz = self.clk_freq/(10**9)
+        period = 1/freq_in_ghz
+        num_loops = int(ns_time/period)
+        for i in range(num_loops+1):
+            yield
+
+    def gen_simulation(self, selfp):
+        baud_in_ghz = self.baud/(10**9)
+        uart_period = int(1/baud_in_ghz)
+        half_uart_period = int(1/(2*baud_in_ghz))
+
+        # Set TX an RX lines idle
+        selfp.pads.tx = 1
+        selfp.pads.rx = 1
+        yield
+
+        # First send a few characters
+
+        tx_string = "01234"
+        print("Sending string: " + tx_string)
+        for c in tx_string:
+            selfp.slave._r_rxtx.r = ord(c)
+            selfp.slave._r_rxtx.re = 1
+            yield
+            selfp.slave._r_rxtx.re = 0
+
+            yield from self.wait_for(half_uart_period)
+
+            if selfp.pads.tx:
+                print("FAILURE: no start bit sent")
+
+            val = 0
+            for i in range(8):
+                yield from self.wait_for(uart_period)
+                val >>= 1
+                if selfp.pads.tx:
+                    val |= 0x80
+
+            yield from self.wait_for(uart_period)
+
+            if selfp.pads.tx == 0:
+                print("FAILURE: no stop bit sent")
+
+            if ord(c) != val:
+                print("FAILURE: sent decimal value "+str(val)+" (char "+chr(val)+") instead of "+c)
+            else:
+                print("SUCCESS: sent "+c)
+            while selfp.slave.ev.tx.trigger != 1:
+                yield
+
+        # Then receive a character
+
+        rx_string = '5'
+        print("Receiving character "+rx_string)
+        rx_value = ord(rx_string)
+        for i in range(11):
+            if (i == 0):
+                # start bit
+                selfp.pads.rx = 0
+            elif (i == 9):
+                # stop bit
+                selfp.pads.rx = 1
+            elif (i == 10):
+                selfp.pads.rx = 1
+                break
+            else:
+                selfp.pads.rx = 1 if (rx_value & 1) else 0
+                rx_value >>= 1
+            yield from self.wait_for(uart_period)
+
+        rx_value = ord(rx_string)
+        received_value = selfp.slave._r_rxtx.w
+        if (received_value == rx_value):
+            print("RX SUCCESS: ")
+        else:
+            print("RX FAILURE: ")
+
+        print("received "+chr(received_value))
+
+        while True:
+            yield
+
+if __name__ == "__main__":
+    from migen.sim.generic import Simulator, TopLevel
+    from migen.sim import icarus
+    with Simulator(UARTTB(), TopLevel("top.vcd", clk_period=int(1/0.08333333)),
+                   icarus.Runner(keep_files=False)) as s:
+        s.run(20000)
diff --git a/misoc/cpu/__init__.py b/misoc/cpu/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/cpu/identifier.py b/misoc/cpu/identifier.py
new file mode 100644 (file)
index 0000000..7f24c61
--- /dev/null
@@ -0,0 +1,26 @@
+import subprocess
+
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+def get_id():
+    output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii")
+    return int(output[:8], 16)
+
+
+class Identifier(Module, AutoCSR):
+    def __init__(self, sysid, frequency, revision=None):
+        self._sysid = CSRStatus(16)
+        self._revision = CSRStatus(32)
+        self._frequency = CSRStatus(32)
+
+        ###
+
+        if revision is None:
+            revision = get_id()
+
+        self.comb += [
+            self._sysid.status.eq(sysid),
+            self._revision.status.eq(revision),
+            self._frequency.status.eq(frequency)
+        ]
diff --git a/misoc/cpu/lm32.py b/misoc/cpu/lm32.py
new file mode 100644 (file)
index 0000000..8ea7637
--- /dev/null
@@ -0,0 +1,63 @@
+import os
+
+from migen.fhdl.std import *
+from migen.bus import wishbone
+
+
+class LM32(Module):
+    def __init__(self, platform, eba_reset):
+        self.ibus = i = wishbone.Interface()
+        self.dbus = d = wishbone.Interface()
+        self.interrupt = Signal(32)
+
+        ###
+
+        i_adr_o = Signal(32)
+        d_adr_o = Signal(32)
+        self.specials += Instance("lm32_cpu",
+                                   p_eba_reset=Instance.PreformattedParam("32'h{:08x}".format(eba_reset)),
+
+                                   i_clk_i=ClockSignal(),
+                                   i_rst_i=ResetSignal(),
+
+                                   i_interrupt=self.interrupt,
+
+                                   o_I_ADR_O=i_adr_o,
+                                   o_I_DAT_O=i.dat_w,
+                                   o_I_SEL_O=i.sel,
+                                   o_I_CYC_O=i.cyc,
+                                   o_I_STB_O=i.stb,
+                                   o_I_WE_O=i.we,
+                                   o_I_CTI_O=i.cti,
+                                   o_I_BTE_O=i.bte,
+                                   i_I_DAT_I=i.dat_r,
+                                   i_I_ACK_I=i.ack,
+                                   i_I_ERR_I=i.err,
+                                   i_I_RTY_I=0,
+
+                                   o_D_ADR_O=d_adr_o,
+                                   o_D_DAT_O=d.dat_w,
+                                   o_D_SEL_O=d.sel,
+                                   o_D_CYC_O=d.cyc,
+                                   o_D_STB_O=d.stb,
+                                   o_D_WE_O=d.we,
+                                   o_D_CTI_O=d.cti,
+                                   o_D_BTE_O=d.bte,
+                                   i_D_DAT_I=d.dat_r,
+                                   i_D_ACK_I=d.ack,
+                                   i_D_ERR_I=d.err,
+                                   i_D_RTY_I=0)
+
+        self.comb += [
+            self.ibus.adr.eq(i_adr_o[2:]),
+            self.dbus.adr.eq(d_adr_o[2:])
+        ]
+
+        # add Verilog sources
+        platform.add_sources(os.path.join("extcores", "lm32", "submodule", "rtl"),
+                "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
+                "lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
+                "lm32_shifter.v", "lm32_multiplier.v", "lm32_mc_arithmetic.v",
+                "lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
+                "lm32_dcache.v", "lm32_debug.v", "lm32_itlb.v", "lm32_dtlb.v")
+        platform.add_verilog_include_path(os.path.join("extcores", "lm32"))
diff --git a/misoc/cpu/mor1kx.py b/misoc/cpu/mor1kx.py
new file mode 100644 (file)
index 0000000..1169aba
--- /dev/null
@@ -0,0 +1,80 @@
+import os
+
+from migen.fhdl.std import *
+from migen.bus import wishbone
+
+
+class MOR1KX(Module):
+    def __init__(self, platform, reset_pc):
+        self.ibus = i = wishbone.Interface()
+        self.dbus = d = wishbone.Interface()
+        self.interrupt = Signal(32)
+
+        ###
+
+        i_adr_o = Signal(32)
+        d_adr_o = Signal(32)
+        self.specials += Instance("mor1kx",
+                                  p_FEATURE_INSTRUCTIONCACHE="ENABLED",
+                                  p_OPTION_ICACHE_BLOCK_WIDTH=4,
+                                  p_OPTION_ICACHE_SET_WIDTH=8,
+                                  p_OPTION_ICACHE_WAYS=1,
+                                  p_OPTION_ICACHE_LIMIT_WIDTH=31,
+                                  p_FEATURE_DATACACHE="ENABLED",
+                                  p_OPTION_DCACHE_BLOCK_WIDTH=4,
+                                  p_OPTION_DCACHE_SET_WIDTH=8,
+                                  p_OPTION_DCACHE_WAYS=1,
+                                  p_OPTION_DCACHE_LIMIT_WIDTH=31,
+                                  p_FEATURE_TIMER="NONE",
+                                  p_OPTION_PIC_TRIGGER="LEVEL",
+                                  p_FEATURE_SYSCALL="NONE",
+                                  p_FEATURE_TRAP="NONE",
+                                  p_FEATURE_RANGE="NONE",
+                                  p_FEATURE_OVERFLOW="NONE",
+                                  p_FEATURE_ADDC="ENABLED",
+                                  p_FEATURE_CMOV="ENABLED",
+                                  p_FEATURE_FFL1="ENABLED",
+                                  p_OPTION_CPU0="CAPPUCCINO",
+                                  p_OPTION_RESET_PC=reset_pc,
+                                  p_IBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
+                                  p_DBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
+
+                                  i_clk=ClockSignal(),
+                                  i_rst=ResetSignal(),
+
+                                  i_irq_i=self.interrupt,
+
+                                  o_iwbm_adr_o=i_adr_o,
+                                  o_iwbm_dat_o=i.dat_w,
+                                  o_iwbm_sel_o=i.sel,
+                                  o_iwbm_cyc_o=i.cyc,
+                                  o_iwbm_stb_o=i.stb,
+                                  o_iwbm_we_o=i.we,
+                                  o_iwbm_cti_o=i.cti,
+                                  o_iwbm_bte_o=i.bte,
+                                  i_iwbm_dat_i=i.dat_r,
+                                  i_iwbm_ack_i=i.ack,
+                                  i_iwbm_err_i=i.err,
+                                  i_iwbm_rty_i=0,
+
+                                  o_dwbm_adr_o=d_adr_o,
+                                  o_dwbm_dat_o=d.dat_w,
+                                  o_dwbm_sel_o=d.sel,
+                                  o_dwbm_cyc_o=d.cyc,
+                                  o_dwbm_stb_o=d.stb,
+                                  o_dwbm_we_o=d.we,
+                                  o_dwbm_cti_o=d.cti,
+                                  o_dwbm_bte_o=d.bte,
+                                  i_dwbm_dat_i=d.dat_r,
+                                  i_dwbm_ack_i=d.ack,
+                                  i_dwbm_err_i=d.err,
+                                  i_dwbm_rty_i=0)
+
+        self.comb += [
+            self.ibus.adr.eq(i_adr_o[2:]),
+            self.dbus.adr.eq(d_adr_o[2:])
+        ]
+
+        # add Verilog sources
+        platform.add_source_dir(os.path.join("extcores", "mor1kx", "submodule",
+                                             "rtl", "verilog"))
diff --git a/misoc/cpu/timer.py b/misoc/cpu/timer.py
new file mode 100644 (file)
index 0000000..4061f83
--- /dev/null
@@ -0,0 +1,34 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+from migen.bank.eventmanager import *
+
+
+class Timer(Module, AutoCSR):
+    def __init__(self, width=32):
+        self._load = CSRStorage(width)
+        self._reload = CSRStorage(width)
+        self._en = CSRStorage()
+        self._update_value = CSR()
+        self._value = CSRStatus(width)
+
+        self.submodules.ev = EventManager()
+        self.ev.zero = EventSourceProcess()
+        self.ev.finalize()
+
+        ###
+
+        value = Signal(width)
+        self.sync += [
+            If(self._en.storage,
+                If(value == 0,
+                    # set reload to 0 to disable reloading
+                    value.eq(self._reload.storage)
+                ).Else(
+                    value.eq(value - 1)
+                )
+            ).Else(
+                value.eq(self._load.storage)
+            ),
+            If(self._update_value.re, self._value.status.eq(value))
+        ]
+        self.comb += self.ev.zero.trigger.eq(value != 0)
diff --git a/misoc/mem/__init__.py b/misoc/mem/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/mem/flash/__init__.py b/misoc/mem/flash/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/mem/flash/norflash16.py b/misoc/mem/flash/norflash16.py
new file mode 100644 (file)
index 0000000..42c68c0
--- /dev/null
@@ -0,0 +1,103 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.fsm import FSM, NextState
+
+
+class NorFlash16(Module):
+    def __init__(self, pads, rd_timing, wr_timing):
+        self.bus = wishbone.Interface()
+
+        ###
+
+        data = TSTriple(16)
+        lsb = Signal()
+
+        self.specials += data.get_tristate(pads.d)
+        self.comb += [
+            data.oe.eq(pads.oe_n),
+            pads.ce_n.eq(0)
+        ]
+
+        load_lo = Signal()
+        load_hi = Signal()
+        store = Signal()
+
+        pads.oe_n.reset, pads.we_n.reset = 1, 1
+        self.sync += [
+            pads.oe_n.eq(1),
+            pads.we_n.eq(1),
+
+            # Register data/address to avoid off-chip glitches
+            If(self.bus.cyc & self.bus.stb,
+                pads.adr.eq(Cat(lsb, self.bus.adr)),
+                If(self.bus.we,
+                    # Only 16-bit writes are supported. Assume sel=0011 or 1100.
+                    If(self.bus.sel[0],
+                        data.o.eq(self.bus.dat_w[:16])
+                    ).Else(
+                        data.o.eq(self.bus.dat_w[16:])
+                    )
+                ).Else(
+                    pads.oe_n.eq(0)
+                )
+            ),
+
+            If(load_lo, self.bus.dat_r[:16].eq(data.i)),
+            If(load_hi, self.bus.dat_r[16:].eq(data.i)),
+            If(store, pads.we_n.eq(0))
+        ]
+
+        # Typical timing of the flash chips:
+        #  - 110ns address to output
+        #  - 50ns write pulse width
+        counter = Signal(max=max(rd_timing, wr_timing)+1)
+        counter_en = Signal()
+        counter_wr_mode = Signal()
+        counter_done = Signal()
+        self.comb += counter_done.eq(counter == Mux(counter_wr_mode, wr_timing, rd_timing))
+        self.sync += If(counter_en & ~counter_done,
+                counter.eq(counter + 1)
+            ).Else(
+                counter.eq(0)
+            )
+
+        fsm = FSM()
+        self.submodules += fsm
+
+        fsm.act("IDLE",
+            If(self.bus.cyc & self.bus.stb,
+                If(self.bus.we,
+                    NextState("WR")
+                ).Else(
+                    NextState("RD_HI")
+                )
+            )
+        )
+        fsm.act("RD_HI",
+            lsb.eq(0),
+            counter_en.eq(1),
+            If(counter_done,
+                load_hi.eq(1),
+                NextState("RD_LO")
+            )
+        )
+        fsm.act("RD_LO",
+            lsb.eq(1),
+            counter_en.eq(1),
+            If(counter_done,
+                load_lo.eq(1),
+                NextState("ACK")
+            )
+        )
+        fsm.act("WR",
+            # supported cases: sel=0011 [lsb=1] and sel=1100 [lsb=0]
+            lsb.eq(self.bus.sel[0]),
+            counter_wr_mode.eq(1),
+            counter_en.eq(1),
+            store.eq(1),
+            If(counter_done, NextState("ACK"))
+        )
+        fsm.act("ACK",
+            self.bus.ack.eq(1),
+            NextState("IDLE")
+        )
diff --git a/misoc/mem/flash/spiflash.py b/misoc/mem/flash/spiflash.py
new file mode 100644 (file)
index 0000000..1e099a7
--- /dev/null
@@ -0,0 +1,181 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import *
+from migen.bus import wishbone
+from migen.genlib.misc import timeline
+from migen.genlib.record import Record
+from migen.bank.description import AutoCSR, CSRStorage, CSRStatus
+
+_FAST_READ = 0x0b
+_DIOFR = 0xbb
+_QIOFR = 0xeb
+
+
+def _format_cmd(cmd, spi_width):
+    """
+    `cmd` is the read instruction. Since everything is transmitted on all
+    dq lines (cmd, adr and data), extend/interleave cmd to full pads.dq
+    width even if dq1-dq3 are don't care during the command phase:
+    For example, for N25Q128, 0xeb is the quad i/o fast read, and
+    extended to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
+    """
+    c = 2**(8*spi_width)-1
+    for b in range(8):
+        if not (cmd>>b)%2:
+            c &= ~(1<<(b*spi_width))
+    return c
+
+
+class SpiFlash(Module, AutoCSR):
+    def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
+        """
+        Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.
+
+        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
+        Read). Only supports mode0 (cpol=0, cpha=0).
+        Optionally supports software bitbanging (for write, erase, or other commands).
+        """
+        self.bus = bus = wishbone.Interface()
+        spi_width = flen(pads.dq)
+        if with_bitbang:
+            self.bitbang = CSRStorage(4)
+            self.miso = CSRStatus()
+            self.bitbang_en = CSRStorage()
+
+        ###
+
+        cs_n = Signal(reset=1)
+        clk = Signal()
+        dq_oe = Signal()
+        wbone_width = flen(bus.dat_r)
+
+
+        read_cmd_params = {
+            4: (_format_cmd(_QIOFR, 4), 4*8),
+            2: (_format_cmd(_DIOFR, 2), 2*8),
+            1: (_format_cmd(_FAST_READ, 1), 1*8)
+        }
+        read_cmd, cmd_width = read_cmd_params[spi_width]
+        addr_width = 24
+
+        pads.cs_n.reset = 1
+
+        dq = TSTriple(spi_width)
+        self.specials.dq = dq.get_tristate(pads.dq)
+
+        sr = Signal(max(cmd_width, addr_width, wbone_width))
+        dqs = Replicate(1, spi_width-1)
+
+        self.comb += bus.dat_r.eq(sr)
+
+        hw_read_logic = [
+            pads.clk.eq(clk),
+            pads.cs_n.eq(cs_n),
+            dq.o.eq(sr[-spi_width:]),
+            dq.oe.eq(dq_oe)
+        ]
+
+        if with_bitbang:
+            bitbang_logic = [
+                pads.clk.eq(self.bitbang.storage[1]),
+                pads.cs_n.eq(self.bitbang.storage[2]),
+                dq.o.eq(Cat(self.bitbang.storage[0], dqs)),
+                If(self.bitbang.storage[3],
+                    dq.oe.eq(0)
+                ).Else(
+                    dq.oe.eq(1)
+                ),
+                If(self.bitbang.storage[1],
+                    self.miso.status.eq(dq.i[1])
+                )
+            ]
+
+            self.comb += \
+                If(self.bitbang_en.storage,
+                    bitbang_logic
+                ).Else(
+                    hw_read_logic
+                )
+        else:
+            self.comb += hw_read_logic
+
+        if div < 2:
+            raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
+        else:
+            i = Signal(max=div)
+            dqi = Signal(spi_width)
+            self.sync += [
+                If(i == div//2 - 1,
+                    clk.eq(1),
+                    dqi.eq(dq.i),
+                ),
+                If(i == div - 1,
+                    i.eq(0),
+                    clk.eq(0),
+                    sr.eq(Cat(dqi, sr[:-spi_width]))
+                ).Else(
+                    i.eq(i + 1),
+                ),
+            ]
+
+        # spi is byte-addressed, prefix by zeros
+        z = Replicate(0, log2_int(wbone_width//8))
+
+        seq = [
+            (cmd_width//spi_width*div,
+                [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
+            (addr_width//spi_width*div,
+                [sr[-addr_width:].eq(Cat(z, bus.adr))]),
+            ((dummy + wbone_width//spi_width)*div,
+                [dq_oe.eq(0)]),
+            (1,
+                [bus.ack.eq(1), cs_n.eq(1)]),
+            (div, # tSHSL!
+                [bus.ack.eq(0)]),
+            (0,
+                []),
+        ]
+
+        # accumulate timeline deltas
+        t, tseq = 0, []
+        for dt, a in seq:
+            tseq.append((t, a))
+            t += dt
+
+        self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
+
+
+class SpiFlashTB(Module):
+    def __init__(self):
+        self.submodules.master = wishbone.Initiator(self.gen_reads())
+        self.pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
+        self.submodules.slave = SpiFlash(self.pads)
+        self.submodules.tap = wishbone.Tap(self.slave.bus)
+        self.submodules.intercon = wishbone.InterconnectPointToPoint(
+                self.master.bus, self.slave.bus)
+        self.cycle = 0
+
+    def gen_reads(self):
+        for a in range(10):
+            t = TRead(a)
+            yield t
+            print("read {} in {} cycles(s)".format(t.data, t.latency))
+
+    def do_simulation(self, selfp):
+        if selfp.pads.cs_n:
+            self.cycle = 0
+        else:
+            self.cycle += 1
+            if not selfp.slave.dq.oe:
+                selfp.slave.dq.i = self.cycle & 0xf
+    do_simulation.passive = True
+
+if __name__ == "__main__":
+    from migen.sim.generic import run_simulation
+    from migen.fhdl import verilog
+
+    pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
+    s = SpiFlash(pads)
+    print(verilog.convert(s, ios={pads.clk, pads.cs_n, pads.dq, s.bus.adr,
+        s.bus.dat_r, s.bus.cyc, s.bus.ack, s.bus.stb}))
+
+    run_simulation(SpiFlashTB(), vcd_name="spiflash.vcd")
diff --git a/misoc/mem/sdram/__init__.py b/misoc/mem/sdram/__init__.py
new file mode 100644 (file)
index 0000000..b327bb0
--- /dev/null
@@ -0,0 +1,11 @@
+from collections import namedtuple
+
+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")
diff --git a/misoc/mem/sdram/core/__init__.py b/misoc/mem/sdram/core/__init__.py
new file mode 100644 (file)
index 0000000..287bdf5
--- /dev/null
@@ -0,0 +1,36 @@
+from migen.fhdl.std import *
+from migen.genlib.record import *
+from migen.bank.description import *
+
+from misoc.mem.sdram.phy import dfii
+from misoc.mem.sdram.core import minicon, lasmicon
+from misoc.mem.sdram.core import lasmixbar
+
+
+class SDRAMCore(Module, AutoCSR):
+    def __init__(self, phy, geom_settings, timing_settings, controller_settings, **kwargs):
+        # DFI
+        self.submodules.dfii = dfii.DFIInjector(geom_settings.addressbits, geom_settings.bankbits,
+                phy.settings.dfi_databits, phy.settings.nphases)
+        self.comb += Record.connect(self.dfii.master, phy.dfi)
+
+        # LASMICON
+        if isinstance(controller_settings, lasmicon.LASMIconSettings):
+            self.submodules.controller = controller = lasmicon.LASMIcon(phy.settings,
+                                                                        geom_settings,
+                                                                        timing_settings,
+                                                                        controller_settings,
+                                                                        **kwargs)
+            self.comb += Record.connect(controller.dfi, self.dfii.slave)
+
+            self.submodules.crossbar = lasmixbar.LASMIxbar([controller.lasmic],
+                                                           controller.nrowbits)
+
+        # MINICON
+        elif isinstance(controller_settings, minicon.MiniconSettings):
+            self.submodules.controller = controller = minicon.Minicon(phy.settings,
+                                                                      geom_settings,
+                                                                      timing_settings)
+            self.comb += Record.connect(controller.dfi, self.dfii.slave)
+        else:
+            raise ValueError("Unsupported SDRAM controller type")
diff --git a/misoc/mem/sdram/core/lasmibus.py b/misoc/mem/sdram/core/lasmibus.py
new file mode 100644 (file)
index 0000000..c1d3b0c
--- /dev/null
@@ -0,0 +1,164 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import *
+from migen.genlib import roundrobin
+from migen.genlib.record import *
+from migen.genlib.misc import optree
+
+
+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)
+
+
+class Initiator(Module):
+    def __init__(self, generator, bus):
+        self.generator = generator
+        self.bus = bus
+        self.transaction_start = 0
+        self.transaction = None
+        self.transaction_end = None
+
+    def do_simulation(self, selfp):
+        selfp.bus.dat_w = 0
+        selfp.bus.dat_we = 0
+
+        if self.transaction is not None:
+            if selfp.bus.req_ack:
+                selfp.bus.stb = 0
+            if selfp.bus.dat_ack:
+                if isinstance(self.transaction, TRead):
+                    self.transaction_end = selfp.simulator.cycle_counter + self.bus.read_latency
+                else:
+                    self.transaction_end = selfp.simulator.cycle_counter + self.bus.write_latency - 1
+
+        if self.transaction is None or selfp.simulator.cycle_counter == self.transaction_end:
+            if self.transaction is not None:
+                self.transaction.latency = selfp.simulator.cycle_counter - self.transaction_start - 1
+                if isinstance(self.transaction, TRead):
+                    self.transaction.data = selfp.bus.dat_r
+                else:
+                    selfp.bus.dat_w = self.transaction.data
+                    selfp.bus.dat_we = self.transaction.sel
+            try:
+                self.transaction = next(self.generator)
+            except StopIteration:
+                raise StopSimulation
+            if self.transaction is not None:
+                self.transaction_start = selfp.simulator.cycle_counter
+                selfp.bus.stb = 1
+                selfp.bus.adr = self.transaction.address
+                if isinstance(self.transaction, TRead):
+                    selfp.bus.we = 0
+                else:
+                    selfp.bus.we = 1
+
+
+class TargetModel:
+    def __init__(self):
+        self.last_bank = 0
+
+    def read(self, bank, address):
+        return 0
+
+    def write(self, bank, address, data, we):
+        pass
+
+    # Round-robin scheduling
+    def select_bank(self, pending_banks):
+        if not pending_banks:
+            return -1
+        self.last_bank += 1
+        if self.last_bank > max(pending_banks):
+            self.last_bank = 0
+        while self.last_bank not in pending_banks:
+            self.last_bank += 1
+        return self.last_bank
+
+
+class _ReqFIFO(Module):
+    def __init__(self, req_queue_size, bank):
+        self.req_queue_size = req_queue_size
+        self.bank = bank
+        self.contents = []
+
+    def do_simulation(self, selfp):
+        if len(self.contents) < self.req_queue_size:
+            if selfp.bank.stb:
+                self.contents.append((selfp.bank.we, selfp.bank.adr))
+            selfp.bank.req_ack = 1
+        else:
+            selfp.bank.req_ack = 0
+        selfp.bank.lock = bool(self.contents)
+    do_simulation.passive = True
+
+
+class Target(Module):
+    def __init__(self, model, *ifargs, **ifkwargs):
+        self.model = model
+        self.bus = Interface(*ifargs, **ifkwargs)
+        self.req_fifos = [_ReqFIFO(self.bus.req_queue_size, getattr(self.bus, "bank"+str(nb)))
+            for nb in range(self.bus.nbanks)]
+        self.submodules += self.req_fifos
+        self.rd_pipeline = [None]*self.bus.read_latency
+        self.wr_pipeline = [None]*(self.bus.write_latency + 1)
+
+    def do_simulation(self, selfp):
+        # determine banks with pending requests
+        pending_banks = set(nb for nb, rf in enumerate(self.req_fifos) if rf.contents)
+
+        # issue new transactions
+        selected_bank_n = self.model.select_bank(pending_banks)
+        selected_transaction = None
+        for nb in range(self.bus.nbanks):
+            bank = getattr(selfp.bus, "bank"+str(nb))
+            if nb == selected_bank_n:
+                bank.dat_ack = 1
+                selected_transaction = self.req_fifos[nb].contents.pop(0)
+            else:
+                bank.dat_ack = 0
+
+        rd_transaction = None
+        wr_transaction = None
+        if selected_bank_n >= 0:
+            we, adr = selected_transaction
+            if we:
+                wr_transaction = selected_bank_n, adr
+            else:
+                rd_transaction = selected_bank_n, adr
+
+        # data pipeline
+        self.rd_pipeline.append(rd_transaction)
+        self.wr_pipeline.append(wr_transaction)
+        done_rd_transaction = self.rd_pipeline.pop(0)
+        done_wr_transaction = self.wr_pipeline.pop(0)
+        if done_rd_transaction is not None:
+            selfp.bus.dat_r = self.model.read(done_rd_transaction[0], done_rd_transaction[1])
+        if done_wr_transaction is not None:
+            self.model.write(done_wr_transaction[0], done_wr_transaction[1],
+                selfp.bus.dat_w, selfp.bus.dat_we)
+    do_simulation.passive = True
diff --git a/misoc/mem/sdram/core/lasmicon/__init__.py b/misoc/mem/sdram/core/lasmicon/__init__.py
new file mode 100644 (file)
index 0000000..170e085
--- /dev/null
@@ -0,0 +1,63 @@
+from migen.fhdl.std import *
+
+from misoc.mem.sdram.phy import dfi
+from misoc.mem.sdram.core import lasmibus
+from misoc.mem.sdram.core.lasmicon.refresher import *
+from misoc.mem.sdram.core.lasmicon.bankmachine import *
+from misoc.mem.sdram.core.lasmicon.multiplexer import *
+
+
+class LASMIconSettings:
+    def __init__(self, req_queue_size=8,
+            read_time=32, write_time=16,
+            l2_size=8192,
+            with_bandwidth=False,
+            with_memtest=False,
+            with_refresh=True):
+        self.req_queue_size = req_queue_size
+        self.read_time = read_time
+        self.write_time = write_time
+        self.l2_size = l2_size
+        if with_memtest:
+            self.with_bandwidth = True
+        else:
+            self.with_bandwidth = with_bandwidth
+        self.with_memtest = with_memtest
+        self.with_refresh = with_refresh
+
+
+class LASMIcon(Module):
+    def __init__(self, phy_settings, geom_settings, timing_settings, controller_settings, **kwargs):
+        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 = lasmibus.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, enabled=controller_settings.with_refresh)
+        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,
+            **kwargs)
+
+    def get_csrs(self):
+        return self.multiplexer.get_csrs()
diff --git a/misoc/mem/sdram/core/lasmicon/bankmachine.py b/misoc/mem/sdram/core/lasmicon/bankmachine.py
new file mode 100644 (file)
index 0000000..1f58dd4
--- /dev/null
@@ -0,0 +1,148 @@
+from migen.fhdl.std import *
+from migen.genlib.roundrobin import *
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import optree
+from migen.genlib.fifo import SyncFIFO
+
+from misoc.mem.sdram.core.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
+        self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))],
+                                            controller_settings.req_queue_size)
+        self.comb += [
+            self.req_fifo.din.we.eq(req.we),
+            self.req_fifo.din.adr.eq(req.adr),
+            self.req_fifo.we.eq(req.stb),
+            req.req_ack.eq(self.req_fifo.writable),
+
+            self.req_fifo.re.eq(req.dat_w_ack | req.dat_r_ack),
+            req.lock.eq(self.req_fifo.readable)
+        ]
+        reqf = self.req_fifo.dout
+
+        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/misoc/mem/sdram/core/lasmicon/multiplexer.py b/misoc/mem/sdram/core/lasmicon/multiplexer.py
new file mode 100644 (file)
index 0000000..d03d4df
--- /dev/null
@@ -0,0 +1,228 @@
+from migen.fhdl.std import *
+from migen.genlib.roundrobin import *
+from migen.genlib.misc import optree
+from migen.genlib.fsm import FSM, NextState
+from migen.bank.description import AutoCSR
+
+from misoc.mem.sdram.core.lasmicon.perf import Bandwidth
+
+
+class CommandRequest:
+    def __init__(self, a, ba):
+        self.a = Signal(a)
+        self.ba = Signal(ba)
+        self.cas_n = Signal(reset=1)
+        self.ras_n = Signal(reset=1)
+        self.we_n = Signal(reset=1)
+
+
+class CommandRequestRW(CommandRequest):
+    def __init__(self, a, ba):
+        CommandRequest.__init__(self, a, ba)
+        self.stb = Signal()
+        self.ack = Signal()
+        self.is_cmd = Signal()
+        self.is_read = Signal()
+        self.is_write = Signal()
+
+
+class _CommandChooser(Module):
+    def __init__(self, requests):
+        self.want_reads = Signal()
+        self.want_writes = Signal()
+        self.want_cmds = Signal()
+        # NB: cas_n/ras_n/we_n are 1 when stb is inactive
+        self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
+
+        ###
+
+        rr = RoundRobin(len(requests), SP_CE)
+        self.submodules += rr
+
+        self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
+            for i, req in enumerate(requests)]
+
+        stb = Signal()
+        self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
+        for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
+            choices = Array(getattr(req, name) for req in requests)
+            self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
+        for name in ["cas_n", "ras_n", "we_n"]:
+            # we should only assert those signals when stb is 1
+            choices = Array(getattr(req, name) for req in requests)
+            self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
+        self.comb += self.cmd.stb.eq(stb \
+            & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
+            & (self.cmd.is_write == self.want_writes))))
+
+        self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
+            for i, req in enumerate(requests)]
+        self.comb += rr.ce.eq(self.cmd.ack)
+
+
+class _Steerer(Module):
+    def __init__(self, commands, dfi):
+        ncmd = len(commands)
+        nph = len(dfi.phases)
+        self.sel = [Signal(max=ncmd) for i in range(nph)]
+
+        ###
+
+        def stb_and(cmd, attr):
+            if not hasattr(cmd, "stb"):
+                return 0
+            else:
+                return cmd.stb & getattr(cmd, attr)
+        for phase, sel in zip(dfi.phases, self.sel):
+            self.comb += [
+                phase.cke.eq(1),
+                phase.cs_n.eq(0)
+            ]
+            if hasattr(phase, "odt"):
+                self.comb += phase.odt.eq(1)
+            if hasattr(phase, "reset_n"):
+                self.comb += phase.reset_n.eq(1)
+            self.sync += [
+                phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
+                phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
+                phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
+                phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
+                phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
+                phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
+                phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
+            ]
+
+
+class Multiplexer(Module, AutoCSR):
+    def __init__(self, phy_settings, geom_settings, timing_settings, 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(optree("|", [req.stb & req.is_read for req in requests])),
+            write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
+        ]
+
+        def anti_starvation(timeout):
+            en = Signal()
+            max_time = Signal()
+            if timeout:
+                t = timeout - 1
+                time = Signal(max=t+1)
+                self.comb += max_time.eq(time == 0)
+                self.sync += If(~en,
+                        time.eq(t)
+                    ).Elif(~max_time,
+                        time.eq(time - 1)
+                    )
+            else:
+                self.comb += max_time.eq(0)
+            return en, max_time
+        read_time_en, max_read_time = anti_starvation(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(optree("&", [bm.refresh_gnt for bm in bank_machines]))
+
+        # Datapath
+        all_rddata = [p.rddata for p in dfi.phases]
+        all_wrdata = [p.wrdata for p in dfi.phases]
+        all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
+        self.comb += [
+            lasmic.dat_r.eq(Cat(*all_rddata)),
+            Cat(*all_wrdata).eq(lasmic.dat_w),
+            Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
+        ]
+
+        # Control FSM
+        fsm = FSM()
+        self.submodules += fsm
+
+        def steerer_sel(steerer, phy_settings, r_w_n):
+            r = []
+            for i in range(phy_settings.nphases):
+                s = steerer.sel[i].eq(STEER_NOP)
+                if r_w_n == "read":
+                    if i == phy_settings.rdphase:
+                        s = steerer.sel[i].eq(STEER_REQ)
+                    elif i == phy_settings.rdcmdphase:
+                        s = steerer.sel[i].eq(STEER_CMD)
+                elif r_w_n == "write":
+                    if i == phy_settings.wrphase:
+                        s = steerer.sel[i].eq(STEER_REQ)
+                    elif i == phy_settings.wrcmdphase:
+                        s = steerer.sel[i].eq(STEER_CMD)
+                else:
+                    raise ValueError
+                r.append(s)
+            return r
+
+        fsm.act("READ",
+            read_time_en.eq(1),
+            choose_req.want_reads.eq(1),
+            choose_cmd.cmd.ack.eq(1),
+            choose_req.cmd.ack.eq(1),
+            steerer_sel(steerer, phy_settings, "read"),
+            If(write_available,
+                # TODO: switch only after several cycles of ~read_available?
+                If(~read_available | max_read_time, NextState("RTW"))
+            ),
+            If(go_to_refresh, NextState("REFRESH"))
+        )
+        fsm.act("WRITE",
+            write_time_en.eq(1),
+            choose_req.want_writes.eq(1),
+            choose_cmd.cmd.ack.eq(1),
+            choose_req.cmd.ack.eq(1),
+            steerer_sel(steerer, phy_settings, "write"),
+            If(read_available,
+                If(~write_available | max_write_time, NextState("WTR"))
+            ),
+            If(go_to_refresh, NextState("REFRESH"))
+        )
+        fsm.act("REFRESH",
+            steerer.sel[0].eq(STEER_REFRESH),
+            If(~refresher.req, NextState("READ"))
+        )
+        fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1)  # FIXME: reduce this, actual limit is around (cl+1)/nphases
+        fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
+        # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
+        fsm.finalize()
+        self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])
+
+        self.with_bandwidth = with_bandwidth
+
+    def add_bandwidth(self):
+        self.with_bandwidth = True
+
+    def do_finalize(self):
+        if self.with_bandwidth:
+            data_width = self.phy_settings.dfi_databits*self.phy_settings.nphases
+            self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width)
diff --git a/misoc/mem/sdram/core/lasmicon/perf.py b/misoc/mem/sdram/core/lasmicon/perf.py
new file mode 100644 (file)
index 0000000..2c7e8cf
--- /dev/null
@@ -0,0 +1,46 @@
+from migen.fhdl.std import *
+from migen.bank.description 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/misoc/mem/sdram/core/lasmicon/refresher.py b/misoc/mem/sdram/core/lasmicon/refresher.py
new file mode 100644 (file)
index 0000000..12aeefc
--- /dev/null
@@ -0,0 +1,70 @@
+from migen.fhdl.std import *
+from migen.genlib.misc import timeline
+from migen.genlib.fsm import FSM
+
+from misoc.mem.sdram.core.lasmicon.multiplexer import *
+
+
+class Refresher(Module):
+    def __init__(self, a, ba, tRP, tREFI, tRFC, enabled=True):
+        self.req = Signal()
+        self.ack = Signal()  # 1st command 1 cycle after assertion of ack
+        self.cmd = CommandRequest(a, ba)
+
+        ###
+
+        if enabled:
+            # 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/misoc/mem/sdram/core/lasmixbar.py b/misoc/mem/sdram/core/lasmixbar.py
new file mode 100644 (file)
index 0000000..cbba949
--- /dev/null
@@ -0,0 +1,178 @@
+from migen.fhdl.std import *
+from migen.genlib import roundrobin
+from migen.genlib.record import *
+from migen.genlib.misc import optree
+
+from misoc.mem.sdram.core.lasmibus import Interface
+
+
+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(optree("|", dat_w_maskselect)),
+                controller.dat_we.eq(optree("|", 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/misoc/mem/sdram/core/minicon/__init__.py b/misoc/mem/sdram/core/minicon/__init__.py
new file mode 100644 (file)
index 0000000..dd70f58
--- /dev/null
@@ -0,0 +1,238 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import optree, WaitTimer
+
+from misoc.mem.sdram.phy import dfi as dfibus
+
+
+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])
+
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+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 MiniconSettings:
+    def __init__(self, l2_size=0):
+        self.l2_size = l2_size
+
+
+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_open = Signal()
+        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(optree("|", [bank.hit & bank.ce for bank in banks])),
+            bank_idle.eq(optree("|", [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/misoc/mem/sdram/frontend/__init__.py b/misoc/mem/sdram/frontend/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/mem/sdram/frontend/dma_lasmi.py b/misoc/mem/sdram/frontend/dma_lasmi.py
new file mode 100644 (file)
index 0000000..54c4843
--- /dev/null
@@ -0,0 +1,90 @@
+from migen.fhdl.std import *
+from migen.flow.actor import *
+from migen.genlib.fifo import SyncFIFO
+
+
+class Reader(Module):
+    def __init__(self, lasmim, fifo_depth=None):
+        self.address = Sink([("a", lasmim.aw)])
+        self.data = Source([("d", 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(self.address.stb & request_enable),
+            lasmim.adr.eq(self.address.a),
+            self.address.ack.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),
+
+            self.data.stb.eq(fifo.readable),
+            fifo.re.eq(self.data.ack),
+            self.data.d.eq(fifo.dout),
+            data_dequeued.eq(self.data.stb & self.data.ack)
+        ]
+
+
+class Writer(Module):
+    def __init__(self, lasmim, fifo_depth=None):
+        self.address_data = Sink([("a", lasmim.aw), ("d", 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 & self.address_data.stb),
+            lasmim.adr.eq(self.address_data.a),
+            self.address_data.ack.eq(fifo.writable & lasmim.req_ack),
+            fifo.we.eq(self.address_data.stb & lasmim.req_ack),
+            fifo.din.eq(self.address_data.d)
+        ]
+
+        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/misoc/mem/sdram/frontend/memtest.py b/misoc/mem/sdram/frontend/memtest.py
new file mode 100644 (file)
index 0000000..9b3c62a
--- /dev/null
@@ -0,0 +1,119 @@
+from migen.fhdl.std import *
+from migen.genlib.misc import optree
+from migen.bank.description import *
+from migen.actorlib.spi import *
+
+from misoc.mem.sdram.frontend import dma_lasmi
+
+
+@DecorateModule(InsertReset)
+@DecorateModule(InsertCE)
+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 = ~optree("^", [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 MemtestWriter(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 MemtestReader(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 migen.fhdl import verilog
+    from migen.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/misoc/mem/sdram/frontend/wishbone2lasmi.py b/misoc/mem/sdram/frontend/wishbone2lasmi.py
new file mode 100644 (file)
index 0000000..9524734
--- /dev/null
@@ -0,0 +1,48 @@
+from migen.fhdl.std import *
+from migen.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/misoc/mem/sdram/module.py b/misoc/mem/sdram/module.py
new file mode 100644 (file)
index 0000000..f15867d
--- /dev/null
@@ -0,0 +1,225 @@
+# SDRAM memory modules library
+#
+# This library avoid duplications of memory modules definitions in targets and
+# ease SDRAM usage. (User can only select an already existing module or create
+# one for its board and contribute to this library)
+#
+# 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)
+
+from math import ceil
+
+from migen.fhdl.std import *
+from misoc.mem import sdram
+
+
+class SDRAMModule:
+    def __init__(self, clk_freq, memtype, geom_settings, timing_settings):
+        self.clk_freq = clk_freq
+        self.memtype = memtype
+        self.geom_settings = sdram.GeomSettings(
+            bankbits=log2_int(geom_settings["nbanks"]),
+            rowbits=log2_int(geom_settings["nrows"]),
+            colbits=log2_int(geom_settings["ncols"]),
+        )
+        self.timing_settings = sdram.TimingSettings(
+            tRP=self.ns(timing_settings["tRP"]),
+            tRCD=self.ns(timing_settings["tRCD"]),
+            tWR=self.ns(timing_settings["tWR"]),
+            tWTR=timing_settings["tWTR"],
+            tREFI=self.ns(timing_settings["tREFI"], False),
+            tRFC=self.ns(timing_settings["tRFC"])
+        )
+
+    def ns(self, t, margin=True):
+        clk_period_ns = 1000000000/self.clk_freq
+        if margin:
+            t += clk_period_ns/2
+        return ceil(t/clk_period_ns)
+
+
+# SDR
+class IS42S16160(SDRAMModule):
+    geom_settings = {
+        "nbanks": 4,
+        "nrows":  8192,
+        "ncols":  512
+    }
+    # Note: timings for -7 speedgrade (add support for others speedgrades)
+    timing_settings = {
+        "tRP":   20,
+        "tRCD":  20,
+        "tWR":   20,
+        "tWTR":  2,
+        "tREFI": 64*1000*1000/8192,
+        "tRFC":  70
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq,  "SDR", self.geom_settings,
+            self.timing_settings)
+
+
+class MT48LC4M16(SDRAMModule):
+    geom_settings = {
+        "nbanks": 4,
+        "nrows":  4096,
+        "ncols":  256
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   14,
+        "tWTR":  2,
+        "tREFI": 64*1000*1000/4096,
+        "tRFC":  66
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
+            self.timing_settings)
+
+
+class AS4C16M16(SDRAMModule):
+    geom_settings = {
+        "nbanks": 4,
+        "nrows":  8192,
+        "ncols":  512
+    }
+    # Note: timings for -6 speedgrade (add support for others speedgrades)
+    timing_settings = {
+        "tRP":   18,
+        "tRCD":  18,
+        "tWR":   12,
+        "tWTR":  2,
+        "tREFI": 64*1000*1000/8192,
+        "tRFC":  60
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
+            self.timing_settings)
+
+
+# DDR
+class MT46V32M16(SDRAMModule):
+    geom_settings = {
+        "nbanks": 4,
+        "nrows":  8192,
+        "ncols":  1024
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   15,
+        "tWTR":  2,
+        "tREFI": 64*1000*1000/8192,
+        "tRFC":  70
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "DDR", self.geom_settings,
+            self.timing_settings)
+
+
+# LPDDR
+class MT46H32M16(SDRAMModule):
+    geom_settings = {
+        "nbanks": 4,
+        "nrows":  8192,
+        "ncols":  1024
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   15,
+        "tWTR":  2,
+        "tREFI": 64*1000*1000/8192,
+        "tRFC":  72
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "LPDDR", self.geom_settings,
+            self.timing_settings)
+
+
+# DDR2
+class MT47H128M8(SDRAMModule):
+    geom_settings = {
+        "nbanks": 8,
+        "nrows":  16384,
+        "ncols":  1024
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   15,
+        "tWTR":  2,
+        "tREFI": 7800,
+        "tRFC":  127.5
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
+            self.timing_settings)
+
+
+class P3R1GE4JGF(SDRAMModule):
+    geom_settings = {
+        "nbanks": 8,
+        "nrows": 8192,
+        "ncols": 1024
+    }
+    timing_settings = {
+        "tRP":   12.5,
+        "tRCD":  12.5,
+        "tWR":   15,
+        "tWTR":  3,
+        "tREFI": 7800,
+        "tRFC":  127.5,
+    }
+
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
+            self.timing_settings)
+
+
+# DDR3
+class MT8JTF12864(SDRAMModule):
+    geom_settings = {
+        "nbanks": 8,
+        "nrows":  16384,
+        "ncols":  1024
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   15,
+        "tWTR":  2,
+        "tREFI": 7800,
+        "tRFC":  70
+    }
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
+            self.timing_settings)
+
+
+class MT41J128M16(SDRAMModule):
+    geom_settings = {
+        "nbanks": 8,
+        "nrows":  16384,
+        "ncols":  1024,
+    }
+    timing_settings = {
+        "tRP":   15,
+        "tRCD":  15,
+        "tWR":   15,
+        "tWTR":  3,
+        "tREFI": 64*1000*1000/16384,
+        "tRFC":  260,
+    }
+
+    def __init__(self, clk_freq):
+        SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
+            self.timing_settings)
diff --git a/misoc/mem/sdram/phy/__init__.py b/misoc/mem/sdram/phy/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/mem/sdram/phy/dfi.py b/misoc/mem/sdram/phy/dfi.py
new file mode 100644 (file)
index 0000000..76379e2
--- /dev/null
@@ -0,0 +1,73 @@
+from migen.fhdl.std import *
+from migen.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/misoc/mem/sdram/phy/dfii.py b/misoc/mem/sdram/phy/dfii.py
new file mode 100644 (file)
index 0000000..ffbdc7d
--- /dev/null
@@ -0,0 +1,60 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+from misoc.mem.sdram.phy import dfi
+
+
+class PhaseInjector(Module, AutoCSR):
+    def __init__(self, phase):
+        self._command = CSRStorage(6)  # cs, we, cas, ras, wren, rden
+        self._command_issue = CSR()
+        self._address = CSRStorage(flen(phase.address))
+        self._baddress = CSRStorage(flen(phase.bank))
+        self._wrdata = CSRStorage(flen(phase.wrdata))
+        self._rddata = CSRStatus(flen(phase.rddata))
+
+        ###
+
+        self.comb += [
+            If(self._command_issue.re,
+                phase.cs_n.eq(~self._command.storage[0]),
+                phase.we_n.eq(~self._command.storage[1]),
+                phase.cas_n.eq(~self._command.storage[2]),
+                phase.ras_n.eq(~self._command.storage[3])
+            ).Else(
+                phase.cs_n.eq(1),
+                phase.we_n.eq(1),
+                phase.cas_n.eq(1),
+                phase.ras_n.eq(1)
+            ),
+            phase.address.eq(self._address.storage),
+            phase.bank.eq(self._baddress.storage),
+            phase.wrdata_en.eq(self._command_issue.re & self._command.storage[4]),
+            phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]),
+            phase.wrdata.eq(self._wrdata.storage),
+            phase.wrdata_mask.eq(0)
+        ]
+        self.sync += If(phase.rddata_valid, self._rddata.status.eq(phase.rddata))
+
+
+class DFIInjector(Module, AutoCSR):
+    def __init__(self, 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/misoc/mem/sdram/phy/gensdrphy.py b/misoc/mem/sdram/phy/gensdrphy.py
new file mode 100644 (file)
index 0000000..80c589d
--- /dev/null
@@ -0,0 +1,96 @@
+#
+# 1:1 frequency-ratio Generic SDR PHY
+#
+# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
+# not use vendor-dependent code, it can also be used on other architectures.
+#
+# The PHY needs 2 Clock domains:
+#  - sys_clk    : The System Clock domain
+#  - sys_clk_ps : The System Clock domain with its phase shifted
+#                 (-3ns on C4@100MHz)
+#
+# Assert dfi_wrdata_en and present the data
+# on dfi_wrdata_mask/dfi_wrdata in the same
+# cycle as the write command.
+#
+# Assert dfi_rddata_en in the same cycle as the read
+# command. The data will come back on dfi_rddata
+# 4 cycles later, along with the assertion of
+# dfi_rddata_valid.
+#
+# This PHY only supports CAS Latency 2.
+#
+
+from migen.fhdl.std import *
+from migen.genlib.record import *
+from migen.fhdl.specials import *
+
+from misoc.mem.sdram.phy.dfi import *
+from misoc.mem import sdram
+
+
+class GENSDRPHY(Module):
+    def __init__(self, pads, module):
+        addressbits = flen(pads.a)
+        bankbits = flen(pads.ba)
+        databits = flen(pads.dq)
+
+        self.settings = sdram.PhySettings(
+            memtype=module.memtype,
+            dfi_databits=databits,
+            nphases=1,
+            rdphase=0,
+            wrphase=0,
+            rdcmdphase=0,
+            wrcmdphase=0,
+            cl=2,
+            read_latency=4,
+            write_latency=0
+        )
+        self.module = module
+
+        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/misoc/mem/sdram/phy/initsequence.py b/misoc/mem/sdram/phy/initsequence.py
new file mode 100644 (file)
index 0000000..3bdf5f3
--- /dev/null
@@ -0,0 +1,229 @@
+from migen.fhdl.std import log2_int
+
+
+def get_sdram_phy_header(sdram_phy_settings):
+    r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
+    r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
+
+    nphases = sdram_phy_settings.nphases
+    r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
+
+    r += "static void cdelay(int i);\n"
+
+    # commands_px functions
+    for n in range(nphases):
+        r += """
+static void command_p{n}(int cmd)
+{{
+    sdram_dfii_pi{n}_command_write(cmd);
+    sdram_dfii_pi{n}_command_issue_write(1);
+}}""".format(n=str(n))
+    r += "\n\n"
+
+    # rd/wr access macros
+    r += """
+#define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X)
+#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X)
+
+#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X)
+#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X)
+
+#define command_prd(X) command_p{rdphase}(X)
+#define command_pwr(X) command_p{wrphase}(X)
+""".format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase))
+    r += "\n"
+
+    #
+    # sdrrd/sdrwr functions utilities
+    #
+    r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
+    sdram_dfii_pix_wrdata_addr = []
+    for n in range(nphases):
+        sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
+    r += """
+const unsigned int sdram_dfii_pix_wrdata_addr[{n}] = {{
+    {sdram_dfii_pix_wrdata_addr}
+}};
+""".format(n=nphases, sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr))
+
+    sdram_dfii_pix_rddata_addr = []
+    for n in range(nphases):
+        sdram_dfii_pix_rddata_addr.append("CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n))
+    r += """
+const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
+    {sdram_dfii_pix_rddata_addr}
+}};
+""".format(n=nphases, sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr))
+    r += "\n"
+
+    # init sequence
+    cmds = {
+        "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+        "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
+        "AUTO_REFRESH":  "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
+        "UNRESET":       "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
+        "CKE":           "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
+    }
+
+    cl = sdram_phy_settings.cl
+
+    if sdram_phy_settings.memtype == "SDR":
+        bl = sdram_phy_settings.nphases
+        mr = log2_int(bl) + (cl << 4)
+        reset_dll = 1 << 8
+
+        init_sequence = [
+            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+        ]
+
+    elif sdram_phy_settings.memtype == "DDR":
+        bl = 2*sdram_phy_settings.nphases
+        mr  = log2_int(bl) + (cl << 4)
+        emr = 0
+        reset_dll = 1 << 8
+
+        init_sequence = [
+            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+        ]
+
+    elif sdram_phy_settings.memtype == "LPDDR":
+        bl = 2*sdram_phy_settings.nphases
+        mr  = log2_int(bl) + (cl << 4)
+        emr = 0
+        reset_dll = 1 << 8
+
+        init_sequence = [
+            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
+        ]
+
+    elif sdram_phy_settings.memtype == "DDR2":
+        bl = 2*sdram_phy_settings.nphases
+        wr = 2
+        mr = log2_int(bl) + (cl << 4) + (wr << 9)
+        emr = 0
+        emr2 = 0
+        emr3 = 0
+        reset_dll = 1 << 8
+        ocd = 7 << 7
+
+        init_sequence = [
+            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
+            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
+            ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
+            ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
+            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
+            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
+            ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
+            ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
+        ]
+    elif sdram_phy_settings.memtype == "DDR3":
+        bl = 2*sdram_phy_settings.nphases
+
+        def format_mr0(bl, cl, wr, dll_reset):
+            bl_to_mr0 = {
+                4: 0b10,
+                8: 0b00
+            }
+            cl_to_mr0 = {
+                 5: 0b0010,
+                 6: 0b0100,
+                 7: 0b0110,
+                 8: 0b1000,
+                 9: 0b1010,
+                10: 0b1100,
+                11: 0b1110,
+                12: 0b0001,
+                13: 0b0011,
+                14: 0b0101
+            }
+            wr_to_mr0 = {
+                16: 0b000,
+                 5: 0b001,
+                 6: 0b010,
+                 7: 0b011,
+                 8: 0b100,
+                10: 0b101,
+                12: 0b110,
+                14: 0b111
+            }
+            mr0 = bl_to_mr0[bl]
+            mr0 |= (cl_to_mr0[cl] & 1) << 2
+            mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
+            mr0 |= dll_reset << 8
+            mr0 |= wr_to_mr0[wr] << 9
+            return mr0
+
+        def format_mr1(output_drive_strength, rtt_nom):
+            mr1 = ((output_drive_strength >> 0) & 1) << 1
+            mr1 |= ((output_drive_strength >> 1) & 1) << 5
+            mr1 |= ((rtt_nom >> 0) & 1) << 2
+            mr1 |= ((rtt_nom >> 1) & 1) << 6
+            mr1 |= ((rtt_nom >> 2) & 1) << 9
+            return mr1
+
+        def format_mr2(cwl, rtt_wr):
+            mr2 = (cwl-5) << 3
+            mr2 |= rtt_wr << 9
+            return mr2
+
+        mr0 = format_mr0(bl, cl, 8, 1)  # wr=8 FIXME: this should be ceiling(tWR/tCK)
+        mr1 = format_mr1(1, 1)  # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm)
+        mr2 = format_mr2(sdram_phy_settings.cwl, 2)  # Rtt(WR) RZQ/4
+        mr3 = 0
+
+        init_sequence = [
+            ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
+            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
+            ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
+            ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
+            ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
+        ]
+
+        # the value of MR1 needs to be modified during write leveling
+        r += "#define DDR3_MR1 {}\n\n".format(mr1)
+    else:
+        raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype)
+
+    r += "static void init_sequence(void)\n{\n"
+    for comment, a, ba, cmd, delay in init_sequence:
+        r += "\t/* {0} */\n".format(comment)
+        r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a)
+        r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba)
+        if cmd[:12] == "DFII_CONTROL":
+            r += "\tsdram_dfii_control_write({0});\n".format(cmd)
+        else:
+            r += "\tcommand_p0({0});\n".format(cmd)
+        if delay:
+            r += "\tcdelay({0:d});\n".format(delay)
+        r += "\n"
+    r += "}\n"
+
+    r += "#endif\n"
+
+    return r
diff --git a/misoc/mem/sdram/phy/k7ddrphy.py b/misoc/mem/sdram/phy/k7ddrphy.py
new file mode 100644 (file)
index 0000000..5a2e0fc
--- /dev/null
@@ -0,0 +1,293 @@
+# tCK=5ns CL=7 CWL=6
+
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+from misoc.mem.sdram.phy.dfi import *
+from misoc.mem import sdram
+
+
+class K7DDRPHY(Module, AutoCSR):
+    def __init__(self, pads, module):
+        addressbits = flen(pads.a)
+        bankbits = flen(pads.ba)
+        databits = flen(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.PhySettings(
+            memtype=module.memtype,
+            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.module = module
+
+        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/misoc/mem/sdram/phy/s6ddrphy.py b/misoc/mem/sdram/phy/s6ddrphy.py
new file mode 100644 (file)
index 0000000..7153f05
--- /dev/null
@@ -0,0 +1,490 @@
+# 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 migen.fhdl.std import *
+from migen.genlib.record import *
+
+from misoc.mem.sdram.phy.dfi import *
+from misoc.mem import sdram
+
+
+class S6HalfRateDDRPHY(Module):
+    def __init__(self, pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
+        if module.memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
+            raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
+        addressbits = flen(pads.a)
+        bankbits = flen(pads.ba)
+        databits = flen(pads.dq)
+        nphases = 2
+
+        if module.memtype == "DDR3":
+            self.settings = sdram.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.PhySettings(
+                memtype=module.memtype,
+                dfi_databits=2*databits,
+                nphases=nphases,
+                rdphase=0,
+                wrphase=1,
+                rdcmdphase=1,
+                wrcmdphase=0,
+                cl=3,
+                read_latency=5,
+                write_latency=0
+            )
+
+        self.module = module
+
+        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(optree("|", [d_dfi[p].wrdata_en for p in range(nphases)]))
+
+        if module.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 module.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(optree("|", [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, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
+        if module.memtype not in ["DDR3"]:
+            raise NotImplementedError("S6QuarterRateDDRPHY only supports DDR3")
+        half_rate_phy = S6HalfRateDDRPHY(pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment)
+        self.submodules += RenameClockDomains(half_rate_phy, {"sys" : "sys2x"})
+
+        addressbits = flen(pads.a)
+        bankbits = flen(pads.ba)
+        databits = flen(pads.dq)
+        nphases = 4
+
+        self.settings = sdram.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.module = module
+
+        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_leave_out = set(["rddata", "rddata_valid", "wrdata_en"])
+        self.comb += [
+            If(~phase_sel,
+                Record.connect(self.dfi.phases[0], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
+                Record.connect(self.dfi.phases[1], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
+            ).Else(
+                Record.connect(self.dfi.phases[2], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
+                Record.connect(self.dfi.phases[3], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
+            ),
+        ]
+        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/misoc/mem/sdram/phy/simphy.py b/misoc/mem/sdram/phy/simphy.py
new file mode 100644 (file)
index 0000000..0588d08
--- /dev/null
@@ -0,0 +1,192 @@
+# 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 Migen and manage timing violations?
+
+from migen.fhdl.std import *
+from migen.fhdl.specials import *
+from misoc.mem.sdram.phy.dfi import *
+from misoc.mem import sdram
+
+
+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 SDRAMPHYSim(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))
+            read_data = Signal(data_width)
+            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(optree("|", [bank.read for bank in banks])),
+            banks_read_data.eq(optree("|", [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/misoc/mem/sdram/test/abstract_transactions_lasmi.py b/misoc/mem/sdram/test/abstract_transactions_lasmi.py
new file mode 100644 (file)
index 0000000..fd027f7
--- /dev/null
@@ -0,0 +1,42 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.core import lasmibus
+
+
+def my_generator(n):
+    bank = n % 4
+    for x in range(4):
+        t = TWrite(4*bank+x, 0x1000*bank + 0x100*x)
+        yield t
+        print("{0}: Wrote in {1} cycle(s)".format(n, t.latency))
+
+    for x in range(4):
+        t = TRead(4*bank+x)
+        yield t
+        print("{0}: Read {1:x} in {2} cycle(s)".format(n, t.data, t.latency))
+        assert(t.data == 0x1000*bank + 0x100*x)
+
+
+class MyModel(lasmibus.TargetModel):
+    def read(self, bank, address):
+        r = 0x1000*bank + 0x100*address
+        #print("read from bank {0} address {1} -> {2:x}".format(bank, address, r))
+        return r
+
+    def write(self, bank, address, data, we):
+        print("write to bank {0} address {1:x} data {2:x}".format(bank, address, data))
+        assert(data == 0x1000*bank + 0x100*address)
+
+
+class TB(Module):
+    def __init__(self):
+        self.submodules.controller = lasmibus.Target(MyModel(), aw=4, dw=32, nbanks=4, req_queue_size=4,
+            read_latency=4, write_latency=1)
+        self.submodules.xbar = lasmibus.Crossbar([self.controller.bus], 2)
+        self.initiators = [lasmibus.Initiator(my_generator(n), self.xbar.get_master()) for n in range(4)]
+        self.submodules += self.initiators
+
+if __name__ == "__main__":
+    run_simulation(TB())
diff --git a/misoc/mem/sdram/test/bankmachine_tb.py b/misoc/mem/sdram/test/bankmachine_tb.py
new file mode 100644 (file)
index 0000000..54578dc
--- /dev/null
@@ -0,0 +1,43 @@
+from migen.fhdl.std import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.code import lasmibus
+from misoc.mem.sdram.core.lasmicon.bankmachine import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger
+
+
+def my_generator():
+    for x in range(10):
+        yield True, x
+    for x in range(10):
+        yield False, 128*x
+
+
+class TB(Module):
+    def __init__(self):
+        self.req = Interface(32, 32, 1,
+            sdram_timing.req_queue_size, sdram_phy.read_latency, sdram_phy.write_latency)
+        self.submodules.dut = BankMachine(sdram_geom, sdram_timing, 2, 0, self.req)
+        self.submodules.logger = CommandLogger(self.dut.cmd, True)
+        self.generator = my_generator()
+        self.dat_ack_cnt = 0
+
+    def do_simulation(self, selfp):
+        if selfp.req.dat_ack:
+            self.dat_ack_cnt += 1
+        if selfp.req.req_ack:
+            try:
+                we, adr = next(self.generator)
+            except StopIteration:
+                selfp.req.stb = 0
+                if not selfp.req.lock:
+                    print("data ack count: {0}".format(self.dat_ack_cnt))
+                    raise StopSimulation
+                return
+            selfp.req.adr = adr
+            selfp.req.we = we
+            selfp.req.stb = 1
+
+if __name__ == "__main__":
+    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoc/mem/sdram/test/common.py b/misoc/mem/sdram/test/common.py
new file mode 100644 (file)
index 0000000..6c1c09d
--- /dev/null
@@ -0,0 +1,106 @@
+from fractions import Fraction
+from math import ceil
+
+from migen.fhdl.std import *
+
+from misoc import sdram
+
+MHz = 1000000
+clk_freq = (83 + Fraction(1, 3))*MHz
+
+clk_period_ns = 1000000000/clk_freq
+
+
+def ns(t, margin=True):
+    if margin:
+        t += clk_period_ns/2
+    return ceil(t/clk_period_ns)
+
+sdram_phy = sdram.PhySettings(
+    memtype="DDR",
+    dfi_databits=64,
+    nphases=2,
+    rdphase=0,
+    wrphase=1,
+    rdcmdphase=1,
+    wrcmdphase=0,
+    cl=3,
+    read_latency=5,
+    write_latency=0
+)
+
+sdram_geom = sdram.GeomSettings(
+    bankbits=2,
+    rowbits=13,
+    colbits=10
+)
+sdram_timing = sdram.TimingSettings(
+    tRP=ns(15),
+    tRCD=ns(15),
+    tWR=ns(15),
+    tWTR=2,
+    tREFI=ns(7800, False),
+    tRFC=ns(70),
+
+    req_queue_size=8,
+    read_time=32,
+    write_time=16
+)
+
+
+def decode_sdram(ras_n, cas_n, we_n, bank, address):
+    elts = []
+    if not ras_n and cas_n and we_n:
+        elts.append("ACTIVATE")
+        elts.append("BANK " + str(bank))
+        elts.append("ROW " + str(address))
+    elif ras_n and not cas_n and we_n:
+        elts.append("READ\t")
+        elts.append("BANK " + str(bank))
+        elts.append("COL " + str(address))
+    elif ras_n and not cas_n and not we_n:
+        elts.append("WRITE\t")
+        elts.append("BANK " + str(bank))
+        elts.append("COL " + str(address))
+    elif ras_n and cas_n and not we_n:
+        elts.append("BST")
+    elif not ras_n and not cas_n and we_n:
+        elts.append("AUTO REFRESH")
+    elif not ras_n and cas_n and not we_n:
+        elts.append("PRECHARGE")
+        if address & 2**10:
+            elts.append("ALL")
+        else:
+            elts.append("BANK " + str(bank))
+    elif not ras_n and not cas_n and not we_n:
+        elts.append("LMR")
+    return elts
+
+
+class CommandLogger(Module):
+    def __init__(self, cmd, rw=False):
+        self.cmd = cmd
+        if rw:
+            self.comb += self.cmd.ack.eq(1)
+
+    def do_simulation(self, selfp):
+        elts = ["@" + str(selfp.simulator.cycle_counter)]
+        cmdp = selfp.cmd
+        elts += decode_sdram(cmdp.ras_n, cmdp.cas_n, cmdp.we_n, cmdp.ba, cmdp.a)
+        if len(elts) > 1:
+            print("\t".join(elts))
+    do_simulation.passive = True
+
+
+class DFILogger(Module):
+    def __init__(self, dfi):
+        self.dfi = dfi
+
+    def do_simulation(self, selfp):
+        dfip = selfp.dfi
+        for i, p in enumerate(dfip.phases):
+            elts = ["@" + str(selfp.simulator.cycle_counter) + ":" + str(i)]
+            elts += decode_sdram(p.ras_n, p.cas_n, p.we_n, p.bank, p.address)
+            if len(elts) > 1:
+                print("\t".join(elts))
+    do_simulation.passive = True
diff --git a/misoc/mem/sdram/test/lasmicon_df_tb.py b/misoc/mem/sdram/test/lasmicon_df_tb.py
new file mode 100644 (file)
index 0000000..bee4a7d
--- /dev/null
@@ -0,0 +1,40 @@
+from migen.fhdl.std import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.core import lasmibus
+from misoc.mem.sdram.core.lasmicon import *
+from misoc.mem.sdram.frontend import dma_lasmi
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+
+class TB(Module):
+    def __init__(self):
+        self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+        self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
+        self.submodules.logger = DFILogger(self.ctler.dfi)
+        self.submodules.writer = dma_lasmi.Writer(self.xbar.get_master())
+
+        self.comb += self.writer.address_data.stb.eq(1)
+        pl = self.writer.address_data.payload
+        pl.a.reset = 255
+        pl.d.reset = pl.a.reset*2
+        self.sync += If(self.writer.address_data.ack,
+            pl.a.eq(pl.a + 1),
+            pl.d.eq(pl.d + 2)
+        )
+        self.open_row = None
+
+    def do_simulation(self, selfp):
+        dfip = selfp.ctler.dfi
+        for p in dfip.phases:
+            if p.ras_n and not p.cas_n and not p.we_n:  # write
+                d = dfip.phases[0].wrdata | (dfip.phases[1].wrdata << 64)
+                print(d)
+                if d != p.address//2 + p.bank*512 + self.open_row*2048:
+                    print("**** ERROR ****")
+            elif not p.ras_n and p.cas_n and p.we_n:  # activate
+                self.open_row = p.address
+
+if __name__ == "__main__":
+    run_simulation(TB(), ncycles=3500, vcd_name="my.vcd")
diff --git a/misoc/mem/sdram/test/lasmicon_tb.py b/misoc/mem/sdram/test/lasmicon_tb.py
new file mode 100644 (file)
index 0000000..957e3e7
--- /dev/null
@@ -0,0 +1,43 @@
+from migen.fhdl.std import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.core import lasmibus
+from misoc.mem.sdram.core.lasmicon import *
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+
+def my_generator_r(n):
+    for x in range(10):
+        t = TRead(128*n + 48*n*x)
+        yield t
+    print("{0:3}: reads done".format(n))
+
+
+def my_generator_w(n):
+    for x in range(10):
+        t = TWrite(128*n + 48*n*x, x)
+        yield t
+    print("{0:3}: writes done".format(n))
+
+
+def my_generator(n):
+    if n % 2:
+        return my_generator_w(n // 2)
+    else:
+        return my_generator_r(n // 2)
+
+
+class TB(Module):
+    def __init__(self):
+        self.submodules.dut = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+        self.submodules.xbar = lasmibus.Crossbar([self.dut.lasmic], self.dut.nrowbits)
+        self.submodules.logger = DFILogger(self.dut.dfi)
+
+        masters = [self.xbar.get_master() for i in range(6)]
+        self.initiators = [Initiator(my_generator(n), master)
+            for n, master in enumerate(masters)]
+        self.submodules += self.initiators
+
+if __name__ == "__main__":
+    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoc/mem/sdram/test/lasmicon_wb.py b/misoc/mem/sdram/test/lasmicon_wb.py
new file mode 100644 (file)
index 0000000..425bdf7
--- /dev/null
@@ -0,0 +1,40 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.bus.transactions import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.core import lasmibus
+from misoc.mem.sdram.core.lasmicon import *
+from misoc.mem.sdram.frontend import wishbone2lasmi
+
+from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
+
+l2_size = 8192  # in bytes
+
+
+def my_generator():
+    for x in range(20):
+        t = TWrite(x, x)
+        yield t
+        print(str(t) + " delay=" + str(t.latency))
+    for x in range(20):
+        t = TRead(x)
+        yield t
+        print(str(t) + " delay=" + str(t.latency))
+    for x in range(20):
+        t = TRead(x+l2_size//4)
+        yield t
+        print(str(t) + " delay=" + str(t.latency))
+
+
+class TB(Module):
+    def __init__(self):
+        self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
+        self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
+        self.submodules.logger = DFILogger(self.ctler.dfi)
+        self.submodules.bridge = wishbone2lasmi.WB2LASMI(l2_size//4, self.xbar.get_master())
+        self.submodules.initiator = wishbone.Initiator(my_generator())
+        self.submodules.conn = wishbone.InterconnectPointToPoint(self.initiator.bus, self.bridge.wishbone)
+
+if __name__ == "__main__":
+    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoc/mem/sdram/test/minicon_tb.py b/misoc/mem/sdram/test/minicon_tb.py
new file mode 100644 (file)
index 0000000..8aa4f89
--- /dev/null
@@ -0,0 +1,195 @@
+from migen.fhdl.std import *
+from migen.bus.transactions import TRead, TWrite
+from migen.bus import wishbone
+from migen.sim.generic import Simulator
+from migen.sim import icarus
+from mibuild.platforms import papilio_pro as board
+from misoc import sdram
+from misoc.mem.sdram.core.minicon import Minicon
+from misoc.mem.sdram.phy import gensdrphy
+from itertools import chain
+from os.path import isfile
+import sys
+
+clk_freq = 80000000
+
+from math import ceil
+
+
+def ns(t, margin=True):
+    clk_period_ns = 1000000000/clk_freq
+    if margin:
+        t += clk_period_ns/2
+    return ceil(t/clk_period_ns)
+
+
+class MiniconTB(Module):
+    def __init__(self, sdrphy, dfi, sdram_geom, sdram_timing, pads, sdram_clk):
+
+        self.clk_freq = 80000000
+        phy_settings = sdrphy.settings
+        rdphase = phy_settings.rdphase
+        self.submodules.slave = Minicon(phy_settings, sdram_geom, sdram_timing)
+
+        self.submodules.tap = wishbone.Tap(self.slave.bus)
+        self.submodules.dc = dc = wishbone.DownConverter(32, phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
+        self.submodules.master = wishbone.Initiator(self.genxfers(), bus=dc.wishbone_i)
+        self.submodules.intercon = wishbone.InterconnectPointToPoint(dc.wishbone_o, self.slave.bus)
+
+        self.submodules.sdrphy = self.sdrphy = sdrphy
+        self.dfi = dfi
+        self.pads = pads
+
+        self.specials += Instance("mt48lc4m16a2",
+                                  io_Dq=pads.dq,
+                                  i_Addr=pads.a,
+                                  i_Ba=pads.ba,
+                                  i_Clk=ClockSignal(),
+                                  i_Cke=pads.cke,
+                                  i_Cs_n=pads.cs_n,
+                                  i_Ras_n=pads.ras_n,
+                                  i_Cas_n=pads.cas_n,
+                                  i_We_n=pads.we_n,
+                                  i_Dqm=pads.dm
+        )
+
+    def genxfers(self):
+        cycle = 0
+        for a in chain(range(4), range(256, 260), range(1024, 1028)):
+            t = TRead(a)
+            yield t
+            print("read {} in {} cycles".format(t.data, t.latency))
+        for a in chain(range(4), range(256, 260), range(1024, 1028), range(4096, 4100)):
+            t = TWrite(a, 0xaa55aa55+cycle)
+            cycle += 1
+            yield t
+            print("read {} in {} cycles".format(t.data, t.latency))
+        for a in chain(range(4), range(256, 260), range(1024, 1028), range(4096, 4100)):
+            t = TRead(a)
+            yield t
+            print("read {} in {} cycles".format(t.data, t.latency))
+
+    def gen_simulation(self, selfp):
+        dfi = selfp.dfi
+        phy = self.sdrphy
+        rdphase = phy.settings.rdphase
+        cycle = 0
+
+        while True:
+            yield
+
+
+class MyTopLevel:
+    def __init__(self, vcd_name=None, vcd_level=1,
+      top_name="top", dut_type="dut", dut_name="dut",
+      cd_name="sys", clk_period=10):
+        self.vcd_name = vcd_name
+        self.vcd_level = vcd_level
+        self.top_name = top_name
+        self.dut_type = dut_type
+        self.dut_name = dut_name
+
+        self._cd_name = cd_name
+        self._clk_period = clk_period
+
+        cd = ClockDomain(self._cd_name)
+        cd_ps = ClockDomain("sys_ps")
+        self.clock_domains = [cd, cd_ps]
+        self.ios = {cd.clk, cd.rst, cd_ps.clk}
+
+    def get(self, sockaddr):
+        template1 = """`timescale 1ns / 1ps
+
+module {top_name}();
+
+reg {clk_name};
+reg {rst_name};
+reg sys_ps_clk;
+
+initial begin
+    {rst_name} <= 1'b1;
+    @(posedge {clk_name});
+    {rst_name} <= 1'b0;
+end
+
+always begin
+    {clk_name} <= 1'b0;
+    #{hclk_period};
+    {clk_name} <= 1'b1;
+    #{hclk_period};
+end
+
+always @(posedge {clk_name} or negedge {clk_name})
+    sys_ps_clk <= #({hclk_period}*2-3) {clk_name};
+
+{dut_type} {dut_name}(
+    .{rst_name}({rst_name}),
+    .{clk_name}({clk_name}),
+    .sys_ps_clk(sys_ps_clk)
+);
+
+initial $migensim_connect("{sockaddr}");
+always @(posedge {clk_name}) $migensim_tick;
+"""
+        template2 = """
+initial begin
+    $dumpfile("{vcd_name}");
+    $dumpvars({vcd_level}, {dut_name});
+end
+"""
+        r = template1.format(top_name=self.top_name,
+            dut_type=self.dut_type,
+            dut_name=self.dut_name,
+            clk_name=self._cd_name + "_clk",
+            rst_name=self._cd_name + "_rst",
+            hclk_period=str(self._clk_period/2),
+            sockaddr=sockaddr)
+        if self.vcd_name is not None:
+            r += template2.format(vcd_name=self.vcd_name,
+                vcd_level=str(self.vcd_level),
+                dut_name=self.dut_name)
+        r += "\nendmodule"
+        return r
+
+
+if __name__ == "__main__":
+
+    plat = board.Platform()
+
+    sdram_geom = sdram.GeomSettings(
+        bankbits=2,
+        rowbits=12,
+        colbits=8
+    )
+
+    sdram_timing = sdram.TimingSettings(
+        tRP=ns(15),
+        tRCD=ns(15),
+        tWR=ns(14),
+        tWTR=2,
+        tREFI=ns(64*1000*1000/4096, False),
+        tRFC=ns(66),
+        req_queue_size=8,
+        read_time=32,
+        write_time=16
+    )
+
+    sdram_pads = plat.request("sdram")
+    sdram_clk = plat.request("sdram_clock")
+
+    sdrphy = gensdrphy.GENSDRPHY(sdram_pads)
+
+# This sets CL to 2 during LMR done on 1st cycle
+    sdram_pads.a.reset = 1<<5
+
+    s = MiniconTB(sdrphy, sdrphy.dfi, sdram_geom, sdram_timing, pads=sdram_pads, sdram_clk=sdram_clk)
+
+    extra_files = ["sdram_model/mt48lc4m16a2.v"]
+
+    if not isfile(extra_files[0]):
+        print("ERROR: You need to download Micron Verilog simulation model for MT48LC4M16A2 and put it in sdram_model/mt48lc4m16a2.v")
+        print("File can be downloaded from this URL: http://www.micron.com/-/media/documents/products/sim%20model/dram/dram/4054mt48lc4m16a2.zip")
+        sys.exit(1)
+
+    with Simulator(s, MyTopLevel("top.vcd", clk_period=int(1/0.08)), icarus.Runner(extra_files=extra_files, keep_files=True)) as sim:
+        sim.run(5000)
diff --git a/misoc/mem/sdram/test/refresher.py b/misoc/mem/sdram/test/refresher.py
new file mode 100644 (file)
index 0000000..4a13c19
--- /dev/null
@@ -0,0 +1,47 @@
+from random import Random
+
+from migen.fhdl.std import *
+from migen.sim.generic import run_simulation
+
+from misoc.mem.sdram.core.lasmicon.refresher import *
+
+from common import CommandLogger
+
+
+class Granter(Module):
+    def __init__(self, req, ack):
+        self.req = req
+        self.ack = ack
+        self.state = 0
+        self.prng = Random(92837)
+
+    def do_simulation(self, selfp):
+        elts = ["@" + str(selfp.simulator.cycle_counter)]
+
+        if self.state == 0:
+            if selfp.req:
+                elts.append("Refresher requested access")
+                self.state = 1
+        elif self.state == 1:
+            if self.prng.randrange(0, 5) == 0:
+                elts.append("Granted access to refresher")
+                selfp.ack = 1
+                self.state = 2
+        elif self.state == 2:
+            if not selfp.req:
+                elts.append("Refresher released access")
+                selfp.ack = 0
+                self.state = 0
+
+        if len(elts) > 1:
+            print("\t".join(elts))
+
+
+class TB(Module):
+    def __init__(self):
+        self.submodules.dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5)
+        self.submodules.logger = CommandLogger(self.dut.cmd)
+        self.submodules.granter = Granter(self.dut.req, self.dut.ack)
+
+if __name__ == "__main__":
+    run_simulation(TB(), ncycles=400)
diff --git a/misoc/mxcrg.v b/misoc/mxcrg.v
new file mode 100644 (file)
index 0000000..140c848
--- /dev/null
@@ -0,0 +1,247 @@
+module mxcrg #(
+       parameter in_period = 0.0,
+       parameter f_mult = 0,
+       parameter f_div = 0,
+       parameter clk2x_period = (in_period*f_div)/(2.0*f_mult)
+) (
+       input clk50_pad,
+       input trigger_reset,
+
+       output sys_clk,
+       output reg sys_rst,
+
+       /* Reset NOR flash */
+       output norflash_rst_n,
+
+       /* DDR PHY clocks */
+       output clk2x_270,
+       output clk4x_wr,
+       output clk4x_wr_strb,
+       output clk4x_rd,
+       output clk4x_rd_strb,
+
+       /* DDR off-chip clocking */
+       output ddr_clk_pad_p,
+       output ddr_clk_pad_n,
+
+       /* Base clock, buffered */
+       output base50_clk
+);
+
+/*
+ * Reset
+ */
+
+reg [19:0] rst_debounce;
+always @(posedge sys_clk) begin
+       if(trigger_reset)
+               rst_debounce <= 20'hFFFFF;
+       else if(rst_debounce != 20'd0)
+               rst_debounce <= rst_debounce - 20'd1;
+       sys_rst <= rst_debounce != 20'd0;
+end
+
+initial rst_debounce <= 20'hFFFFF;
+
+/*
+ * We must release the Flash reset before the system reset
+ * because the Flash needs some time to come out of reset
+ * and the CPU begins fetching instructions from it
+ * as soon as the system reset is released.
+ * From datasheet, minimum reset pulse width is 100ns
+ * and reset-to-read time is 150ns.
+ */
+
+reg [7:0] flash_rstcounter;
+
+always @(posedge sys_clk) begin
+       if(trigger_reset)
+               flash_rstcounter <= 8'd0;
+       else if(~flash_rstcounter[7])
+               flash_rstcounter <= flash_rstcounter + 8'd1;
+end
+
+initial flash_rstcounter <= 8'd0;
+
+assign norflash_rst_n = flash_rstcounter[7];
+
+/*
+ * Clock management. Inspired by the NWL reference design.
+ */
+
+wire sdr_clk50;
+wire clkdiv;
+
+IBUF #(
+       .IOSTANDARD("DEFAULT")
+) clk2_iob (
+       .I(clk50_pad),
+       .O(sdr_clk50)
+);
+
+BUFIO2 #(
+       .DIVIDE(1),
+       .DIVIDE_BYPASS("FALSE"),
+       .I_INVERT("FALSE")
+) bufio2_inst2 (
+       .I(sdr_clk50),
+       .IOCLK(),
+       .DIVCLK(clkdiv),
+       .SERDESSTROBE()
+);
+
+wire pll_lckd;
+wire buf_pll_fb_out;
+wire pllout0;
+wire pllout1;
+wire pllout2;
+wire pllout3;
+wire pllout4;
+wire pllout5;
+
+PLL_ADV #(
+       .BANDWIDTH("OPTIMIZED"),
+       .CLKFBOUT_MULT(4*f_mult),
+       .CLKFBOUT_PHASE(0.0),
+       .CLKIN1_PERIOD(in_period),
+       .CLKIN2_PERIOD(in_period),
+
+       .CLKOUT0_DIVIDE(f_div),
+       .CLKOUT0_DUTY_CYCLE(0.5),
+       .CLKOUT0_PHASE(0.0),
+
+       .CLKOUT1_DIVIDE(f_div),
+       .CLKOUT1_DUTY_CYCLE(0.5),
+       .CLKOUT1_PHASE(0.0),
+
+       .CLKOUT2_DIVIDE(2*f_div),
+       .CLKOUT2_DUTY_CYCLE(0.5),
+       .CLKOUT2_PHASE(270.0),
+
+       .CLKOUT3_DIVIDE(4*f_div),
+       .CLKOUT3_DUTY_CYCLE(0.5),
+       .CLKOUT3_PHASE(0.0),
+
+       .CLKOUT4_DIVIDE(4*f_mult),
+       .CLKOUT4_DUTY_CYCLE(0.5),
+       .CLKOUT4_PHASE(0.0),
+
+       .CLKOUT5_DIVIDE(2*f_div),
+       .CLKOUT5_DUTY_CYCLE(0.5),
+       .CLKOUT5_PHASE(250.0),
+
+       .COMPENSATION("INTERNAL"),
+       .DIVCLK_DIVIDE(1),
+       .REF_JITTER(0.100),
+       .CLK_FEEDBACK("CLKFBOUT"),
+       .SIM_DEVICE("SPARTAN6")
+) pll (
+       .CLKFBDCM(),
+       .CLKFBOUT(buf_pll_fb_out),
+       .CLKOUT0(pllout0), /* < x4 clock for writes */
+       .CLKOUT1(pllout1), /* < x4 clock for reads */
+       .CLKOUT2(pllout2), /* < x2 270 clock for DQS, memory address and control signals */
+       .CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
+       .CLKOUT4(pllout4), /* < buffered clk50 */
+       .CLKOUT5(pllout5), /* < x2 clock to off-chip DDR */
+       .CLKOUTDCM0(),
+       .CLKOUTDCM1(),
+       .CLKOUTDCM2(),
+       .CLKOUTDCM3(),
+       .CLKOUTDCM4(),
+       .CLKOUTDCM5(),
+       .DO(),
+       .DRDY(),
+       .LOCKED(pll_lckd),
+       .CLKFBIN(buf_pll_fb_out),
+       .CLKIN1(clkdiv),
+       .CLKIN2(1'b0),
+       .CLKINSEL(1'b1),
+       .DADDR(5'b00000),
+       .DCLK(1'b0),
+       .DEN(1'b0),
+       .DI(16'h0000),
+       .DWE(1'b0),
+       .RST(1'b0),
+       .REL(1'b0)
+);
+
+BUFPLL #(
+       .DIVIDE(4)
+) wr_bufpll (
+       .PLLIN(pllout0),
+       .GCLK(sys_clk),
+       .LOCKED(pll_lckd),
+       .IOCLK(clk4x_wr),
+       .LOCK(),
+       .SERDESSTROBE(clk4x_wr_strb)
+);
+
+BUFPLL #(
+       .DIVIDE(4)
+) rd_bufpll (
+       .PLLIN(pllout1),
+       .GCLK(sys_clk),
+       .LOCKED(pll_lckd),
+       .IOCLK(clk4x_rd),
+       .LOCK(),
+       .SERDESSTROBE(clk4x_rd_strb)
+);
+
+BUFG bufg_x2_2(
+       .I(pllout2),
+       .O(clk2x_270)
+);
+
+BUFG bufg_x1(
+       .I(pllout3),
+       .O(sys_clk)
+);
+
+wire base50_clk;
+BUFG bufg_50(
+       .I(pllout4),
+       .O(base50_clk)
+);
+
+wire clk2x_off;
+BUFG bufg_x2_offclk(
+       .I(pllout5),
+       .O(clk2x_off)
+);
+
+
+/*
+ * SDRAM clock
+ */
+
+ODDR2 #(
+       .DDR_ALIGNMENT("NONE"),
+       .INIT(1'b0),
+       .SRTYPE("SYNC")
+) sd_clk_forward_p (
+       .Q(ddr_clk_pad_p),
+       .C0(clk2x_off),
+       .C1(~clk2x_off),
+       .CE(1'b1),
+       .D0(1'b1),
+       .D1(1'b0),
+       .R(1'b0),
+       .S(1'b0)
+);
+ODDR2 #(
+       .DDR_ALIGNMENT("NONE"),
+       .INIT(1'b0),
+       .SRTYPE("SYNC")
+) sd_clk_forward_n (
+       .Q(ddr_clk_pad_n),
+       .C0(clk2x_off),
+       .C1(~clk2x_off),
+       .CE(1'b1),
+       .D0(1'b0),
+       .D1(1'b1),
+       .R(1'b0),
+       .S(1'b0)
+);
+
+endmodule
diff --git a/misoc/soc/__init__.py b/misoc/soc/__init__.py
new file mode 100644 (file)
index 0000000..889be51
--- /dev/null
@@ -0,0 +1,204 @@
+from operator import itemgetter
+
+from migen.fhdl.std import *
+from migen.bank import csrgen
+from migen.bus import wishbone, csr, wishbone2csr
+
+from misoc.com.uart.phy import UARTPHY
+from misoc.com import uart
+from misoc.cpu import lm32, mor1kx
+from misoc.cpu import identifier, timer
+
+
+def mem_decoder(address, start=26, end=29):
+    return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1)
+
+
+class SoC(Module):
+    csr_map = {
+        "crg":        0,  # user
+        "uart_phy":   1,  # provided by default (optional)
+        "uart":       2,  # provided by default (optional)
+        "identifier": 3,  # provided by default (optional)
+        "timer0":     4,  # provided by default (optional)
+        "buttons":    5,  # user
+        "leds":       6,  # user
+    }
+    interrupt_map = {
+        "uart":   0,
+        "timer0": 1,
+    }
+    mem_map = {
+        "rom":      0x00000000,  # (default shadow @0x80000000)
+        "sram":     0x10000000,  # (default shadow @0x90000000)
+        "main_ram": 0x40000000,  # (default shadow @0xc0000000)
+        "csr":      0x60000000,  # (default shadow @0xe0000000)
+    }
+    def __init__(self, platform, clk_freq,
+                cpu_type="lm32", cpu_reset_address=0x00000000,
+                integrated_rom_size=0,
+                integrated_sram_size=4096,
+                integrated_main_ram_size=0,
+                shadow_base=0x80000000,
+                with_csr=True, csr_data_width=8, csr_address_width=14,
+                with_uart=True, uart_baudrate=115200,
+                with_identifier=True,
+                with_timer=True):
+        self.platform = platform
+        self.clk_freq = clk_freq
+
+        self.cpu_type = cpu_type
+        if integrated_rom_size:
+            cpu_reset_address = 0
+        self.cpu_reset_address = cpu_reset_address
+
+        self.integrated_rom_size = integrated_rom_size
+        self.integrated_sram_size = integrated_sram_size
+        self.integrated_main_ram_size = integrated_main_ram_size
+
+        self.with_uart = with_uart
+        self.uart_baudrate = uart_baudrate
+
+        self.with_identifier = with_identifier
+
+        self.shadow_base = shadow_base
+
+        self.with_csr = with_csr
+        self.csr_data_width = csr_data_width
+        self.csr_address_width = csr_address_width
+
+        self._memory_regions = []  # list of (name, origin, length)
+        self._csr_regions = []  # list of (name, origin, busword, csr_list/Memory)
+        self._constants = []  # list of (name, value)
+
+        self._wb_masters = []
+        self._wb_slaves = []
+
+        if cpu_type != "none":
+            if cpu_type == "lm32":
+                self.add_cpu_or_bridge(lm32.LM32(platform, self.cpu_reset_address))
+            elif cpu_type == "or1k":
+                self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address))
+            else:
+                raise ValueError("Unsupported CPU type: {}".format(cpu_type))
+            self.add_wb_master(self.cpu_or_bridge.ibus)
+            self.add_wb_master(self.cpu_or_bridge.dbus)
+
+            if integrated_rom_size:
+                self.submodules.rom = wishbone.SRAM(integrated_rom_size, read_only=True)
+                self.register_rom(self.rom.bus, integrated_rom_size)
+
+            if integrated_sram_size:
+                self.submodules.sram = wishbone.SRAM(integrated_sram_size)
+                self.register_mem("sram", self.mem_map["sram"], self.sram.bus, integrated_sram_size)
+
+            # Note: Main Ram can be used when no external SDRAM is available and use SDRAM mapping.
+            if integrated_main_ram_size:
+                self.submodules.main_ram = wishbone.SRAM(integrated_main_ram_size)
+                self.register_mem("main_ram", self.mem_map["main_ram"], self.main_ram.bus, integrated_main_ram_size)
+
+        if with_csr:
+            self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(csr_data_width, csr_address_width))
+            self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone)
+
+            if with_uart:
+                self.submodules.uart_phy = UARTPHY(platform.request("serial"), clk_freq, uart_baudrate)
+                self.submodules.uart = uart.UART(self.uart_phy)
+
+            if with_identifier:
+                platform_id = 0x554E if not hasattr(platform, "identifier") else platform.identifier
+                self.submodules.identifier = identifier.Identifier(platform_id, int(clk_freq))
+
+            if with_timer:
+                self.submodules.timer0 = timer.Timer()
+
+    def add_cpu_or_bridge(self, cpu_or_bridge):
+        if self.finalized:
+            raise FinalizeError
+        if hasattr(self, "cpu_or_bridge"):
+            raise NotImplementedError("More than one CPU is not supported")
+        self.submodules.cpu_or_bridge = cpu_or_bridge
+
+    def init_rom(self, data):
+        self.rom.mem.init = data
+
+    def add_wb_master(self, wbm):
+        if self.finalized:
+            raise FinalizeError
+        self._wb_masters.append(wbm)
+
+    def add_wb_slave(self, address_decoder, interface):
+        if self.finalized:
+            raise FinalizeError
+        self._wb_slaves.append((address_decoder, interface))
+
+    def add_memory_region(self, name, origin, length):
+        def in_this_region(addr):
+            return addr >= origin and addr < origin + length
+        for n, o, l in self._memory_regions:
+            if n == name or in_this_region(o) or in_this_region(o+l-1):
+                raise ValueError("Memory region conflict between {} and {}".format(n, name))
+
+        self._memory_regions.append((name, origin, length))
+
+    def register_mem(self, name, address, interface, size=None):
+        self.add_wb_slave(mem_decoder(address), interface)
+        if size is not None:
+            self.add_memory_region(name, address, size)
+
+    def register_rom(self, interface, rom_size=0xa000):
+        self.add_wb_slave(mem_decoder(self.mem_map["rom"]), interface)
+        self.add_memory_region("rom", self.cpu_reset_address, rom_size)
+
+    def get_memory_regions(self):
+        return self._memory_regions
+
+    def check_csr_region(self, name, origin):
+        for n, o, l, obj in self._csr_regions:
+            if n == name or o == origin:
+                raise ValueError("CSR region conflict between {} and {}".format(n, name))
+
+    def add_csr_region(self, name, origin, busword, obj):
+        self.check_csr_region(name, origin)
+        self._csr_regions.append((name, origin, busword, obj))
+
+    def get_csr_regions(self):
+        return self._csr_regions
+
+    def add_constant(self, name, value=None):
+        self._constants.append((name, value))
+
+    def get_constants(self):
+        r = []
+        for name, interrupt in sorted(self.interrupt_map.items(), key=itemgetter(1)):
+            r.append((name.upper() + "_INTERRUPT", interrupt))
+        r += self._constants
+        return r
+
+    def do_finalize(self):
+        registered_mems = {regions[0] for regions in self._memory_regions}
+        if self.cpu_type != "none":
+            for mem in "rom", "sram":
+                if mem not in registered_mems:
+                    raise FinalizeError("CPU needs a {} to be registered with SoC.register_mem()".format(mem))
+
+        # Wishbone
+        self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
+            self._wb_slaves, register=True)
+
+        # CSR
+        if self.with_csr:
+            self.submodules.csrbankarray = csrgen.BankArray(self,
+                lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override],
+                data_width=self.csr_data_width, address_width=self.csr_address_width)
+            self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
+            for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
+                self.add_csr_region(name, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, csrs)
+            for name, memory, mapaddr, mmap in self.csrbankarray.srams:
+                self.add_csr_region(name + "_" + memory.name_override, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, memory)
+
+        # Interrupts
+        if hasattr(self.cpu_or_bridge, "interrupt"):
+            for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
+                if hasattr(self, k):
+                    self.comb += self.cpu_or_bridge.interrupt[v].eq(getattr(self, k).ev.irq)
diff --git a/misoc/soc/cpuif.py b/misoc/soc/cpuif.py
new file mode 100644 (file)
index 0000000..ac812d5
--- /dev/null
@@ -0,0 +1,119 @@
+from migen.fhdl.std import *
+from migen.bank.description import CSRStatus
+
+
+def get_cpu_mak(cpu_type):
+    if cpu_type == "lm32":
+        triple = "lm32-elf"
+        cpuflags = "-mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled"
+        clang = ""
+    elif cpu_type == "or1k":
+        triple = "or1k-linux"
+        cpuflags = "-mhard-mul -mhard-div -mror -mffl1 -maddc"
+        clang = "1"
+    else:
+        raise ValueError("Unsupported CPU type: "+cpu_type)
+    return "TRIPLE={}\nCPU={}\nCPUFLAGS={}\nCLANG={}".format(triple, cpu_type, cpuflags, clang)
+
+
+def get_linker_output_format(cpu_type):
+    return "OUTPUT_FORMAT(\"elf32-{}\")\n".format(cpu_type)
+
+
+def get_linker_regions(regions):
+    r = "MEMORY {\n"
+    for name, origin, length in regions:
+        r += "\t{} : ORIGIN = 0x{:08x}, LENGTH = 0x{:08x}\n".format(name, origin, length)
+    r += "}\n"
+    return r
+
+
+def get_mem_header(regions, flash_boot_address):
+    r = "#ifndef __GENERATED_MEM_H\n#define __GENERATED_MEM_H\n\n"
+    for name, base, size in regions:
+        r += "#define {name}_BASE 0x{base:08x}\n#define {name}_SIZE 0x{size:08x}\n\n".format(name=name.upper(), base=base, size=size)
+    if flash_boot_address is not None:
+        r += "#define FLASH_BOOT_ADDRESS 0x{:08x}\n\n".format(flash_boot_address)
+    r += "#endif\n"
+    return r
+
+
+def _get_rw_functions(reg_name, reg_base, nwords, busword, read_only, with_access_functions):
+    r = ""
+
+    r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"\n"
+    r += "#define CSR_"+reg_name.upper()+"_SIZE "+str(nwords)+"\n"
+
+    size = nwords*busword
+    if size > 64:
+        return r
+    elif size > 32:
+        ctype = "unsigned long long int"
+    elif size > 16:
+        ctype = "unsigned int"
+    elif size > 8:
+        ctype = "unsigned short int"
+    else:
+        ctype = "unsigned char"
+
+    if with_access_functions:
+        r += "static inline "+ctype+" "+reg_name+"_read(void) {\n"
+        if size > 1:
+            r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n"
+            for byte in range(1, nwords):
+                r += "\tr <<= "+str(busword)+";\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n"
+            r += "\treturn r;\n}\n"
+        else:
+            r += "\treturn MMPTR("+hex(reg_base)+");\n}\n"
+
+        if not read_only:
+            r += "static inline void "+reg_name+"_write("+ctype+" value) {\n"
+            for word in range(nwords):
+                shift = (nwords-word-1)*busword
+                if shift:
+                    value_shifted = "value >> "+str(shift)
+                else:
+                    value_shifted = "value"
+                r += "\tMMPTR("+hex(reg_base+4*word)+") = "+value_shifted+";\n"
+            r += "}\n"
+    return r
+
+
+def get_csr_header(regions, constants, with_access_functions=True):
+    r = "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
+    if with_access_functions:
+        r += "#include <hw/common.h>\n"
+    for name, origin, busword, obj in regions:
+        if isinstance(obj, Memory):
+            r += "#define CSR_"+name.upper()+"_BASE "+hex(origin)+"\n"
+        else:
+            r += "\n/* "+name+" */\n"
+            r += "#define CSR_"+name.upper()+"_BASE "+hex(origin)+"\n"
+            for csr in obj:
+                nr = (csr.size + busword - 1)//busword
+                r += _get_rw_functions(name + "_" + csr.name, origin, nr, busword, isinstance(csr, CSRStatus), with_access_functions)
+                origin += 4*nr
+
+    r += "\n/* constants */\n"
+    for name, value in constants:
+        r += "#define " + name
+        if value is not None:
+            if isinstance(value, str):
+                r +=  " \"" + value + "\""
+            else:
+                r += " " + str(value)
+        r += "\n"
+
+    r += "\n#endif\n"
+    return r
+
+
+def get_csr_csv(regions):
+    r = ""
+    for name, origin, busword, obj in regions:
+        if not isinstance(obj, Memory):
+            for csr in obj:
+                nr = (csr.size + busword - 1)//busword
+                r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
+                origin += 4*nr
+    return r
diff --git a/misoc/soc/sdram.py b/misoc/soc/sdram.py
new file mode 100644 (file)
index 0000000..d46beb1
--- /dev/null
@@ -0,0 +1,111 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.record import *
+
+from misoc.mem.sdram.core import SDRAMCore
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.mem.sdram.core.minicon import MiniconSettings
+from misoc.mem.sdram.frontend import memtest, wishbone2lasmi
+from misoc.soc import SoC
+
+
+class SDRAMSoC(SoC):
+    csr_map = {
+        "sdram":           8,
+        "l2_cache":        9,
+        "memtest_w":      10,
+        "memtest_r":      11
+    }
+    csr_map.update(SoC.csr_map)
+
+    def __init__(self, platform, clk_freq, sdram_controller_settings,
+            **kwargs):
+        SoC.__init__(self, platform, clk_freq, **kwargs)
+        if isinstance(sdram_controller_settings, str):
+            self.sdram_controller_settings = eval(sdram_controller_settings)
+        else:
+            self.sdram_controller_settings = sdram_controller_settings
+        self._sdram_phy_registered = False
+        self._wb_sdram_ifs = []
+        self._wb_sdram = wishbone.Interface()
+
+    def add_wb_sdram_if(self, interface):
+        if self.finalized:
+            raise FinalizeError
+        self._wb_sdram_ifs.append(interface)
+
+    def register_sdram_phy(self, phy):
+        if self._sdram_phy_registered:
+            raise FinalizeError
+        self._sdram_phy_registered = True
+
+        # Core
+        self.submodules.sdram = SDRAMCore(phy,
+                                          phy.module.geom_settings,
+                                          phy.module.timing_settings,
+                                          self.sdram_controller_settings)
+
+        dfi_databits_divisor = 1 if phy.settings.memtype == "SDR" else 2
+        sdram_width = phy.settings.dfi_databits//dfi_databits_divisor
+        main_ram_size = 2**(phy.module.geom_settings.bankbits +
+                            phy.module.geom_settings.rowbits +
+                            phy.module.geom_settings.colbits)*sdram_width//8
+        # XXX: Limit main_ram_size to 256MB, we should modify mem_map to allow larger memories.
+        main_ram_size = min(main_ram_size, 256*1024*1024)
+        l2_size = self.sdram_controller_settings.l2_size
+        if l2_size:
+            self.add_constant("L2_SIZE", l2_size)
+
+        # add a Wishbone interface to the DRAM
+        wb_sdram = wishbone.Interface()
+        self.add_wb_sdram_if(wb_sdram)
+        self.register_mem("main_ram", self.mem_map["main_ram"], wb_sdram, main_ram_size)
+
+        # LASMICON frontend
+        if isinstance(self.sdram_controller_settings, LASMIconSettings):
+            if self.sdram_controller_settings.with_bandwidth:
+                self.sdram.controller.multiplexer.add_bandwidth()
+
+            if self.sdram_controller_settings.with_memtest:
+                self.submodules.memtest_w = memtest.MemtestWriter(self.sdram.crossbar.get_master())
+                self.submodules.memtest_r = memtest.MemtestReader(self.sdram.crossbar.get_master())
+
+            if l2_size:
+                lasmim = self.sdram.crossbar.get_master()
+                l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, wishbone.Interface(lasmim.dw))
+                # XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
+                # Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
+                # Remove this workaround when fixed by Xilinx.
+                from mibuild.xilinx.vivado import XilinxVivadoToolchain
+                if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
+                    from migen.fhdl.simplify import FullMemoryWE
+                    self.submodules.l2_cache = FullMemoryWE()(l2_cache)
+                else:
+                    self.submodules.l2_cache = l2_cache
+                self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_cache.slave, lasmim)
+
+        # MINICON frontend
+        elif isinstance(self.sdram_controller_settings, MiniconSettings):
+            if l2_size:
+                l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, self.sdram.controller.bus)
+                # XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
+                # Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
+                # Remove this workaround when fixed by Xilinx.
+                from mibuild.xilinx.vivado import XilinxVivadoToolchain
+                if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
+                    from migen.fhdl.simplify import FullMemoryWE
+                    self.submodules.l2_cache = FullMemoryWE()(l2_cache)
+                else:
+                    self.submodules.l2_cache = l2_cache
+            else:
+                self.submodules.converter = wishbone.Converter(self._wb_sdram, self.sdram.controller.bus)
+
+    def do_finalize(self):
+        if not self.integrated_main_ram_size:
+            if not self._sdram_phy_registered:
+                raise FinalizeError("Need to call SDRAMSoC.register_sdram_phy()")
+
+            # arbitrate wishbone interfaces to the DRAM
+            self.submodules.wb_sdram_con = wishbone.Arbiter(self._wb_sdram_ifs,
+                                                            self._wb_sdram)
+        SoC.do_finalize(self)
diff --git a/misoc/tools/__init__.py b/misoc/tools/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/tools/wishbone.py b/misoc/tools/wishbone.py
new file mode 100644 (file)
index 0000000..5b712bf
--- /dev/null
@@ -0,0 +1,149 @@
+from migen.fhdl.std import *
+from migen.bus import wishbone
+from migen.genlib.misc import chooser, Counter, WaitTimer
+from migen.genlib.record import Record
+from migen.genlib.fsm import FSM, NextState
+from migen.flow.actor import Sink, Source
+
+
+class WishboneStreamingBridge(Module):
+    cmds = {
+        "write": 0x01,
+        "read": 0x02
+    }
+
+    def __init__(self, phy, clk_freq):
+        self.wishbone = wishbone.Interface()
+
+        # # #
+
+        byte_counter = Counter(3)
+        word_counter = Counter(8)
+        self.submodules += byte_counter, word_counter
+
+        cmd = Signal(8)
+        cmd_ce = Signal()
+
+        length = Signal(8)
+        length_ce = Signal()
+
+        address = Signal(32)
+        address_ce = Signal()
+
+        data = Signal(32)
+        rx_data_ce = Signal()
+        tx_data_ce = Signal()
+
+        self.sync += [
+            If(cmd_ce, cmd.eq(phy.source.data)),
+            If(length_ce, length.eq(phy.source.data)),
+            If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))),
+            If(rx_data_ce,
+                data.eq(Cat(phy.source.data, data[0:24]))
+            ).Elif(tx_data_ce,
+                data.eq(self.wishbone.dat_r)
+            )
+        ]
+
+        fsm = InsertReset(FSM(reset_state="IDLE"))
+        timer = WaitTimer(clk_freq//10)
+        self.submodules += fsm, timer
+        self.comb += [
+            fsm.reset.eq(timer.done),
+            phy.source.ack.eq(1)
+        ]
+        fsm.act("IDLE",
+            If(phy.source.stb,
+                cmd_ce.eq(1),
+                If((phy.source.data == self.cmds["write"]) |
+                   (phy.source.data == self.cmds["read"]),
+                    NextState("RECEIVE_LENGTH")
+                ),
+                byte_counter.reset.eq(1),
+                word_counter.reset.eq(1)
+            )
+        )
+        fsm.act("RECEIVE_LENGTH",
+            If(phy.source.stb,
+                length_ce.eq(1),
+                NextState("RECEIVE_ADDRESS")
+            )
+        )
+        fsm.act("RECEIVE_ADDRESS",
+            If(phy.source.stb,
+                address_ce.eq(1),
+                byte_counter.ce.eq(1),
+                If(byte_counter.value == 3,
+                    If(cmd == self.cmds["write"],
+                        NextState("RECEIVE_DATA")
+                    ).Elif(cmd == self.cmds["read"],
+                        NextState("READ_DATA")
+                    ),
+                    byte_counter.reset.eq(1),
+                )
+            )
+        )
+        fsm.act("RECEIVE_DATA",
+            If(phy.source.stb,
+                rx_data_ce.eq(1),
+                byte_counter.ce.eq(1),
+                If(byte_counter.value == 3,
+                    NextState("WRITE_DATA"),
+                    byte_counter.reset.eq(1)
+                )
+            )
+        )
+        self.comb += [
+            self.wishbone.adr.eq(address + word_counter.value),
+            self.wishbone.dat_w.eq(data),
+            self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1)
+        ]
+        fsm.act("WRITE_DATA",
+            self.wishbone.stb.eq(1),
+            self.wishbone.we.eq(1),
+            self.wishbone.cyc.eq(1),
+            If(self.wishbone.ack,
+                word_counter.ce.eq(1),
+                If(word_counter.value == (length-1),
+                    NextState("IDLE")
+                ).Else(
+                    NextState("RECEIVE_DATA")
+                )
+            )
+        )
+        fsm.act("READ_DATA",
+            self.wishbone.stb.eq(1),
+            self.wishbone.we.eq(0),
+            self.wishbone.cyc.eq(1),
+            If(self.wishbone.ack,
+                tx_data_ce.eq(1),
+                NextState("SEND_DATA")
+            )
+        )
+        self.comb += \
+            chooser(data, byte_counter.value, phy.sink.data, n=4, reverse=True)
+        fsm.act("SEND_DATA",
+            phy.sink.stb.eq(1),
+            If(phy.sink.ack,
+                byte_counter.ce.eq(1),
+                If(byte_counter.value == 3,
+                    word_counter.ce.eq(1),
+                    If(word_counter.value == (length-1),
+                        NextState("IDLE")
+                    ).Else(
+                        NextState("READ_DATA"),
+                        byte_counter.reset.eq(1)
+                    )
+                )
+            )
+        )
+
+        self.comb += timer.wait.eq(~fsm.ongoing("IDLE"))
+
+        if phy.sink.description.packetized:
+            self.comb += [
+                phy.sink.sop.eq((byte_counter.value == 0) & (word_counter.value == 0)),
+                phy.sink.eop.eq((byte_counter.value == 3) & (word_counter.value == (length-1)))
+            ]
+            if hasattr(phy.sink, "length"):
+                self.comb += phy.sink.length.eq(4*length)
diff --git a/misoc/video/__init__.py b/misoc/video/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/misoc/video/dvisampler/__init__.py b/misoc/video/dvisampler/__init__.py
new file mode 100644 (file)
index 0000000..1670ccf
--- /dev/null
@@ -0,0 +1,80 @@
+from migen.fhdl.std import *
+from migen.bank.description import AutoCSR
+
+from misoc.video.dvisampler.edid import EDID
+from misoc.video.dvisampler.clocking import Clocking
+from misoc.video.dvisampler.datacapture import DataCapture
+from misoc.video.dvisampler.charsync import CharSync
+from misoc.video.dvisampler.wer import WER
+from misoc.video.dvisampler.decoding import Decoding
+from misoc.video.dvisampler.chansync import ChanSync
+from misoc.video.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction
+from misoc.video.dvisampler.dma import DMA
+
+
+class DVISampler(Module, AutoCSR):
+    def __init__(self, pads, lasmim, n_dma_slots=2, fifo_depth=512):
+        self.submodules.edid = EDID(pads)
+        self.submodules.clocking = Clocking(pads)
+
+        for datan in range(3):
+            name = "data" + str(datan)
+
+            cap = DataCapture(getattr(pads, name + "_p"), getattr(pads, name + "_n"), 8)
+            setattr(self.submodules, name + "_cap", cap)
+            self.comb += cap.serdesstrobe.eq(self.clocking.serdesstrobe)
+
+            charsync = CharSync()
+            setattr(self.submodules, name + "_charsync", charsync)
+            self.comb += charsync.raw_data.eq(cap.d)
+
+            wer = WER()
+            setattr(self.submodules, name + "_wer", wer)
+            self.comb += wer.data.eq(charsync.data)
+
+            decoding = Decoding()
+            setattr(self.submodules, name + "_decod", decoding)
+            self.comb += [
+                decoding.valid_i.eq(charsync.synced),
+                decoding.input.eq(charsync.data)
+            ]
+
+        self.submodules.chansync = ChanSync()
+        self.comb += [
+            self.chansync.valid_i.eq(self.data0_decod.valid_o & \
+              self.data1_decod.valid_o & self.data2_decod.valid_o),
+            self.chansync.data_in0.eq(self.data0_decod.output),
+            self.chansync.data_in1.eq(self.data1_decod.output),
+            self.chansync.data_in2.eq(self.data2_decod.output),
+        ]
+
+        self.submodules.syncpol = SyncPolarity()
+        self.comb += [
+            self.syncpol.valid_i.eq(self.chansync.chan_synced),
+            self.syncpol.data_in0.eq(self.chansync.data_out0),
+            self.syncpol.data_in1.eq(self.chansync.data_out1),
+            self.syncpol.data_in2.eq(self.chansync.data_out2)
+        ]
+
+        self.submodules.resdetection = ResolutionDetection()
+        self.comb += [
+            self.resdetection.valid_i.eq(self.syncpol.valid_o),
+            self.resdetection.de.eq(self.syncpol.de),
+            self.resdetection.vsync.eq(self.syncpol.vsync)
+        ]
+
+        self.submodules.frame = FrameExtraction(24*lasmim.dw//32, fifo_depth)
+        self.comb += [
+            self.frame.valid_i.eq(self.syncpol.valid_o),
+            self.frame.de.eq(self.syncpol.de),
+            self.frame.vsync.eq(self.syncpol.vsync),
+            self.frame.r.eq(self.syncpol.r),
+            self.frame.g.eq(self.syncpol.g),
+            self.frame.b.eq(self.syncpol.b)
+        ]
+
+        self.submodules.dma = DMA(lasmim, n_dma_slots)
+        self.comb += self.frame.frame.connect(self.dma.frame)
+        self.ev = self.dma.ev
+
+    autocsr_exclude = {"ev"}
diff --git a/misoc/video/dvisampler/analysis.py b/misoc/video/dvisampler/analysis.py
new file mode 100644 (file)
index 0000000..77003c7
--- /dev/null
@@ -0,0 +1,208 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg, PulseSynchronizer
+from migen.genlib.fifo import AsyncFIFO
+from migen.genlib.record import Record
+from migen.bank.description import *
+from migen.flow.actor import *
+
+from misoc.video.dvisampler.common import channel_layout
+
+
+class SyncPolarity(Module):
+    def __init__(self):
+        self.valid_i = Signal()
+        self.data_in0 = Record(channel_layout)
+        self.data_in1 = Record(channel_layout)
+        self.data_in2 = Record(channel_layout)
+
+        self.valid_o = Signal()
+        self.de = Signal()
+        self.hsync = Signal()
+        self.vsync = Signal()
+        self.r = Signal(8)
+        self.g = Signal(8)
+        self.b = Signal(8)
+
+        ###
+
+        de = self.data_in0.de
+        de_r = Signal()
+        c = self.data_in0.c
+        c_polarity = Signal(2)
+        c_out = Signal(2)
+
+        self.comb += [
+            self.de.eq(de_r),
+            self.hsync.eq(c_out[0]),
+            self.vsync.eq(c_out[1])
+        ]
+
+        self.sync.pix += [
+            self.valid_o.eq(self.valid_i),
+            self.r.eq(self.data_in2.d),
+            self.g.eq(self.data_in1.d),
+            self.b.eq(self.data_in0.d),
+
+            de_r.eq(de),
+            If(de_r & ~de,
+                c_polarity.eq(c),
+                c_out.eq(0)
+            ).Else(
+                c_out.eq(c ^ c_polarity)
+            )
+        ]
+
+
+class ResolutionDetection(Module, AutoCSR):
+    def __init__(self, nbits=11):
+        self.valid_i = Signal()
+        self.vsync = Signal()
+        self.de = Signal()
+
+        self._hres = CSRStatus(nbits)
+        self._vres = CSRStatus(nbits)
+
+        ###
+
+        # Detect DE transitions
+        de_r = Signal()
+        pn_de = Signal()
+        self.sync.pix += de_r.eq(self.de)
+        self.comb += pn_de.eq(~self.de & de_r)
+
+        # HRES
+        hcounter = Signal(nbits)
+        self.sync.pix += If(self.valid_i & self.de,
+                hcounter.eq(hcounter + 1)
+            ).Else(
+                hcounter.eq(0)
+            )
+
+        hcounter_st = Signal(nbits)
+        self.sync.pix += If(self.valid_i,
+                If(pn_de, hcounter_st.eq(hcounter))
+            ).Else(
+                hcounter_st.eq(0)
+            )
+        self.specials += MultiReg(hcounter_st, self._hres.status)
+
+        # VRES
+        vsync_r = Signal()
+        p_vsync = Signal()
+        self.sync.pix += vsync_r.eq(self.vsync),
+        self.comb += p_vsync.eq(self.vsync & ~vsync_r)
+
+        vcounter = Signal(nbits)
+        self.sync.pix += If(self.valid_i & p_vsync,
+                vcounter.eq(0)
+            ).Elif(pn_de,
+                vcounter.eq(vcounter + 1)
+            )
+
+        vcounter_st = Signal(nbits)
+        self.sync.pix += If(self.valid_i,
+                If(p_vsync, vcounter_st.eq(vcounter))
+            ).Else(
+                vcounter_st.eq(0)
+            )
+        self.specials += MultiReg(vcounter_st, self._vres.status)
+
+
+class FrameExtraction(Module, AutoCSR):
+    def __init__(self, word_width, fifo_depth):
+        # in pix clock domain
+        self.valid_i = Signal()
+        self.vsync = Signal()
+        self.de = Signal()
+        self.r = Signal(8)
+        self.g = Signal(8)
+        self.b = Signal(8)
+
+        # in sys clock domain
+        word_layout = [("sof", 1), ("pixels", word_width)]
+        self.frame = Source(word_layout)
+        self.busy = Signal()
+
+        self._overflow = CSR()
+
+        ###
+
+        # start of frame detection
+        vsync_r = Signal()
+        new_frame = Signal()
+        self.comb += new_frame.eq(self.vsync & ~vsync_r)
+        self.sync.pix += vsync_r.eq(self.vsync)
+
+        # pack pixels into words
+        cur_word = Signal(word_width)
+        cur_word_valid = Signal()
+        encoded_pixel = Signal(24)
+        self.comb += encoded_pixel.eq(Cat(self.b, self.g, self.r))
+        pack_factor = word_width//24
+        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
+        pack_counter = Signal(max=pack_factor)
+        self.sync.pix += [
+            cur_word_valid.eq(0),
+            If(new_frame,
+                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
+                pack_counter.eq(0),
+            ).Elif(self.valid_i & self.de,
+                [If(pack_counter == (pack_factor-i-1),
+                    cur_word[24*i:24*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)],
+                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
+                pack_counter.eq(pack_counter + 1)
+            )
+        ]
+
+        # FIFO
+        fifo = RenameClockDomains(AsyncFIFO(word_layout, fifo_depth),
+            {"write": "pix", "read": "sys"})
+        self.submodules += fifo
+        self.comb += [
+            fifo.din.pixels.eq(cur_word),
+            fifo.we.eq(cur_word_valid)
+        ]
+        self.sync.pix += \
+            If(new_frame,
+                fifo.din.sof.eq(1)
+            ).Elif(cur_word_valid,
+                fifo.din.sof.eq(0)
+            )
+        self.comb += [
+            self.frame.stb.eq(fifo.readable),
+            self.frame.payload.eq(fifo.dout),
+            fifo.re.eq(self.frame.ack),
+            self.busy.eq(0)
+        ]
+
+        # overflow detection
+        pix_overflow = Signal()
+        pix_overflow_reset = Signal()
+        self.sync.pix += [
+            If(fifo.we & ~fifo.writable,
+                pix_overflow.eq(1)
+            ).Elif(pix_overflow_reset,
+                pix_overflow.eq(0)
+            )
+        ]
+
+        sys_overflow = Signal()
+        self.specials += MultiReg(pix_overflow, sys_overflow)
+        self.submodules.overflow_reset = PulseSynchronizer("sys", "pix")
+        self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys")
+        self.comb += [
+            pix_overflow_reset.eq(self.overflow_reset.o),
+            self.overflow_reset_ack.i.eq(pix_overflow_reset)
+        ]
+
+        overflow_mask = Signal()
+        self.comb += [
+            self._overflow.w.eq(sys_overflow & ~overflow_mask),
+            self.overflow_reset.i.eq(self._overflow.re)
+        ]
+        self.sync += \
+            If(self._overflow.re,
+                overflow_mask.eq(1)
+            ).Elif(self.overflow_reset_ack.o,
+                overflow_mask.eq(0)
+            )
diff --git a/misoc/video/dvisampler/chansync.py b/misoc/video/dvisampler/chansync.py
new file mode 100644 (file)
index 0000000..b83b818
--- /dev/null
@@ -0,0 +1,132 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.genlib.fifo import _inc
+from migen.genlib.record import Record, layout_len
+from migen.genlib.misc import optree
+from migen.bank.description import *
+
+from misoc.video.dvisampler.common import channel_layout
+
+
+class _SyncBuffer(Module):
+    def __init__(self, width, depth):
+        self.din = Signal(width)
+        self.dout = Signal(width)
+        self.re = Signal()
+
+        ###
+
+        produce = Signal(max=depth)
+        consume = Signal(max=depth)
+        storage = Memory(width, depth)
+        self.specials += storage
+
+        wrport = storage.get_port(write_capable=True)
+        self.specials += wrport
+        self.comb += [
+            wrport.adr.eq(produce),
+            wrport.dat_w.eq(self.din),
+            wrport.we.eq(1)
+        ]
+        self.sync += _inc(produce, depth)
+
+        rdport = storage.get_port(async_read=True)
+        self.specials += rdport
+        self.comb += [
+            rdport.adr.eq(consume),
+            self.dout.eq(rdport.dat_r)
+        ]
+        self.sync += If(self.re, _inc(consume, depth))
+
+
+class ChanSync(Module, AutoCSR):
+    def __init__(self, nchan=3, depth=8):
+        self.valid_i = Signal()
+        self.chan_synced = Signal()
+
+        self._channels_synced = CSRStatus()
+
+        lst_control = []
+        all_control = Signal()
+        for i in range(nchan):
+            name = "data_in" + str(i)
+            data_in = Record(channel_layout, name=name)
+            setattr(self, name, data_in)
+            name = "data_out" + str(i)
+            data_out = Record(channel_layout, name=name)
+            setattr(self, name, data_out)
+
+            ###
+
+            syncbuffer = RenameClockDomains(_SyncBuffer(layout_len(channel_layout), depth), "pix")
+            self.submodules += syncbuffer
+            self.comb += [
+                syncbuffer.din.eq(data_in.raw_bits()),
+                data_out.raw_bits().eq(syncbuffer.dout)
+            ]
+            is_control = Signal()
+            self.comb += [
+                is_control.eq(~data_out.de),
+                syncbuffer.re.eq(~is_control | all_control)
+            ]
+            lst_control.append(is_control)
+
+        some_control = Signal()
+        self.comb += [
+            all_control.eq(optree("&", lst_control)),
+            some_control.eq(optree("|", lst_control))
+        ]
+        self.sync.pix += If(~self.valid_i,
+                self.chan_synced.eq(0)
+            ).Else(
+                If(some_control,
+                    If(all_control,
+                        self.chan_synced.eq(1)
+                    ).Else(
+                        self.chan_synced.eq(0)
+                    )
+                )
+            )
+        self.specials += MultiReg(self.chan_synced, self._channels_synced.status)
+
+
+class _TB(Module):
+    def __init__(self, test_seq_it):
+        self.test_seq_it = test_seq_it
+
+        self.submodules.chansync = RenameClockDomains(ChanSync(), {"pix": "sys"})
+        self.comb += self.chansync.valid_i.eq(1)
+
+    def do_simulation(self, selfp):
+        try:
+            de0, de1, de2 = next(self.test_seq_it)
+        except StopIteration:
+            raise StopSimulation
+
+        selfp.chansync.data_in0.de = de0
+        selfp.chansync.data_in1.de = de1
+        selfp.chansync.data_in2.de = de2
+        selfp.chansync.data_in0.d = selfp.simulator.cycle_counter
+        selfp.chansync.data_in1.d = selfp.simulator.cycle_counter
+        selfp.chansync.data_in2.d = selfp.simulator.cycle_counter
+
+        out0 = selfp.chansync.data_out0.d
+        out1 = selfp.chansync.data_out1.d
+        out2 = selfp.chansync.data_out2.d
+
+        print("{0:5} {1:5} {2:5}".format(out0, out1, out2))
+
+if __name__ == "__main__":
+    from migen.sim.generic import run_simulation
+
+    test_seq = [
+        (1, 1, 1),
+        (1, 1, 0),
+        (0, 0, 0),
+        (0, 0, 0),
+        (0, 0, 1),
+        (1, 1, 1),
+        (1, 1, 1),
+    ]
+    tb = _TB(iter(test_seq*2))
+    run_simulation(tb)
diff --git a/misoc/video/dvisampler/charsync.py b/misoc/video/dvisampler/charsync.py
new file mode 100644 (file)
index 0000000..102da27
--- /dev/null
@@ -0,0 +1,54 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.genlib.misc import optree
+from migen.bank.description import *
+
+from misoc.video.dvisampler.common import control_tokens
+
+
+class CharSync(Module, AutoCSR):
+    def __init__(self, required_controls=8):
+        self.raw_data = Signal(10)
+        self.synced = Signal()
+        self.data = Signal(10)
+
+        self._char_synced = CSRStatus()
+        self._ctl_pos = CSRStatus(bits_for(9))
+
+        ###
+
+        raw_data1 = Signal(10)
+        self.sync.pix += raw_data1.eq(self.raw_data)
+        raw = Signal(20)
+        self.comb += raw.eq(Cat(raw_data1, self.raw_data))
+
+        found_control = Signal()
+        control_position = Signal(max=10)
+        self.sync.pix += found_control.eq(0)
+        for i in range(10):
+            self.sync.pix += If(optree("|", [raw[i:i+10] == t for t in control_tokens]),
+                  found_control.eq(1),
+                  control_position.eq(i)
+            )
+
+        control_counter = Signal(max=required_controls)
+        previous_control_position = Signal(max=10)
+        word_sel = Signal(max=10)
+        self.sync.pix += [
+            If(found_control & (control_position == previous_control_position),
+                If(control_counter == (required_controls - 1),
+                    control_counter.eq(0),
+                    self.synced.eq(1),
+                    word_sel.eq(control_position)
+                ).Else(
+                    control_counter.eq(control_counter + 1)
+                )
+            ).Else(
+                control_counter.eq(0)
+            ),
+            previous_control_position.eq(control_position)
+        ]
+        self.specials += MultiReg(self.synced, self._char_synced.status)
+        self.specials += MultiReg(word_sel, self._ctl_pos.status)
+
+        self.sync.pix += self.data.eq(raw >> word_sel)
diff --git a/misoc/video/dvisampler/clocking.py b/misoc/video/dvisampler/clocking.py
new file mode 100644 (file)
index 0000000..d13b1fb
--- /dev/null
@@ -0,0 +1,80 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg
+from migen.bank.description import *
+
+
+class Clocking(Module, AutoCSR):
+    def __init__(self, pads):
+        self._pll_reset = CSRStorage(reset=1)
+        self._locked = CSRStatus()
+
+        # DRP
+        self._pll_adr = CSRStorage(5)
+        self._pll_dat_r = CSRStatus(16)
+        self._pll_dat_w = CSRStorage(16)
+        self._pll_read = CSR()
+        self._pll_write = CSR()
+        self._pll_drdy = CSRStatus()
+
+        self.locked = Signal()
+        self.serdesstrobe = Signal()
+        self.clock_domains._cd_pix = ClockDomain()
+        self.clock_domains._cd_pix2x = ClockDomain()
+        self.clock_domains._cd_pix10x = ClockDomain(reset_less=True)
+
+        ###
+
+        clk_se = Signal()
+        self.specials += Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_se)
+
+        clkfbout = Signal()
+        pll_locked = Signal()
+        pll_clk0 = Signal()
+        pll_clk1 = Signal()
+        pll_clk2 = Signal()
+        pll_drdy = Signal()
+        self.sync += If(self._pll_read.re | self._pll_write.re,
+            self._pll_drdy.status.eq(0)
+        ).Elif(pll_drdy,
+            self._pll_drdy.status.eq(1)
+        )
+        self.specials += Instance("PLL_ADV",
+                                  p_CLKFBOUT_MULT=10,
+                                  p_CLKOUT0_DIVIDE=1,   # pix10x
+                                  p_CLKOUT1_DIVIDE=5,   # pix2x
+                                  p_CLKOUT2_DIVIDE=10,  # pix
+                                  p_COMPENSATION="INTERNAL",
+
+                                  i_CLKINSEL=1,
+                                  i_CLKIN1=clk_se,
+                                  o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
+                                  o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
+                                  o_LOCKED=pll_locked, i_RST=self._pll_reset.storage,
+
+                                  i_DADDR=self._pll_adr.storage,
+                                  o_DO=self._pll_dat_r.status,
+                                  i_DI=self._pll_dat_w.storage,
+                                  i_DEN=self._pll_read.re | self._pll_write.re,
+                                  i_DWE=self._pll_write.re,
+                                  o_DRDY=pll_drdy,
+                                  i_DCLK=ClockSignal())
+
+        locked_async = Signal()
+        self.specials += [
+            Instance("BUFPLL", p_DIVIDE=5,
+                     i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
+                     o_IOCLK=self._cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
+            Instance("BUFG", i_I=pll_clk1, o_O=self._cd_pix2x.clk),
+            Instance("BUFG", i_I=pll_clk2, o_O=self._cd_pix.clk),
+            MultiReg(locked_async, self.locked, "sys")
+        ]
+        self.comb += self._locked.status.eq(self.locked)
+
+        # sychronize pix+pix2x reset
+        pix_rst_n = 1
+        for i in range(2):
+            new_pix_rst_n = Signal()
+            self.specials += Instance("FDCE", i_D=pix_rst_n, i_CE=1, i_C=ClockSignal("pix"),
+                i_CLR=~locked_async, o_Q=new_pix_rst_n)
+            pix_rst_n = new_pix_rst_n
+        self.comb += self._cd_pix.rst.eq(~pix_rst_n), self._cd_pix2x.rst.eq(~pix_rst_n)
diff --git a/misoc/video/dvisampler/common.py b/misoc/video/dvisampler/common.py
new file mode 100644 (file)
index 0000000..7fb9a42
--- /dev/null
@@ -0,0 +1,2 @@
+control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
+channel_layout = [("d", 8), ("c", 2), ("de", 1)]
diff --git a/misoc/video/dvisampler/datacapture.py b/misoc/video/dvisampler/datacapture.py
new file mode 100644 (file)
index 0000000..8e91ad0
--- /dev/null
@@ -0,0 +1,187 @@
+from migen.fhdl.std import *
+from migen.genlib.cdc import MultiReg, PulseSynchronizer
+from migen.bank.description import *
+
+
+class DataCapture(Module, AutoCSR):
+    def __init__(self, pad_p, pad_n, ntbits):
+        self.serdesstrobe = Signal()
+        self.d = Signal(10)
+
+        self._dly_ctl = CSR(6)
+        self._dly_busy = CSRStatus(2)
+        self._phase = CSRStatus(2)
+        self._phase_reset = CSR()
+
+        ###
+
+        # IO
+        pad_se = Signal()
+        self.specials += Instance("IBUFDS", i_I=pad_p, i_IB=pad_n, o_O=pad_se)
+
+        pad_delayed_master = Signal()
+        pad_delayed_slave = Signal()
+        delay_inc = Signal()
+        delay_ce = Signal()
+        delay_master_cal = Signal()
+        delay_master_rst = Signal()
+        delay_master_busy = Signal()
+        delay_slave_cal = Signal()
+        delay_slave_rst = Signal()
+        delay_slave_busy = Signal()
+        self.specials += Instance("IODELAY2",
+                                  p_SERDES_MODE="MASTER",
+                                  p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
+                                  p_COUNTER_WRAPAROUND="STAY_AT_LIMIT", p_DATA_RATE="SDR",
+
+                                  i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_master,
+                                  i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
+
+                                  i_INC=delay_inc, i_CE=delay_ce,
+                                  i_CAL=delay_master_cal, i_RST=delay_master_rst, o_BUSY=delay_master_busy,
+                                  i_T=1)
+        self.specials += Instance("IODELAY2",
+                                  p_SERDES_MODE="SLAVE",
+                                  p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
+                                  p_COUNTER_WRAPAROUND="WRAPAROUND", p_DATA_RATE="SDR",
+
+                                  i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_slave,
+                                  i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
+
+                                  i_INC=delay_inc, i_CE=delay_ce,
+                                  i_CAL=delay_slave_cal, i_RST=delay_slave_rst, o_BUSY=delay_slave_busy,
+                                  i_T=1)
+
+        dsr2 = Signal(5)
+        pd_valid = Signal()
+        pd_incdec = Signal()
+        pd_edge = Signal()
+        pd_cascade = Signal()
+        self.specials += Instance("ISERDES2",
+                                  p_SERDES_MODE="MASTER",
+                                  p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
+                                  p_INTERFACE_TYPE="RETIMED",
+
+                                  i_D=pad_delayed_master,
+                                  o_Q4=dsr2[4], o_Q3=dsr2[3], o_Q2=dsr2[2], o_Q1=dsr2[1],
+
+                                  i_BITSLIP=0, i_CE0=1, i_RST=0,
+                                  i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
+                                  i_IOCE=self.serdesstrobe,
+
+                                  o_VALID=pd_valid, o_INCDEC=pd_incdec,
+                                  i_SHIFTIN=pd_edge, o_SHIFTOUT=pd_cascade)
+        self.specials += Instance("ISERDES2",
+                                  p_SERDES_MODE="SLAVE",
+                                  p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
+                                  p_INTERFACE_TYPE="RETIMED",
+
+                                  i_D=pad_delayed_slave,
+                                  o_Q4=dsr2[0],
+
+                                  i_BITSLIP=0, i_CE0=1, i_RST=0,
+                                  i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
+                                  i_IOCE=self.serdesstrobe,
+
+                                  i_SHIFTIN=pd_cascade, o_SHIFTOUT=pd_edge)
+
+        # Phase error accumulator
+        lateness = Signal(ntbits, reset=2**(ntbits - 1))
+        too_late = Signal()
+        too_early = Signal()
+        reset_lateness = Signal()
+        self.comb += [
+            too_late.eq(lateness == (2**ntbits - 1)),
+            too_early.eq(lateness == 0)
+        ]
+        self.sync.pix2x += [
+            If(reset_lateness,
+                lateness.eq(2**(ntbits - 1))
+            ).Elif(~delay_master_busy & ~delay_slave_busy & ~too_late & ~too_early,
+                If(pd_valid & pd_incdec, lateness.eq(lateness - 1)),
+                If(pd_valid & ~pd_incdec, lateness.eq(lateness + 1))
+            )
+        ]
+
+        # Delay control
+        self.submodules.delay_master_done = PulseSynchronizer("pix2x", "sys")
+        delay_master_pending = Signal()
+        self.sync.pix2x += [
+            self.delay_master_done.i.eq(0),
+            If(~delay_master_pending,
+                If(delay_master_cal | delay_ce, delay_master_pending.eq(1))
+            ).Else(
+                If(~delay_master_busy,
+                    self.delay_master_done.i.eq(1),
+                    delay_master_pending.eq(0)
+                )
+            )
+        ]
+        self.submodules.delay_slave_done = PulseSynchronizer("pix2x", "sys")
+        delay_slave_pending = Signal()
+        self.sync.pix2x += [
+            self.delay_slave_done.i.eq(0),
+            If(~delay_slave_pending,
+                If(delay_slave_cal | delay_ce, delay_slave_pending.eq(1))
+            ).Else(
+                If(~delay_slave_busy,
+                    self.delay_slave_done.i.eq(1),
+                    delay_slave_pending.eq(0)
+                )
+            )
+        ]
+
+        self.submodules.do_delay_master_cal = PulseSynchronizer("sys", "pix2x")
+        self.submodules.do_delay_master_rst = PulseSynchronizer("sys", "pix2x")
+        self.submodules.do_delay_slave_cal = PulseSynchronizer("sys", "pix2x")
+        self.submodules.do_delay_slave_rst = PulseSynchronizer("sys", "pix2x")
+        self.submodules.do_delay_inc = PulseSynchronizer("sys", "pix2x")
+        self.submodules.do_delay_dec = PulseSynchronizer("sys", "pix2x")
+        self.comb += [
+            delay_master_cal.eq(self.do_delay_master_cal.o),
+            delay_master_rst.eq(self.do_delay_master_rst.o),
+            delay_slave_cal.eq(self.do_delay_slave_cal.o),
+            delay_slave_rst.eq(self.do_delay_slave_rst.o),
+            delay_inc.eq(self.do_delay_inc.o),
+            delay_ce.eq(self.do_delay_inc.o | self.do_delay_dec.o),
+        ]
+
+        sys_delay_master_pending = Signal()
+        self.sync += [
+            If(self.do_delay_master_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
+                sys_delay_master_pending.eq(1)
+            ).Elif(self.delay_master_done.o,
+                sys_delay_master_pending.eq(0)
+            )
+        ]
+        sys_delay_slave_pending = Signal()
+        self.sync += [
+            If(self.do_delay_slave_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
+                sys_delay_slave_pending.eq(1)
+            ).Elif(self.delay_slave_done.o,
+                sys_delay_slave_pending.eq(0)
+            )
+        ]
+
+        self.comb += [
+            self.do_delay_master_cal.i.eq(self._dly_ctl.re & self._dly_ctl.r[0]),
+            self.do_delay_master_rst.i.eq(self._dly_ctl.re & self._dly_ctl.r[1]),
+            self.do_delay_slave_cal.i.eq(self._dly_ctl.re & self._dly_ctl.r[2]),
+            self.do_delay_slave_rst.i.eq(self._dly_ctl.re & self._dly_ctl.r[3]),
+            self.do_delay_inc.i.eq(self._dly_ctl.re & self._dly_ctl.r[4]),
+            self.do_delay_dec.i.eq(self._dly_ctl.re & self._dly_ctl.r[5]),
+            self._dly_busy.status.eq(Cat(sys_delay_master_pending, sys_delay_slave_pending))
+        ]
+
+        # Phase detector control
+        self.specials += MultiReg(Cat(too_late, too_early), self._phase.status)
+        self.submodules.do_reset_lateness = PulseSynchronizer("sys", "pix2x")
+        self.comb += [
+            reset_lateness.eq(self.do_reset_lateness.o),
+            self.do_reset_lateness.i.eq(self._phase_reset.re)
+        ]
+
+        # 5:10 deserialization
+        dsr = Signal(10)
+        self.sync.pix2x += dsr.eq(Cat(dsr[5:], dsr2))
+        self.sync.pix += self.d.eq(dsr)
diff --git a/misoc/video/dvisampler/debug.py b/misoc/video/dvisampler/debug.py
new file mode 100644 (file)
index 0000000..67af06e
--- /dev/null
@@ -0,0 +1,48 @@
+from migen.fhdl.std import *
+from migen.genlib.fifo import AsyncFIFO
+from migen.genlib.record import layout_len
+from migen.bank.description import AutoCSR
+from migen.actorlib import structuring, spi
+
+from misoc.mem.sdram.frontend import dma_lasmi
+from misoc.video.dvisampler.edid import EDID
+from misoc.video.dvisampler.clocking import Clocking
+from misoc.video.dvisampler.datacapture import DataCapture
+
+
+class RawDVISampler(Module, AutoCSR):
+    def __init__(self, pads, asmiport):
+        self.submodules.edid = EDID(pads)
+        self.submodules.clocking = Clocking(pads)
+
+        invert = False
+        try:
+            s = getattr(pads, "data0")
+        except AttributeError:
+            s = getattr(pads, "data0_n")
+            invert = True
+        self.submodules.data0_cap = DataCapture(8, invert)
+        self.comb += [
+            self.data0_cap.pad.eq(s),
+            self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe)
+        ]
+
+        fifo = RenameClockDomains(AsyncFIFO(10, 256),
+            {"write": "pix", "read": "sys"})
+        self.submodules += fifo
+        self.comb += [
+            fifo.din.eq(self.data0_cap.d),
+            fifo.we.eq(1)
+        ]
+
+        pack_factor = asmiport.hub.dw//16
+        self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
+        self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
+        self.submodules.dma = spi.DMAWriteController(dma_lasmi.Writer(lasmim), spi.MODE_SINGLE_SHOT)
+        self.comb += [
+            self.packer.sink.stb.eq(fifo.readable),
+            fifo.re.eq(self.packer.sink.ack),
+            self.packer.sink.word.eq(fifo.dout),
+            self.packer.source.connect_flat(self.cast.sink),
+            self.cast.source.connect_flat(self.dma.data)
+        ]
diff --git a/misoc/video/dvisampler/decoding.py b/misoc/video/dvisampler/decoding.py
new file mode 100644 (file)
index 0000000..2d0ddbf
--- /dev/null
@@ -0,0 +1,25 @@
+from migen.fhdl.std import *
+from migen.genlib.record import Record
+
+from misoc.video.dvisampler.common import control_tokens, channel_layout
+
+
+class Decoding(Module):
+    def __init__(self):
+        self.valid_i = Signal()
+        self.input = Signal(10)
+        self.valid_o = Signal()
+        self.output = Record(channel_layout)
+
+        ###
+
+        self.sync.pix += self.output.de.eq(1)
+        for i, t in enumerate(control_tokens):
+            self.sync.pix += If(self.input == t,
+                self.output.de.eq(0),
+                self.output.c.eq(i)
+            )
+        self.sync.pix += self.output.d[0].eq(self.input[0] ^ self.input[9])
+        for i in range(1, 8):
+            self.sync.pix += self.output.d[i].eq(self.input[i] ^ self.input[i-1] ^ ~self.input[8])
+        self.sync.pix += self.valid_o.eq(self.valid_i)
diff --git a/misoc/video/dvisampler/dma.py b/misoc/video/dvisampler/dma.py
new file mode 100644 (file)
index 0000000..75458df
--- /dev/null
@@ -0,0 +1,144 @@
+from migen.fhdl.std import *
+from migen.genlib.fsm import FSM, NextState
+from migen.bank.description import *
+from migen.bank.eventmanager import *
+from migen.flow.actor import *
+
+from misoc.mem.sdram.frontend import dma_lasmi
+
+
+# Slot status: EMPTY=0 LOADED=1 PENDING=2
+class _Slot(Module, AutoCSR):
+    def __init__(self, addr_bits, alignment_bits):
+        self.ev_source = EventSourceLevel()
+        self.address = Signal(addr_bits)
+        self.address_reached = Signal(addr_bits)
+        self.address_valid = Signal()
+        self.address_done = Signal()
+
+        self._status = CSRStorage(2, write_from_dev=True)
+        self._address = CSRStorage(addr_bits + alignment_bits, alignment_bits=alignment_bits, write_from_dev=True)
+
+        ###
+
+        self.comb += [
+            self.address.eq(self._address.storage),
+            self.address_valid.eq(self._status.storage[0]),
+            self._status.dat_w.eq(2),
+            self._status.we.eq(self.address_done),
+            self._address.dat_w.eq(self.address_reached),
+            self._address.we.eq(self.address_done),
+            self.ev_source.trigger.eq(self._status.storage[1])
+        ]
+
+
+class _SlotArray(Module, AutoCSR):
+    def __init__(self, nslots, addr_bits, alignment_bits):
+        self.submodules.ev = EventManager()
+        self.address = Signal(addr_bits)
+        self.address_reached = Signal(addr_bits)
+        self.address_valid = Signal()
+        self.address_done = Signal()
+
+        ###
+
+        slots = [_Slot(addr_bits, alignment_bits) for i in range(nslots)]
+        for n, slot in enumerate(slots):
+            setattr(self.submodules, "slot"+str(n), slot)
+            setattr(self.ev, "slot"+str(n), slot.ev_source)
+        self.ev.finalize()
+
+        change_slot = Signal()
+        current_slot = Signal(max=nslots)
+        self.sync += If(change_slot, [If(slot.address_valid, current_slot.eq(n)) for n, slot in reversed(list(enumerate(slots)))])
+        self.comb += change_slot.eq(~self.address_valid | self.address_done)
+
+        self.comb += [
+            self.address.eq(Array(slot.address for slot in slots)[current_slot]),
+            self.address_valid.eq(Array(slot.address_valid for slot in slots)[current_slot])
+        ]
+        self.comb += [slot.address_reached.eq(self.address_reached) for slot in slots]
+        self.comb += [slot.address_done.eq(self.address_done & (current_slot == n)) for n, slot in enumerate(slots)]
+
+
+class DMA(Module):
+    def __init__(self, lasmim, nslots):
+        bus_aw = lasmim.aw
+        bus_dw = lasmim.dw
+        alignment_bits = bits_for(bus_dw//8) - 1
+
+        fifo_word_width = 24*bus_dw//32
+        self.frame = Sink([("sof", 1), ("pixels", fifo_word_width)])
+        self._frame_size = CSRStorage(bus_aw + alignment_bits, alignment_bits=alignment_bits)
+        self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits)
+        self.ev = self._slot_array.ev
+
+        ###
+
+        # address generator + maximum memory word count to prevent DMA buffer overrun
+        reset_words = Signal()
+        count_word = Signal()
+        last_word = Signal()
+        current_address = Signal(bus_aw)
+        mwords_remaining = Signal(bus_aw)
+        self.comb += [
+            self._slot_array.address_reached.eq(current_address),
+            last_word.eq(mwords_remaining == 1)
+        ]
+        self.sync += [
+            If(reset_words,
+                current_address.eq(self._slot_array.address),
+                mwords_remaining.eq(self._frame_size.storage)
+            ).Elif(count_word,
+                current_address.eq(current_address + 1),
+                mwords_remaining.eq(mwords_remaining - 1)
+            )
+        ]
+
+        # 24bpp -> 32bpp
+        memory_word = Signal(bus_dw)
+        pixbits = []
+        for i in range(bus_dw//32):
+            for j in range(3):
+                b = (i*3+j)*8
+                pixbits.append(self.frame.pixels[b+6:b+8])
+                pixbits.append(self.frame.pixels[b:b+8])
+            pixbits.append(0)
+            pixbits.append(0)
+        self.comb += memory_word.eq(Cat(*pixbits))
+
+        # bus accessor
+        self.submodules._bus_accessor = dma_lasmi.Writer(lasmim)
+        self.comb += [
+            self._bus_accessor.address_data.a.eq(current_address),
+            self._bus_accessor.address_data.d.eq(memory_word)
+        ]
+
+        # control FSM
+        fsm = FSM()
+        self.submodules += fsm
+
+        fsm.act("WAIT_SOF",
+            reset_words.eq(1),
+            self.frame.ack.eq(~self._slot_array.address_valid | ~self.frame.sof),
+            If(self._slot_array.address_valid & self.frame.sof & self.frame.stb, NextState("TRANSFER_PIXELS"))
+        )
+        fsm.act("TRANSFER_PIXELS",
+            self.frame.ack.eq(self._bus_accessor.address_data.ack),
+            If(self.frame.stb,
+                self._bus_accessor.address_data.stb.eq(1),
+                If(self._bus_accessor.address_data.ack,
+                    count_word.eq(1),
+                    If(last_word, NextState("EOF"))
+                )
+            )
+        )
+        fsm.act("EOF",
+            If(~self._bus_accessor.busy,
+                self._slot_array.address_done.eq(1),
+                NextState("WAIT_SOF")
+            )
+        )
+
+    def get_csrs(self):
+        return [self._frame_size] + self._slot_array.get_csrs()
diff --git a/misoc/video/dvisampler/edid.py b/misoc/video/dvisampler/edid.py
new file mode 100644 (file)
index 0000000..2a8e8b0
--- /dev/null
@@ -0,0 +1,194 @@
+from migen.fhdl.std import *
+from migen.fhdl.specials import Tristate
+from migen.genlib.cdc import MultiReg
+from migen.genlib.fsm import FSM, NextState
+from migen.genlib.misc import chooser
+from migen.bank.description import CSRStorage, CSRStatus, AutoCSR
+
+_default_edid = [
+    0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3D, 0x17, 0x32, 0x12, 0x2A, 0x6A, 0xBF, 0x00,
+    0x05, 0x17, 0x01, 0x03, 0x80, 0x28, 0x1E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xB2, 0x0C, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88,
+    0x36, 0x00, 0x28, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x4D, 0x31, 0x20,
+    0x44, 0x56, 0x49, 0x20, 0x6D, 0x69, 0x78, 0x65, 0x72, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
+]
+
+
+class EDID(Module, AutoCSR):
+    def __init__(self, pads, default=_default_edid):
+        self._hpd_notif = CSRStatus()
+        self._hpd_en = CSRStorage()
+        self.specials.mem = Memory(8, 128, init=default)
+
+        ###
+
+        # HPD
+        if hasattr(pads, "hpd_notif"):
+            self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status)
+        else:
+            self.comb += self._hpd_notif.status.eq(1)
+        if hasattr(pads, "hpd_en"):
+            self.comb += pads.hpd_en.eq(self._hpd_en.storage)
+
+        # EDID
+        scl_raw = Signal()
+        sda_i = Signal()
+        sda_raw = Signal()
+        sda_drv = Signal()
+        _sda_drv_reg = Signal()
+        _sda_i_async = Signal()
+        self.sync += _sda_drv_reg.eq(sda_drv)
+        self.specials += [
+            MultiReg(pads.scl, scl_raw),
+            Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
+            MultiReg(_sda_i_async, sda_raw)
+        ]
+
+        scl_i = Signal()
+        samp_count = Signal(6)
+        samp_carry = Signal()
+        self.sync += [
+            Cat(samp_count, samp_carry).eq(samp_count + 1),
+            If(samp_carry,
+                scl_i.eq(scl_raw),
+                sda_i.eq(sda_raw)
+            )
+        ]
+
+        scl_r = Signal()
+        sda_r = Signal()
+        scl_rising = Signal()
+        sda_rising = Signal()
+        sda_falling = Signal()
+        self.sync += [
+            scl_r.eq(scl_i),
+            sda_r.eq(sda_i)
+        ]
+        self.comb += [
+            scl_rising.eq(scl_i & ~scl_r),
+            sda_rising.eq(sda_i & ~sda_r),
+            sda_falling.eq(~sda_i & sda_r)
+        ]
+
+        start = Signal()
+        self.comb += start.eq(scl_i & sda_falling)
+
+        din = Signal(8)
+        counter = Signal(max=9)
+        self.sync += [
+            If(start, counter.eq(0)),
+            If(scl_rising,
+                If(counter == 8,
+                    counter.eq(0)
+                ).Else(
+                    counter.eq(counter + 1),
+                    din.eq(Cat(sda_i, din[:7]))
+                )
+            )
+        ]
+
+        is_read = Signal()
+        update_is_read = Signal()
+        self.sync += If(update_is_read, is_read.eq(din[0]))
+
+        offset_counter = Signal(max=128)
+        oc_load = Signal()
+        oc_inc = Signal()
+        self.sync += [
+            If(oc_load,
+                offset_counter.eq(din)
+            ).Elif(oc_inc,
+                offset_counter.eq(offset_counter + 1)
+            )
+        ]
+        rdport = self.mem.get_port()
+        self.specials += rdport
+        self.comb += rdport.adr.eq(offset_counter)
+        data_bit = Signal()
+
+        zero_drv = Signal()
+        data_drv = Signal()
+        self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))
+
+        data_drv_en = Signal()
+        data_drv_stop = Signal()
+        self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
+        self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
+
+        fsm = FSM()
+        self.submodules += fsm
+
+        fsm.act("WAIT_START")
+        fsm.act("RCV_ADDRESS",
+            If(counter == 8,
+                If(din[1:] == 0x50,
+                    update_is_read.eq(1),
+                    NextState("ACK_ADDRESS0")
+                ).Else(
+                    NextState("WAIT_START")
+                )
+            )
+        )
+        fsm.act("ACK_ADDRESS0",
+            If(~scl_i, NextState("ACK_ADDRESS1"))
+        )
+        fsm.act("ACK_ADDRESS1",
+            zero_drv.eq(1),
+            If(scl_i, NextState("ACK_ADDRESS2"))
+        )
+        fsm.act("ACK_ADDRESS2",
+            zero_drv.eq(1),
+            If(~scl_i,
+                If(is_read,
+                    NextState("READ")
+                ).Else(
+                    NextState("RCV_OFFSET")
+                )
+            )
+        )
+
+        fsm.act("RCV_OFFSET",
+            If(counter == 8,
+                oc_load.eq(1),
+                NextState("ACK_OFFSET0")
+            )
+        )
+        fsm.act("ACK_OFFSET0",
+            If(~scl_i, NextState("ACK_OFFSET1"))
+        )
+        fsm.act("ACK_OFFSET1",
+            zero_drv.eq(1),
+            If(scl_i, NextState("ACK_OFFSET2"))
+        )
+        fsm.act("ACK_OFFSET2",
+            zero_drv.eq(1),
+            If(~scl_i, NextState("RCV_ADDRESS"))
+        )
+
+        fsm.act("READ",
+            If(~scl_i,
+                If(counter == 8,
+                    data_drv_stop.eq(1),
+                    NextState("ACK_READ")
+                ).Else(
+                    data_drv_en.eq(1)
+                )
+            )
+        )
+        fsm.act("ACK_READ",
+            If(scl_rising,
+                oc_inc.eq(1),
+                If(sda_i,
+                    NextState("WAIT_START")
+                ).Else(
+                    NextState("READ")
+                )
+            )
+        )
+
+        for state in fsm.actions.keys():
+            fsm.act(state, If(start, NextState("RCV_ADDRESS")))
+            fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
diff --git a/misoc/video/dvisampler/wer.py b/misoc/video/dvisampler/wer.py
new file mode 100644 (file)
index 0000000..310e6d4
--- /dev/null
@@ -0,0 +1,60 @@
+from migen.fhdl.std import *
+from migen.bank.description import *
+from migen.genlib.misc import optree
+from migen.genlib.cdc import PulseSynchronizer
+
+from misoc.video.dvisampler.common import control_tokens
+
+
+class WER(Module, AutoCSR):
+    def __init__(self, period_bits=24):
+        self.data = Signal(10)
+        self._update = CSR()
+        self._value = CSRStatus(period_bits)
+
+        ###
+
+        # pipeline stage 1
+        # we ignore the 10th (inversion) bit, as it is independent of the transition minimization
+        data_r = Signal(9)
+        self.sync.pix += data_r.eq(self.data[:9])
+
+        # pipeline stage 2
+        transitions = Signal(8)
+        self.comb += [transitions[i].eq(data_r[i] ^ data_r[i+1]) for i in range(8)]
+        transition_count = Signal(max=9)
+        self.sync.pix += transition_count.eq(optree("+", [transitions[i] for i in range(8)]))
+
+        is_control = Signal()
+        self.sync.pix += is_control.eq(optree("|", [data_r == ct for ct in control_tokens]))
+
+        # pipeline stage 3
+        is_error = Signal()
+        self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)
+
+        # counter
+        period_counter = Signal(period_bits)
+        period_done = Signal()
+        self.sync.pix += Cat(period_counter, period_done).eq(period_counter + 1)
+
+        wer_counter = Signal(period_bits)
+        wer_counter_r = Signal(period_bits)
+        wer_counter_r_updated = Signal()
+        self.sync.pix += [
+            wer_counter_r_updated.eq(period_done),
+            If(period_done,
+                wer_counter_r.eq(wer_counter),
+                wer_counter.eq(0)
+            ).Elif(is_error,
+                wer_counter.eq(wer_counter + 1)
+            )
+        ]
+
+        # sync to system clock domain
+        wer_counter_sys = Signal(period_bits)
+        self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
+        self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
+        self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))
+
+        # register interface
+        self.sync += If(self._update.re, self._value.status.eq(wer_counter_sys))
diff --git a/misoc/video/framebuffer/__init__.py b/misoc/video/framebuffer/__init__.py
new file mode 100644 (file)
index 0000000..eec9404
--- /dev/null
@@ -0,0 +1,33 @@
+from migen.fhdl.std import *
+from migen.flow.network import *
+from migen.flow import plumbing
+from migen.bank.description import AutoCSR
+from migen.actorlib import structuring, misc
+
+from misoc.mem.sdram.frontend import dma_lasmi
+from misoc.video.framebuffer.format import bpp, pixel_layout, FrameInitiator, VTG
+from misoc.video.framebuffer.phy import Driver
+
+
+class Framebuffer(Module, AutoCSR):
+    def __init__(self, pads_vga, pads_dvi, lasmim):
+        pack_factor = lasmim.dw//bpp
+
+        g = DataFlowGraph()
+
+        self.fi = FrameInitiator(lasmim.aw, pack_factor)
+
+        intseq = misc.IntSequence(lasmim.aw, lasmim.aw)
+        dma_out = AbstractActor(plumbing.Buffer)
+        g.add_connection(self.fi, intseq, source_subr=self.fi.dma_subr())
+        g.add_pipeline(intseq, AbstractActor(plumbing.Buffer), dma_lasmi.Reader(lasmim), dma_out)
+
+        cast = structuring.Cast(lasmim.dw, pixel_layout(pack_factor), reverse_to=True)
+        vtg = VTG(pack_factor)
+        self.driver = Driver(pack_factor, pads_vga, pads_dvi)
+
+        g.add_connection(self.fi, vtg, source_subr=self.fi.timing_subr, sink_ep="timing")
+        g.add_connection(dma_out, cast)
+        g.add_connection(cast, vtg, sink_ep="pixels")
+        g.add_connection(vtg, self.driver)
+        self.submodules += CompositeActor(g)
diff --git a/misoc/video/framebuffer/dvi.py b/misoc/video/framebuffer/dvi.py
new file mode 100644 (file)
index 0000000..0ba8b4b
--- /dev/null
@@ -0,0 +1,224 @@
+from migen.fhdl.std import *
+from migen.genlib.misc import optree
+
+control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
+
+
+class Encoder(Module):
+    def __init__(self):
+        self.d = Signal(8)
+        self.c = Signal(2)
+        self.de = Signal()
+
+        self.out = Signal(10)
+
+        ###
+
+        # stage 1 - count number of 1s in data
+        d = Signal(8)
+        n1d = Signal(max=9)
+        self.sync += [
+            n1d.eq(optree("+", [self.d[i] for i in range(8)])),
+            d.eq(self.d)
+        ]
+
+        # stage 2 - add 9th bit
+        q_m = Signal(9)
+        q_m8_n = Signal()
+        self.comb += q_m8_n.eq((n1d > 4) | ((n1d == 4) & ~d[0]))
+        for i in range(8):
+            if i:
+                curval = curval ^ d[i] ^ q_m8_n
+            else:
+                curval = d[0]
+            self.sync += q_m[i].eq(curval)
+        self.sync += q_m[8].eq(~q_m8_n)
+
+        # stage 3 - count number of 1s and 0s in q_m[:8]
+        q_m_r = Signal(9)
+        n0q_m = Signal(max=9)
+        n1q_m = Signal(max=9)
+        self.sync += [
+            n0q_m.eq(optree("+", [~q_m[i] for i in range(8)])),
+            n1q_m.eq(optree("+", [q_m[i] for i in range(8)])),
+            q_m_r.eq(q_m)
+        ]
+
+        # stage 4 - final encoding
+        cnt = Signal((6, True))
+
+        s_c = self.c
+        s_de = self.de
+        for p in range(3):
+            new_c = Signal(2)
+            new_de = Signal()
+            self.sync += new_c.eq(s_c), new_de.eq(s_de)
+            s_c, s_de = new_c, new_de
+
+        self.sync += If(s_de,
+                If((cnt == 0) | (n1q_m == n0q_m),
+                    self.out[9].eq(~q_m_r[8]),
+                    self.out[8].eq(q_m_r[8]),
+                    If(q_m_r[8],
+                        self.out[:8].eq(q_m_r[:8]),
+                        cnt.eq(cnt + n1q_m - n0q_m)
+                    ).Else(
+                        self.out[:8].eq(~q_m_r[:8]),
+                        cnt.eq(cnt + n0q_m - n1q_m)
+                    )
+                ).Else(
+                    If((~cnt[5] & (n1q_m > n0q_m)) | (cnt[5] & (n0q_m > n1q_m)),
+                        self.out[9].eq(1),
+                        self.out[8].eq(q_m_r[8]),
+                        self.out[:8].eq(~q_m_r[:8]),
+                        cnt.eq(cnt + Cat(0, q_m_r[8]) + n0q_m - n1q_m)
+                    ).Else(
+                        self.out[9].eq(0),
+                        self.out[8].eq(q_m_r[8]),
+                        self.out[:8].eq(q_m_r[:8]),
+                        cnt.eq(cnt - Cat(0, ~q_m_r[8]) + n1q_m - n0q_m)
+                    )
+                )
+            ).Else(
+                self.out.eq(Array(control_tokens)[s_c]),
+                cnt.eq(0)
+            )
+
+
+class _EncoderSerializer(Module):
+    def __init__(self, serdesstrobe, pad_p, pad_n):
+        self.submodules.encoder = RenameClockDomains(Encoder(), "pix")
+        self.d, self.c, self.de = self.encoder.d, self.encoder.c, self.encoder.de
+
+        ###
+
+        # 2X soft serialization
+        ed_2x = Signal(5)
+        self.sync.pix2x += ed_2x.eq(Mux(ClockSignal("pix"), self.encoder.out[:5], self.encoder.out[5:]))
+
+        # 5X hard serialization
+        cascade_di = Signal()
+        cascade_do = Signal()
+        cascade_ti = Signal()
+        cascade_to = Signal()
+        pad_se = Signal()
+        self.specials += [
+            Instance("OSERDES2",
+                     p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
+                     p_SERDES_MODE="MASTER", p_OUTPUT_MODE="DIFFERENTIAL",
+
+                     o_OQ=pad_se,
+                     i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
+                     i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
+                     i_D1=ed_2x[4], i_D2=0, i_D3=0, i_D4=0,
+                     i_T1=0, i_T2=0, i_T3=0, i_T4=0,
+                     i_TRAIN=0, i_TCE=1,
+                     i_SHIFTIN1=1, i_SHIFTIN2=1,
+                     i_SHIFTIN3=cascade_do, i_SHIFTIN4=cascade_to,
+                     o_SHIFTOUT1=cascade_di, o_SHIFTOUT2=cascade_ti),
+            Instance("OSERDES2",
+                     p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
+                     p_SERDES_MODE="SLAVE", p_OUTPUT_MODE="DIFFERENTIAL",
+
+                     i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
+                     i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
+                     i_D1=ed_2x[0], i_D2=ed_2x[1], i_D3=ed_2x[2], i_D4=ed_2x[3],
+                     i_T1=0, i_T2=0, i_T3=0, i_T4=0,
+                     i_TRAIN=0, i_TCE=1,
+                     i_SHIFTIN1=cascade_di, i_SHIFTIN2=cascade_ti,
+                     i_SHIFTIN3=1, i_SHIFTIN4=1,
+                     o_SHIFTOUT3=cascade_do, o_SHIFTOUT4=cascade_to),
+            Instance("OBUFDS", i_I=pad_se, o_O=pad_p, o_OB=pad_n)
+        ]
+
+
+class PHY(Module):
+    def __init__(self, serdesstrobe, pads):
+        self.hsync = Signal()
+        self.vsync = Signal()
+        self.de = Signal()
+        self.r = Signal(8)
+        self.g = Signal(8)
+        self.b = Signal(8)
+
+        ###
+
+        self.submodules.es0 = _EncoderSerializer(serdesstrobe, pads.data0_p, pads.data0_n)
+        self.submodules.es1 = _EncoderSerializer(serdesstrobe, pads.data1_p, pads.data1_n)
+        self.submodules.es2 = _EncoderSerializer(serdesstrobe, pads.data2_p, pads.data2_n)
+        self.comb += [
+            self.es0.d.eq(self.r),
+            self.es1.d.eq(self.g),
+            self.es2.d.eq(self.b),
+            self.es0.c.eq(Cat(self.hsync, self.vsync)),
+            self.es1.c.eq(0),
+            self.es2.c.eq(0),
+            self.es0.de.eq(self.de),
+            self.es1.de.eq(self.de),
+            self.es2.de.eq(self.de),
+        ]
+
+
+class _EncoderTB(Module):
+    def __init__(self, inputs):
+        self.outs = []
+        self._iter_inputs = iter(inputs)
+        self._end_cycle = None
+        self.submodules.dut = Encoder()
+        self.comb += self.dut.de.eq(1)
+
+    def do_simulation(self, selfp):
+        if self._end_cycle is None:
+            try:
+                nv = next(self._iter_inputs)
+            except StopIteration:
+                self._end_cycle = selfp.simulator.cycle_counter + 4
+            else:
+                selfp.dut.d = nv
+        if selfp.simulator.cycle_counter == self._end_cycle:
+            raise StopSimulation
+        if selfp.simulator.cycle_counter > 4:
+            self.outs.append(selfp.dut.out)
+
+
+def _bit(i, n):
+    return (i >> n) & 1
+
+
+def _decode_tmds(b):
+    try:
+        c = control_tokens.index(b)
+        de = False
+    except ValueError:
+        c = 0
+        de = True
+    vsync = bool(c & 2)
+    hsync = bool(c & 1)
+
+    value = _bit(b, 0) ^ _bit(b, 9)
+    for i in range(1, 8):
+        value |= (_bit(b, i) ^ _bit(b, i-1) ^ (~_bit(b, 8) & 1)) << i
+
+    return de, hsync, vsync, value
+
+if __name__ == "__main__":
+    from migen.sim.generic import run_simulation
+    from random import Random
+
+    rng = Random(788)
+    test_list = [rng.randrange(256) for i in range(500)]
+    tb = _EncoderTB(test_list)
+    run_simulation(tb)
+
+    check = [_decode_tmds(out)[3] for out in tb.outs]
+    assert(check == test_list)
+
+    nb0 = 0
+    nb1 = 0
+    for out in tb.outs:
+        for i in range(10):
+            if _bit(out, i):
+                nb1 += 1
+            else:
+                nb0 += 1
+    print("0/1: {}/{} ({:.2f})".format(nb0, nb1, nb0/nb1))
diff --git a/misoc/video/framebuffer/format.py b/misoc/video/framebuffer/format.py
new file mode 100644 (file)
index 0000000..e3a3931
--- /dev/null
@@ -0,0 +1,150 @@
+from migen.fhdl.std import *
+from migen.flow.actor import *
+from migen.bank.description import CSRStorage
+from migen.genlib.record import Record
+from migen.genlib.fsm import FSM, NextState
+from migen.actorlib import spi
+
+_hbits = 12
+_vbits = 12
+
+bpp = 32
+bpc = 10
+pixel_layout_s = [
+    ("pad", bpp-3*bpc),
+    ("r", bpc),
+    ("g", bpc),
+    ("b", bpc)
+]
+
+
+def pixel_layout(pack_factor):
+    return [("p"+str(i), pixel_layout_s) for i in range(pack_factor)]
+
+bpc_phy = 8
+phy_layout_s = [
+    ("r", bpc_phy),
+    ("g", bpc_phy),
+    ("b", bpc_phy)
+]
+
+
+def phy_layout(pack_factor):
+    r = [("hsync", 1), ("vsync", 1), ("de", 1)]
+    for i in range(pack_factor):
+        r.append(("p"+str(i), phy_layout_s))
+    return r
+
+
+class FrameInitiator(spi.SingleGenerator):
+    def __init__(self, bus_aw, pack_factor, ndmas=1):
+        h_alignment_bits = log2_int(pack_factor)
+        hbits_dyn = _hbits - h_alignment_bits
+        bus_alignment_bits = h_alignment_bits + log2_int(bpp//8)
+        layout = [
+            ("hres", hbits_dyn, 640, h_alignment_bits),
+            ("hsync_start", hbits_dyn, 656, h_alignment_bits),
+            ("hsync_end", hbits_dyn, 752, h_alignment_bits),
+            ("hscan", hbits_dyn, 800, h_alignment_bits),
+
+            ("vres", _vbits, 480),
+            ("vsync_start", _vbits, 492),
+            ("vsync_end", _vbits, 494),
+            ("vscan", _vbits, 525),
+
+            ("length", bus_aw + bus_alignment_bits, 640*480*bpp//8, bus_alignment_bits)
+        ]
+        layout += [("base"+str(i), bus_aw + bus_alignment_bits, 0, bus_alignment_bits)
+            for i in range(ndmas)]
+        spi.SingleGenerator.__init__(self, layout, spi.MODE_CONTINUOUS)
+
+    timing_subr = ["hres", "hsync_start", "hsync_end", "hscan",
+        "vres", "vsync_start", "vsync_end", "vscan"]
+
+    def dma_subr(self, i=0):
+        return ["length", "base"+str(i)]
+
+
+class VTG(Module):
+    def __init__(self, pack_factor):
+        hbits_dyn = _hbits - log2_int(pack_factor)
+        timing_layout = [
+            ("hres", hbits_dyn),
+            ("hsync_start", hbits_dyn),
+            ("hsync_end", hbits_dyn),
+            ("hscan", hbits_dyn),
+            ("vres", _vbits),
+            ("vsync_start", _vbits),
+            ("vsync_end", _vbits),
+            ("vscan", _vbits)]
+        self.timing = Sink(timing_layout)
+        self.pixels = Sink(pixel_layout(pack_factor))
+        self.phy = Source(phy_layout(pack_factor))
+        self.busy = Signal()
+
+        ###
+
+        hactive = Signal()
+        vactive = Signal()
+        active = Signal()
+
+        hcounter = Signal(hbits_dyn)
+        vcounter = Signal(_vbits)
+
+        skip = bpc - bpc_phy
+        self.comb += [
+            active.eq(hactive & vactive),
+            If(active,
+                [getattr(getattr(self.phy.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
+                    for p in ["p"+str(i) for i in range(pack_factor)] for c in ["r", "g", "b"]],
+                self.phy.de.eq(1)
+            ),
+            self.pixels.ack.eq(self.phy.ack & active)
+        ]
+
+        load_timing = Signal()
+        tr = Record(timing_layout)
+        self.sync += If(load_timing, tr.eq(self.timing.payload))
+
+        generate_en = Signal()
+        generate_frame_done = Signal()
+        self.sync += [
+            generate_frame_done.eq(0),
+            If(generate_en,
+                hcounter.eq(hcounter + 1),
+
+                If(hcounter == 0, hactive.eq(1)),
+                If(hcounter == tr.hres, hactive.eq(0)),
+                If(hcounter == tr.hsync_start, self.phy.hsync.eq(1)),
+                If(hcounter == tr.hsync_end, self.phy.hsync.eq(0)),
+                If(hcounter == tr.hscan,
+                    hcounter.eq(0),
+                    If(vcounter == tr.vscan,
+                        vcounter.eq(0),
+                        generate_frame_done.eq(1)
+                    ).Else(
+                        vcounter.eq(vcounter + 1)
+                    )
+                ),
+
+                If(vcounter == 0, vactive.eq(1)),
+                If(vcounter == tr.vres, vactive.eq(0)),
+                If(vcounter == tr.vsync_start, self.phy.vsync.eq(1)),
+                If(vcounter == tr.vsync_end, self.phy.vsync.eq(0))
+            )
+        ]
+
+        self.submodules.fsm = FSM()
+        self.fsm.act("GET_TIMING",
+            self.timing.ack.eq(1),
+            load_timing.eq(1),
+            If(self.timing.stb, NextState("GENERATE"))
+        )
+        self.fsm.act("GENERATE",
+            self.busy.eq(1),
+            If(~active | self.pixels.stb,
+                self.phy.stb.eq(1),
+                If(self.phy.ack, generate_en.eq(1))
+            ),
+            If(generate_frame_done,    NextState("GET_TIMING"))
+        )
diff --git a/misoc/video/framebuffer/phy.py b/misoc/video/framebuffer/phy.py
new file mode 100644 (file)
index 0000000..d77426c
--- /dev/null
@@ -0,0 +1,222 @@
+from migen.fhdl.std import *
+from migen.genlib.fifo import AsyncFIFO
+from migen.genlib.cdc import MultiReg
+from migen.bank.description import *
+from migen.flow.actor import *
+
+from misoc.video.framebuffer.format import bpc_phy, phy_layout
+from misoc.video.framebuffer import dvi
+
+
+class _FIFO(Module):
+    def __init__(self, pack_factor):
+        self.phy = Sink(phy_layout(pack_factor))
+        self.busy = Signal()
+
+        self.pix_hsync = Signal()
+        self.pix_vsync = Signal()
+        self.pix_de = Signal()
+        self.pix_r = Signal(bpc_phy)
+        self.pix_g = Signal(bpc_phy)
+        self.pix_b = Signal(bpc_phy)
+
+        ###
+
+        fifo = RenameClockDomains(AsyncFIFO(phy_layout(pack_factor), 512),
+            {"write": "sys", "read": "pix"})
+        self.submodules += fifo
+        self.comb += [
+            self.phy.ack.eq(fifo.writable),
+            fifo.we.eq(self.phy.stb),
+            fifo.din.eq(self.phy.payload),
+            self.busy.eq(0)
+        ]
+
+        unpack_counter = Signal(max=pack_factor)
+        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
+        self.sync.pix += [
+            unpack_counter.eq(unpack_counter + 1),
+            self.pix_hsync.eq(fifo.dout.hsync),
+            self.pix_vsync.eq(fifo.dout.vsync),
+            self.pix_de.eq(fifo.dout.de)
+        ]
+        for i in range(pack_factor):
+            pixel = getattr(fifo.dout, "p"+str(i))
+            self.sync.pix += If(unpack_counter == i,
+                self.pix_r.eq(pixel.r),
+                self.pix_g.eq(pixel.g),
+                self.pix_b.eq(pixel.b)
+            )
+        self.comb += fifo.re.eq(unpack_counter == (pack_factor - 1))
+
+
+# This assumes a 50MHz base clock
+class _Clocking(Module, AutoCSR):
+    def __init__(self, pads_vga, pads_dvi):
+        self._cmd_data = CSRStorage(10)
+        self._send_cmd_data = CSR()
+        self._send_go = CSR()
+        self._status = CSRStatus(4)
+
+        self.clock_domains.cd_pix = ClockDomain(reset_less=True)
+        if pads_dvi is not None:
+            self._pll_reset = CSRStorage()
+            self._pll_adr = CSRStorage(5)
+            self._pll_dat_r = CSRStatus(16)
+            self._pll_dat_w = CSRStorage(16)
+            self._pll_read = CSR()
+            self._pll_write = CSR()
+            self._pll_drdy = CSRStatus()
+
+            self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
+            self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
+            self.serdesstrobe = Signal()
+
+        ###
+
+        # Generate 1x pixel clock
+        clk_pix_unbuffered = Signal()
+        pix_progdata = Signal()
+        pix_progen = Signal()
+        pix_progdone = Signal()
+        pix_locked = Signal()
+        self.specials += Instance("DCM_CLKGEN",
+                                  p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=1.0, p_CLKFX_MULTIPLY=2,
+                                  p_CLKIN_PERIOD=20.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
+
+                                  i_CLKIN=ClockSignal("base50"), o_CLKFX=clk_pix_unbuffered,
+                                  i_PROGCLK=ClockSignal(), i_PROGDATA=pix_progdata, i_PROGEN=pix_progen,
+                                  o_PROGDONE=pix_progdone, o_LOCKED=pix_locked,
+                                  i_FREEZEDCM=0, i_RST=ResetSignal())
+
+        remaining_bits = Signal(max=11)
+        transmitting = Signal()
+        self.comb += transmitting.eq(remaining_bits != 0)
+        sr = Signal(10)
+        self.sync += [
+            If(self._send_cmd_data.re,
+                remaining_bits.eq(10),
+                sr.eq(self._cmd_data.storage)
+            ).Elif(transmitting,
+                remaining_bits.eq(remaining_bits - 1),
+                sr.eq(sr[1:])
+            )
+        ]
+        self.comb += [
+            pix_progdata.eq(transmitting & sr[0]),
+            pix_progen.eq(transmitting | self._send_go.re)
+        ]
+
+        # enforce gap between commands
+        busy_counter = Signal(max=14)
+        busy = Signal()
+        self.comb += busy.eq(busy_counter != 0)
+        self.sync += If(self._send_cmd_data.re,
+                busy_counter.eq(13)
+            ).Elif(busy,
+                busy_counter.eq(busy_counter - 1)
+            )
+
+        mult_locked = Signal()
+        self.comb += self._status.status.eq(Cat(busy, pix_progdone, pix_locked, mult_locked))
+
+        # Clock multiplication and buffering
+        if pads_dvi is None:
+            # Just buffer 1x pixel clock
+            self.specials += Instance("BUFG", i_I=clk_pix_unbuffered, o_O=self.cd_pix.clk)
+            self.comb += mult_locked.eq(pix_locked)
+        else:
+            # Route unbuffered 1x pixel clock to PLL
+            # Generate 1x, 2x and 10x IO pixel clocks
+            clkfbout = Signal()
+            pll_locked = Signal()
+            pll_clk0 = Signal()
+            pll_clk1 = Signal()
+            pll_clk2 = Signal()
+            locked_async = Signal()
+            pll_drdy = Signal()
+            self.sync += If(self._pll_read.re | self._pll_write.re,
+                self._pll_drdy.status.eq(0)
+            ).Elif(pll_drdy,
+                self._pll_drdy.status.eq(1)
+            )
+            self.specials += [
+                Instance("PLL_ADV",
+                         p_CLKFBOUT_MULT=10,
+                         p_CLKOUT0_DIVIDE=1,   # pix10x
+                         p_CLKOUT1_DIVIDE=5,   # pix2x
+                         p_CLKOUT2_DIVIDE=10,  # pix
+                         p_COMPENSATION="INTERNAL",
+
+                         i_CLKINSEL=1,
+                         i_CLKIN1=clk_pix_unbuffered,
+                         o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
+                         o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
+                         o_LOCKED=pll_locked,
+                         i_RST=~pix_locked | self._pll_reset.storage,
+
+                         i_DADDR=self._pll_adr.storage,
+                         o_DO=self._pll_dat_r.status,
+                         i_DI=self._pll_dat_w.storage,
+                         i_DEN=self._pll_read.re | self._pll_write.re,
+                         i_DWE=self._pll_write.re,
+                         o_DRDY=pll_drdy,
+                         i_DCLK=ClockSignal()),
+                Instance("BUFPLL", p_DIVIDE=5,
+                         i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
+                         o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
+                Instance("BUFG", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
+                Instance("BUFG", name="dviout_pix_bufg", i_I=pll_clk2, o_O=self.cd_pix.clk),
+                MultiReg(locked_async, mult_locked, "sys")
+            ]
+
+        # Drive VGA/DVI clock pads
+        if pads_vga is not None:
+            self.specials += Instance("ODDR2",
+                                      p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
+                                      o_Q=pads_vga.clk,
+                                      i_C0=ClockSignal("pix"),
+                                      i_C1=~ClockSignal("pix"),
+                                      i_CE=1, i_D0=1, i_D1=0,
+                                      i_R=0, i_S=0)
+        if pads_dvi is not None:
+            dvi_clk_se = Signal()
+            self.specials += Instance("ODDR2",
+                                      p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
+                                      o_Q=dvi_clk_se,
+                                      i_C0=ClockSignal("pix"),
+                                      i_C1=~ClockSignal("pix"),
+                                      i_CE=1, i_D0=1, i_D1=0,
+                                      i_R=0, i_S=0)
+            self.specials += Instance("OBUFDS", i_I=dvi_clk_se,
+                                      o_O=pads_dvi.clk_p, o_OB=pads_dvi.clk_n)
+
+
+class Driver(Module, AutoCSR):
+    def __init__(self, pack_factor, pads_vga, pads_dvi):
+        fifo = _FIFO(pack_factor)
+        self.submodules += fifo
+        self.phy = fifo.phy
+        self.busy = fifo.busy
+
+        self.submodules.clocking = _Clocking(pads_vga, pads_dvi)
+
+        if pads_vga is not None:
+            self.comb += [
+                pads_vga.hsync_n.eq(~fifo.pix_hsync),
+                pads_vga.vsync_n.eq(~fifo.pix_vsync),
+                pads_vga.r.eq(fifo.pix_r),
+                pads_vga.g.eq(fifo.pix_g),
+                pads_vga.b.eq(fifo.pix_b),
+                pads_vga.psave_n.eq(1)
+            ]
+        if pads_dvi is not None:
+            self.submodules.dvi_phy = dvi.PHY(self.clocking.serdesstrobe, pads_dvi)
+            self.comb += [
+                self.dvi_phy.hsync.eq(fifo.pix_hsync),
+                self.dvi_phy.vsync.eq(fifo.pix_vsync),
+                self.dvi_phy.de.eq(fifo.pix_de),
+                self.dvi_phy.r.eq(fifo.pix_r),
+                self.dvi_phy.g.eq(fifo.pix_g),
+                self.dvi_phy.b.eq(fifo.pix_b)
+            ]
diff --git a/misoclib/__init__.py b/misoclib/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/com/__init__.py b/misoclib/com/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/com/gpio.py b/misoclib/com/gpio.py
deleted file mode 100644 (file)
index 88a4904..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-
-
-class GPIOIn(Module, AutoCSR):
-    def __init__(self, signal):
-        self._in = CSRStatus(flen(signal))
-        self.specials += MultiReg(signal, self._in.status)
-
-
-class GPIOOut(Module, AutoCSR):
-    def __init__(self, signal):
-        self._out = CSRStorage(flen(signal))
-        self.comb += signal.eq(self._out.storage)
-
-
-class GPIOInOut(Module):
-    def __init__(self, in_signal, out_signal):
-        self.submodules.gpio_in = GPIOIn(in_signal)
-        self.submodules.gpio_out = GPIOOut(out_signal)
-
-    def get_csrs(self):
-        return self.gpio_in.get_csrs() + self.gpio_out.get_csrs()
-
-
-class Blinker(Module):
-    def __init__(self, signal, divbits=26):
-        counter = Signal(divbits)
-        self.comb += signal.eq(counter[divbits-1])
-        self.sync += counter.eq(counter + 1)
diff --git a/misoclib/com/liteethmini/LICENSE b/misoclib/com/liteethmini/LICENSE
deleted file mode 100644 (file)
index cbbfe8b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Unless otherwise noted, LiteEth is copyright (C) 2015 Florent Kermarrec.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-Other authors retain ownership of their contributions. If a submission can
-reasonably be considered independently copyrightable, it's yours and we
-encourage you to claim it with appropriate copyright notices. This submission
-then falls under the "otherwise noted" category. All submissions are strongly
-encouraged to use the two-clause BSD license reproduced above.
diff --git a/misoclib/com/liteethmini/README b/misoclib/com/liteethmini/README
deleted file mode 100644 (file)
index 595d2fc..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-         __   _ __      ______  __   __  ____      _
-        / /  (_) /____ / __/ /_/ /  /  |/  (_)__  (_)
-       / /__/ / __/ -_) _// __/ _ \/ /|_/ / / _ \/ /
-      /____/_/\__/\__/___/\__/_//_/_/  /_/_/_//_/_/
-
-        Copyright 2012-2015 / EnjoyDigital / M-Labs Ltd
-
-   A small footprint and configurable minimal Ethernet core
-                  powered by Migen
-
-[> Intro
----------
-LiteEthMini is a subset of LiteEth (https://github.com/enjoy-digital/liteeth)
-intended to be used with a CPU and a software stack.
-
-[> Features
------------
-- Ethernet MAC with various various PHYs (GMII, MII, RGMII, Loopback)
-- SRAM storage and wishbone interface
-
-[> Possible improvements
--------------------------
-- add DMA interface to MAC
-- add SGMII PHY
-- ... See below Support and consulting :)
-
-If you want to support these features, please contact us at florent [AT]
-enjoy-digital.fr. You can also contact our partner on the public mailing list
-devel [AT] lists.m-labs.hk.
-
-[> License
------------
-LiteEthMini is released under the very permissive two-clause BSD license. Under
-the terms of this license, you are authorized to use LiteEthMini for closed-source
-proprietary designs.
-Even though we do not require you to do so, those things are awesome, so please
-do them if possible:
- - tell us that you are using LiteEthMini
- - cite LiteEthMini in publications related to research it has helped
- - send us feedback and suggestions for improvements
- - send us bug reports when something goes wrong
- - send us the modifications and improvements you have done to LiteEthMini.
-
-[> Support and consulting
---------------------------
-We love open-source hardware and like sharing our designs with others.
-
-LiteEthMini is mainly developed and maintained by EnjoyDigital.
-
-If you would like to know more about LiteEthMini or if you are already a happy
-user and would like to extend it for your needs, EnjoyDigital can provide standard
-commercial support as well as consulting services.
-
-So feel free to contact us, we'd love to work with you! (and eventually shorten
-the list of the possible improvements :)
-
-[> Contact
-E-mail: florent [AT] enjoy-digital.fr
\ No newline at end of file
diff --git a/misoclib/com/liteethmini/__init__.py b/misoclib/com/liteethmini/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/com/liteethmini/common.py b/misoclib/com/liteethmini/common.py
deleted file mode 100644 (file)
index a5f0b3f..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-import math
-from collections import OrderedDict
-
-from migen.fhdl.std import *
-from migen.genlib.resetsync import AsyncResetSynchronizer
-from migen.genlib.record import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import chooser, reverse_bytes, FlipFlop, Counter, WaitTimer
-from migen.flow.actor import *
-from migen.actorlib.structuring import Converter, Pipeline
-from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
-from migen.actorlib.packet import *
-from migen.bank.description import *
-
-class Port:
-    def connect(self, port):
-        r = [
-            Record.connect(self.source, port.sink),
-            Record.connect(port.source, self.sink)
-        ]
-        return r
-
-eth_mtu = 1532
-eth_min_len = 46
-eth_interpacket_gap = 12
-eth_preamble = 0xD555555555555555
-buffer_depth = 2**log2_int(eth_mtu, need_pow2=False)
-
-def eth_phy_description(dw):
-    payload_layout = [
-        ("data", dw),
-        ("last_be", dw//8),
-        ("error", dw//8)
-    ]
-    return EndpointDescription(payload_layout, packetized=True)
-
-
-def eth_mac_description(dw):
-    payload_layout = mac_header.get_layout() + [
-        ("data", dw),
-        ("last_be", dw//8),
-        ("error", dw//8)
-    ]
-    return EndpointDescription(payload_layout, packetized=True)
diff --git a/misoclib/com/liteethmini/mac/__init__.py b/misoclib/com/liteethmini/mac/__init__.py
deleted file mode 100644 (file)
index 958f84a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-from misoclib.com.liteethmini.common import *
-from misoclib.com.liteethmini.mac.core import LiteEthMACCore
-from misoclib.com.liteethmini.mac.frontend.wishbone import LiteEthMACWishboneInterface
-
-
-class LiteEthMAC(Module, AutoCSR):
-    def __init__(self, phy, dw,
-                 interface="wishbone",
-                 endianness="big",
-                 with_preamble_crc=True):
-        self.submodules.core = LiteEthMACCore(phy, dw, endianness, with_preamble_crc)
-        self.csrs = []
-        if interface == "wishbone":
-            self.submodules.interface = LiteEthMACWishboneInterface(dw, 2, 2)
-            self.comb += Port.connect(self.interface, self.core)
-            self.ev, self.bus = self.interface.sram.ev, self.interface.bus
-            self.csrs = self.interface.get_csrs() + self.core.get_csrs()
-        else:
-            raise NotImplementedError
-
-    def get_csrs(self):
-        return self.csrs
diff --git a/misoclib/com/liteethmini/mac/core/__init__.py b/misoclib/com/liteethmini/mac/core/__init__.py
deleted file mode 100644 (file)
index 99c7436..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-from misoclib.com.liteethmini.common import *
-from misoclib.com.liteethmini.mac.core import gap, preamble, crc, padding, last_be
-from misoclib.com.liteethmini.phy.sim import LiteEthPHYSim
-from misoclib.com.liteethmini.phy.mii import LiteEthPHYMII
-
-
-class LiteEthMACCore(Module, AutoCSR):
-    def __init__(self, phy, dw, endianness="big",
-            with_preamble_crc=True,
-            with_padding=True):
-        if dw < phy.dw:
-            raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
-
-        rx_pipeline = [phy]
-        tx_pipeline = [phy]
-
-        # Interpacket gap
-        tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
-        rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
-        self.submodules += RenameClockDomains(tx_gap_inserter, "eth_tx")
-        self.submodules += RenameClockDomains(rx_gap_checker, "eth_rx")
-
-        tx_pipeline += [tx_gap_inserter]
-        rx_pipeline += [rx_gap_checker]
-
-        # Preamble / CRC
-        if isinstance(phy, LiteEthPHYSim):
-            # In simulation, avoid CRC/Preamble to enable direct connection
-            # to the Ethernet tap.
-            self._preamble_crc = CSRStatus(reset=1)
-        elif with_preamble_crc:
-            self._preamble_crc = CSRStatus(reset=1)
-            # Preamble insert/check
-            preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
-            preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
-            self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
-            self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
-
-            # CRC insert/check
-            crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
-            crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
-            self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
-            self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
-
-            tx_pipeline += [preamble_inserter, crc32_inserter]
-            rx_pipeline += [preamble_checker, crc32_checker]
-
-        # Padding
-        if with_padding:
-            padding_inserter = padding.LiteEthMACPaddingInserter(phy.dw, 60)
-            padding_checker = padding.LiteEthMACPaddingChecker(phy.dw, 60)
-            self.submodules += RenameClockDomains(padding_inserter, "eth_tx")
-            self.submodules += RenameClockDomains(padding_checker, "eth_rx")
-
-            tx_pipeline += [padding_inserter]
-            rx_pipeline += [padding_checker]
-
-        # Delimiters
-        if dw != 8:
-            tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
-            rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
-            self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
-            self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
-
-            tx_pipeline += [tx_last_be]
-            rx_pipeline += [rx_last_be]
-
-        # Converters
-        if dw != phy.dw:
-            reverse = endianness == "big"
-            tx_converter = Converter(eth_phy_description(dw),
-                                     eth_phy_description(phy.dw),
-                                     reverse=reverse)
-            rx_converter = Converter(eth_phy_description(phy.dw),
-                                     eth_phy_description(dw),
-                                     reverse=reverse)
-            self.submodules += RenameClockDomains(tx_converter, "eth_tx")
-            self.submodules += RenameClockDomains(rx_converter, "eth_rx")
-
-            tx_pipeline += [tx_converter]
-            rx_pipeline += [rx_converter]
-
-        # Cross Domain Crossing
-        if isinstance(phy, LiteEthPHYMII):
-            fifo_depth = 8
-        else:
-            fifo_depth = 64
-        tx_cdc = AsyncFIFO(eth_phy_description(dw), fifo_depth)
-        rx_cdc = AsyncFIFO(eth_phy_description(dw), fifo_depth)
-        self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
-        self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
-
-        tx_pipeline += [tx_cdc]
-        rx_pipeline += [rx_cdc]
-
-        # Graph
-        self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
-        self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
-
-        self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
diff --git a/misoclib/com/liteethmini/mac/core/crc.py b/misoclib/com/liteethmini/mac/core/crc.py
deleted file mode 100644 (file)
index e06b928..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthMACCRCEngine(Module):
-    """Cyclic Redundancy Check Engine
-
-    Compute next CRC value from last CRC value and data input using
-    an optimized asynchronous LFSR.
-
-    Parameters
-    ----------
-    data_width : int
-        Width of the data bus.
-    width : int
-        Width of the CRC.
-    polynom : int
-        Polynom of the CRC (ex: 0x04C11DB7 for IEEE 802.3 CRC)
-
-    Attributes
-    ----------
-    data : in
-        Data input.
-    last : in
-        last CRC value.
-    next :
-        next CRC value.
-    """
-    def __init__(self, data_width, width, polynom):
-        self.data = Signal(data_width)
-        self.last = Signal(width)
-        self.next = Signal(width)
-
-        # # #
-
-        def _optimize_eq(l):
-            """
-            Replace even numbers of XORs in the equation
-            with an equivalent XOR
-            """
-            d = OrderedDict()
-            for e in l:
-                if e in d:
-                    d[e] += 1
-                else:
-                    d[e] = 1
-            r = []
-            for key, value in d.items():
-                if value%2 != 0:
-                    r.append(key)
-            return r
-
-        # compute and optimize CRC's LFSR
-        curval = [[("state", i)] for i in range(width)]
-        for i in range(data_width):
-            feedback = curval.pop() + [("din", i)]
-            for j in range(width-1):
-                if (polynom & (1<<(j+1))):
-                    curval[j] += feedback
-                curval[j] = _optimize_eq(curval[j])
-            curval.insert(0, feedback)
-
-        # implement logic
-        for i in range(width):
-            xors = []
-            for t, n in curval[i]:
-                if t == "state":
-                    xors += [self.last[n]]
-                elif t == "din":
-                    xors += [self.data[n]]
-            self.comb += self.next[i].eq(optree("^", xors))
-
-
-@DecorateModule(InsertReset)
-@DecorateModule(InsertCE)
-class LiteEthMACCRC32(Module):
-    """IEEE 802.3 CRC
-
-    Implement an IEEE 802.3 CRC generator/checker.
-
-    Parameters
-    ----------
-    data_width : int
-        Width of the data bus.
-
-    Attributes
-    ----------
-    d : in
-        Data input.
-    value : out
-        CRC value (used for generator).
-    error : out
-        CRC error (used for checker).
-    """
-    width = 32
-    polynom = 0x04C11DB7
-    init = 2**width-1
-    check = 0xC704DD7B
-    def __init__(self, data_width):
-        self.data = Signal(data_width)
-        self.value = Signal(self.width)
-        self.error = Signal()
-
-        # # #
-
-        self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
-        reg = Signal(self.width, reset=self.init)
-        self.sync += reg.eq(self.engine.next)
-        self.comb += [
-            self.engine.data.eq(self.data),
-            self.engine.last.eq(reg),
-
-            self.value.eq(~reg[::-1]),
-            self.error.eq(self.engine.next != self.check)
-        ]
-
-
-class LiteEthMACCRCInserter(Module):
-    """CRC Inserter
-
-    Append a CRC at the end of each packet.
-
-    Parameters
-    ----------
-    description : description
-        description of the dataflow.
-
-    Attributes
-    ----------
-    sink : in
-        Packets input without CRC.
-    source : out
-        Packets output with CRC.
-    """
-    def __init__(self, crc_class, description):
-        self.sink = sink = Sink(description)
-        self.source = source = Source(description)
-        self.busy = Signal()
-
-        # # #
-
-        dw = flen(sink.data)
-        crc = crc_class(dw)
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += crc, fsm
-
-        fsm.act("IDLE",
-            crc.reset.eq(1),
-            sink.ack.eq(1),
-            If(sink.stb & sink.sop,
-                sink.ack.eq(0),
-                NextState("COPY"),
-            )
-        )
-        fsm.act("COPY",
-            crc.ce.eq(sink.stb & source.ack),
-            crc.data.eq(sink.data),
-            Record.connect(sink, source),
-            source.eop.eq(0),
-            If(sink.stb & sink.eop & source.ack,
-                NextState("INSERT"),
-            )
-        )
-        ratio = crc.width//dw
-        if ratio > 1:
-            cnt = Signal(max=ratio, reset=ratio-1)
-            cnt_done = Signal()
-            fsm.act("INSERT",
-                source.stb.eq(1),
-                chooser(crc.value, cnt, source.data, reverse=True),
-                If(cnt_done,
-                    source.eop.eq(1),
-                    If(source.ack, NextState("IDLE"))
-                )
-            )
-            self.comb += cnt_done.eq(cnt == 0)
-            self.sync += \
-                If(fsm.ongoing("IDLE"),
-                    cnt.eq(cnt.reset)
-                ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
-                    cnt.eq(cnt - source.ack)
-                )
-        else:
-            fsm.act("INSERT",
-                source.stb.eq(1),
-                source.eop.eq(1),
-                source.data.eq(crc.value),
-                If(source.ack, NextState("IDLE"))
-            )
-        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
-
-
-class LiteEthMACCRC32Inserter(LiteEthMACCRCInserter):
-    def __init__(self, description):
-        LiteEthMACCRCInserter.__init__(self, LiteEthMACCRC32, description)
-
-
-class LiteEthMACCRCChecker(Module):
-    """CRC Checker
-
-    Check CRC at the end of each packet.
-
-    Parameters
-    ----------
-    description : description
-        description of the dataflow.
-
-    Attributes
-    ----------
-    sink : in
-        Packets input with CRC.
-    source : out
-        Packets output without CRC and "error" set to 0
-        on eop when CRC OK / set to 1 when CRC KO.
-    """
-    def __init__(self, crc_class, description):
-        self.sink = sink = Sink(description)
-        self.source = source = Source(description)
-        self.busy = Signal()
-
-        # # #
-
-        dw = flen(sink.data)
-        crc = crc_class(dw)
-        self.submodules += crc
-        ratio = crc.width//dw
-
-        error = Signal()
-        fifo = InsertReset(SyncFIFO(description, ratio + 1))
-        self.submodules += fifo
-
-        fsm = FSM(reset_state="RESET")
-        self.submodules += fsm
-
-        fifo_in = Signal()
-        fifo_out = Signal()
-        fifo_full = Signal()
-
-        self.comb += [
-            fifo_full.eq(fifo.fifo.level == ratio),
-            fifo_in.eq(sink.stb & (~fifo_full | fifo_out)),
-            fifo_out.eq(source.stb & source.ack),
-
-            Record.connect(sink, fifo.sink),
-            fifo.sink.stb.eq(fifo_in),
-            self.sink.ack.eq(fifo_in),
-
-            source.stb.eq(sink.stb & fifo_full),
-            source.sop.eq(fifo.source.sop),
-            source.eop.eq(sink.eop),
-            fifo.source.ack.eq(fifo_out),
-            source.payload.eq(fifo.source.payload),
-
-            source.error.eq(sink.error | crc.error),
-        ]
-
-        fsm.act("RESET",
-            crc.reset.eq(1),
-            fifo.reset.eq(1),
-            NextState("IDLE"),
-        )
-        self.comb += crc.data.eq(sink.data)
-        fsm.act("IDLE",
-            If(sink.stb & sink.sop & sink.ack,
-                crc.ce.eq(1),
-                NextState("COPY")
-            )
-        )
-        fsm.act("COPY",
-            If(sink.stb & sink.ack,
-                crc.ce.eq(1),
-                If(sink.eop,
-                    NextState("RESET")
-                )
-            )
-        )
-        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
-
-
-class LiteEthMACCRC32Checker(LiteEthMACCRCChecker):
-    def __init__(self, description):
-        LiteEthMACCRCChecker.__init__(self, LiteEthMACCRC32, description)
diff --git a/misoclib/com/liteethmini/mac/core/gap.py b/misoclib/com/liteethmini/mac/core/gap.py
deleted file mode 100644 (file)
index fa95d18..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-class LiteEthMACGap(Module):
-    def __init__(self, dw, ack_on_gap=False):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.source = source = Source(eth_phy_description(dw))
-
-        # # #
-
-        gap = math.ceil(eth_interpacket_gap/(dw//8))
-        self.submodules.counter = counter = Counter(max=gap)
-
-        self.submodules.fsm = fsm = FSM(reset_state="COPY")
-        fsm.act("COPY",
-            counter.reset.eq(1),
-            Record.connect(sink, source),
-            If(sink.stb & sink.eop & sink.ack,
-                NextState("GAP")
-            )
-        )
-        fsm.act("GAP",
-            counter.ce.eq(1),
-            sink.ack.eq(int(ack_on_gap)),
-            If(counter.value == (gap-1),
-                NextState("COPY")
-            )
-        )
diff --git a/misoclib/com/liteethmini/mac/core/last_be.py b/misoclib/com/liteethmini/mac/core/last_be.py
deleted file mode 100644 (file)
index e469008..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthMACTXLastBE(Module):
-    def __init__(self, dw):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.source = source = Source(eth_phy_description(dw))
-
-        # # #
-
-        ongoing = Signal()
-        self.sync += \
-            If(sink.stb & sink.ack,
-                If(sink.sop,
-                    ongoing.eq(1)
-                ).Elif(sink.last_be,
-                    ongoing.eq(0)
-                )
-            )
-        self.comb += [
-            source.stb.eq(sink.stb & (sink.sop | ongoing)),
-            source.sop.eq(sink.sop),
-            source.eop.eq(sink.last_be),
-            source.data.eq(sink.data),
-            sink.ack.eq(source.ack)
-        ]
-
-
-class LiteEthMACRXLastBE(Module):
-    def __init__(self, dw):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.source = source = Source(eth_phy_description(dw))
-
-        # # #
-
-        self.comb += [
-            source.stb.eq(sink.stb),
-            source.sop.eq(sink.sop),
-            source.eop.eq(sink.eop),
-            source.data.eq(sink.data),
-            source.last_be.eq(sink.eop),
-            sink.ack.eq(source.ack)
-        ]
diff --git a/misoclib/com/liteethmini/mac/core/padding.py b/misoclib/com/liteethmini/mac/core/padding.py
deleted file mode 100644 (file)
index fbd8783..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthMACPaddingInserter(Module):
-    def __init__(self, dw, padding):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.source = source = Source(eth_phy_description(dw))
-
-        # # #
-
-        padding_limit = math.ceil(padding/(dw/8))-1
-
-        self.submodules.counter = counter = Counter(16, reset=1)
-        counter_done = Signal()
-        self.comb += [
-            counter.reset.eq(sink.stb & sink.sop & sink.ack),
-            counter.ce.eq(source.stb & source.ack),
-            counter_done.eq(counter.value >= padding_limit),
-        ]
-
-        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
-        fsm.act("IDLE",
-            Record.connect(sink, source),
-            If(source.stb & source.ack,
-                counter.ce.eq(1),
-                If(sink.eop,
-                    If(~counter_done,
-                        source.eop.eq(0),
-                        NextState("PADDING")
-                    )
-                )
-            )
-        )
-        fsm.act("PADDING",
-            source.stb.eq(1),
-            source.eop.eq(counter_done),
-            source.data.eq(0),
-            If(source.ack,
-                If(counter_done,
-                    NextState("IDLE")
-                )
-            )
-        )
-
-
-class LiteEthMACPaddingChecker(Module):
-    def __init__(self, dw, packet_min_length):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.source = source = Source(eth_phy_description(dw))
-
-        # # #
-
-        # XXX see if we should drop the packet when
-        # payload size < minimum ethernet payload size
-        self.comb += Record.connect(sink, source)
-
diff --git a/misoclib/com/liteethmini/mac/core/preamble.py b/misoclib/com/liteethmini/mac/core/preamble.py
deleted file mode 100644 (file)
index 445a073..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthMACPreambleInserter(Module):
-    def __init__(self, dw):
-        self.sink = Sink(eth_phy_description(dw))
-        self.source = Source(eth_phy_description(dw))
-
-        # # #
-
-        preamble = Signal(64, reset=eth_preamble)
-        cnt_max = (64//dw)-1
-        cnt = Signal(max=cnt_max+1)
-        clr_cnt = Signal()
-        inc_cnt = Signal()
-
-        self.sync += \
-            If(clr_cnt,
-                cnt.eq(0)
-            ).Elif(inc_cnt,
-                cnt.eq(cnt+1)
-            )
-
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-        fsm.act("IDLE",
-            self.sink.ack.eq(1),
-            clr_cnt.eq(1),
-            If(self.sink.stb & self.sink.sop,
-                self.sink.ack.eq(0),
-                NextState("INSERT"),
-            )
-        )
-        fsm.act("INSERT",
-            self.source.stb.eq(1),
-            self.source.sop.eq(cnt == 0),
-            chooser(preamble, cnt, self.source.data),
-            If(cnt == cnt_max,
-                If(self.source.ack, NextState("COPY"))
-            ).Else(
-                inc_cnt.eq(self.source.ack)
-            )
-        )
-
-        self.comb += [
-            self.source.data.eq(self.sink.data),
-            self.source.last_be.eq(self.sink.last_be)
-        ]
-        fsm.act("COPY",
-            Record.connect(self.sink, self.source, leave_out=set(["data", "last_be"])),
-            self.source.sop.eq(0),
-
-            If(self.sink.stb & self.sink.eop & self.source.ack,
-                NextState("IDLE"),
-            )
-        )
-
-
-class LiteEthMACPreambleChecker(Module):
-    def __init__(self, dw):
-        self.sink = Sink(eth_phy_description(dw))
-        self.source = Source(eth_phy_description(dw))
-
-        # # #
-
-        preamble = Signal(64, reset=eth_preamble)
-        cnt_max = (64//dw) - 1
-        cnt = Signal(max=cnt_max+1)
-        clr_cnt = Signal()
-        inc_cnt = Signal()
-
-        self.sync += \
-            If(clr_cnt,
-                cnt.eq(0)
-            ).Elif(inc_cnt,
-                cnt.eq(cnt+1)
-            )
-
-        discard = Signal()
-        clr_discard = Signal()
-        set_discard = Signal()
-
-        self.sync += \
-            If(clr_discard,
-                discard.eq(0)
-            ).Elif(set_discard,
-                discard.eq(1)
-            )
-
-        sop = Signal()
-        clr_sop = Signal()
-        set_sop = Signal()
-        self.sync += \
-            If(clr_sop,
-                sop.eq(0)
-            ).Elif(set_sop,
-                sop.eq(1)
-            )
-
-        ref = Signal(dw)
-        match = Signal()
-        self.comb += [
-            chooser(preamble, cnt, ref),
-            match.eq(self.sink.data == ref)
-        ]
-
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-
-        fsm.act("IDLE",
-            self.sink.ack.eq(1),
-            clr_cnt.eq(1),
-            clr_discard.eq(1),
-            If(self.sink.stb & self.sink.sop,
-                clr_cnt.eq(0),
-                inc_cnt.eq(1),
-                clr_discard.eq(0),
-                set_discard.eq(~match),
-                NextState("CHECK"),
-            )
-        )
-        fsm.act("CHECK",
-            self.sink.ack.eq(1),
-            If(self.sink.stb,
-                set_discard.eq(~match),
-                If(cnt == cnt_max,
-                    If(discard | (~match),
-                        NextState("IDLE")
-                    ).Else(
-                        set_sop.eq(1),
-                        NextState("COPY")
-                    )
-                ).Else(
-                    inc_cnt.eq(1)
-                )
-            )
-        )
-        self.comb += [
-            self.source.data.eq(self.sink.data),
-            self.source.last_be.eq(self.sink.last_be)
-        ]
-        fsm.act("COPY",
-            Record.connect(self.sink, self.source, leave_out=set(["data", "last_be"])),
-            self.source.sop.eq(sop),
-            clr_sop.eq(self.source.stb & self.source.ack),
-
-            If(self.source.stb & self.source.eop & self.source.ack,
-                NextState("IDLE"),
-            )
-        )
diff --git a/misoclib/com/liteethmini/mac/frontend/__init__.py b/misoclib/com/liteethmini/mac/frontend/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/com/liteethmini/mac/frontend/sram.py b/misoclib/com/liteethmini/mac/frontend/sram.py
deleted file mode 100644 (file)
index b5e91a3..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-
-
-class LiteEthMACSRAMWriter(Module, AutoCSR):
-    def __init__(self, dw, depth, nslots=2):
-        self.sink = sink = Sink(eth_phy_description(dw))
-        self.crc_error = Signal()
-
-        slotbits = max(log2_int(nslots), 1)
-        lengthbits = log2_int(depth*4)  # length in bytes
-
-        self._slot = CSRStatus(slotbits)
-        self._length = CSRStatus(lengthbits)
-
-        self.submodules.ev = EventManager()
-        self.ev.available = EventSourceLevel()
-        self.ev.finalize()
-
-        # # #
-
-        # packet dropped if no slot available
-        sink.ack.reset = 1
-
-        # length computation
-        increment = Signal(3)
-        self.comb += \
-            If(sink.last_be[3],
-                increment.eq(1)
-            ).Elif(sink.last_be[2],
-                increment.eq(2)
-            ).Elif(sink.last_be[1],
-                increment.eq(3)
-            ).Else(
-                increment.eq(4)
-            )
-        counter = Counter(lengthbits, increment=increment)
-        self.submodules += counter
-
-        # slot computation
-        slot = Counter(slotbits)
-        self.submodules += slot
-
-        ongoing = Signal()
-
-        # status fifo
-        fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
-        self.submodules += fifo
-
-        # fsm
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-
-        fsm.act("IDLE",
-            If(sink.stb & sink.sop,
-                If(fifo.sink.ack,
-                    ongoing.eq(1),
-                    counter.ce.eq(1),
-                    NextState("WRITE")
-                )
-            )
-        )
-        fsm.act("WRITE",
-            counter.ce.eq(sink.stb),
-            ongoing.eq(1),
-            If(sink.stb & sink.eop,
-                If((sink.error & sink.last_be) != 0,
-                    NextState("DISCARD")
-                ).Else(
-                    NextState("TERMINATE")
-                )
-            )
-        )
-        fsm.act("DISCARD",
-            counter.reset.eq(1),
-            NextState("IDLE")
-        )
-        self.comb += [
-            fifo.sink.slot.eq(slot.value),
-            fifo.sink.length.eq(counter.value)
-        ]
-        fsm.act("TERMINATE",
-            counter.reset.eq(1),
-            slot.ce.eq(1),
-            fifo.sink.stb.eq(1),
-            NextState("IDLE")
-        )
-        self.comb += [
-            fifo.source.ack.eq(self.ev.available.clear),
-            self.ev.available.trigger.eq(fifo.source.stb),
-            self._slot.status.eq(fifo.source.slot),
-            self._length.status.eq(fifo.source.length),
-        ]
-
-        # memory
-        mems = [None]*nslots
-        ports = [None]*nslots
-        for n in range(nslots):
-            mems[n] = Memory(dw, depth)
-            ports[n] = mems[n].get_port(write_capable=True)
-            self.specials += ports[n]
-        self.mems = mems
-
-        cases = {}
-        for n, port in enumerate(ports):
-            cases[n] = [
-                ports[n].adr.eq(counter.value[2:]),
-                ports[n].dat_w.eq(sink.data),
-                If(sink.stb & ongoing,
-                    ports[n].we.eq(0xf)
-                )
-            ]
-        self.comb += Case(slot.value, cases)
-
-
-class LiteEthMACSRAMReader(Module, AutoCSR):
-    def __init__(self, dw, depth, nslots=2):
-        self.source = source = Source(eth_phy_description(dw))
-
-        slotbits = max(log2_int(nslots), 1)
-        lengthbits = log2_int(depth*4)  # length in bytes
-        self.lengthbits = lengthbits
-
-        self._start = CSR()
-        self._ready = CSRStatus()
-        self._slot = CSRStorage(slotbits)
-        self._length = CSRStorage(lengthbits)
-
-        self.submodules.ev = EventManager()
-        self.ev.done = EventSourcePulse()
-        self.ev.finalize()
-
-        # # #
-
-        # command fifo
-        fifo = SyncFIFO([("slot", slotbits), ("length", lengthbits)], nslots)
-        self.submodules += fifo
-        self.comb += [
-            fifo.sink.stb.eq(self._start.re),
-            fifo.sink.slot.eq(self._slot.storage),
-            fifo.sink.length.eq(self._length.storage),
-            self._ready.status.eq(fifo.sink.ack)
-        ]
-
-        # length computation
-        self.submodules.counter = counter = Counter(lengthbits, increment=4)
-
-        # fsm
-        first = Signal()
-        last  = Signal()
-        last_d = Signal()
-
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-
-        fsm.act("IDLE",
-            counter.reset.eq(1),
-            If(fifo.source.stb,
-                NextState("CHECK")
-            )
-        )
-        fsm.act("CHECK",
-            If(~last_d,
-                NextState("SEND"),
-            ).Else(
-                NextState("END"),
-            )
-        )
-        length_lsb = fifo.source.length[0:2]
-        self.comb += [
-            If(last,
-                If(length_lsb == 3,
-                    source.last_be.eq(0b0010)
-                ).Elif(length_lsb == 2,
-                    source.last_be.eq(0b0100)
-                ).Elif(length_lsb == 1,
-                    source.last_be.eq(0b1000)
-                ).Else(
-                    source.last_be.eq(0b0001)
-                )
-            )
-        ]
-        fsm.act("SEND",
-            source.stb.eq(1),
-            source.sop.eq(first),
-            source.eop.eq(last),
-            If(source.ack,
-                counter.ce.eq(~last),
-                NextState("CHECK")
-            )
-        )
-        fsm.act("END",
-            fifo.source.ack.eq(1),
-            self.ev.done.trigger.eq(1),
-            NextState("IDLE")
-        )
-
-        # first/last computation
-        self.sync += [
-            If(fsm.ongoing("IDLE"),
-                first.eq(1)
-            ).Elif(source.stb & source.ack,
-                first.eq(0)
-            )
-        ]
-        self.comb += last.eq((counter.value + 4) >= fifo.source.length)
-        self.sync += last_d.eq(last)
-
-        # memory
-        rd_slot = fifo.source.slot
-
-        mems = [None]*nslots
-        ports = [None]*nslots
-        for n in range(nslots):
-            mems[n] = Memory(dw, depth)
-            ports[n] = mems[n].get_port()
-            self.specials += ports[n]
-        self.mems = mems
-
-        cases = {}
-        for n, port in enumerate(ports):
-            self.comb += ports[n].adr.eq(counter.value[2:])
-            cases[n] = [source.data.eq(port.dat_r)]
-        self.comb += Case(rd_slot, cases)
-
-
-class LiteEthMACSRAM(Module, AutoCSR):
-    def __init__(self, dw, depth, nrxslots, ntxslots):
-        self.submodules.writer = LiteEthMACSRAMWriter(dw, depth, nrxslots)
-        self.submodules.reader = LiteEthMACSRAMReader(dw, depth, ntxslots)
-        self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
-        self.sink, self.source = self.writer.sink, self.reader.source
diff --git a/misoclib/com/liteethmini/mac/frontend/wishbone.py b/misoclib/com/liteethmini/mac/frontend/wishbone.py
deleted file mode 100644 (file)
index 8962308..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-from misoclib.com.liteethmini.common import *
-from misoclib.com.liteethmini.mac.frontend import sram
-
-from migen.bus import wishbone
-from migen.fhdl.simplify import FullMemoryWE
-
-
-class LiteEthMACWishboneInterface(Module, AutoCSR):
-    def __init__(self, dw, nrxslots=2, ntxslots=2):
-        self.sink = Sink(eth_phy_description(dw))
-        self.source = Source(eth_phy_description(dw))
-        self.bus = wishbone.Interface()
-
-        # # #
-
-        # storage in SRAM
-        sram_depth = buffer_depth//(dw//8)
-        self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots)
-        self.comb += [
-            Record.connect(self.sink, self.sram.sink),
-            Record.connect(self.sram.source, self.source)
-        ]
-
-        # Wishbone interface
-        wb_rx_sram_ifs = [wishbone.SRAM(self.sram.writer.mems[n], read_only=True)
-            for n in range(nrxslots)]
-        # TODO: FullMemoryWE should move to Mibuild
-        wb_tx_sram_ifs = [FullMemoryWE()(wishbone.SRAM(self.sram.reader.mems[n], read_only=False))
-            for n in range(ntxslots)]
-        wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs
-
-        wb_slaves = []
-        decoderoffset = log2_int(sram_depth)
-        decoderbits = log2_int(len(wb_sram_ifs))
-        for n, wb_sram_if in enumerate(wb_sram_ifs):
-            def slave_filter(a, v=n):
-                return a[decoderoffset:decoderoffset+decoderbits] == v
-            wb_slaves.append((slave_filter, wb_sram_if.bus))
-            self.submodules += wb_sram_if
-        wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True)
-        self.submodules += wb_con
diff --git a/misoclib/com/liteethmini/phy/__init__.py b/misoclib/com/liteethmini/phy/__init__.py
deleted file mode 100644 (file)
index f3a15b8..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-def LiteEthPHY(clock_pads, pads, clk_freq=None, **kwargs):
-    # Autodetect PHY
-    if hasattr(pads, "source_stb"):
-        # This is a simulation PHY
-        from misoclib.com.liteethmini.phy.sim import LiteEthPHYSim
-        return LiteEthPHYSim(pads)
-    elif hasattr(clock_pads, "gtx") and flen(pads.tx_data) == 8:
-        if hasattr(clock_pads, "tx"):
-            # This is a 10/100/1G PHY
-            from misoclib.com.liteethmini.phy.gmii_mii import LiteEthPHYGMIIMII
-            return LiteEthPHYGMIIMII(clock_pads, pads, clk_freq=clk_freq, **kwargs)
-        else:
-            # This is a pure 1G PHY
-            from misoclib.com.liteethmini.phy.gmii import LiteEthPHYGMII
-            return LiteEthPHYGMII(clock_pads, pads, **kwargs)
-    elif hasattr(pads, "rx_ctl"):
-        # This is a 10/100/1G RGMII PHY
-        raise ValueError("RGMII PHYs are specific to vendors (for now), use direct instantiation")
-    elif flen(pads.tx_data) == 4:
-        # This is a MII PHY
-        from misoclib.com.liteethmini.phy.mii import LiteEthPHYMII
-        return LiteEthPHYMII(clock_pads, pads, **kwargs)
-    else:
-        raise ValueError("Unable to autodetect PHY from platform file, use direct instantiation")
diff --git a/misoclib/com/liteethmini/phy/gmii.py b/misoclib/com/liteethmini/phy/gmii.py
deleted file mode 100644 (file)
index db9c287..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-from migen.genlib.io import DDROutput
-
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthPHYGMIITX(Module):
-    def __init__(self, pads, pads_register=True):
-        self.sink = sink = Sink(eth_phy_description(8))
-
-        # # #
-
-        if hasattr(pads, "tx_er"):
-            self.sync += pads.tx_er.eq(0)
-        pads_eq = [
-            pads.tx_en.eq(sink.stb),
-            pads.tx_data.eq(sink.data)
-        ]
-        if pads_register:
-            self.sync += pads_eq
-        else:
-            self.comb += pads_eq
-        self.comb += sink.ack.eq(1)
-
-
-class LiteEthPHYGMIIRX(Module):
-    def __init__(self, pads):
-        self.source = source = Source(eth_phy_description(8))
-
-        # # #
-
-        dv_d = Signal()
-        self.sync += dv_d.eq(pads.dv)
-
-        sop = Signal()
-        eop = Signal()
-        self.comb += [
-            sop.eq(pads.dv & ~dv_d),
-            eop.eq(~pads.dv & dv_d)
-        ]
-        self.sync += [
-            source.stb.eq(pads.dv),
-            source.sop.eq(sop),
-            source.data.eq(pads.rx_data)
-        ]
-        self.comb += source.eop.eq(eop)
-
-
-class LiteEthPHYGMIICRG(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0):
-        self._reset = CSRStorage()
-
-        # # #
-
-        self.clock_domains.cd_eth_rx = ClockDomain()
-        self.clock_domains.cd_eth_tx = ClockDomain()
-
-        # RX : Let the synthesis tool insert the appropriate clock buffer
-        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
-
-        # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused
-        #      MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx
-        self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx"))
-        # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer?
-        self.specials += Instance("BUFGMUX",
-                                  i_I0=self.cd_eth_rx.clk,
-                                  i_I1=clock_pads.tx,
-                                  i_S=mii_mode,
-                                  o_O=self.cd_eth_tx.clk)
-
-        if with_hw_init_reset:
-            reset = Signal()
-            counter_done = Signal()
-            self.submodules.counter = counter = Counter(max=512)
-            self.comb += [
-                counter_done.eq(counter.value == 256),
-                counter.ce.eq(~counter_done),
-                reset.eq(~counter_done | self._reset.storage)
-            ]
-        else:
-            reset = self._reset.storage
-        self.comb += pads.rst_n.eq(~reset)
-        self.specials += [
-            AsyncResetSynchronizer(self.cd_eth_tx, reset),
-            AsyncResetSynchronizer(self.cd_eth_rx, reset),
-        ]
-
-
-class LiteEthPHYGMII(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
-        self.dw = 8
-        self.submodules.crg = LiteEthPHYGMIICRG(clock_pads,
-                                                pads,
-                                                with_hw_init_reset)
-        self.submodules.tx = RenameClockDomains(LiteEthPHYGMIITX(pads),
-                                                "eth_tx")
-        self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIRX(pads),
-                                                "eth_rx")
-        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoclib/com/liteethmini/phy/gmii_mii.py b/misoclib/com/liteethmini/phy/gmii_mii.py
deleted file mode 100644 (file)
index 2d92d82..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-from migen.genlib.io import DDROutput
-from migen.flow.plumbing import Multiplexer, Demultiplexer
-from migen.genlib.cdc import PulseSynchronizer
-
-from misoclib.com.liteethmini.common import *
-
-from misoclib.com.liteethmini.phy.gmii import LiteEthPHYGMIICRG
-from misoclib.com.liteethmini.phy.mii import LiteEthPHYMIITX, LiteEthPHYMIIRX
-from misoclib.com.liteethmini.phy.gmii import LiteEthPHYGMIITX, LiteEthPHYGMIIRX
-
-modes = {
-    "GMII": 0,
-    "MII": 1
-}
-
-tx_pads_layout = [("tx_er", 1), ("tx_en", 1), ("tx_data", 8)]
-rx_pads_layout = [("rx_er", 1), ("dv", 1), ("rx_data", 8)]
-
-
-class LiteEthPHYGMIIMIITX(Module):
-    def __init__(self, pads, mode):
-        self.sink = sink = Sink(eth_phy_description(8))
-
-        # # #
-
-        gmii_tx_pads = Record(tx_pads_layout)
-        gmii_tx = LiteEthPHYGMIITX(gmii_tx_pads, pads_register=False)
-        self.submodules += gmii_tx
-
-        mii_tx_pads = Record(tx_pads_layout)
-        mii_tx = LiteEthPHYMIITX(mii_tx_pads, pads_register=False)
-        self.submodules += mii_tx
-
-        demux = Demultiplexer(eth_phy_description(8), 2)
-        self.submodules += demux
-        self.comb += [
-            demux.sel.eq(mode == modes["MII"]),
-            Record.connect(sink, demux.sink),
-            Record.connect(demux.source0, gmii_tx.sink),
-            Record.connect(demux.source1, mii_tx.sink),
-        ]
-
-        if hasattr(pads, "tx_er"):
-            self.comb += pads.tx_er.eq(0)
-        self.sync += [
-            If(mode == modes["MII"],
-                pads.tx_en.eq(mii_tx_pads.tx_en),
-                pads.tx_data.eq(mii_tx_pads.tx_data),
-            ).Else(
-                pads.tx_en.eq(gmii_tx_pads.tx_en),
-                pads.tx_data.eq(gmii_tx_pads.tx_data),
-            )
-        ]
-
-
-class LiteEthPHYGMIIMIIRX(Module):
-    def __init__(self, pads, mode):
-        self.source = source = Source(eth_phy_description(8))
-
-        # # #
-
-        pads_d = Record(rx_pads_layout)
-        self.sync += [
-            pads_d.dv.eq(pads.dv),
-            pads_d.rx_data.eq(pads.rx_data)
-        ]
-
-        gmii_rx = LiteEthPHYGMIIRX(pads_d)
-        self.submodules += gmii_rx
-
-        mii_rx = LiteEthPHYMIIRX(pads_d)
-        self.submodules += mii_rx
-
-        mux = Multiplexer(eth_phy_description(8), 2)
-        self.submodules += mux
-        self.comb += [
-            mux.sel.eq(mode == modes["MII"]),
-            Record.connect(gmii_rx.source, mux.sink0),
-            Record.connect(mii_rx.source, mux.sink1),
-            Record.connect(mux.source, source)
-        ]
-
-
-class LiteEthGMIIMIIModeDetection(Module, AutoCSR):
-    def __init__(self, clk_freq):
-        self.mode = Signal()
-        self._mode = CSRStatus()
-
-        # # #
-
-        mode = Signal()
-        update_mode = Signal()
-        self.sync += \
-            If(update_mode,
-                self.mode.eq(mode)
-            )
-        self.comb += self._mode.status.eq(self.mode)
-
-        # Principle:
-        #  sys_clk >= 125MHz
-        #  eth_rx <= 125Mhz
-        # We generate ticks every 1024 clock cycles in eth_rx domain
-        # and measure ticks period in sys_clk domain.
-
-        # Generate a tick every 1024 clock cycles (eth_rx clock domain)
-        eth_tick = Signal()
-        eth_counter = Signal(10)
-        self.sync.eth_rx += eth_counter.eq(eth_counter + 1)
-        self.comb += eth_tick.eq(eth_counter == 0)
-
-        # Synchronize tick (sys clock domain)
-        sys_tick = Signal()
-        eth_ps = PulseSynchronizer("eth_rx", "sys")
-        self.comb += [
-            eth_ps.i.eq(eth_tick),
-            sys_tick.eq(eth_ps.o)
-        ]
-        self.submodules += eth_ps
-
-        # sys_clk domain counter
-        sys_counter = Counter(24)
-        self.submodules += sys_counter
-
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-
-        fsm.act("IDLE",
-            sys_counter.reset.eq(1),
-            If(sys_tick,
-                NextState("COUNT")
-            )
-        )
-        fsm.act("COUNT",
-            sys_counter.ce.eq(1),
-            If(sys_tick,
-                NextState("DETECTION")
-            )
-        )
-        fsm.act("DETECTION",
-            update_mode.eq(1),
-            # if freq < 125MHz-5% use MII mode
-            If(sys_counter.value > int((clk_freq/125000000)*1024*1.05),
-                mode.eq(1)
-            # if freq >= 125MHz-5% use GMII mode
-            ).Else(
-                mode.eq(0)
-            ),
-            NextState("IDLE")
-        )
-
-
-class LiteEthPHYGMIIMII(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, clk_freq, with_hw_init_reset=True):
-        self.dw = 8
-        # Note: we can use GMII CRG since it also handles tx clock pad used for MII
-        self.submodules.mode_detection = LiteEthGMIIMIIModeDetection(clk_freq)
-        mode = self.mode_detection.mode
-        self.submodules.crg = LiteEthPHYGMIICRG(clock_pads, pads, with_hw_init_reset, mode == modes["MII"])
-        self.submodules.tx = RenameClockDomains(LiteEthPHYGMIIMIITX(pads, mode), "eth_tx")
-        self.submodules.rx = RenameClockDomains(LiteEthPHYGMIIMIIRX(pads, mode), "eth_rx")
-        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoclib/com/liteethmini/phy/loopback.py b/misoclib/com/liteethmini/phy/loopback.py
deleted file mode 100644 (file)
index 7e4863c..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-from misoclib.com.liteethmini.common import *
-from misoclib.com.liteethmini.generic import *
-
-
-class LiteEthPHYLoopbackCRG(Module, AutoCSR):
-    def __init__(self):
-        self._reset = CSRStorage()
-
-        # # #
-
-        self.clock_domains.cd_eth_rx = ClockDomain()
-        self.clock_domains.cd_eth_tx = ClockDomain()
-        self.comb += [
-            self.cd_eth_rx.clk.eq(ClockSignal()),
-            self.cd_eth_tx.clk.eq(ClockSignal())
-        ]
-
-        reset = self._reset.storage
-        self.comb += [
-            self.cd_eth_rx.rst.eq(reset),
-            self.cd_eth_tx.rst.eq(reset)
-        ]
-
-
-class LiteEthPHYLoopback(Module, AutoCSR):
-    def __init__(self):
-        self.dw = 8
-        self.submodules.crg = LiteEthLoopbackPHYCRG()
-        self.sink = sink = Sink(eth_phy_description(8))
-        self.source = source = Source(eth_phy_description(8))
-        self.comb += Record.connect(self.sink, self.source)
diff --git a/misoclib/com/liteethmini/phy/mii.py b/misoclib/com/liteethmini/phy/mii.py
deleted file mode 100644 (file)
index 53a20a7..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-from misoclib.com.liteethmini.common import *
-
-
-def converter_description(dw):
-    payload_layout = [("data", dw)]
-    return EndpointDescription(payload_layout, packetized=True)
-
-
-class LiteEthPHYMIITX(Module):
-    def __init__(self, pads, pads_register=True):
-        self.sink = sink = Sink(eth_phy_description(8))
-
-        # # #
-
-        if hasattr(pads, "tx_er"):
-            self.sync += pads.tx_er.eq(0)
-        converter = Converter(converter_description(8),
-                              converter_description(4))
-        self.submodules += converter
-        self.comb += [
-            converter.sink.stb.eq(sink.stb),
-            converter.sink.data.eq(sink.data),
-            sink.ack.eq(converter.sink.ack),
-            converter.source.ack.eq(1)
-        ]
-        pads_eq = [
-            pads.tx_en.eq(converter.source.stb),
-            pads.tx_data.eq(converter.source.data)
-        ]
-        if pads_register:
-            self.sync += pads_eq
-        else:
-            self.comb += pads_eq
-
-
-class LiteEthPHYMIIRX(Module):
-    def __init__(self, pads):
-        self.source = source = Source(eth_phy_description(8))
-
-        # # #
-
-        sop = FlipFlop(reset=1)
-        self.submodules += sop
-
-        converter = Converter(converter_description(4),
-                              converter_description(8))
-        converter = InsertReset(converter)
-        self.submodules += converter
-
-        self.sync += [
-            converter.reset.eq(~pads.dv),
-            converter.sink.stb.eq(1),
-            converter.sink.data.eq(pads.rx_data)
-        ]
-        self.comb += [
-            sop.reset.eq(~pads.dv),
-            sop.ce.eq(pads.dv),
-            converter.sink.sop.eq(sop.q),
-            converter.sink.eop.eq(~pads.dv)
-        ]
-        self.comb += Record.connect(converter.source, source)
-
-
-class LiteEthPHYMIICRG(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset):
-        self._reset = CSRStorage()
-
-        # # #
-
-        if hasattr(clock_pads, "phy"):
-            self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy)
-
-        self.clock_domains.cd_eth_rx = ClockDomain()
-        self.clock_domains.cd_eth_tx = ClockDomain()
-        self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx)
-        self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx)
-
-        if with_hw_init_reset:
-            reset = Signal()
-            counter_done = Signal()
-            self.submodules.counter = counter = Counter(max=512)
-            self.comb += [
-                counter_done.eq(counter.value == 256),
-                counter.ce.eq(~counter_done),
-                reset.eq(~counter_done | self._reset.storage)
-            ]
-        else:
-            reset = self._reset.storage
-        self.comb += pads.rst_n.eq(~reset)
-        self.specials += [
-            AsyncResetSynchronizer(self.cd_eth_tx, reset),
-            AsyncResetSynchronizer(self.cd_eth_rx, reset),
-        ]
-
-
-class LiteEthPHYMII(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
-        self.dw = 8
-        self.submodules.crg = LiteEthPHYMIICRG(clock_pads, pads, with_hw_init_reset)
-        self.submodules.tx = RenameClockDomains(LiteEthPHYMIITX(pads), "eth_tx")
-        self.submodules.rx = RenameClockDomains(LiteEthPHYMIIRX(pads), "eth_rx")
-        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoclib/com/liteethmini/phy/s6rgmii.py b/misoclib/com/liteethmini/phy/s6rgmii.py
deleted file mode 100644 (file)
index 31656d2..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-# RGMII PHY for Spartan-6
-
-from migen.genlib.io import DDROutput
-from migen.genlib.misc import WaitTimer
-from migen.genlib.fsm import FSM, NextState
-
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthPHYRGMIITX(Module):
-    def __init__(self, pads, pads_register=True):
-        self.sink = sink = Sink(eth_phy_description(8))
-
-        # # #
-
-        self.specials += Instance("ODDR2",
-                p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
-                i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
-                i_CE=1, i_S=0, i_R=0,
-                i_D0=sink.stb, i_D1=sink.stb, o_Q=pads.tx_ctl,
-        )
-        for i in range(4):
-            self.specials += Instance("ODDR2",
-                    p_DDR_ALIGNMENT="C0", p_INIT=0, p_SRTYPE="ASYNC",
-                    i_C0=ClockSignal("eth_tx"), i_C1=~ClockSignal("eth_tx"),
-                    i_CE=1, i_S=0, i_R=0,
-                    i_D0=sink.data[i], i_D1=sink.data[4+i], o_Q=pads.tx_data[i],
-            )
-        self.comb += sink.ack.eq(1)
-
-
-class LiteEthPHYRGMIIRX(Module):
-    def __init__(self, pads):
-        self.source = source = Source(eth_phy_description(8))
-
-        # # #
-
-        rx_ctl = Signal()
-        rx_data = Signal(8)
-
-        self.specials += Instance("IDDR2",
-                p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
-                i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
-                i_CE=1, i_S=0, i_R=0,
-                i_D=pads.rx_ctl, o_Q1=rx_ctl,
-        )
-        for i in range(4):
-            self.specials += Instance("IDDR2",
-                    p_DDR_ALIGNMENT="C0", p_INIT_Q0=0, p_INIT_Q1=0, p_SRTYPE="ASYNC",
-                    i_C0=ClockSignal("eth_rx"), i_C1=~ClockSignal("eth_rx"),
-                    i_CE=1, i_S=0, i_R=0,
-                    i_D=pads.rx_data[i], o_Q0=rx_data[4+i], o_Q1=rx_data[i],
-            )
-
-
-        rx_ctl_d = Signal()
-        self.sync += rx_ctl_d.eq(rx_ctl)
-
-        sop = Signal()
-        eop = Signal()
-        self.comb += [
-            sop.eq(rx_ctl & ~rx_ctl_d),
-            eop.eq(~rx_ctl & rx_ctl_d)
-        ]
-        self.sync += [
-            source.stb.eq(rx_ctl),
-            source.sop.eq(sop),
-            source.data.eq(rx_data)
-        ]
-        self.comb += source.eop.eq(eop)
-
-
-class LiteEthPHYRGMIICRG(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset):
-        self._reset = CSRStorage()
-
-        # # #
-
-        self.clock_domains.cd_eth_rx = ClockDomain()
-        self.clock_domains.cd_eth_tx = ClockDomain()
-
-
-        # RX
-        dcm_reset = Signal()
-        dcm_locked = Signal()
-
-        timer = WaitTimer(1024)
-        fsm = FSM(reset_state="DCM_RESET")
-        self.submodules += timer, fsm
-
-        fsm.act("DCM_RESET",
-            dcm_reset.eq(1),
-            timer.wait.eq(1),
-            If(timer.done,
-                timer.wait.eq(0),
-                NextState("DCM_WAIT")
-            )
-        )
-        fsm.act("DCM_WAIT",
-            timer.wait.eq(1),
-            If(timer.done,
-                NextState("DCM_CHECK_LOCK")
-            )
-        )
-        fsm.act("DCM_CHECK_LOCK",
-            If(~dcm_locked,
-                NextState("DCM_RESET")
-            )
-        )
-
-        clk90_rx = Signal()
-        clk0_rx = Signal()
-        clk0_rx_bufg = Signal()
-        self.specials += Instance("DCM",
-                i_CLKIN=clock_pads.rx,
-                i_CLKFB=clk0_rx_bufg,
-                o_CLK0=clk0_rx,
-                o_CLK90=clk90_rx,
-                o_LOCKED=dcm_locked,
-                i_PSEN=0,
-                i_PSCLK=0,
-                i_PSINCDEC=0,
-                i_RST=dcm_reset
-        )
-
-        self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg)
-        self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk)
-
-        # TX
-        self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx"))
-        self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk)
-
-        # Reset
-        if with_hw_init_reset:
-            reset = Signal()
-            counter_done = Signal()
-            self.submodules.counter = counter = Counter(max=512)
-            self.comb += [
-                counter_done.eq(counter.value == 256),
-                counter.ce.eq(~counter_done),
-                reset.eq(~counter_done | self._reset.storage)
-            ]
-        else:
-            reset = self._reset.storage
-        self.comb += pads.rst_n.eq(~reset)
-        self.specials += [
-            AsyncResetSynchronizer(self.cd_eth_tx, reset),
-            AsyncResetSynchronizer(self.cd_eth_rx, reset),
-        ]
-
-
-class LiteEthPHYRGMII(Module, AutoCSR):
-    def __init__(self, clock_pads, pads, with_hw_init_reset=True):
-        self.dw = 8
-        self.submodules.crg = LiteEthPHYRGMIICRG(clock_pads,
-                                                 pads,
-                                                 with_hw_init_reset)
-        self.submodules.tx = RenameClockDomains(LiteEthPHYRGMIITX(pads),
-                                                "eth_tx")
-        self.submodules.rx = RenameClockDomains(LiteEthPHYRGMIIRX(pads),
-                                                "eth_rx")
-        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoclib/com/liteethmini/phy/sim.py b/misoclib/com/liteethmini/phy/sim.py
deleted file mode 100644 (file)
index 8c29052..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-import os
-
-from misoclib.com.liteethmini.common import *
-
-
-class LiteEthPHYSimCRG(Module, AutoCSR):
-    def __init__(self):
-        self._reset = CSRStorage()
-
-        # # #
-
-        self.clock_domains.cd_eth_rx = ClockDomain()
-        self.clock_domains.cd_eth_tx = ClockDomain()
-        self.comb += [
-            self.cd_eth_rx.clk.eq(ClockSignal()),
-            self.cd_eth_tx.clk.eq(ClockSignal())
-        ]
-
-        reset = self._reset.storage
-        self.comb += [
-            self.cd_eth_rx.rst.eq(reset),
-            self.cd_eth_tx.rst.eq(reset)
-        ]
-
-
-class LiteEthPHYSim(Module, AutoCSR):
-    def __init__(self, pads, tap="tap0", ip_address="192.168.0.14"):
-        self.dw = 8
-        self.submodules.crg = LiteEthPHYSimCRG()
-        self.sink = sink = Sink(eth_phy_description(8))
-        self.source = source = Source(eth_phy_description(8))
-        self.tap = tap
-        self.ip_address = ip_address
-
-        self.comb += [
-            pads.source_stb.eq(self.sink.stb),
-            pads.source_data.eq(self.sink.data),
-            self.sink.ack.eq(1)
-        ]
-
-        self.sync += [
-            self.source.stb.eq(pads.sink_stb),
-            self.source.sop.eq(pads.sink_stb & ~self.source.stb),
-            self.source.data.eq(pads.sink_data),
-        ]
-        self.comb += [
-            self.source.eop.eq(~pads.sink_stb & self.source.stb),
-        ]
-
-        # XXX avoid use of os.system
-        os.system("openvpn --mktun --dev {}".format(self.tap))
-        os.system("ifconfig {} {} up".format(self.tap, self.ip_address))
-        os.system("mknod /dev/net/{} c 10 200".format(self.tap))
-
-    def do_exit(self, *args, **kwargs):
-        # XXX avoid use of os.system
-        os.system("rm -f /dev/net/{}".format(self.tap))
-        os.system("openvpn --rmtun --dev {}".format(self.tap))
diff --git a/misoclib/com/spi/__init__.py b/misoclib/com/spi/__init__.py
deleted file mode 100644 (file)
index a78a6db..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.genlib.fsm import FSM, NextState
-
-
-class SPIMaster(Module, AutoCSR):
-    def __init__(self, pads, width=24, div=2, cpha=1):
-        self.pads = pads
-
-        self._ctrl = CSR()
-        self._length = CSRStorage(8)
-        self._status = CSRStatus()
-        if hasattr(pads, "mosi"):
-            self._mosi = CSRStorage(width)
-        if hasattr(pads, "miso"):
-            self._miso = CSRStatus(width)
-
-        self.irq = Signal()
-
-    ###
-
-        # ctrl
-        start = Signal()
-        length = self._length.storage
-        enable_cs = Signal()
-        enable_shift = Signal()
-        done = Signal()
-
-        self.comb += [
-            start.eq(self._ctrl.re & self._ctrl.r[0]),
-            self._status.status.eq(done)
-        ]
-
-        # clk
-        i = Signal(max=div)
-        clk_en = Signal()
-        set_clk = Signal()
-        clr_clk = Signal()
-        self.sync += [
-            If(set_clk,
-                pads.clk.eq(enable_cs)
-            ),
-            If(clr_clk,
-                pads.clk.eq(0),
-                i.eq(0)
-            ).Else(
-                i.eq(i + 1),
-            )
-        ]
-
-        self.comb += [
-            set_clk.eq(i == (div//2-1)),
-            clr_clk.eq(i == (div-1))
-        ]
-
-        # fsm
-        cnt = Signal(8)
-        clr_cnt = Signal()
-        inc_cnt = Signal()
-        self.sync += \
-            If(clr_cnt,
-                cnt.eq(0)
-            ).Elif(inc_cnt,
-                cnt.eq(cnt+1)
-            )
-
-        fsm = FSM(reset_state="IDLE")
-        self.submodules += fsm
-        fsm.act("IDLE",
-            If(start,
-                NextState("WAIT_CLK")
-            ),
-            done.eq(1),
-            clr_cnt.eq(1)
-        )
-        fsm.act("WAIT_CLK",
-            If(clr_clk,
-                NextState("SHIFT")
-            ),
-        )
-        fsm.act("SHIFT",
-            If(cnt == length,
-                NextState("END")
-            ).Else(
-                inc_cnt.eq(clr_clk),
-            ),
-            enable_cs.eq(1),
-            enable_shift.eq(1),
-        )
-        fsm.act("END",
-            If(set_clk,
-                NextState("IDLE")
-            ),
-            enable_shift.eq(1),
-            self.irq.eq(1)
-        )
-
-        # miso
-        if hasattr(pads, "miso"):
-            miso = Signal()
-            sr_miso = Signal(width)
-
-            # (cpha = 1: capture on clk falling edge)
-            if cpha:
-                self.sync += \
-                    If(enable_shift,
-                        If(clr_clk,
-                            miso.eq(pads.miso),
-                        ).Elif(set_clk,
-                            sr_miso.eq(Cat(miso, sr_miso[:-1]))
-                        )
-                    )
-            # (cpha = 0: capture on clk rising edge)
-            else:
-                self.sync += \
-                    If(enable_shift,
-                        If(set_clk,
-                            miso.eq(pads.miso),
-                        ).Elif(clr_clk,
-                            sr_miso.eq(Cat(miso, sr_miso[:-1]))
-                        )
-                    )
-            self.comb += self._miso.status.eq(sr_miso)
-
-        # mosi
-        if hasattr(pads, "mosi"):
-            mosi = Signal()
-            sr_mosi = Signal(width)
-
-            # (cpha = 1: propagated on clk rising edge)
-            if cpha:
-                self.sync += \
-                    If(start,
-                        sr_mosi.eq(self._mosi.storage)
-                    ).Elif(clr_clk & enable_shift,
-                        sr_mosi.eq(Cat(Signal(), sr_mosi[:-1]))
-                    ).Elif(set_clk,
-                        pads.mosi.eq(sr_mosi[-1])
-                    )
-
-            # (cpha = 0: propagated on clk falling edge)
-            else:
-                self.sync += [
-                    If(start,
-                        sr_mosi.eq(self._mosi.storage)
-                    ).Elif(set_clk & enable_shift,
-                        sr_mosi.eq(Cat(Signal(), sr_mosi[:-1]))
-                    ).Elif(clr_clk,
-                        pads.mosi.eq(sr_mosi[-1])
-                    )
-                ]
-
-        # cs_n
-        self.comb += pads.cs_n.eq(~enable_cs)
diff --git a/misoclib/com/spi/test/spi_master_tb.py b/misoclib/com/spi/test/spi_master_tb.py
deleted file mode 100644 (file)
index f20aa19..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.record import *
-from migen.sim.generic import run_simulation
-
-from misoclib.com.spi import SPIMaster
-
-
-class SPISlave(Module):
-    def __init__(self, pads, width):
-        self.pads = pads
-        self.width = width
-
-        ###
-
-        self.mosi = 0
-        self.miso = 0
-
-        self.last_cs_n = 1
-        self.last_clk = 0
-
-
-    def get_mosi(self):
-        return self.mosi
-
-    def set_miso(self, value):
-        self.miso = value
-
-    def do_simulation(self, selfp):
-        # detect edges
-        cs_n_rising = 0
-        cs_n_falling = 0
-        clk_rising = 0
-        clk_falling = 0
-        if selfp.pads.cs_n and not self.last_cs_n:
-            cs_n_rising = 1
-        if not selfp.pads.cs_n and self.last_cs_n:
-            cs_n_falling = 1
-        if selfp.pads.clk and not self.last_clk:
-            clk_rising = 1
-        if not selfp.pads.clk and self.last_clk:
-            clk_falling = 1
-
-        # input mosi
-        if clk_falling and not selfp.pads.cs_n:
-            self.mosi = self.mosi << 1
-            self.mosi |= selfp.pads.mosi
-
-        # output miso
-        if (clk_rising and not selfp.pads.cs_n):
-            selfp.pads.miso = (self.miso >> (self.width-1)) & 0x1
-            self.miso = self.miso << 1
-
-        # save signal states
-        self.last_cs_n = selfp.pads.cs_n
-        self.last_clk = selfp.pads.clk
-
-
-def spi_access(selfp, length, mosi):
-    selfp.spi_master._mosi.storage = mosi
-    yield
-    selfp.spi_master._ctrl.r = (length << 8) | 1
-    selfp.spi_master._ctrl.re = 1
-    yield
-    selfp.spi_master._ctrl.r = 0
-    selfp.spi_master._ctrl.re = 0
-    yield
-    while not (selfp.spi_master._status.status & 0x1):
-        yield
-
-
-class TB(Module):
-    def __init__(self):
-        pads = Record([("cs_n", 1), ("clk", 1), ("mosi", 1), ("miso", 1)])
-        self.submodules.spi_master = SPIMaster(pads, 24, 4)
-        self.submodules.spi_slave = SPISlave(pads, 24)
-
-    def gen_simulation(self, selfp):
-        for i in range(16):
-            yield
-        self.spi_slave.set_miso(0x123457)
-        yield from spi_access(selfp, 8, 0x123457)
-        print("{:08x}".format(self.spi_slave.get_mosi()))
-        print("{:08x}".format(selfp.spi_master._miso.status))
-
-if __name__ == "__main__":
-    run_simulation(TB(), ncycles=1000, vcd_name="my.vcd", keep_files=True)
diff --git a/misoclib/com/uart/__init__.py b/misoclib/com/uart/__init__.py
deleted file mode 100644 (file)
index ffc39b4..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-from migen.genlib.record import Record
-from migen.actorlib.fifo import SyncFIFO, AsyncFIFO
-
-
-def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
-    if sink_cd != source_cd:
-        fifo = AsyncFIFO([("data", 8)], depth)
-        return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
-    else:
-        return SyncFIFO([("data", 8)], depth)
-
-
-class UART(Module, AutoCSR):
-    def __init__(self, phy,
-                 tx_fifo_depth=16,
-                 rx_fifo_depth=16,
-                 phy_cd="sys"):
-        self._rxtx = CSR(8)
-        self._txfull = CSRStatus()
-        self._rxempty = CSRStatus()
-
-        self.submodules.ev = EventManager()
-        self.ev.tx = EventSourceProcess()
-        self.ev.rx = EventSourceProcess()
-        self.ev.finalize()
-
-        # # #
-
-        # TX
-        tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
-        self.submodules += tx_fifo
-
-        self.comb += [
-            tx_fifo.sink.stb.eq(self._rxtx.re),
-            tx_fifo.sink.data.eq(self._rxtx.r),
-            self._txfull.status.eq(~tx_fifo.sink.ack),
-            Record.connect(tx_fifo.source, phy.sink),
-            # Generate TX IRQ when tx_fifo becomes non-full
-            self.ev.tx.trigger.eq(~tx_fifo.sink.ack)
-        ]
-
-
-        # RX
-        rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
-        self.submodules += rx_fifo
-
-
-        self.comb += [
-            Record.connect(phy.source, rx_fifo.sink),
-            self._rxempty.status.eq(~rx_fifo.source.stb),
-            self._rxtx.w.eq(rx_fifo.source.data),
-            rx_fifo.source.ack.eq(self.ev.rx.clear),
-            # Generate RX IRQ when tx_fifo becomes non-empty
-            self.ev.rx.trigger.eq(~rx_fifo.source.stb)
-        ]
diff --git a/misoclib/com/uart/bridge.py b/misoclib/com/uart/bridge.py
deleted file mode 100644 (file)
index fc0d292..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-from migen.fhdl.std import *
-
-from misoclib.tools.wishbone import WishboneStreamingBridge
-from misoclib.com.uart.phy.serial import UARTPHYSerial
-
-class UARTWishboneBridge(WishboneStreamingBridge):
-    def __init__(self, pads, clk_freq, baudrate=115200):
-        self.submodules.phy = UARTPHYSerial(pads, clk_freq, baudrate)
-        WishboneStreamingBridge.__init__(self, self.phy, clk_freq)
diff --git a/misoclib/com/uart/phy/__init__.py b/misoclib/com/uart/phy/__init__.py
deleted file mode 100644 (file)
index c6506c8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-def UARTPHY(pads, *args, **kwargs):
-    # Autodetect PHY
-    if hasattr(pads, "source_stb"):
-        from misoclib.com.uart.phy.sim import UARTPHYSim
-        return UARTPHYSim(pads, *args, **kwargs)
-    else:
-        from misoclib.com.uart.phy.serial import UARTPHYSerial
-        return UARTPHYSerial(pads, *args, **kwargs)
diff --git a/misoclib/com/uart/phy/serial.py b/misoclib/com/uart/phy/serial.py
deleted file mode 100644 (file)
index 747dbd2..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-from migen.flow.actor import Sink, Source
-
-
-class UARTPHYSerialRX(Module):
-    def __init__(self, pads, tuning_word):
-        self.source = Source([("data", 8)])
-        ###
-        uart_clk_rxen = Signal()
-        phase_accumulator_rx = Signal(32)
-
-        rx = Signal()
-        self.specials += MultiReg(pads.rx, rx)
-        rx_r = Signal()
-        rx_reg = Signal(8)
-        rx_bitcount = Signal(4)
-        rx_busy = Signal()
-        rx_done = self.source.stb
-        rx_data = self.source.data
-        self.sync += [
-            rx_done.eq(0),
-            rx_r.eq(rx),
-            If(~rx_busy,
-                If(~rx & rx_r,  # look for start bit
-                    rx_busy.eq(1),
-                    rx_bitcount.eq(0),
-                )
-            ).Else(
-                If(uart_clk_rxen,
-                    rx_bitcount.eq(rx_bitcount + 1),
-                    If(rx_bitcount == 0,
-                        If(rx,  # verify start bit
-                            rx_busy.eq(0)
-                        )
-                    ).Elif(rx_bitcount == 9,
-                        rx_busy.eq(0),
-                        If(rx,  # verify stop bit
-                            rx_data.eq(rx_reg),
-                            rx_done.eq(1)
-                        )
-                    ).Else(
-                        rx_reg.eq(Cat(rx_reg[1:], rx))
-                    )
-                )
-            )
-        ]
-        self.sync += \
-                If(rx_busy,
-                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(phase_accumulator_rx + tuning_word)
-                ).Else(
-                    Cat(phase_accumulator_rx, uart_clk_rxen).eq(2**31)
-                )
-
-
-class UARTPHYSerialTX(Module):
-    def __init__(self, pads, tuning_word):
-        self.sink = Sink([("data", 8)])
-        ###
-        uart_clk_txen = Signal()
-        phase_accumulator_tx = Signal(32)
-
-        pads.tx.reset = 1
-
-        tx_reg = Signal(8)
-        tx_bitcount = Signal(4)
-        tx_busy = Signal()
-        self.sync += [
-            self.sink.ack.eq(0),
-            If(self.sink.stb & ~tx_busy & ~self.sink.ack,
-                tx_reg.eq(self.sink.data),
-                tx_bitcount.eq(0),
-                tx_busy.eq(1),
-                pads.tx.eq(0)
-            ).Elif(uart_clk_txen & tx_busy,
-                tx_bitcount.eq(tx_bitcount + 1),
-                If(tx_bitcount == 8,
-                    pads.tx.eq(1)
-                ).Elif(tx_bitcount == 9,
-                    pads.tx.eq(1),
-                    tx_busy.eq(0),
-                    self.sink.ack.eq(1),
-                ).Else(
-                    pads.tx.eq(tx_reg[0]),
-                    tx_reg.eq(Cat(tx_reg[1:], 0))
-                )
-            )
-        ]
-        self.sync += [
-                If(tx_busy,
-                    Cat(phase_accumulator_tx, uart_clk_txen).eq(phase_accumulator_tx + tuning_word)
-                ).Else(
-                    Cat(phase_accumulator_tx, uart_clk_txen).eq(0)
-                )
-        ]
-
-
-class UARTPHYSerial(Module, AutoCSR):
-    def __init__(self, pads, clk_freq, baudrate=115200):
-        self._tuning_word = CSRStorage(32, reset=int((baudrate/clk_freq)*2**32))
-        self.submodules.tx = UARTPHYSerialTX(pads, self._tuning_word.storage)
-        self.submodules.rx = UARTPHYSerialRX(pads, self._tuning_word.storage)
-        self.sink, self.source = self.tx.sink, self.rx.source
diff --git a/misoclib/com/uart/phy/sim.py b/misoclib/com/uart/phy/sim.py
deleted file mode 100644 (file)
index a7348e0..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-import os
-import pty
-import time
-
-from migen.fhdl.std import *
-from migen.flow.actor import Sink, Source
-
-
-class UARTPHYSim(Module):
-    def __init__(self, pads, *args, **kwargs):
-        self.sink = Sink([("data", 8)])
-        self.source = Source([("data", 8)])
-
-        self.comb += [
-            pads.source_stb.eq(self.sink.stb),
-            pads.source_data.eq(self.sink.data),
-            self.sink.ack.eq(pads.source_ack),
-
-            self.source.stb.eq(pads.sink_stb),
-            self.source.data.eq(pads.sink_data),
-            pads.sink_ack.eq(self.source.ack)
-        ]
-
-        m, s = pty.openpty()
-        name = os.ttyname(s)
-        print("UART tty: "+name)
-        time.sleep(0.5)  # pause for user
-        f = open("/tmp/simserial", "w")
-        f.write(os.ttyname(s))
-        f.close()
-
-    def do_exit(self, *args, **kwargs):
-        os.remove("/tmp/simserial")
diff --git a/misoclib/com/uart/software/__init__.py b/misoclib/com/uart/software/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/com/uart/software/reg.py b/misoclib/com/uart/software/reg.py
deleted file mode 100644 (file)
index 204a626..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-import csv
-
-
-class MappedReg:
-    def __init__(self, readfn, writefn, name, addr, length, busword, mode):
-        self.readfn = readfn
-        self.writefn = writefn
-        self.addr = addr
-        self.length = length
-        self.busword = busword
-        self.mode = mode
-
-    def read(self):
-        if self.mode not in ["rw", "ro"]:
-            raise KeyError(name + "register not readable")
-        datas = self.readfn(self.addr, burst_length=self.length)
-        if isinstance(datas, int):
-            return datas
-        else:
-            data = 0
-            for i in range(self.length):
-                data = data << self.busword
-                data |= datas[i]
-            return data
-    def write(self, value):
-        if self.mode not in ["rw", "wo"]:
-            raise KeyError(name + "register not writable")
-        datas = []
-        for i in range(self.length):
-            datas.append((value >> ((self.length-1-i)*self.busword)) & (2**self.busword-1))
-        self.writefn(self.addr, datas)
-
-
-class MappedRegs:
-    def __init__(self, d):
-        self.d = d
-
-    def __getattr__(self, attr):
-        try:
-            return self.__dict__['d'][attr]
-        except KeyError:
-            pass
-        raise KeyError("No such register " + attr)
-
-
-def build_map(addrmap, busword, readfn, writefn):
-    csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#')
-    d = {}
-    for item in csv_reader:
-        name, addr, length, mode = item
-        addr = int(addr.replace("0x", ""), 16)
-        length = int(length)
-        d[name] = MappedReg(readfn, writefn, name, addr, length, busword, mode)
-    return MappedRegs(d)
diff --git a/misoclib/com/uart/software/wishbone.py b/misoclib/com/uart/software/wishbone.py
deleted file mode 100644 (file)
index d581dbb..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-import serial
-from struct import *
-from misoclib.com.uart.software.reg import *
-
-
-def write_b(uart, data):
-    uart.write(pack('B', data))
-
-
-class UARTWishboneBridgeDriver:
-    cmds = {
-        "write": 0x01,
-        "read":  0x02
-    }
-    def __init__(self, port, baudrate=115200, addrmap=None, busword=8, debug=False):
-        self.port = port
-        self.baudrate = str(baudrate)
-        self.debug = debug
-        self.uart = serial.Serial(port, baudrate, timeout=0.25)
-        if addrmap is not None:
-            self.regs = build_map(addrmap, busword, self.read, self.write)
-
-    def open(self):
-        self.uart.flushOutput()
-        self.uart.close()
-        self.uart.open()
-        self.uart.flushInput()
-
-    def close(self):
-        self.uart.flushOutput()
-        self.uart.close()
-
-    def read(self, addr, burst_length=1):
-        datas = []
-        self.uart.flushInput()
-        write_b(self.uart, self.cmds["read"])
-        write_b(self.uart, burst_length)
-        word_addr = addr//4
-        write_b(self.uart, (word_addr >> 24) & 0xff)
-        write_b(self.uart, (word_addr >> 16) & 0xff)
-        write_b(self.uart, (word_addr >>  8) & 0xff)
-        write_b(self.uart, (word_addr >>  0) & 0xff)
-        for i in range(burst_length):
-            data = 0
-            for k in range(4):
-                data = data << 8
-                data |= ord(self.uart.read())
-            if self.debug:
-                print("RD {:08X} @ {:08X}".format(data, addr + 4*i))
-            datas.append(data)
-        if burst_length == 1:
-            return datas[0]
-        else:
-            return datas
-
-    def write(self, addr, data):
-        if isinstance(data, list):
-            burst_length = len(data)
-        else:
-            burst_length = 1
-            data = [data]
-        write_b(self.uart, self.cmds["write"])
-        write_b(self.uart, burst_length)
-        word_addr = addr//4
-        write_b(self.uart, (word_addr >> 24) & 0xff)
-        write_b(self.uart, (word_addr >> 16) & 0xff)
-        write_b(self.uart, (word_addr >>  8) & 0xff)
-        write_b(self.uart, (word_addr >>  0) & 0xff)
-        for i in range(len(data)):
-            dat = data[i]
-            for j in range(4):
-                write_b(self.uart, (dat >> 24) & 0xff)
-                dat = dat << 8
-            if self.debug:
-                print("WR {:08X} @ {:08X}".format(data[i], addr + 4*i))
diff --git a/misoclib/com/uart/test/test_serial_phy.py b/misoclib/com/uart/test/test_serial_phy.py
deleted file mode 100644 (file)
index 71318c7..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-# XXX Adapt test to new architecture
-class UARTTB(Module):
-    def __init__(self):
-        self.clk_freq = 83333333
-        self.baud = 3000000
-        self.pads = Record([("rx", 1), ("tx", 1)])
-        self.submodules.slave = UART(self.pads, self.clk_freq, self.baud)
-
-    def wait_for(self, ns_time):
-        freq_in_ghz = self.clk_freq/(10**9)
-        period = 1/freq_in_ghz
-        num_loops = int(ns_time/period)
-        for i in range(num_loops+1):
-            yield
-
-    def gen_simulation(self, selfp):
-        baud_in_ghz = self.baud/(10**9)
-        uart_period = int(1/baud_in_ghz)
-        half_uart_period = int(1/(2*baud_in_ghz))
-
-        # Set TX an RX lines idle
-        selfp.pads.tx = 1
-        selfp.pads.rx = 1
-        yield
-
-        # First send a few characters
-
-        tx_string = "01234"
-        print("Sending string: " + tx_string)
-        for c in tx_string:
-            selfp.slave._r_rxtx.r = ord(c)
-            selfp.slave._r_rxtx.re = 1
-            yield
-            selfp.slave._r_rxtx.re = 0
-
-            yield from self.wait_for(half_uart_period)
-
-            if selfp.pads.tx:
-                print("FAILURE: no start bit sent")
-
-            val = 0
-            for i in range(8):
-                yield from self.wait_for(uart_period)
-                val >>= 1
-                if selfp.pads.tx:
-                    val |= 0x80
-
-            yield from self.wait_for(uart_period)
-
-            if selfp.pads.tx == 0:
-                print("FAILURE: no stop bit sent")
-
-            if ord(c) != val:
-                print("FAILURE: sent decimal value "+str(val)+" (char "+chr(val)+") instead of "+c)
-            else:
-                print("SUCCESS: sent "+c)
-            while selfp.slave.ev.tx.trigger != 1:
-                yield
-
-        # Then receive a character
-
-        rx_string = '5'
-        print("Receiving character "+rx_string)
-        rx_value = ord(rx_string)
-        for i in range(11):
-            if (i == 0):
-                # start bit
-                selfp.pads.rx = 0
-            elif (i == 9):
-                # stop bit
-                selfp.pads.rx = 1
-            elif (i == 10):
-                selfp.pads.rx = 1
-                break
-            else:
-                selfp.pads.rx = 1 if (rx_value & 1) else 0
-                rx_value >>= 1
-            yield from self.wait_for(uart_period)
-
-        rx_value = ord(rx_string)
-        received_value = selfp.slave._r_rxtx.w
-        if (received_value == rx_value):
-            print("RX SUCCESS: ")
-        else:
-            print("RX FAILURE: ")
-
-        print("received "+chr(received_value))
-
-        while True:
-            yield
-
-if __name__ == "__main__":
-    from migen.sim.generic import Simulator, TopLevel
-    from migen.sim import icarus
-    with Simulator(UARTTB(), TopLevel("top.vcd", clk_period=int(1/0.08333333)),
-                   icarus.Runner(keep_files=False)) as s:
-        s.run(20000)
diff --git a/misoclib/cpu/__init__.py b/misoclib/cpu/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/cpu/identifier.py b/misoclib/cpu/identifier.py
deleted file mode 100644 (file)
index 7f24c61..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-import subprocess
-
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-def get_id():
-    output = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii")
-    return int(output[:8], 16)
-
-
-class Identifier(Module, AutoCSR):
-    def __init__(self, sysid, frequency, revision=None):
-        self._sysid = CSRStatus(16)
-        self._revision = CSRStatus(32)
-        self._frequency = CSRStatus(32)
-
-        ###
-
-        if revision is None:
-            revision = get_id()
-
-        self.comb += [
-            self._sysid.status.eq(sysid),
-            self._revision.status.eq(revision),
-            self._frequency.status.eq(frequency)
-        ]
diff --git a/misoclib/cpu/lm32.py b/misoclib/cpu/lm32.py
deleted file mode 100644 (file)
index 8ea7637..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-import os
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-
-
-class LM32(Module):
-    def __init__(self, platform, eba_reset):
-        self.ibus = i = wishbone.Interface()
-        self.dbus = d = wishbone.Interface()
-        self.interrupt = Signal(32)
-
-        ###
-
-        i_adr_o = Signal(32)
-        d_adr_o = Signal(32)
-        self.specials += Instance("lm32_cpu",
-                                   p_eba_reset=Instance.PreformattedParam("32'h{:08x}".format(eba_reset)),
-
-                                   i_clk_i=ClockSignal(),
-                                   i_rst_i=ResetSignal(),
-
-                                   i_interrupt=self.interrupt,
-
-                                   o_I_ADR_O=i_adr_o,
-                                   o_I_DAT_O=i.dat_w,
-                                   o_I_SEL_O=i.sel,
-                                   o_I_CYC_O=i.cyc,
-                                   o_I_STB_O=i.stb,
-                                   o_I_WE_O=i.we,
-                                   o_I_CTI_O=i.cti,
-                                   o_I_BTE_O=i.bte,
-                                   i_I_DAT_I=i.dat_r,
-                                   i_I_ACK_I=i.ack,
-                                   i_I_ERR_I=i.err,
-                                   i_I_RTY_I=0,
-
-                                   o_D_ADR_O=d_adr_o,
-                                   o_D_DAT_O=d.dat_w,
-                                   o_D_SEL_O=d.sel,
-                                   o_D_CYC_O=d.cyc,
-                                   o_D_STB_O=d.stb,
-                                   o_D_WE_O=d.we,
-                                   o_D_CTI_O=d.cti,
-                                   o_D_BTE_O=d.bte,
-                                   i_D_DAT_I=d.dat_r,
-                                   i_D_ACK_I=d.ack,
-                                   i_D_ERR_I=d.err,
-                                   i_D_RTY_I=0)
-
-        self.comb += [
-            self.ibus.adr.eq(i_adr_o[2:]),
-            self.dbus.adr.eq(d_adr_o[2:])
-        ]
-
-        # add Verilog sources
-        platform.add_sources(os.path.join("extcores", "lm32", "submodule", "rtl"),
-                "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
-                "lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
-                "lm32_shifter.v", "lm32_multiplier.v", "lm32_mc_arithmetic.v",
-                "lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
-                "lm32_dcache.v", "lm32_debug.v", "lm32_itlb.v", "lm32_dtlb.v")
-        platform.add_verilog_include_path(os.path.join("extcores", "lm32"))
diff --git a/misoclib/cpu/mor1kx.py b/misoclib/cpu/mor1kx.py
deleted file mode 100644 (file)
index 1169aba..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-import os
-
-from migen.fhdl.std import *
-from migen.bus import wishbone
-
-
-class MOR1KX(Module):
-    def __init__(self, platform, reset_pc):
-        self.ibus = i = wishbone.Interface()
-        self.dbus = d = wishbone.Interface()
-        self.interrupt = Signal(32)
-
-        ###
-
-        i_adr_o = Signal(32)
-        d_adr_o = Signal(32)
-        self.specials += Instance("mor1kx",
-                                  p_FEATURE_INSTRUCTIONCACHE="ENABLED",
-                                  p_OPTION_ICACHE_BLOCK_WIDTH=4,
-                                  p_OPTION_ICACHE_SET_WIDTH=8,
-                                  p_OPTION_ICACHE_WAYS=1,
-                                  p_OPTION_ICACHE_LIMIT_WIDTH=31,
-                                  p_FEATURE_DATACACHE="ENABLED",
-                                  p_OPTION_DCACHE_BLOCK_WIDTH=4,
-                                  p_OPTION_DCACHE_SET_WIDTH=8,
-                                  p_OPTION_DCACHE_WAYS=1,
-                                  p_OPTION_DCACHE_LIMIT_WIDTH=31,
-                                  p_FEATURE_TIMER="NONE",
-                                  p_OPTION_PIC_TRIGGER="LEVEL",
-                                  p_FEATURE_SYSCALL="NONE",
-                                  p_FEATURE_TRAP="NONE",
-                                  p_FEATURE_RANGE="NONE",
-                                  p_FEATURE_OVERFLOW="NONE",
-                                  p_FEATURE_ADDC="ENABLED",
-                                  p_FEATURE_CMOV="ENABLED",
-                                  p_FEATURE_FFL1="ENABLED",
-                                  p_OPTION_CPU0="CAPPUCCINO",
-                                  p_OPTION_RESET_PC=reset_pc,
-                                  p_IBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
-                                  p_DBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
-
-                                  i_clk=ClockSignal(),
-                                  i_rst=ResetSignal(),
-
-                                  i_irq_i=self.interrupt,
-
-                                  o_iwbm_adr_o=i_adr_o,
-                                  o_iwbm_dat_o=i.dat_w,
-                                  o_iwbm_sel_o=i.sel,
-                                  o_iwbm_cyc_o=i.cyc,
-                                  o_iwbm_stb_o=i.stb,
-                                  o_iwbm_we_o=i.we,
-                                  o_iwbm_cti_o=i.cti,
-                                  o_iwbm_bte_o=i.bte,
-                                  i_iwbm_dat_i=i.dat_r,
-                                  i_iwbm_ack_i=i.ack,
-                                  i_iwbm_err_i=i.err,
-                                  i_iwbm_rty_i=0,
-
-                                  o_dwbm_adr_o=d_adr_o,
-                                  o_dwbm_dat_o=d.dat_w,
-                                  o_dwbm_sel_o=d.sel,
-                                  o_dwbm_cyc_o=d.cyc,
-                                  o_dwbm_stb_o=d.stb,
-                                  o_dwbm_we_o=d.we,
-                                  o_dwbm_cti_o=d.cti,
-                                  o_dwbm_bte_o=d.bte,
-                                  i_dwbm_dat_i=d.dat_r,
-                                  i_dwbm_ack_i=d.ack,
-                                  i_dwbm_err_i=d.err,
-                                  i_dwbm_rty_i=0)
-
-        self.comb += [
-            self.ibus.adr.eq(i_adr_o[2:]),
-            self.dbus.adr.eq(d_adr_o[2:])
-        ]
-
-        # add Verilog sources
-        platform.add_source_dir(os.path.join("extcores", "mor1kx", "submodule",
-                                             "rtl", "verilog"))
diff --git a/misoclib/cpu/timer.py b/misoclib/cpu/timer.py
deleted file mode 100644 (file)
index 4061f83..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-
-
-class Timer(Module, AutoCSR):
-    def __init__(self, width=32):
-        self._load = CSRStorage(width)
-        self._reload = CSRStorage(width)
-        self._en = CSRStorage()
-        self._update_value = CSR()
-        self._value = CSRStatus(width)
-
-        self.submodules.ev = EventManager()
-        self.ev.zero = EventSourceProcess()
-        self.ev.finalize()
-
-        ###
-
-        value = Signal(width)
-        self.sync += [
-            If(self._en.storage,
-                If(value == 0,
-                    # set reload to 0 to disable reloading
-                    value.eq(self._reload.storage)
-                ).Else(
-                    value.eq(value - 1)
-                )
-            ).Else(
-                value.eq(self._load.storage)
-            ),
-            If(self._update_value.re, self._value.status.eq(value))
-        ]
-        self.comb += self.ev.zero.trigger.eq(value != 0)
diff --git a/misoclib/mem/__init__.py b/misoclib/mem/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/mem/flash/__init__.py b/misoclib/mem/flash/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/mem/flash/norflash16.py b/misoclib/mem/flash/norflash16.py
deleted file mode 100644 (file)
index 42c68c0..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.fsm import FSM, NextState
-
-
-class NorFlash16(Module):
-    def __init__(self, pads, rd_timing, wr_timing):
-        self.bus = wishbone.Interface()
-
-        ###
-
-        data = TSTriple(16)
-        lsb = Signal()
-
-        self.specials += data.get_tristate(pads.d)
-        self.comb += [
-            data.oe.eq(pads.oe_n),
-            pads.ce_n.eq(0)
-        ]
-
-        load_lo = Signal()
-        load_hi = Signal()
-        store = Signal()
-
-        pads.oe_n.reset, pads.we_n.reset = 1, 1
-        self.sync += [
-            pads.oe_n.eq(1),
-            pads.we_n.eq(1),
-
-            # Register data/address to avoid off-chip glitches
-            If(self.bus.cyc & self.bus.stb,
-                pads.adr.eq(Cat(lsb, self.bus.adr)),
-                If(self.bus.we,
-                    # Only 16-bit writes are supported. Assume sel=0011 or 1100.
-                    If(self.bus.sel[0],
-                        data.o.eq(self.bus.dat_w[:16])
-                    ).Else(
-                        data.o.eq(self.bus.dat_w[16:])
-                    )
-                ).Else(
-                    pads.oe_n.eq(0)
-                )
-            ),
-
-            If(load_lo, self.bus.dat_r[:16].eq(data.i)),
-            If(load_hi, self.bus.dat_r[16:].eq(data.i)),
-            If(store, pads.we_n.eq(0))
-        ]
-
-        # Typical timing of the flash chips:
-        #  - 110ns address to output
-        #  - 50ns write pulse width
-        counter = Signal(max=max(rd_timing, wr_timing)+1)
-        counter_en = Signal()
-        counter_wr_mode = Signal()
-        counter_done = Signal()
-        self.comb += counter_done.eq(counter == Mux(counter_wr_mode, wr_timing, rd_timing))
-        self.sync += If(counter_en & ~counter_done,
-                counter.eq(counter + 1)
-            ).Else(
-                counter.eq(0)
-            )
-
-        fsm = FSM()
-        self.submodules += fsm
-
-        fsm.act("IDLE",
-            If(self.bus.cyc & self.bus.stb,
-                If(self.bus.we,
-                    NextState("WR")
-                ).Else(
-                    NextState("RD_HI")
-                )
-            )
-        )
-        fsm.act("RD_HI",
-            lsb.eq(0),
-            counter_en.eq(1),
-            If(counter_done,
-                load_hi.eq(1),
-                NextState("RD_LO")
-            )
-        )
-        fsm.act("RD_LO",
-            lsb.eq(1),
-            counter_en.eq(1),
-            If(counter_done,
-                load_lo.eq(1),
-                NextState("ACK")
-            )
-        )
-        fsm.act("WR",
-            # supported cases: sel=0011 [lsb=1] and sel=1100 [lsb=0]
-            lsb.eq(self.bus.sel[0]),
-            counter_wr_mode.eq(1),
-            counter_en.eq(1),
-            store.eq(1),
-            If(counter_done, NextState("ACK"))
-        )
-        fsm.act("ACK",
-            self.bus.ack.eq(1),
-            NextState("IDLE")
-        )
diff --git a/misoclib/mem/flash/spiflash.py b/misoclib/mem/flash/spiflash.py
deleted file mode 100644 (file)
index 1e099a7..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import *
-from migen.bus import wishbone
-from migen.genlib.misc import timeline
-from migen.genlib.record import Record
-from migen.bank.description import AutoCSR, CSRStorage, CSRStatus
-
-_FAST_READ = 0x0b
-_DIOFR = 0xbb
-_QIOFR = 0xeb
-
-
-def _format_cmd(cmd, spi_width):
-    """
-    `cmd` is the read instruction. Since everything is transmitted on all
-    dq lines (cmd, adr and data), extend/interleave cmd to full pads.dq
-    width even if dq1-dq3 are don't care during the command phase:
-    For example, for N25Q128, 0xeb is the quad i/o fast read, and
-    extended to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
-    """
-    c = 2**(8*spi_width)-1
-    for b in range(8):
-        if not (cmd>>b)%2:
-            c &= ~(1<<(b*spi_width))
-    return c
-
-
-class SpiFlash(Module, AutoCSR):
-    def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
-        """
-        Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.
-
-        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
-        Read). Only supports mode0 (cpol=0, cpha=0).
-        Optionally supports software bitbanging (for write, erase, or other commands).
-        """
-        self.bus = bus = wishbone.Interface()
-        spi_width = flen(pads.dq)
-        if with_bitbang:
-            self.bitbang = CSRStorage(4)
-            self.miso = CSRStatus()
-            self.bitbang_en = CSRStorage()
-
-        ###
-
-        cs_n = Signal(reset=1)
-        clk = Signal()
-        dq_oe = Signal()
-        wbone_width = flen(bus.dat_r)
-
-
-        read_cmd_params = {
-            4: (_format_cmd(_QIOFR, 4), 4*8),
-            2: (_format_cmd(_DIOFR, 2), 2*8),
-            1: (_format_cmd(_FAST_READ, 1), 1*8)
-        }
-        read_cmd, cmd_width = read_cmd_params[spi_width]
-        addr_width = 24
-
-        pads.cs_n.reset = 1
-
-        dq = TSTriple(spi_width)
-        self.specials.dq = dq.get_tristate(pads.dq)
-
-        sr = Signal(max(cmd_width, addr_width, wbone_width))
-        dqs = Replicate(1, spi_width-1)
-
-        self.comb += bus.dat_r.eq(sr)
-
-        hw_read_logic = [
-            pads.clk.eq(clk),
-            pads.cs_n.eq(cs_n),
-            dq.o.eq(sr[-spi_width:]),
-            dq.oe.eq(dq_oe)
-        ]
-
-        if with_bitbang:
-            bitbang_logic = [
-                pads.clk.eq(self.bitbang.storage[1]),
-                pads.cs_n.eq(self.bitbang.storage[2]),
-                dq.o.eq(Cat(self.bitbang.storage[0], dqs)),
-                If(self.bitbang.storage[3],
-                    dq.oe.eq(0)
-                ).Else(
-                    dq.oe.eq(1)
-                ),
-                If(self.bitbang.storage[1],
-                    self.miso.status.eq(dq.i[1])
-                )
-            ]
-
-            self.comb += \
-                If(self.bitbang_en.storage,
-                    bitbang_logic
-                ).Else(
-                    hw_read_logic
-                )
-        else:
-            self.comb += hw_read_logic
-
-        if div < 2:
-            raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
-        else:
-            i = Signal(max=div)
-            dqi = Signal(spi_width)
-            self.sync += [
-                If(i == div//2 - 1,
-                    clk.eq(1),
-                    dqi.eq(dq.i),
-                ),
-                If(i == div - 1,
-                    i.eq(0),
-                    clk.eq(0),
-                    sr.eq(Cat(dqi, sr[:-spi_width]))
-                ).Else(
-                    i.eq(i + 1),
-                ),
-            ]
-
-        # spi is byte-addressed, prefix by zeros
-        z = Replicate(0, log2_int(wbone_width//8))
-
-        seq = [
-            (cmd_width//spi_width*div,
-                [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
-            (addr_width//spi_width*div,
-                [sr[-addr_width:].eq(Cat(z, bus.adr))]),
-            ((dummy + wbone_width//spi_width)*div,
-                [dq_oe.eq(0)]),
-            (1,
-                [bus.ack.eq(1), cs_n.eq(1)]),
-            (div, # tSHSL!
-                [bus.ack.eq(0)]),
-            (0,
-                []),
-        ]
-
-        # accumulate timeline deltas
-        t, tseq = 0, []
-        for dt, a in seq:
-            tseq.append((t, a))
-            t += dt
-
-        self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
-
-
-class SpiFlashTB(Module):
-    def __init__(self):
-        self.submodules.master = wishbone.Initiator(self.gen_reads())
-        self.pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
-        self.submodules.slave = SpiFlash(self.pads)
-        self.submodules.tap = wishbone.Tap(self.slave.bus)
-        self.submodules.intercon = wishbone.InterconnectPointToPoint(
-                self.master.bus, self.slave.bus)
-        self.cycle = 0
-
-    def gen_reads(self):
-        for a in range(10):
-            t = TRead(a)
-            yield t
-            print("read {} in {} cycles(s)".format(t.data, t.latency))
-
-    def do_simulation(self, selfp):
-        if selfp.pads.cs_n:
-            self.cycle = 0
-        else:
-            self.cycle += 1
-            if not selfp.slave.dq.oe:
-                selfp.slave.dq.i = self.cycle & 0xf
-    do_simulation.passive = True
-
-if __name__ == "__main__":
-    from migen.sim.generic import run_simulation
-    from migen.fhdl import verilog
-
-    pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
-    s = SpiFlash(pads)
-    print(verilog.convert(s, ios={pads.clk, pads.cs_n, pads.dq, s.bus.adr,
-        s.bus.dat_r, s.bus.cyc, s.bus.ack, s.bus.stb}))
-
-    run_simulation(SpiFlashTB(), vcd_name="spiflash.vcd")
diff --git a/misoclib/mem/sdram/__init__.py b/misoclib/mem/sdram/__init__.py
deleted file mode 100644 (file)
index b327bb0..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-from collections import namedtuple
-
-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")
diff --git a/misoclib/mem/sdram/core/__init__.py b/misoclib/mem/sdram/core/__init__.py
deleted file mode 100644 (file)
index 1892f81..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.record import *
-from migen.bank.description import *
-
-from misoclib.mem.sdram.phy import dfii
-from misoclib.mem.sdram.core import minicon, lasmicon
-from misoclib.mem.sdram.core import lasmixbar
-
-
-class SDRAMCore(Module, AutoCSR):
-    def __init__(self, phy, geom_settings, timing_settings, controller_settings, **kwargs):
-        # DFI
-        self.submodules.dfii = dfii.DFIInjector(geom_settings.addressbits, geom_settings.bankbits,
-                phy.settings.dfi_databits, phy.settings.nphases)
-        self.comb += Record.connect(self.dfii.master, phy.dfi)
-
-        # LASMICON
-        if isinstance(controller_settings, lasmicon.LASMIconSettings):
-            self.submodules.controller = controller = lasmicon.LASMIcon(phy.settings,
-                                                                        geom_settings,
-                                                                        timing_settings,
-                                                                        controller_settings,
-                                                                        **kwargs)
-            self.comb += Record.connect(controller.dfi, self.dfii.slave)
-
-            self.submodules.crossbar = lasmixbar.LASMIxbar([controller.lasmic],
-                                                           controller.nrowbits)
-
-        # MINICON
-        elif isinstance(controller_settings, minicon.MiniconSettings):
-            self.submodules.controller = controller = minicon.Minicon(phy.settings,
-                                                                      geom_settings,
-                                                                      timing_settings)
-            self.comb += Record.connect(controller.dfi, self.dfii.slave)
-        else:
-            raise ValueError("Unsupported SDRAM controller type")
diff --git a/misoclib/mem/sdram/core/lasmibus.py b/misoclib/mem/sdram/core/lasmibus.py
deleted file mode 100644 (file)
index c1d3b0c..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import *
-from migen.genlib import roundrobin
-from migen.genlib.record import *
-from migen.genlib.misc import optree
-
-
-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)
-
-
-class Initiator(Module):
-    def __init__(self, generator, bus):
-        self.generator = generator
-        self.bus = bus
-        self.transaction_start = 0
-        self.transaction = None
-        self.transaction_end = None
-
-    def do_simulation(self, selfp):
-        selfp.bus.dat_w = 0
-        selfp.bus.dat_we = 0
-
-        if self.transaction is not None:
-            if selfp.bus.req_ack:
-                selfp.bus.stb = 0
-            if selfp.bus.dat_ack:
-                if isinstance(self.transaction, TRead):
-                    self.transaction_end = selfp.simulator.cycle_counter + self.bus.read_latency
-                else:
-                    self.transaction_end = selfp.simulator.cycle_counter + self.bus.write_latency - 1
-
-        if self.transaction is None or selfp.simulator.cycle_counter == self.transaction_end:
-            if self.transaction is not None:
-                self.transaction.latency = selfp.simulator.cycle_counter - self.transaction_start - 1
-                if isinstance(self.transaction, TRead):
-                    self.transaction.data = selfp.bus.dat_r
-                else:
-                    selfp.bus.dat_w = self.transaction.data
-                    selfp.bus.dat_we = self.transaction.sel
-            try:
-                self.transaction = next(self.generator)
-            except StopIteration:
-                raise StopSimulation
-            if self.transaction is not None:
-                self.transaction_start = selfp.simulator.cycle_counter
-                selfp.bus.stb = 1
-                selfp.bus.adr = self.transaction.address
-                if isinstance(self.transaction, TRead):
-                    selfp.bus.we = 0
-                else:
-                    selfp.bus.we = 1
-
-
-class TargetModel:
-    def __init__(self):
-        self.last_bank = 0
-
-    def read(self, bank, address):
-        return 0
-
-    def write(self, bank, address, data, we):
-        pass
-
-    # Round-robin scheduling
-    def select_bank(self, pending_banks):
-        if not pending_banks:
-            return -1
-        self.last_bank += 1
-        if self.last_bank > max(pending_banks):
-            self.last_bank = 0
-        while self.last_bank not in pending_banks:
-            self.last_bank += 1
-        return self.last_bank
-
-
-class _ReqFIFO(Module):
-    def __init__(self, req_queue_size, bank):
-        self.req_queue_size = req_queue_size
-        self.bank = bank
-        self.contents = []
-
-    def do_simulation(self, selfp):
-        if len(self.contents) < self.req_queue_size:
-            if selfp.bank.stb:
-                self.contents.append((selfp.bank.we, selfp.bank.adr))
-            selfp.bank.req_ack = 1
-        else:
-            selfp.bank.req_ack = 0
-        selfp.bank.lock = bool(self.contents)
-    do_simulation.passive = True
-
-
-class Target(Module):
-    def __init__(self, model, *ifargs, **ifkwargs):
-        self.model = model
-        self.bus = Interface(*ifargs, **ifkwargs)
-        self.req_fifos = [_ReqFIFO(self.bus.req_queue_size, getattr(self.bus, "bank"+str(nb)))
-            for nb in range(self.bus.nbanks)]
-        self.submodules += self.req_fifos
-        self.rd_pipeline = [None]*self.bus.read_latency
-        self.wr_pipeline = [None]*(self.bus.write_latency + 1)
-
-    def do_simulation(self, selfp):
-        # determine banks with pending requests
-        pending_banks = set(nb for nb, rf in enumerate(self.req_fifos) if rf.contents)
-
-        # issue new transactions
-        selected_bank_n = self.model.select_bank(pending_banks)
-        selected_transaction = None
-        for nb in range(self.bus.nbanks):
-            bank = getattr(selfp.bus, "bank"+str(nb))
-            if nb == selected_bank_n:
-                bank.dat_ack = 1
-                selected_transaction = self.req_fifos[nb].contents.pop(0)
-            else:
-                bank.dat_ack = 0
-
-        rd_transaction = None
-        wr_transaction = None
-        if selected_bank_n >= 0:
-            we, adr = selected_transaction
-            if we:
-                wr_transaction = selected_bank_n, adr
-            else:
-                rd_transaction = selected_bank_n, adr
-
-        # data pipeline
-        self.rd_pipeline.append(rd_transaction)
-        self.wr_pipeline.append(wr_transaction)
-        done_rd_transaction = self.rd_pipeline.pop(0)
-        done_wr_transaction = self.wr_pipeline.pop(0)
-        if done_rd_transaction is not None:
-            selfp.bus.dat_r = self.model.read(done_rd_transaction[0], done_rd_transaction[1])
-        if done_wr_transaction is not None:
-            self.model.write(done_wr_transaction[0], done_wr_transaction[1],
-                selfp.bus.dat_w, selfp.bus.dat_we)
-    do_simulation.passive = True
diff --git a/misoclib/mem/sdram/core/lasmicon/__init__.py b/misoclib/mem/sdram/core/lasmicon/__init__.py
deleted file mode 100644 (file)
index 5614cec..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-from migen.fhdl.std import *
-
-from misoclib.mem.sdram.phy import dfi
-from misoclib.mem.sdram.core import lasmibus
-from misoclib.mem.sdram.core.lasmicon.refresher import *
-from misoclib.mem.sdram.core.lasmicon.bankmachine import *
-from misoclib.mem.sdram.core.lasmicon.multiplexer import *
-
-
-class LASMIconSettings:
-    def __init__(self, req_queue_size=8,
-            read_time=32, write_time=16,
-            l2_size=8192,
-            with_bandwidth=False,
-            with_memtest=False,
-            with_refresh=True):
-        self.req_queue_size = req_queue_size
-        self.read_time = read_time
-        self.write_time = write_time
-        self.l2_size = l2_size
-        if with_memtest:
-            self.with_bandwidth = True
-        else:
-            self.with_bandwidth = with_bandwidth
-        self.with_memtest = with_memtest
-        self.with_refresh = with_refresh
-
-
-class LASMIcon(Module):
-    def __init__(self, phy_settings, geom_settings, timing_settings, controller_settings, **kwargs):
-        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 = lasmibus.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, enabled=controller_settings.with_refresh)
-        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,
-            **kwargs)
-
-    def get_csrs(self):
-        return self.multiplexer.get_csrs()
diff --git a/misoclib/mem/sdram/core/lasmicon/bankmachine.py b/misoclib/mem/sdram/core/lasmicon/bankmachine.py
deleted file mode 100644 (file)
index cd5bcab..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.roundrobin import *
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import optree
-from migen.genlib.fifo import SyncFIFO
-
-from misoclib.mem.sdram.core.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
-        self.submodules.req_fifo = SyncFIFO([("we", 1), ("adr", flen(req.adr))],
-                                            controller_settings.req_queue_size)
-        self.comb += [
-            self.req_fifo.din.we.eq(req.we),
-            self.req_fifo.din.adr.eq(req.adr),
-            self.req_fifo.we.eq(req.stb),
-            req.req_ack.eq(self.req_fifo.writable),
-
-            self.req_fifo.re.eq(req.dat_w_ack | req.dat_r_ack),
-            req.lock.eq(self.req_fifo.readable)
-        ]
-        reqf = self.req_fifo.dout
-
-        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/misoclib/mem/sdram/core/lasmicon/multiplexer.py b/misoclib/mem/sdram/core/lasmicon/multiplexer.py
deleted file mode 100644 (file)
index ca9b962..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.roundrobin import *
-from migen.genlib.misc import optree
-from migen.genlib.fsm import FSM, NextState
-from migen.bank.description import AutoCSR
-
-from misoclib.mem.sdram.core.lasmicon.perf import Bandwidth
-
-
-class CommandRequest:
-    def __init__(self, a, ba):
-        self.a = Signal(a)
-        self.ba = Signal(ba)
-        self.cas_n = Signal(reset=1)
-        self.ras_n = Signal(reset=1)
-        self.we_n = Signal(reset=1)
-
-
-class CommandRequestRW(CommandRequest):
-    def __init__(self, a, ba):
-        CommandRequest.__init__(self, a, ba)
-        self.stb = Signal()
-        self.ack = Signal()
-        self.is_cmd = Signal()
-        self.is_read = Signal()
-        self.is_write = Signal()
-
-
-class _CommandChooser(Module):
-    def __init__(self, requests):
-        self.want_reads = Signal()
-        self.want_writes = Signal()
-        self.want_cmds = Signal()
-        # NB: cas_n/ras_n/we_n are 1 when stb is inactive
-        self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
-
-        ###
-
-        rr = RoundRobin(len(requests), SP_CE)
-        self.submodules += rr
-
-        self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
-            for i, req in enumerate(requests)]
-
-        stb = Signal()
-        self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
-        for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
-            choices = Array(getattr(req, name) for req in requests)
-            self.comb += getattr(self.cmd, name).eq(choices[rr.grant])
-        for name in ["cas_n", "ras_n", "we_n"]:
-            # we should only assert those signals when stb is 1
-            choices = Array(getattr(req, name) for req in requests)
-            self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
-        self.comb += self.cmd.stb.eq(stb \
-            & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
-            & (self.cmd.is_write == self.want_writes))))
-
-        self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
-            for i, req in enumerate(requests)]
-        self.comb += rr.ce.eq(self.cmd.ack)
-
-
-class _Steerer(Module):
-    def __init__(self, commands, dfi):
-        ncmd = len(commands)
-        nph = len(dfi.phases)
-        self.sel = [Signal(max=ncmd) for i in range(nph)]
-
-        ###
-
-        def stb_and(cmd, attr):
-            if not hasattr(cmd, "stb"):
-                return 0
-            else:
-                return cmd.stb & getattr(cmd, attr)
-        for phase, sel in zip(dfi.phases, self.sel):
-            self.comb += [
-                phase.cke.eq(1),
-                phase.cs_n.eq(0)
-            ]
-            if hasattr(phase, "odt"):
-                self.comb += phase.odt.eq(1)
-            if hasattr(phase, "reset_n"):
-                self.comb += phase.reset_n.eq(1)
-            self.sync += [
-                phase.address.eq(Array(cmd.a for cmd in commands)[sel]),
-                phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]),
-                phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]),
-                phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]),
-                phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]),
-                phase.rddata_en.eq(Array(stb_and(cmd, "is_read") for cmd in commands)[sel]),
-                phase.wrdata_en.eq(Array(stb_and(cmd, "is_write") for cmd in commands)[sel])
-            ]
-
-
-class Multiplexer(Module, AutoCSR):
-    def __init__(self, phy_settings, geom_settings, timing_settings, 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(optree("|", [req.stb & req.is_read for req in requests])),
-            write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
-        ]
-
-        def anti_starvation(timeout):
-            en = Signal()
-            max_time = Signal()
-            if timeout:
-                t = timeout - 1
-                time = Signal(max=t+1)
-                self.comb += max_time.eq(time == 0)
-                self.sync += If(~en,
-                        time.eq(t)
-                    ).Elif(~max_time,
-                        time.eq(time - 1)
-                    )
-            else:
-                self.comb += max_time.eq(0)
-            return en, max_time
-        read_time_en, max_read_time = anti_starvation(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(optree("&", [bm.refresh_gnt for bm in bank_machines]))
-
-        # Datapath
-        all_rddata = [p.rddata for p in dfi.phases]
-        all_wrdata = [p.wrdata for p in dfi.phases]
-        all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
-        self.comb += [
-            lasmic.dat_r.eq(Cat(*all_rddata)),
-            Cat(*all_wrdata).eq(lasmic.dat_w),
-            Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
-        ]
-
-        # Control FSM
-        fsm = FSM()
-        self.submodules += fsm
-
-        def steerer_sel(steerer, phy_settings, r_w_n):
-            r = []
-            for i in range(phy_settings.nphases):
-                s = steerer.sel[i].eq(STEER_NOP)
-                if r_w_n == "read":
-                    if i == phy_settings.rdphase:
-                        s = steerer.sel[i].eq(STEER_REQ)
-                    elif i == phy_settings.rdcmdphase:
-                        s = steerer.sel[i].eq(STEER_CMD)
-                elif r_w_n == "write":
-                    if i == phy_settings.wrphase:
-                        s = steerer.sel[i].eq(STEER_REQ)
-                    elif i == phy_settings.wrcmdphase:
-                        s = steerer.sel[i].eq(STEER_CMD)
-                else:
-                    raise ValueError
-                r.append(s)
-            return r
-
-        fsm.act("READ",
-            read_time_en.eq(1),
-            choose_req.want_reads.eq(1),
-            choose_cmd.cmd.ack.eq(1),
-            choose_req.cmd.ack.eq(1),
-            steerer_sel(steerer, phy_settings, "read"),
-            If(write_available,
-                # TODO: switch only after several cycles of ~read_available?
-                If(~read_available | max_read_time, NextState("RTW"))
-            ),
-            If(go_to_refresh, NextState("REFRESH"))
-        )
-        fsm.act("WRITE",
-            write_time_en.eq(1),
-            choose_req.want_writes.eq(1),
-            choose_cmd.cmd.ack.eq(1),
-            choose_req.cmd.ack.eq(1),
-            steerer_sel(steerer, phy_settings, "write"),
-            If(read_available,
-                If(~write_available | max_write_time, NextState("WTR"))
-            ),
-            If(go_to_refresh, NextState("REFRESH"))
-        )
-        fsm.act("REFRESH",
-            steerer.sel[0].eq(STEER_REFRESH),
-            If(~refresher.req, NextState("READ"))
-        )
-        fsm.delayed_enter("RTW", "WRITE", phy_settings.read_latency-1)  # FIXME: reduce this, actual limit is around (cl+1)/nphases
-        fsm.delayed_enter("WTR", "READ", timing_settings.tWTR-1)
-        # FIXME: workaround for zero-delay loop simulation problem with Icarus Verilog
-        fsm.finalize()
-        self.comb += refresher.ack.eq(fsm.state == fsm.encoding["REFRESH"])
-
-        self.with_bandwidth = with_bandwidth
-
-    def add_bandwidth(self):
-        self.with_bandwidth = True
-
-    def do_finalize(self):
-        if self.with_bandwidth:
-            data_width = self.phy_settings.dfi_databits*self.phy_settings.nphases
-            self.submodules.bandwidth = Bandwidth(self.choose_req.cmd, data_width)
diff --git a/misoclib/mem/sdram/core/lasmicon/perf.py b/misoclib/mem/sdram/core/lasmicon/perf.py
deleted file mode 100644 (file)
index 2c7e8cf..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description 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/misoclib/mem/sdram/core/lasmicon/refresher.py b/misoclib/mem/sdram/core/lasmicon/refresher.py
deleted file mode 100644 (file)
index 007309a..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.misc import timeline
-from migen.genlib.fsm import FSM
-
-from misoclib.mem.sdram.core.lasmicon.multiplexer import *
-
-
-class Refresher(Module):
-    def __init__(self, a, ba, tRP, tREFI, tRFC, enabled=True):
-        self.req = Signal()
-        self.ack = Signal()  # 1st command 1 cycle after assertion of ack
-        self.cmd = CommandRequest(a, ba)
-
-        ###
-
-        if enabled:
-            # Refresh sequence generator:
-            # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
-            seq_start = Signal()
-            seq_done = Signal()
-            self.sync += [
-                self.cmd.a.eq(2**10),
-                self.cmd.ba.eq(0),
-                self.cmd.cas_n.eq(1),
-                self.cmd.ras_n.eq(1),
-                self.cmd.we_n.eq(1),
-                seq_done.eq(0)
-            ]
-            self.sync += timeline(seq_start, [
-                (1, [
-                    self.cmd.ras_n.eq(0),
-                    self.cmd.we_n.eq(0)
-                ]),
-                (1+tRP, [
-                    self.cmd.cas_n.eq(0),
-                    self.cmd.ras_n.eq(0)
-                ]),
-                (1+tRP+tRFC, [
-                    seq_done.eq(1)
-                ])
-            ])
-
-            # Periodic refresh counter
-            counter = Signal(max=tREFI)
-            start = Signal()
-            self.sync += [
-                start.eq(0),
-                If(counter == 0,
-                    start.eq(1),
-                    counter.eq(tREFI - 1)
-                ).Else(
-                    counter.eq(counter - 1)
-                )
-            ]
-
-            # Control FSM
-            fsm = FSM()
-            self.submodules += fsm
-            fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
-            fsm.act("WAIT_GRANT",
-                self.req.eq(1),
-                If(self.ack,
-                    seq_start.eq(1),
-                    NextState("WAIT_SEQ")
-                )
-            )
-            fsm.act("WAIT_SEQ",
-                self.req.eq(1),
-                If(seq_done, NextState("IDLE"))
-            )
diff --git a/misoclib/mem/sdram/core/lasmixbar.py b/misoclib/mem/sdram/core/lasmixbar.py
deleted file mode 100644 (file)
index 56e67aa..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib import roundrobin
-from migen.genlib.record import *
-from migen.genlib.misc import optree
-
-from misoclib.mem.sdram.core.lasmibus import Interface
-
-
-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(optree("|", dat_w_maskselect)),
-                controller.dat_we.eq(optree("|", 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/misoclib/mem/sdram/core/minicon/__init__.py b/misoclib/mem/sdram/core/minicon/__init__.py
deleted file mode 100644 (file)
index 77259a7..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import optree, WaitTimer
-
-from misoclib.mem.sdram.phy import dfi as dfibus
-
-
-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])
-
-
-@DecorateModule(InsertReset)
-@DecorateModule(InsertCE)
-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 MiniconSettings:
-    def __init__(self, l2_size=0):
-        self.l2_size = l2_size
-
-
-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_open = Signal()
-        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(optree("|", [bank.hit & bank.ce for bank in banks])),
-            bank_idle.eq(optree("|", [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/misoclib/mem/sdram/frontend/__init__.py b/misoclib/mem/sdram/frontend/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/mem/sdram/frontend/dma_lasmi.py b/misoclib/mem/sdram/frontend/dma_lasmi.py
deleted file mode 100644 (file)
index 54c4843..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-from migen.fhdl.std import *
-from migen.flow.actor import *
-from migen.genlib.fifo import SyncFIFO
-
-
-class Reader(Module):
-    def __init__(self, lasmim, fifo_depth=None):
-        self.address = Sink([("a", lasmim.aw)])
-        self.data = Source([("d", 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(self.address.stb & request_enable),
-            lasmim.adr.eq(self.address.a),
-            self.address.ack.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),
-
-            self.data.stb.eq(fifo.readable),
-            fifo.re.eq(self.data.ack),
-            self.data.d.eq(fifo.dout),
-            data_dequeued.eq(self.data.stb & self.data.ack)
-        ]
-
-
-class Writer(Module):
-    def __init__(self, lasmim, fifo_depth=None):
-        self.address_data = Sink([("a", lasmim.aw), ("d", 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 & self.address_data.stb),
-            lasmim.adr.eq(self.address_data.a),
-            self.address_data.ack.eq(fifo.writable & lasmim.req_ack),
-            fifo.we.eq(self.address_data.stb & lasmim.req_ack),
-            fifo.din.eq(self.address_data.d)
-        ]
-
-        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/misoclib/mem/sdram/frontend/memtest.py b/misoclib/mem/sdram/frontend/memtest.py
deleted file mode 100644 (file)
index 790aa76..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.misc import optree
-from migen.bank.description import *
-from migen.actorlib.spi import *
-
-from misoclib.mem.sdram.frontend import dma_lasmi
-
-
-@DecorateModule(InsertReset)
-@DecorateModule(InsertCE)
-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 = ~optree("^", [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 MemtestWriter(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 MemtestReader(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 migen.fhdl import verilog
-    from migen.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/misoclib/mem/sdram/frontend/wishbone2lasmi.py b/misoclib/mem/sdram/frontend/wishbone2lasmi.py
deleted file mode 100644 (file)
index 9524734..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-from migen.fhdl.std import *
-from migen.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/misoclib/mem/sdram/module.py b/misoclib/mem/sdram/module.py
deleted file mode 100644 (file)
index ae26506..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-# SDRAM memory modules library
-#
-# This library avoid duplications of memory modules definitions in targets and
-# ease SDRAM usage. (User can only select an already existing module or create
-# one for its board and contribute to this library)
-#
-# 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)
-
-from math import ceil
-
-from migen.fhdl.std import *
-from misoclib.mem import sdram
-
-
-class SDRAMModule:
-    def __init__(self, clk_freq, memtype, geom_settings, timing_settings):
-        self.clk_freq = clk_freq
-        self.memtype = memtype
-        self.geom_settings = sdram.GeomSettings(
-            bankbits=log2_int(geom_settings["nbanks"]),
-            rowbits=log2_int(geom_settings["nrows"]),
-            colbits=log2_int(geom_settings["ncols"]),
-        )
-        self.timing_settings = sdram.TimingSettings(
-            tRP=self.ns(timing_settings["tRP"]),
-            tRCD=self.ns(timing_settings["tRCD"]),
-            tWR=self.ns(timing_settings["tWR"]),
-            tWTR=timing_settings["tWTR"],
-            tREFI=self.ns(timing_settings["tREFI"], False),
-            tRFC=self.ns(timing_settings["tRFC"])
-        )
-
-    def ns(self, t, margin=True):
-        clk_period_ns = 1000000000/self.clk_freq
-        if margin:
-            t += clk_period_ns/2
-        return ceil(t/clk_period_ns)
-
-
-# SDR
-class IS42S16160(SDRAMModule):
-    geom_settings = {
-        "nbanks": 4,
-        "nrows":  8192,
-        "ncols":  512
-    }
-    # Note: timings for -7 speedgrade (add support for others speedgrades)
-    timing_settings = {
-        "tRP":   20,
-        "tRCD":  20,
-        "tWR":   20,
-        "tWTR":  2,
-        "tREFI": 64*1000*1000/8192,
-        "tRFC":  70
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq,  "SDR", self.geom_settings,
-            self.timing_settings)
-
-
-class MT48LC4M16(SDRAMModule):
-    geom_settings = {
-        "nbanks": 4,
-        "nrows":  4096,
-        "ncols":  256
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   14,
-        "tWTR":  2,
-        "tREFI": 64*1000*1000/4096,
-        "tRFC":  66
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
-            self.timing_settings)
-
-
-class AS4C16M16(SDRAMModule):
-    geom_settings = {
-        "nbanks": 4,
-        "nrows":  8192,
-        "ncols":  512
-    }
-    # Note: timings for -6 speedgrade (add support for others speedgrades)
-    timing_settings = {
-        "tRP":   18,
-        "tRCD":  18,
-        "tWR":   12,
-        "tWTR":  2,
-        "tREFI": 64*1000*1000/8192,
-        "tRFC":  60
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
-            self.timing_settings)
-
-
-# DDR
-class MT46V32M16(SDRAMModule):
-    geom_settings = {
-        "nbanks": 4,
-        "nrows":  8192,
-        "ncols":  1024
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   15,
-        "tWTR":  2,
-        "tREFI": 64*1000*1000/8192,
-        "tRFC":  70
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "DDR", self.geom_settings,
-            self.timing_settings)
-
-
-# LPDDR
-class MT46H32M16(SDRAMModule):
-    geom_settings = {
-        "nbanks": 4,
-        "nrows":  8192,
-        "ncols":  1024
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   15,
-        "tWTR":  2,
-        "tREFI": 64*1000*1000/8192,
-        "tRFC":  72
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "LPDDR", self.geom_settings,
-            self.timing_settings)
-
-
-# DDR2
-class MT47H128M8(SDRAMModule):
-    geom_settings = {
-        "nbanks": 8,
-        "nrows":  16384,
-        "ncols":  1024
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   15,
-        "tWTR":  2,
-        "tREFI": 7800,
-        "tRFC":  127.5
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
-            self.timing_settings)
-
-
-class P3R1GE4JGF(SDRAMModule):
-    geom_settings = {
-        "nbanks": 8,
-        "nrows": 8192,
-        "ncols": 1024
-    }
-    timing_settings = {
-        "tRP":   12.5,
-        "tRCD":  12.5,
-        "tWR":   15,
-        "tWTR":  3,
-        "tREFI": 7800,
-        "tRFC":  127.5,
-    }
-
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
-            self.timing_settings)
-
-
-# DDR3
-class MT8JTF12864(SDRAMModule):
-    geom_settings = {
-        "nbanks": 8,
-        "nrows":  16384,
-        "ncols":  1024
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   15,
-        "tWTR":  2,
-        "tREFI": 7800,
-        "tRFC":  70
-    }
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
-            self.timing_settings)
-
-
-class MT41J128M16(SDRAMModule):
-    geom_settings = {
-        "nbanks": 8,
-        "nrows":  16384,
-        "ncols":  1024,
-    }
-    timing_settings = {
-        "tRP":   15,
-        "tRCD":  15,
-        "tWR":   15,
-        "tWTR":  3,
-        "tREFI": 64*1000*1000/16384,
-        "tRFC":  260,
-    }
-
-    def __init__(self, clk_freq):
-        SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
-            self.timing_settings)
diff --git a/misoclib/mem/sdram/phy/__init__.py b/misoclib/mem/sdram/phy/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/mem/sdram/phy/dfi.py b/misoclib/mem/sdram/phy/dfi.py
deleted file mode 100644 (file)
index 76379e2..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-from migen.fhdl.std import *
-from migen.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/misoclib/mem/sdram/phy/dfii.py b/misoclib/mem/sdram/phy/dfii.py
deleted file mode 100644 (file)
index 09ac053..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-from misoclib.mem.sdram.phy import dfi
-
-
-class PhaseInjector(Module, AutoCSR):
-    def __init__(self, phase):
-        self._command = CSRStorage(6)  # cs, we, cas, ras, wren, rden
-        self._command_issue = CSR()
-        self._address = CSRStorage(flen(phase.address))
-        self._baddress = CSRStorage(flen(phase.bank))
-        self._wrdata = CSRStorage(flen(phase.wrdata))
-        self._rddata = CSRStatus(flen(phase.rddata))
-
-        ###
-
-        self.comb += [
-            If(self._command_issue.re,
-                phase.cs_n.eq(~self._command.storage[0]),
-                phase.we_n.eq(~self._command.storage[1]),
-                phase.cas_n.eq(~self._command.storage[2]),
-                phase.ras_n.eq(~self._command.storage[3])
-            ).Else(
-                phase.cs_n.eq(1),
-                phase.we_n.eq(1),
-                phase.cas_n.eq(1),
-                phase.ras_n.eq(1)
-            ),
-            phase.address.eq(self._address.storage),
-            phase.bank.eq(self._baddress.storage),
-            phase.wrdata_en.eq(self._command_issue.re & self._command.storage[4]),
-            phase.rddata_en.eq(self._command_issue.re & self._command.storage[5]),
-            phase.wrdata.eq(self._wrdata.storage),
-            phase.wrdata_mask.eq(0)
-        ]
-        self.sync += If(phase.rddata_valid, self._rddata.status.eq(phase.rddata))
-
-
-class DFIInjector(Module, AutoCSR):
-    def __init__(self, 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/misoclib/mem/sdram/phy/gensdrphy.py b/misoclib/mem/sdram/phy/gensdrphy.py
deleted file mode 100644 (file)
index 6a3e07c..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#
-# 1:1 frequency-ratio Generic SDR PHY
-#
-# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
-# not use vendor-dependent code, it can also be used on other architectures.
-#
-# The PHY needs 2 Clock domains:
-#  - sys_clk    : The System Clock domain
-#  - sys_clk_ps : The System Clock domain with its phase shifted
-#                 (-3ns on C4@100MHz)
-#
-# Assert dfi_wrdata_en and present the data
-# on dfi_wrdata_mask/dfi_wrdata in the same
-# cycle as the write command.
-#
-# Assert dfi_rddata_en in the same cycle as the read
-# command. The data will come back on dfi_rddata
-# 4 cycles later, along with the assertion of
-# dfi_rddata_valid.
-#
-# This PHY only supports CAS Latency 2.
-#
-
-from migen.fhdl.std import *
-from migen.genlib.record import *
-from migen.fhdl.specials import *
-
-from misoclib.mem.sdram.phy.dfi import *
-from misoclib.mem import sdram
-
-
-class GENSDRPHY(Module):
-    def __init__(self, pads, module):
-        addressbits = flen(pads.a)
-        bankbits = flen(pads.ba)
-        databits = flen(pads.dq)
-
-        self.settings = sdram.PhySettings(
-            memtype=module.memtype,
-            dfi_databits=databits,
-            nphases=1,
-            rdphase=0,
-            wrphase=0,
-            rdcmdphase=0,
-            wrcmdphase=0,
-            cl=2,
-            read_latency=4,
-            write_latency=0
-        )
-        self.module = module
-
-        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/misoclib/mem/sdram/phy/initsequence.py b/misoclib/mem/sdram/phy/initsequence.py
deleted file mode 100644 (file)
index 3bdf5f3..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-from migen.fhdl.std import log2_int
-
-
-def get_sdram_phy_header(sdram_phy_settings):
-    r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
-    r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
-
-    nphases = sdram_phy_settings.nphases
-    r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
-
-    r += "static void cdelay(int i);\n"
-
-    # commands_px functions
-    for n in range(nphases):
-        r += """
-static void command_p{n}(int cmd)
-{{
-    sdram_dfii_pi{n}_command_write(cmd);
-    sdram_dfii_pi{n}_command_issue_write(1);
-}}""".format(n=str(n))
-    r += "\n\n"
-
-    # rd/wr access macros
-    r += """
-#define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X)
-#define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X)
-
-#define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X)
-#define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X)
-
-#define command_prd(X) command_p{rdphase}(X)
-#define command_pwr(X) command_p{wrphase}(X)
-""".format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase))
-    r += "\n"
-
-    #
-    # sdrrd/sdrwr functions utilities
-    #
-    r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n"
-    sdram_dfii_pix_wrdata_addr = []
-    for n in range(nphases):
-        sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n))
-    r += """
-const unsigned int sdram_dfii_pix_wrdata_addr[{n}] = {{
-    {sdram_dfii_pix_wrdata_addr}
-}};
-""".format(n=nphases, sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr))
-
-    sdram_dfii_pix_rddata_addr = []
-    for n in range(nphases):
-        sdram_dfii_pix_rddata_addr.append("CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n))
-    r += """
-const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{
-    {sdram_dfii_pix_rddata_addr}
-}};
-""".format(n=nphases, sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr))
-    r += "\n"
-
-    # init sequence
-    cmds = {
-        "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
-        "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS",
-        "AUTO_REFRESH":  "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS",
-        "UNRESET":       "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N",
-        "CKE":           "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N"
-    }
-
-    cl = sdram_phy_settings.cl
-
-    if sdram_phy_settings.memtype == "SDR":
-        bl = sdram_phy_settings.nphases
-        mr = log2_int(bl) + (cl << 4)
-        reset_dll = 1 << 8
-
-        init_sequence = [
-            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
-            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
-        ]
-
-    elif sdram_phy_settings.memtype == "DDR":
-        bl = 2*sdram_phy_settings.nphases
-        mr  = log2_int(bl) + (cl << 4)
-        emr = 0
-        reset_dll = 1 << 8
-
-        init_sequence = [
-            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
-            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
-        ]
-
-    elif sdram_phy_settings.memtype == "LPDDR":
-        bl = 2*sdram_phy_settings.nphases
-        mr  = log2_int(bl) + (cl << 4)
-        emr = 0
-        reset_dll = 1 << 8
-
-        init_sequence = [
-            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
-            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200)
-        ]
-
-    elif sdram_phy_settings.memtype == "DDR2":
-        bl = 2*sdram_phy_settings.nphases
-        wr = 2
-        mr = log2_int(bl) + (cl << 4) + (wr << 9)
-        emr = 0
-        emr2 = 0
-        emr3 = 0
-        reset_dll = 1 << 8
-        ocd = 7 << 7
-
-        init_sequence = [
-            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000),
-            ("Precharge All",  0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0),
-            ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0),
-            ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200),
-            ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4),
-            ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200),
-            ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0),
-            ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0),
-        ]
-    elif sdram_phy_settings.memtype == "DDR3":
-        bl = 2*sdram_phy_settings.nphases
-
-        def format_mr0(bl, cl, wr, dll_reset):
-            bl_to_mr0 = {
-                4: 0b10,
-                8: 0b00
-            }
-            cl_to_mr0 = {
-                 5: 0b0010,
-                 6: 0b0100,
-                 7: 0b0110,
-                 8: 0b1000,
-                 9: 0b1010,
-                10: 0b1100,
-                11: 0b1110,
-                12: 0b0001,
-                13: 0b0011,
-                14: 0b0101
-            }
-            wr_to_mr0 = {
-                16: 0b000,
-                 5: 0b001,
-                 6: 0b010,
-                 7: 0b011,
-                 8: 0b100,
-                10: 0b101,
-                12: 0b110,
-                14: 0b111
-            }
-            mr0 = bl_to_mr0[bl]
-            mr0 |= (cl_to_mr0[cl] & 1) << 2
-            mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4
-            mr0 |= dll_reset << 8
-            mr0 |= wr_to_mr0[wr] << 9
-            return mr0
-
-        def format_mr1(output_drive_strength, rtt_nom):
-            mr1 = ((output_drive_strength >> 0) & 1) << 1
-            mr1 |= ((output_drive_strength >> 1) & 1) << 5
-            mr1 |= ((rtt_nom >> 0) & 1) << 2
-            mr1 |= ((rtt_nom >> 1) & 1) << 6
-            mr1 |= ((rtt_nom >> 2) & 1) << 9
-            return mr1
-
-        def format_mr2(cwl, rtt_wr):
-            mr2 = (cwl-5) << 3
-            mr2 |= rtt_wr << 9
-            return mr2
-
-        mr0 = format_mr0(bl, cl, 8, 1)  # wr=8 FIXME: this should be ceiling(tWR/tCK)
-        mr1 = format_mr1(1, 1)  # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm)
-        mr2 = format_mr2(sdram_phy_settings.cwl, 2)  # Rtt(WR) RZQ/4
-        mr3 = 0
-
-        init_sequence = [
-            ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000),
-            ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000),
-            ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0),
-            ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200),
-            ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200),
-        ]
-
-        # the value of MR1 needs to be modified during write leveling
-        r += "#define DDR3_MR1 {}\n\n".format(mr1)
-    else:
-        raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype)
-
-    r += "static void init_sequence(void)\n{\n"
-    for comment, a, ba, cmd, delay in init_sequence:
-        r += "\t/* {0} */\n".format(comment)
-        r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a)
-        r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba)
-        if cmd[:12] == "DFII_CONTROL":
-            r += "\tsdram_dfii_control_write({0});\n".format(cmd)
-        else:
-            r += "\tcommand_p0({0});\n".format(cmd)
-        if delay:
-            r += "\tcdelay({0:d});\n".format(delay)
-        r += "\n"
-    r += "}\n"
-
-    r += "#endif\n"
-
-    return r
diff --git a/misoclib/mem/sdram/phy/k7ddrphy.py b/misoclib/mem/sdram/phy/k7ddrphy.py
deleted file mode 100644 (file)
index d516680..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-# tCK=5ns CL=7 CWL=6
-
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-from misoclib.mem.sdram.phy.dfi import *
-from misoclib.mem import sdram
-
-
-class K7DDRPHY(Module, AutoCSR):
-    def __init__(self, pads, module):
-        addressbits = flen(pads.a)
-        bankbits = flen(pads.ba)
-        databits = flen(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.PhySettings(
-            memtype=module.memtype,
-            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.module = module
-
-        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/misoclib/mem/sdram/phy/s6ddrphy.py b/misoclib/mem/sdram/phy/s6ddrphy.py
deleted file mode 100644 (file)
index f98a184..0000000
+++ /dev/null
@@ -1,490 +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 migen.fhdl.std import *
-from migen.genlib.record import *
-
-from misoclib.mem.sdram.phy.dfi import *
-from misoclib.mem import sdram
-
-
-class S6HalfRateDDRPHY(Module):
-    def __init__(self, pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
-        if module.memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
-            raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
-        addressbits = flen(pads.a)
-        bankbits = flen(pads.ba)
-        databits = flen(pads.dq)
-        nphases = 2
-
-        if module.memtype == "DDR3":
-            self.settings = sdram.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.PhySettings(
-                memtype=module.memtype,
-                dfi_databits=2*databits,
-                nphases=nphases,
-                rdphase=0,
-                wrphase=1,
-                rdcmdphase=1,
-                wrcmdphase=0,
-                cl=3,
-                read_latency=5,
-                write_latency=0
-            )
-
-        self.module = module
-
-        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(optree("|", [d_dfi[p].wrdata_en for p in range(nphases)]))
-
-        if module.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 module.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(optree("|", [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, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
-        if module.memtype not in ["DDR3"]:
-            raise NotImplementedError("S6QuarterRateDDRPHY only supports DDR3")
-        half_rate_phy = S6HalfRateDDRPHY(pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment)
-        self.submodules += RenameClockDomains(half_rate_phy, {"sys" : "sys2x"})
-
-        addressbits = flen(pads.a)
-        bankbits = flen(pads.ba)
-        databits = flen(pads.dq)
-        nphases = 4
-
-        self.settings = sdram.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.module = module
-
-        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_leave_out = set(["rddata", "rddata_valid", "wrdata_en"])
-        self.comb += [
-            If(~phase_sel,
-                Record.connect(self.dfi.phases[0], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
-                Record.connect(self.dfi.phases[1], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
-            ).Else(
-                Record.connect(self.dfi.phases[2], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
-                Record.connect(self.dfi.phases[3], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
-            ),
-        ]
-        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/misoclib/mem/sdram/phy/simphy.py b/misoclib/mem/sdram/phy/simphy.py
deleted file mode 100644 (file)
index 9c1eec2..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-# 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 Migen and manage timing violations?
-
-from migen.fhdl.std import *
-from migen.fhdl.specials import *
-from misoclib.mem.sdram.phy.dfi import *
-from misoclib.mem import sdram
-
-
-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 SDRAMPHYSim(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))
-            read_data = Signal(data_width)
-            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(optree("|", [bank.read for bank in banks])),
-            banks_read_data.eq(optree("|", [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/misoclib/mem/sdram/test/abstract_transactions_lasmi.py b/misoclib/mem/sdram/test/abstract_transactions_lasmi.py
deleted file mode 100644 (file)
index b53d46c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.core import lasmibus
-
-
-def my_generator(n):
-    bank = n % 4
-    for x in range(4):
-        t = TWrite(4*bank+x, 0x1000*bank + 0x100*x)
-        yield t
-        print("{0}: Wrote in {1} cycle(s)".format(n, t.latency))
-
-    for x in range(4):
-        t = TRead(4*bank+x)
-        yield t
-        print("{0}: Read {1:x} in {2} cycle(s)".format(n, t.data, t.latency))
-        assert(t.data == 0x1000*bank + 0x100*x)
-
-
-class MyModel(lasmibus.TargetModel):
-    def read(self, bank, address):
-        r = 0x1000*bank + 0x100*address
-        #print("read from bank {0} address {1} -> {2:x}".format(bank, address, r))
-        return r
-
-    def write(self, bank, address, data, we):
-        print("write to bank {0} address {1:x} data {2:x}".format(bank, address, data))
-        assert(data == 0x1000*bank + 0x100*address)
-
-
-class TB(Module):
-    def __init__(self):
-        self.submodules.controller = lasmibus.Target(MyModel(), aw=4, dw=32, nbanks=4, req_queue_size=4,
-            read_latency=4, write_latency=1)
-        self.submodules.xbar = lasmibus.Crossbar([self.controller.bus], 2)
-        self.initiators = [lasmibus.Initiator(my_generator(n), self.xbar.get_master()) for n in range(4)]
-        self.submodules += self.initiators
-
-if __name__ == "__main__":
-    run_simulation(TB())
diff --git a/misoclib/mem/sdram/test/bankmachine_tb.py b/misoclib/mem/sdram/test/bankmachine_tb.py
deleted file mode 100644 (file)
index ca7a16c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-from migen.fhdl.std import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.code import lasmibus
-from misoclib.mem.sdram.core.lasmicon.bankmachine import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, CommandLogger
-
-
-def my_generator():
-    for x in range(10):
-        yield True, x
-    for x in range(10):
-        yield False, 128*x
-
-
-class TB(Module):
-    def __init__(self):
-        self.req = Interface(32, 32, 1,
-            sdram_timing.req_queue_size, sdram_phy.read_latency, sdram_phy.write_latency)
-        self.submodules.dut = BankMachine(sdram_geom, sdram_timing, 2, 0, self.req)
-        self.submodules.logger = CommandLogger(self.dut.cmd, True)
-        self.generator = my_generator()
-        self.dat_ack_cnt = 0
-
-    def do_simulation(self, selfp):
-        if selfp.req.dat_ack:
-            self.dat_ack_cnt += 1
-        if selfp.req.req_ack:
-            try:
-                we, adr = next(self.generator)
-            except StopIteration:
-                selfp.req.stb = 0
-                if not selfp.req.lock:
-                    print("data ack count: {0}".format(self.dat_ack_cnt))
-                    raise StopSimulation
-                return
-            selfp.req.adr = adr
-            selfp.req.we = we
-            selfp.req.stb = 1
-
-if __name__ == "__main__":
-    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/mem/sdram/test/common.py b/misoclib/mem/sdram/test/common.py
deleted file mode 100644 (file)
index 0f3b9c3..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-from fractions import Fraction
-from math import ceil
-
-from migen.fhdl.std import *
-
-from misoclib import sdram
-
-MHz = 1000000
-clk_freq = (83 + Fraction(1, 3))*MHz
-
-clk_period_ns = 1000000000/clk_freq
-
-
-def ns(t, margin=True):
-    if margin:
-        t += clk_period_ns/2
-    return ceil(t/clk_period_ns)
-
-sdram_phy = sdram.PhySettings(
-    memtype="DDR",
-    dfi_databits=64,
-    nphases=2,
-    rdphase=0,
-    wrphase=1,
-    rdcmdphase=1,
-    wrcmdphase=0,
-    cl=3,
-    read_latency=5,
-    write_latency=0
-)
-
-sdram_geom = sdram.GeomSettings(
-    bankbits=2,
-    rowbits=13,
-    colbits=10
-)
-sdram_timing = sdram.TimingSettings(
-    tRP=ns(15),
-    tRCD=ns(15),
-    tWR=ns(15),
-    tWTR=2,
-    tREFI=ns(7800, False),
-    tRFC=ns(70),
-
-    req_queue_size=8,
-    read_time=32,
-    write_time=16
-)
-
-
-def decode_sdram(ras_n, cas_n, we_n, bank, address):
-    elts = []
-    if not ras_n and cas_n and we_n:
-        elts.append("ACTIVATE")
-        elts.append("BANK " + str(bank))
-        elts.append("ROW " + str(address))
-    elif ras_n and not cas_n and we_n:
-        elts.append("READ\t")
-        elts.append("BANK " + str(bank))
-        elts.append("COL " + str(address))
-    elif ras_n and not cas_n and not we_n:
-        elts.append("WRITE\t")
-        elts.append("BANK " + str(bank))
-        elts.append("COL " + str(address))
-    elif ras_n and cas_n and not we_n:
-        elts.append("BST")
-    elif not ras_n and not cas_n and we_n:
-        elts.append("AUTO REFRESH")
-    elif not ras_n and cas_n and not we_n:
-        elts.append("PRECHARGE")
-        if address & 2**10:
-            elts.append("ALL")
-        else:
-            elts.append("BANK " + str(bank))
-    elif not ras_n and not cas_n and not we_n:
-        elts.append("LMR")
-    return elts
-
-
-class CommandLogger(Module):
-    def __init__(self, cmd, rw=False):
-        self.cmd = cmd
-        if rw:
-            self.comb += self.cmd.ack.eq(1)
-
-    def do_simulation(self, selfp):
-        elts = ["@" + str(selfp.simulator.cycle_counter)]
-        cmdp = selfp.cmd
-        elts += decode_sdram(cmdp.ras_n, cmdp.cas_n, cmdp.we_n, cmdp.ba, cmdp.a)
-        if len(elts) > 1:
-            print("\t".join(elts))
-    do_simulation.passive = True
-
-
-class DFILogger(Module):
-    def __init__(self, dfi):
-        self.dfi = dfi
-
-    def do_simulation(self, selfp):
-        dfip = selfp.dfi
-        for i, p in enumerate(dfip.phases):
-            elts = ["@" + str(selfp.simulator.cycle_counter) + ":" + str(i)]
-            elts += decode_sdram(p.ras_n, p.cas_n, p.we_n, p.bank, p.address)
-            if len(elts) > 1:
-                print("\t".join(elts))
-    do_simulation.passive = True
diff --git a/misoclib/mem/sdram/test/lasmicon_df_tb.py b/misoclib/mem/sdram/test/lasmicon_df_tb.py
deleted file mode 100644 (file)
index 89b0d25..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-from migen.fhdl.std import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.core import lasmibus
-from misoclib.mem.sdram.core.lasmicon import *
-from misoclib.mem.sdram.frontend import dma_lasmi
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-
-class TB(Module):
-    def __init__(self):
-        self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-        self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
-        self.submodules.logger = DFILogger(self.ctler.dfi)
-        self.submodules.writer = dma_lasmi.Writer(self.xbar.get_master())
-
-        self.comb += self.writer.address_data.stb.eq(1)
-        pl = self.writer.address_data.payload
-        pl.a.reset = 255
-        pl.d.reset = pl.a.reset*2
-        self.sync += If(self.writer.address_data.ack,
-            pl.a.eq(pl.a + 1),
-            pl.d.eq(pl.d + 2)
-        )
-        self.open_row = None
-
-    def do_simulation(self, selfp):
-        dfip = selfp.ctler.dfi
-        for p in dfip.phases:
-            if p.ras_n and not p.cas_n and not p.we_n:  # write
-                d = dfip.phases[0].wrdata | (dfip.phases[1].wrdata << 64)
-                print(d)
-                if d != p.address//2 + p.bank*512 + self.open_row*2048:
-                    print("**** ERROR ****")
-            elif not p.ras_n and p.cas_n and p.we_n:  # activate
-                self.open_row = p.address
-
-if __name__ == "__main__":
-    run_simulation(TB(), ncycles=3500, vcd_name="my.vcd")
diff --git a/misoclib/mem/sdram/test/lasmicon_tb.py b/misoclib/mem/sdram/test/lasmicon_tb.py
deleted file mode 100644 (file)
index 1169898..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-from migen.fhdl.std import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.core import lasmibus
-from misoclib.mem.sdram.core.lasmicon import *
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-
-def my_generator_r(n):
-    for x in range(10):
-        t = TRead(128*n + 48*n*x)
-        yield t
-    print("{0:3}: reads done".format(n))
-
-
-def my_generator_w(n):
-    for x in range(10):
-        t = TWrite(128*n + 48*n*x, x)
-        yield t
-    print("{0:3}: writes done".format(n))
-
-
-def my_generator(n):
-    if n % 2:
-        return my_generator_w(n // 2)
-    else:
-        return my_generator_r(n // 2)
-
-
-class TB(Module):
-    def __init__(self):
-        self.submodules.dut = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-        self.submodules.xbar = lasmibus.Crossbar([self.dut.lasmic], self.dut.nrowbits)
-        self.submodules.logger = DFILogger(self.dut.dfi)
-
-        masters = [self.xbar.get_master() for i in range(6)]
-        self.initiators = [Initiator(my_generator(n), master)
-            for n, master in enumerate(masters)]
-        self.submodules += self.initiators
-
-if __name__ == "__main__":
-    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/mem/sdram/test/lasmicon_wb.py b/misoclib/mem/sdram/test/lasmicon_wb.py
deleted file mode 100644 (file)
index e6d967b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.bus.transactions import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.core import lasmibus
-from misoclib.mem.sdram.core.lasmicon import *
-from misoclib.mem.sdram.frontend import wishbone2lasmi
-
-from common import sdram_phy, sdram_geom, sdram_timing, DFILogger
-
-l2_size = 8192  # in bytes
-
-
-def my_generator():
-    for x in range(20):
-        t = TWrite(x, x)
-        yield t
-        print(str(t) + " delay=" + str(t.latency))
-    for x in range(20):
-        t = TRead(x)
-        yield t
-        print(str(t) + " delay=" + str(t.latency))
-    for x in range(20):
-        t = TRead(x+l2_size//4)
-        yield t
-        print(str(t) + " delay=" + str(t.latency))
-
-
-class TB(Module):
-    def __init__(self):
-        self.submodules.ctler = LASMIcon(sdram_phy, sdram_geom, sdram_timing)
-        self.submodules.xbar = lasmibus.Crossbar([self.ctler.lasmic], self.ctler.nrowbits)
-        self.submodules.logger = DFILogger(self.ctler.dfi)
-        self.submodules.bridge = wishbone2lasmi.WB2LASMI(l2_size//4, self.xbar.get_master())
-        self.submodules.initiator = wishbone.Initiator(my_generator())
-        self.submodules.conn = wishbone.InterconnectPointToPoint(self.initiator.bus, self.bridge.wishbone)
-
-if __name__ == "__main__":
-    run_simulation(TB(), vcd_name="my.vcd")
diff --git a/misoclib/mem/sdram/test/minicon_tb.py b/misoclib/mem/sdram/test/minicon_tb.py
deleted file mode 100644 (file)
index 8c7f639..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus.transactions import TRead, TWrite
-from migen.bus import wishbone
-from migen.sim.generic import Simulator
-from migen.sim import icarus
-from mibuild.platforms import papilio_pro as board
-from misoclib import sdram
-from misoclib.mem.sdram.core.minicon import Minicon
-from misoclib.mem.sdram.phy import gensdrphy
-from itertools import chain
-from os.path import isfile
-import sys
-
-clk_freq = 80000000
-
-from math import ceil
-
-
-def ns(t, margin=True):
-    clk_period_ns = 1000000000/clk_freq
-    if margin:
-        t += clk_period_ns/2
-    return ceil(t/clk_period_ns)
-
-
-class MiniconTB(Module):
-    def __init__(self, sdrphy, dfi, sdram_geom, sdram_timing, pads, sdram_clk):
-
-        self.clk_freq = 80000000
-        phy_settings = sdrphy.settings
-        rdphase = phy_settings.rdphase
-        self.submodules.slave = Minicon(phy_settings, sdram_geom, sdram_timing)
-
-        self.submodules.tap = wishbone.Tap(self.slave.bus)
-        self.submodules.dc = dc = wishbone.DownConverter(32, phy_settings.nphases*flen(dfi.phases[rdphase].rddata))
-        self.submodules.master = wishbone.Initiator(self.genxfers(), bus=dc.wishbone_i)
-        self.submodules.intercon = wishbone.InterconnectPointToPoint(dc.wishbone_o, self.slave.bus)
-
-        self.submodules.sdrphy = self.sdrphy = sdrphy
-        self.dfi = dfi
-        self.pads = pads
-
-        self.specials += Instance("mt48lc4m16a2",
-                                  io_Dq=pads.dq,
-                                  i_Addr=pads.a,
-                                  i_Ba=pads.ba,
-                                  i_Clk=ClockSignal(),
-                                  i_Cke=pads.cke,
-                                  i_Cs_n=pads.cs_n,
-                                  i_Ras_n=pads.ras_n,
-                                  i_Cas_n=pads.cas_n,
-                                  i_We_n=pads.we_n,
-                                  i_Dqm=pads.dm
-        )
-
-    def genxfers(self):
-        cycle = 0
-        for a in chain(range(4), range(256, 260), range(1024, 1028)):
-            t = TRead(a)
-            yield t
-            print("read {} in {} cycles".format(t.data, t.latency))
-        for a in chain(range(4), range(256, 260), range(1024, 1028), range(4096, 4100)):
-            t = TWrite(a, 0xaa55aa55+cycle)
-            cycle += 1
-            yield t
-            print("read {} in {} cycles".format(t.data, t.latency))
-        for a in chain(range(4), range(256, 260), range(1024, 1028), range(4096, 4100)):
-            t = TRead(a)
-            yield t
-            print("read {} in {} cycles".format(t.data, t.latency))
-
-    def gen_simulation(self, selfp):
-        dfi = selfp.dfi
-        phy = self.sdrphy
-        rdphase = phy.settings.rdphase
-        cycle = 0
-
-        while True:
-            yield
-
-
-class MyTopLevel:
-    def __init__(self, vcd_name=None, vcd_level=1,
-      top_name="top", dut_type="dut", dut_name="dut",
-      cd_name="sys", clk_period=10):
-        self.vcd_name = vcd_name
-        self.vcd_level = vcd_level
-        self.top_name = top_name
-        self.dut_type = dut_type
-        self.dut_name = dut_name
-
-        self._cd_name = cd_name
-        self._clk_period = clk_period
-
-        cd = ClockDomain(self._cd_name)
-        cd_ps = ClockDomain("sys_ps")
-        self.clock_domains = [cd, cd_ps]
-        self.ios = {cd.clk, cd.rst, cd_ps.clk}
-
-    def get(self, sockaddr):
-        template1 = """`timescale 1ns / 1ps
-
-module {top_name}();
-
-reg {clk_name};
-reg {rst_name};
-reg sys_ps_clk;
-
-initial begin
-    {rst_name} <= 1'b1;
-    @(posedge {clk_name});
-    {rst_name} <= 1'b0;
-end
-
-always begin
-    {clk_name} <= 1'b0;
-    #{hclk_period};
-    {clk_name} <= 1'b1;
-    #{hclk_period};
-end
-
-always @(posedge {clk_name} or negedge {clk_name})
-    sys_ps_clk <= #({hclk_period}*2-3) {clk_name};
-
-{dut_type} {dut_name}(
-    .{rst_name}({rst_name}),
-    .{clk_name}({clk_name}),
-    .sys_ps_clk(sys_ps_clk)
-);
-
-initial $migensim_connect("{sockaddr}");
-always @(posedge {clk_name}) $migensim_tick;
-"""
-        template2 = """
-initial begin
-    $dumpfile("{vcd_name}");
-    $dumpvars({vcd_level}, {dut_name});
-end
-"""
-        r = template1.format(top_name=self.top_name,
-            dut_type=self.dut_type,
-            dut_name=self.dut_name,
-            clk_name=self._cd_name + "_clk",
-            rst_name=self._cd_name + "_rst",
-            hclk_period=str(self._clk_period/2),
-            sockaddr=sockaddr)
-        if self.vcd_name is not None:
-            r += template2.format(vcd_name=self.vcd_name,
-                vcd_level=str(self.vcd_level),
-                dut_name=self.dut_name)
-        r += "\nendmodule"
-        return r
-
-
-if __name__ == "__main__":
-
-    plat = board.Platform()
-
-    sdram_geom = sdram.GeomSettings(
-        bankbits=2,
-        rowbits=12,
-        colbits=8
-    )
-
-    sdram_timing = sdram.TimingSettings(
-        tRP=ns(15),
-        tRCD=ns(15),
-        tWR=ns(14),
-        tWTR=2,
-        tREFI=ns(64*1000*1000/4096, False),
-        tRFC=ns(66),
-        req_queue_size=8,
-        read_time=32,
-        write_time=16
-    )
-
-    sdram_pads = plat.request("sdram")
-    sdram_clk = plat.request("sdram_clock")
-
-    sdrphy = gensdrphy.GENSDRPHY(sdram_pads)
-
-# This sets CL to 2 during LMR done on 1st cycle
-    sdram_pads.a.reset = 1<<5
-
-    s = MiniconTB(sdrphy, sdrphy.dfi, sdram_geom, sdram_timing, pads=sdram_pads, sdram_clk=sdram_clk)
-
-    extra_files = ["sdram_model/mt48lc4m16a2.v"]
-
-    if not isfile(extra_files[0]):
-        print("ERROR: You need to download Micron Verilog simulation model for MT48LC4M16A2 and put it in sdram_model/mt48lc4m16a2.v")
-        print("File can be downloaded from this URL: http://www.micron.com/-/media/documents/products/sim%20model/dram/dram/4054mt48lc4m16a2.zip")
-        sys.exit(1)
-
-    with Simulator(s, MyTopLevel("top.vcd", clk_period=int(1/0.08)), icarus.Runner(extra_files=extra_files, keep_files=True)) as sim:
-        sim.run(5000)
diff --git a/misoclib/mem/sdram/test/refresher.py b/misoclib/mem/sdram/test/refresher.py
deleted file mode 100644 (file)
index 0636723..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-from random import Random
-
-from migen.fhdl.std import *
-from migen.sim.generic import run_simulation
-
-from misoclib.mem.sdram.core.lasmicon.refresher import *
-
-from common import CommandLogger
-
-
-class Granter(Module):
-    def __init__(self, req, ack):
-        self.req = req
-        self.ack = ack
-        self.state = 0
-        self.prng = Random(92837)
-
-    def do_simulation(self, selfp):
-        elts = ["@" + str(selfp.simulator.cycle_counter)]
-
-        if self.state == 0:
-            if selfp.req:
-                elts.append("Refresher requested access")
-                self.state = 1
-        elif self.state == 1:
-            if self.prng.randrange(0, 5) == 0:
-                elts.append("Granted access to refresher")
-                selfp.ack = 1
-                self.state = 2
-        elif self.state == 2:
-            if not selfp.req:
-                elts.append("Refresher released access")
-                selfp.ack = 0
-                self.state = 0
-
-        if len(elts) > 1:
-            print("\t".join(elts))
-
-
-class TB(Module):
-    def __init__(self):
-        self.submodules.dut = Refresher(13, 2, tRP=3, tREFI=100, tRFC=5)
-        self.submodules.logger = CommandLogger(self.dut.cmd)
-        self.submodules.granter = Granter(self.dut.req, self.dut.ack)
-
-if __name__ == "__main__":
-    run_simulation(TB(), ncycles=400)
diff --git a/misoclib/mxcrg.v b/misoclib/mxcrg.v
deleted file mode 100644 (file)
index 140c848..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-module mxcrg #(
-       parameter in_period = 0.0,
-       parameter f_mult = 0,
-       parameter f_div = 0,
-       parameter clk2x_period = (in_period*f_div)/(2.0*f_mult)
-) (
-       input clk50_pad,
-       input trigger_reset,
-
-       output sys_clk,
-       output reg sys_rst,
-
-       /* Reset NOR flash */
-       output norflash_rst_n,
-
-       /* DDR PHY clocks */
-       output clk2x_270,
-       output clk4x_wr,
-       output clk4x_wr_strb,
-       output clk4x_rd,
-       output clk4x_rd_strb,
-
-       /* DDR off-chip clocking */
-       output ddr_clk_pad_p,
-       output ddr_clk_pad_n,
-
-       /* Base clock, buffered */
-       output base50_clk
-);
-
-/*
- * Reset
- */
-
-reg [19:0] rst_debounce;
-always @(posedge sys_clk) begin
-       if(trigger_reset)
-               rst_debounce <= 20'hFFFFF;
-       else if(rst_debounce != 20'd0)
-               rst_debounce <= rst_debounce - 20'd1;
-       sys_rst <= rst_debounce != 20'd0;
-end
-
-initial rst_debounce <= 20'hFFFFF;
-
-/*
- * We must release the Flash reset before the system reset
- * because the Flash needs some time to come out of reset
- * and the CPU begins fetching instructions from it
- * as soon as the system reset is released.
- * From datasheet, minimum reset pulse width is 100ns
- * and reset-to-read time is 150ns.
- */
-
-reg [7:0] flash_rstcounter;
-
-always @(posedge sys_clk) begin
-       if(trigger_reset)
-               flash_rstcounter <= 8'd0;
-       else if(~flash_rstcounter[7])
-               flash_rstcounter <= flash_rstcounter + 8'd1;
-end
-
-initial flash_rstcounter <= 8'd0;
-
-assign norflash_rst_n = flash_rstcounter[7];
-
-/*
- * Clock management. Inspired by the NWL reference design.
- */
-
-wire sdr_clk50;
-wire clkdiv;
-
-IBUF #(
-       .IOSTANDARD("DEFAULT")
-) clk2_iob (
-       .I(clk50_pad),
-       .O(sdr_clk50)
-);
-
-BUFIO2 #(
-       .DIVIDE(1),
-       .DIVIDE_BYPASS("FALSE"),
-       .I_INVERT("FALSE")
-) bufio2_inst2 (
-       .I(sdr_clk50),
-       .IOCLK(),
-       .DIVCLK(clkdiv),
-       .SERDESSTROBE()
-);
-
-wire pll_lckd;
-wire buf_pll_fb_out;
-wire pllout0;
-wire pllout1;
-wire pllout2;
-wire pllout3;
-wire pllout4;
-wire pllout5;
-
-PLL_ADV #(
-       .BANDWIDTH("OPTIMIZED"),
-       .CLKFBOUT_MULT(4*f_mult),
-       .CLKFBOUT_PHASE(0.0),
-       .CLKIN1_PERIOD(in_period),
-       .CLKIN2_PERIOD(in_period),
-
-       .CLKOUT0_DIVIDE(f_div),
-       .CLKOUT0_DUTY_CYCLE(0.5),
-       .CLKOUT0_PHASE(0.0),
-
-       .CLKOUT1_DIVIDE(f_div),
-       .CLKOUT1_DUTY_CYCLE(0.5),
-       .CLKOUT1_PHASE(0.0),
-
-       .CLKOUT2_DIVIDE(2*f_div),
-       .CLKOUT2_DUTY_CYCLE(0.5),
-       .CLKOUT2_PHASE(270.0),
-
-       .CLKOUT3_DIVIDE(4*f_div),
-       .CLKOUT3_DUTY_CYCLE(0.5),
-       .CLKOUT3_PHASE(0.0),
-
-       .CLKOUT4_DIVIDE(4*f_mult),
-       .CLKOUT4_DUTY_CYCLE(0.5),
-       .CLKOUT4_PHASE(0.0),
-
-       .CLKOUT5_DIVIDE(2*f_div),
-       .CLKOUT5_DUTY_CYCLE(0.5),
-       .CLKOUT5_PHASE(250.0),
-
-       .COMPENSATION("INTERNAL"),
-       .DIVCLK_DIVIDE(1),
-       .REF_JITTER(0.100),
-       .CLK_FEEDBACK("CLKFBOUT"),
-       .SIM_DEVICE("SPARTAN6")
-) pll (
-       .CLKFBDCM(),
-       .CLKFBOUT(buf_pll_fb_out),
-       .CLKOUT0(pllout0), /* < x4 clock for writes */
-       .CLKOUT1(pllout1), /* < x4 clock for reads */
-       .CLKOUT2(pllout2), /* < x2 270 clock for DQS, memory address and control signals */
-       .CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
-       .CLKOUT4(pllout4), /* < buffered clk50 */
-       .CLKOUT5(pllout5), /* < x2 clock to off-chip DDR */
-       .CLKOUTDCM0(),
-       .CLKOUTDCM1(),
-       .CLKOUTDCM2(),
-       .CLKOUTDCM3(),
-       .CLKOUTDCM4(),
-       .CLKOUTDCM5(),
-       .DO(),
-       .DRDY(),
-       .LOCKED(pll_lckd),
-       .CLKFBIN(buf_pll_fb_out),
-       .CLKIN1(clkdiv),
-       .CLKIN2(1'b0),
-       .CLKINSEL(1'b1),
-       .DADDR(5'b00000),
-       .DCLK(1'b0),
-       .DEN(1'b0),
-       .DI(16'h0000),
-       .DWE(1'b0),
-       .RST(1'b0),
-       .REL(1'b0)
-);
-
-BUFPLL #(
-       .DIVIDE(4)
-) wr_bufpll (
-       .PLLIN(pllout0),
-       .GCLK(sys_clk),
-       .LOCKED(pll_lckd),
-       .IOCLK(clk4x_wr),
-       .LOCK(),
-       .SERDESSTROBE(clk4x_wr_strb)
-);
-
-BUFPLL #(
-       .DIVIDE(4)
-) rd_bufpll (
-       .PLLIN(pllout1),
-       .GCLK(sys_clk),
-       .LOCKED(pll_lckd),
-       .IOCLK(clk4x_rd),
-       .LOCK(),
-       .SERDESSTROBE(clk4x_rd_strb)
-);
-
-BUFG bufg_x2_2(
-       .I(pllout2),
-       .O(clk2x_270)
-);
-
-BUFG bufg_x1(
-       .I(pllout3),
-       .O(sys_clk)
-);
-
-wire base50_clk;
-BUFG bufg_50(
-       .I(pllout4),
-       .O(base50_clk)
-);
-
-wire clk2x_off;
-BUFG bufg_x2_offclk(
-       .I(pllout5),
-       .O(clk2x_off)
-);
-
-
-/*
- * SDRAM clock
- */
-
-ODDR2 #(
-       .DDR_ALIGNMENT("NONE"),
-       .INIT(1'b0),
-       .SRTYPE("SYNC")
-) sd_clk_forward_p (
-       .Q(ddr_clk_pad_p),
-       .C0(clk2x_off),
-       .C1(~clk2x_off),
-       .CE(1'b1),
-       .D0(1'b1),
-       .D1(1'b0),
-       .R(1'b0),
-       .S(1'b0)
-);
-ODDR2 #(
-       .DDR_ALIGNMENT("NONE"),
-       .INIT(1'b0),
-       .SRTYPE("SYNC")
-) sd_clk_forward_n (
-       .Q(ddr_clk_pad_n),
-       .C0(clk2x_off),
-       .C1(~clk2x_off),
-       .CE(1'b1),
-       .D0(1'b0),
-       .D1(1'b1),
-       .R(1'b0),
-       .S(1'b0)
-);
-
-endmodule
diff --git a/misoclib/soc/__init__.py b/misoclib/soc/__init__.py
deleted file mode 100644 (file)
index ef7c454..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-from operator import itemgetter
-
-from migen.fhdl.std import *
-from migen.bank import csrgen
-from migen.bus import wishbone, csr, wishbone2csr
-
-from misoclib.com.uart.phy import UARTPHY
-from misoclib.com import uart
-from misoclib.cpu import lm32, mor1kx
-from misoclib.cpu import identifier, timer
-
-
-def mem_decoder(address, start=26, end=29):
-    return lambda a: a[start:end] == ((address >> (start+2)) & (2**(end-start))-1)
-
-
-class SoC(Module):
-    csr_map = {
-        "crg":        0,  # user
-        "uart_phy":   1,  # provided by default (optional)
-        "uart":       2,  # provided by default (optional)
-        "identifier": 3,  # provided by default (optional)
-        "timer0":     4,  # provided by default (optional)
-        "buttons":    5,  # user
-        "leds":       6,  # user
-    }
-    interrupt_map = {
-        "uart":   0,
-        "timer0": 1,
-    }
-    mem_map = {
-        "rom":      0x00000000,  # (default shadow @0x80000000)
-        "sram":     0x10000000,  # (default shadow @0x90000000)
-        "main_ram": 0x40000000,  # (default shadow @0xc0000000)
-        "csr":      0x60000000,  # (default shadow @0xe0000000)
-    }
-    def __init__(self, platform, clk_freq,
-                cpu_type="lm32", cpu_reset_address=0x00000000,
-                integrated_rom_size=0,
-                integrated_sram_size=4096,
-                integrated_main_ram_size=0,
-                shadow_base=0x80000000,
-                with_csr=True, csr_data_width=8, csr_address_width=14,
-                with_uart=True, uart_baudrate=115200,
-                with_identifier=True,
-                with_timer=True):
-        self.platform = platform
-        self.clk_freq = clk_freq
-
-        self.cpu_type = cpu_type
-        if integrated_rom_size:
-            cpu_reset_address = 0
-        self.cpu_reset_address = cpu_reset_address
-
-        self.integrated_rom_size = integrated_rom_size
-        self.integrated_sram_size = integrated_sram_size
-        self.integrated_main_ram_size = integrated_main_ram_size
-
-        self.with_uart = with_uart
-        self.uart_baudrate = uart_baudrate
-
-        self.with_identifier = with_identifier
-
-        self.shadow_base = shadow_base
-
-        self.with_csr = with_csr
-        self.csr_data_width = csr_data_width
-        self.csr_address_width = csr_address_width
-
-        self._memory_regions = []  # list of (name, origin, length)
-        self._csr_regions = []  # list of (name, origin, busword, csr_list/Memory)
-        self._constants = []  # list of (name, value)
-
-        self._wb_masters = []
-        self._wb_slaves = []
-
-        if cpu_type != "none":
-            if cpu_type == "lm32":
-                self.add_cpu_or_bridge(lm32.LM32(platform, self.cpu_reset_address))
-            elif cpu_type == "or1k":
-                self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address))
-            else:
-                raise ValueError("Unsupported CPU type: {}".format(cpu_type))
-            self.add_wb_master(self.cpu_or_bridge.ibus)
-            self.add_wb_master(self.cpu_or_bridge.dbus)
-
-            if integrated_rom_size:
-                self.submodules.rom = wishbone.SRAM(integrated_rom_size, read_only=True)
-                self.register_rom(self.rom.bus, integrated_rom_size)
-
-            if integrated_sram_size:
-                self.submodules.sram = wishbone.SRAM(integrated_sram_size)
-                self.register_mem("sram", self.mem_map["sram"], self.sram.bus, integrated_sram_size)
-
-            # Note: Main Ram can be used when no external SDRAM is available and use SDRAM mapping.
-            if integrated_main_ram_size:
-                self.submodules.main_ram = wishbone.SRAM(integrated_main_ram_size)
-                self.register_mem("main_ram", self.mem_map["main_ram"], self.main_ram.bus, integrated_main_ram_size)
-
-        if with_csr:
-            self.submodules.wishbone2csr = wishbone2csr.WB2CSR(bus_csr=csr.Interface(csr_data_width, csr_address_width))
-            self.register_mem("csr", self.mem_map["csr"], self.wishbone2csr.wishbone)
-
-            if with_uart:
-                self.submodules.uart_phy = UARTPHY(platform.request("serial"), clk_freq, uart_baudrate)
-                self.submodules.uart = uart.UART(self.uart_phy)
-
-            if with_identifier:
-                platform_id = 0x554E if not hasattr(platform, "identifier") else platform.identifier
-                self.submodules.identifier = identifier.Identifier(platform_id, int(clk_freq))
-
-            if with_timer:
-                self.submodules.timer0 = timer.Timer()
-
-    def add_cpu_or_bridge(self, cpu_or_bridge):
-        if self.finalized:
-            raise FinalizeError
-        if hasattr(self, "cpu_or_bridge"):
-            raise NotImplementedError("More than one CPU is not supported")
-        self.submodules.cpu_or_bridge = cpu_or_bridge
-
-    def init_rom(self, data):
-        self.rom.mem.init = data
-
-    def add_wb_master(self, wbm):
-        if self.finalized:
-            raise FinalizeError
-        self._wb_masters.append(wbm)
-
-    def add_wb_slave(self, address_decoder, interface):
-        if self.finalized:
-            raise FinalizeError
-        self._wb_slaves.append((address_decoder, interface))
-
-    def add_memory_region(self, name, origin, length):
-        def in_this_region(addr):
-            return addr >= origin and addr < origin + length
-        for n, o, l in self._memory_regions:
-            if n == name or in_this_region(o) or in_this_region(o+l-1):
-                raise ValueError("Memory region conflict between {} and {}".format(n, name))
-
-        self._memory_regions.append((name, origin, length))
-
-    def register_mem(self, name, address, interface, size=None):
-        self.add_wb_slave(mem_decoder(address), interface)
-        if size is not None:
-            self.add_memory_region(name, address, size)
-
-    def register_rom(self, interface, rom_size=0xa000):
-        self.add_wb_slave(mem_decoder(self.mem_map["rom"]), interface)
-        self.add_memory_region("rom", self.cpu_reset_address, rom_size)
-
-    def get_memory_regions(self):
-        return self._memory_regions
-
-    def check_csr_region(self, name, origin):
-        for n, o, l, obj in self._csr_regions:
-            if n == name or o == origin:
-                raise ValueError("CSR region conflict between {} and {}".format(n, name))
-
-    def add_csr_region(self, name, origin, busword, obj):
-        self.check_csr_region(name, origin)
-        self._csr_regions.append((name, origin, busword, obj))
-
-    def get_csr_regions(self):
-        return self._csr_regions
-
-    def add_constant(self, name, value=None):
-        self._constants.append((name, value))
-
-    def get_constants(self):
-        r = []
-        for name, interrupt in sorted(self.interrupt_map.items(), key=itemgetter(1)):
-            r.append((name.upper() + "_INTERRUPT", interrupt))
-        r += self._constants
-        return r
-
-    def do_finalize(self):
-        registered_mems = {regions[0] for regions in self._memory_regions}
-        if self.cpu_type != "none":
-            for mem in "rom", "sram":
-                if mem not in registered_mems:
-                    raise FinalizeError("CPU needs a {} to be registered with SoC.register_mem()".format(mem))
-
-        # Wishbone
-        self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters,
-            self._wb_slaves, register=True)
-
-        # CSR
-        if self.with_csr:
-            self.submodules.csrbankarray = csrgen.BankArray(self,
-                lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override],
-                data_width=self.csr_data_width, address_width=self.csr_address_width)
-            self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses())
-            for name, csrs, mapaddr, rmap in self.csrbankarray.banks:
-                self.add_csr_region(name, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, csrs)
-            for name, memory, mapaddr, mmap in self.csrbankarray.srams:
-                self.add_csr_region(name + "_" + memory.name_override, (self.mem_map["csr"] + 0x800*mapaddr) | self.shadow_base, self.csr_data_width, memory)
-
-        # Interrupts
-        if hasattr(self.cpu_or_bridge, "interrupt"):
-            for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)):
-                if hasattr(self, k):
-                    self.comb += self.cpu_or_bridge.interrupt[v].eq(getattr(self, k).ev.irq)
diff --git a/misoclib/soc/cpuif.py b/misoclib/soc/cpuif.py
deleted file mode 100644 (file)
index ac812d5..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import CSRStatus
-
-
-def get_cpu_mak(cpu_type):
-    if cpu_type == "lm32":
-        triple = "lm32-elf"
-        cpuflags = "-mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled"
-        clang = ""
-    elif cpu_type == "or1k":
-        triple = "or1k-linux"
-        cpuflags = "-mhard-mul -mhard-div -mror -mffl1 -maddc"
-        clang = "1"
-    else:
-        raise ValueError("Unsupported CPU type: "+cpu_type)
-    return "TRIPLE={}\nCPU={}\nCPUFLAGS={}\nCLANG={}".format(triple, cpu_type, cpuflags, clang)
-
-
-def get_linker_output_format(cpu_type):
-    return "OUTPUT_FORMAT(\"elf32-{}\")\n".format(cpu_type)
-
-
-def get_linker_regions(regions):
-    r = "MEMORY {\n"
-    for name, origin, length in regions:
-        r += "\t{} : ORIGIN = 0x{:08x}, LENGTH = 0x{:08x}\n".format(name, origin, length)
-    r += "}\n"
-    return r
-
-
-def get_mem_header(regions, flash_boot_address):
-    r = "#ifndef __GENERATED_MEM_H\n#define __GENERATED_MEM_H\n\n"
-    for name, base, size in regions:
-        r += "#define {name}_BASE 0x{base:08x}\n#define {name}_SIZE 0x{size:08x}\n\n".format(name=name.upper(), base=base, size=size)
-    if flash_boot_address is not None:
-        r += "#define FLASH_BOOT_ADDRESS 0x{:08x}\n\n".format(flash_boot_address)
-    r += "#endif\n"
-    return r
-
-
-def _get_rw_functions(reg_name, reg_base, nwords, busword, read_only, with_access_functions):
-    r = ""
-
-    r += "#define CSR_"+reg_name.upper()+"_ADDR "+hex(reg_base)+"\n"
-    r += "#define CSR_"+reg_name.upper()+"_SIZE "+str(nwords)+"\n"
-
-    size = nwords*busword
-    if size > 64:
-        return r
-    elif size > 32:
-        ctype = "unsigned long long int"
-    elif size > 16:
-        ctype = "unsigned int"
-    elif size > 8:
-        ctype = "unsigned short int"
-    else:
-        ctype = "unsigned char"
-
-    if with_access_functions:
-        r += "static inline "+ctype+" "+reg_name+"_read(void) {\n"
-        if size > 1:
-            r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n"
-            for byte in range(1, nwords):
-                r += "\tr <<= "+str(busword)+";\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n"
-            r += "\treturn r;\n}\n"
-        else:
-            r += "\treturn MMPTR("+hex(reg_base)+");\n}\n"
-
-        if not read_only:
-            r += "static inline void "+reg_name+"_write("+ctype+" value) {\n"
-            for word in range(nwords):
-                shift = (nwords-word-1)*busword
-                if shift:
-                    value_shifted = "value >> "+str(shift)
-                else:
-                    value_shifted = "value"
-                r += "\tMMPTR("+hex(reg_base+4*word)+") = "+value_shifted+";\n"
-            r += "}\n"
-    return r
-
-
-def get_csr_header(regions, constants, with_access_functions=True):
-    r = "#ifndef __GENERATED_CSR_H\n#define __GENERATED_CSR_H\n"
-    if with_access_functions:
-        r += "#include <hw/common.h>\n"
-    for name, origin, busword, obj in regions:
-        if isinstance(obj, Memory):
-            r += "#define CSR_"+name.upper()+"_BASE "+hex(origin)+"\n"
-        else:
-            r += "\n/* "+name+" */\n"
-            r += "#define CSR_"+name.upper()+"_BASE "+hex(origin)+"\n"
-            for csr in obj:
-                nr = (csr.size + busword - 1)//busword
-                r += _get_rw_functions(name + "_" + csr.name, origin, nr, busword, isinstance(csr, CSRStatus), with_access_functions)
-                origin += 4*nr
-
-    r += "\n/* constants */\n"
-    for name, value in constants:
-        r += "#define " + name
-        if value is not None:
-            if isinstance(value, str):
-                r +=  " \"" + value + "\""
-            else:
-                r += " " + str(value)
-        r += "\n"
-
-    r += "\n#endif\n"
-    return r
-
-
-def get_csr_csv(regions):
-    r = ""
-    for name, origin, busword, obj in regions:
-        if not isinstance(obj, Memory):
-            for csr in obj:
-                nr = (csr.size + busword - 1)//busword
-                r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, origin, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
-                origin += 4*nr
-    return r
diff --git a/misoclib/soc/sdram.py b/misoclib/soc/sdram.py
deleted file mode 100644 (file)
index 4687c03..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.record import *
-
-from misoclib.mem.sdram.core import SDRAMCore
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.mem.sdram.core.minicon import MiniconSettings
-from misoclib.mem.sdram.frontend import memtest, wishbone2lasmi
-from misoclib.soc import SoC
-
-
-class SDRAMSoC(SoC):
-    csr_map = {
-        "sdram":           8,
-        "l2_cache":        9,
-        "memtest_w":      10,
-        "memtest_r":      11
-    }
-    csr_map.update(SoC.csr_map)
-
-    def __init__(self, platform, clk_freq, sdram_controller_settings,
-            **kwargs):
-        SoC.__init__(self, platform, clk_freq, **kwargs)
-        if isinstance(sdram_controller_settings, str):
-            self.sdram_controller_settings = eval(sdram_controller_settings)
-        else:
-            self.sdram_controller_settings = sdram_controller_settings
-        self._sdram_phy_registered = False
-        self._wb_sdram_ifs = []
-        self._wb_sdram = wishbone.Interface()
-
-    def add_wb_sdram_if(self, interface):
-        if self.finalized:
-            raise FinalizeError
-        self._wb_sdram_ifs.append(interface)
-
-    def register_sdram_phy(self, phy):
-        if self._sdram_phy_registered:
-            raise FinalizeError
-        self._sdram_phy_registered = True
-
-        # Core
-        self.submodules.sdram = SDRAMCore(phy,
-                                          phy.module.geom_settings,
-                                          phy.module.timing_settings,
-                                          self.sdram_controller_settings)
-
-        dfi_databits_divisor = 1 if phy.settings.memtype == "SDR" else 2
-        sdram_width = phy.settings.dfi_databits//dfi_databits_divisor
-        main_ram_size = 2**(phy.module.geom_settings.bankbits +
-                            phy.module.geom_settings.rowbits +
-                            phy.module.geom_settings.colbits)*sdram_width//8
-        # XXX: Limit main_ram_size to 256MB, we should modify mem_map to allow larger memories.
-        main_ram_size = min(main_ram_size, 256*1024*1024)
-        l2_size = self.sdram_controller_settings.l2_size
-        if l2_size:
-            self.add_constant("L2_SIZE", l2_size)
-
-        # add a Wishbone interface to the DRAM
-        wb_sdram = wishbone.Interface()
-        self.add_wb_sdram_if(wb_sdram)
-        self.register_mem("main_ram", self.mem_map["main_ram"], wb_sdram, main_ram_size)
-
-        # LASMICON frontend
-        if isinstance(self.sdram_controller_settings, LASMIconSettings):
-            if self.sdram_controller_settings.with_bandwidth:
-                self.sdram.controller.multiplexer.add_bandwidth()
-
-            if self.sdram_controller_settings.with_memtest:
-                self.submodules.memtest_w = memtest.MemtestWriter(self.sdram.crossbar.get_master())
-                self.submodules.memtest_r = memtest.MemtestReader(self.sdram.crossbar.get_master())
-
-            if l2_size:
-                lasmim = self.sdram.crossbar.get_master()
-                l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, wishbone.Interface(lasmim.dw))
-                # XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
-                # Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
-                # Remove this workaround when fixed by Xilinx.
-                from mibuild.xilinx.vivado import XilinxVivadoToolchain
-                if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
-                    from migen.fhdl.simplify import FullMemoryWE
-                    self.submodules.l2_cache = FullMemoryWE()(l2_cache)
-                else:
-                    self.submodules.l2_cache = l2_cache
-                self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_cache.slave, lasmim)
-
-        # MINICON frontend
-        elif isinstance(self.sdram_controller_settings, MiniconSettings):
-            if l2_size:
-                l2_cache = wishbone.Cache(l2_size//4, self._wb_sdram, self.sdram.controller.bus)
-                # XXX Vivado ->2015.1 workaround, Vivado is not able to map correctly our L2 cache.
-                # Issue is reported to Xilinx and should be fixed in next releases (2015.2?).
-                # Remove this workaround when fixed by Xilinx.
-                from mibuild.xilinx.vivado import XilinxVivadoToolchain
-                if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
-                    from migen.fhdl.simplify import FullMemoryWE
-                    self.submodules.l2_cache = FullMemoryWE()(l2_cache)
-                else:
-                    self.submodules.l2_cache = l2_cache
-            else:
-                self.submodules.converter = wishbone.Converter(self._wb_sdram, self.sdram.controller.bus)
-
-    def do_finalize(self):
-        if not self.integrated_main_ram_size:
-            if not self._sdram_phy_registered:
-                raise FinalizeError("Need to call SDRAMSoC.register_sdram_phy()")
-
-            # arbitrate wishbone interfaces to the DRAM
-            self.submodules.wb_sdram_con = wishbone.Arbiter(self._wb_sdram_ifs,
-                                                            self._wb_sdram)
-        SoC.do_finalize(self)
diff --git a/misoclib/tools/__init__.py b/misoclib/tools/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/tools/wishbone.py b/misoclib/tools/wishbone.py
deleted file mode 100644 (file)
index 5b712bf..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-from migen.fhdl.std import *
-from migen.bus import wishbone
-from migen.genlib.misc import chooser, Counter, WaitTimer
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.flow.actor import Sink, Source
-
-
-class WishboneStreamingBridge(Module):
-    cmds = {
-        "write": 0x01,
-        "read": 0x02
-    }
-
-    def __init__(self, phy, clk_freq):
-        self.wishbone = wishbone.Interface()
-
-        # # #
-
-        byte_counter = Counter(3)
-        word_counter = Counter(8)
-        self.submodules += byte_counter, word_counter
-
-        cmd = Signal(8)
-        cmd_ce = Signal()
-
-        length = Signal(8)
-        length_ce = Signal()
-
-        address = Signal(32)
-        address_ce = Signal()
-
-        data = Signal(32)
-        rx_data_ce = Signal()
-        tx_data_ce = Signal()
-
-        self.sync += [
-            If(cmd_ce, cmd.eq(phy.source.data)),
-            If(length_ce, length.eq(phy.source.data)),
-            If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))),
-            If(rx_data_ce,
-                data.eq(Cat(phy.source.data, data[0:24]))
-            ).Elif(tx_data_ce,
-                data.eq(self.wishbone.dat_r)
-            )
-        ]
-
-        fsm = InsertReset(FSM(reset_state="IDLE"))
-        timer = WaitTimer(clk_freq//10)
-        self.submodules += fsm, timer
-        self.comb += [
-            fsm.reset.eq(timer.done),
-            phy.source.ack.eq(1)
-        ]
-        fsm.act("IDLE",
-            If(phy.source.stb,
-                cmd_ce.eq(1),
-                If((phy.source.data == self.cmds["write"]) |
-                   (phy.source.data == self.cmds["read"]),
-                    NextState("RECEIVE_LENGTH")
-                ),
-                byte_counter.reset.eq(1),
-                word_counter.reset.eq(1)
-            )
-        )
-        fsm.act("RECEIVE_LENGTH",
-            If(phy.source.stb,
-                length_ce.eq(1),
-                NextState("RECEIVE_ADDRESS")
-            )
-        )
-        fsm.act("RECEIVE_ADDRESS",
-            If(phy.source.stb,
-                address_ce.eq(1),
-                byte_counter.ce.eq(1),
-                If(byte_counter.value == 3,
-                    If(cmd == self.cmds["write"],
-                        NextState("RECEIVE_DATA")
-                    ).Elif(cmd == self.cmds["read"],
-                        NextState("READ_DATA")
-                    ),
-                    byte_counter.reset.eq(1),
-                )
-            )
-        )
-        fsm.act("RECEIVE_DATA",
-            If(phy.source.stb,
-                rx_data_ce.eq(1),
-                byte_counter.ce.eq(1),
-                If(byte_counter.value == 3,
-                    NextState("WRITE_DATA"),
-                    byte_counter.reset.eq(1)
-                )
-            )
-        )
-        self.comb += [
-            self.wishbone.adr.eq(address + word_counter.value),
-            self.wishbone.dat_w.eq(data),
-            self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1)
-        ]
-        fsm.act("WRITE_DATA",
-            self.wishbone.stb.eq(1),
-            self.wishbone.we.eq(1),
-            self.wishbone.cyc.eq(1),
-            If(self.wishbone.ack,
-                word_counter.ce.eq(1),
-                If(word_counter.value == (length-1),
-                    NextState("IDLE")
-                ).Else(
-                    NextState("RECEIVE_DATA")
-                )
-            )
-        )
-        fsm.act("READ_DATA",
-            self.wishbone.stb.eq(1),
-            self.wishbone.we.eq(0),
-            self.wishbone.cyc.eq(1),
-            If(self.wishbone.ack,
-                tx_data_ce.eq(1),
-                NextState("SEND_DATA")
-            )
-        )
-        self.comb += \
-            chooser(data, byte_counter.value, phy.sink.data, n=4, reverse=True)
-        fsm.act("SEND_DATA",
-            phy.sink.stb.eq(1),
-            If(phy.sink.ack,
-                byte_counter.ce.eq(1),
-                If(byte_counter.value == 3,
-                    word_counter.ce.eq(1),
-                    If(word_counter.value == (length-1),
-                        NextState("IDLE")
-                    ).Else(
-                        NextState("READ_DATA"),
-                        byte_counter.reset.eq(1)
-                    )
-                )
-            )
-        )
-
-        self.comb += timer.wait.eq(~fsm.ongoing("IDLE"))
-
-        if phy.sink.description.packetized:
-            self.comb += [
-                phy.sink.sop.eq((byte_counter.value == 0) & (word_counter.value == 0)),
-                phy.sink.eop.eq((byte_counter.value == 3) & (word_counter.value == (length-1)))
-            ]
-            if hasattr(phy.sink, "length"):
-                self.comb += phy.sink.length.eq(4*length)
diff --git a/misoclib/video/__init__.py b/misoclib/video/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/misoclib/video/dvisampler/__init__.py b/misoclib/video/dvisampler/__init__.py
deleted file mode 100644 (file)
index 1f56af0..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import AutoCSR
-
-from misoclib.video.dvisampler.edid import EDID
-from misoclib.video.dvisampler.clocking import Clocking
-from misoclib.video.dvisampler.datacapture import DataCapture
-from misoclib.video.dvisampler.charsync import CharSync
-from misoclib.video.dvisampler.wer import WER
-from misoclib.video.dvisampler.decoding import Decoding
-from misoclib.video.dvisampler.chansync import ChanSync
-from misoclib.video.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction
-from misoclib.video.dvisampler.dma import DMA
-
-
-class DVISampler(Module, AutoCSR):
-    def __init__(self, pads, lasmim, n_dma_slots=2, fifo_depth=512):
-        self.submodules.edid = EDID(pads)
-        self.submodules.clocking = Clocking(pads)
-
-        for datan in range(3):
-            name = "data" + str(datan)
-
-            cap = DataCapture(getattr(pads, name + "_p"), getattr(pads, name + "_n"), 8)
-            setattr(self.submodules, name + "_cap", cap)
-            self.comb += cap.serdesstrobe.eq(self.clocking.serdesstrobe)
-
-            charsync = CharSync()
-            setattr(self.submodules, name + "_charsync", charsync)
-            self.comb += charsync.raw_data.eq(cap.d)
-
-            wer = WER()
-            setattr(self.submodules, name + "_wer", wer)
-            self.comb += wer.data.eq(charsync.data)
-
-            decoding = Decoding()
-            setattr(self.submodules, name + "_decod", decoding)
-            self.comb += [
-                decoding.valid_i.eq(charsync.synced),
-                decoding.input.eq(charsync.data)
-            ]
-
-        self.submodules.chansync = ChanSync()
-        self.comb += [
-            self.chansync.valid_i.eq(self.data0_decod.valid_o & \
-              self.data1_decod.valid_o & self.data2_decod.valid_o),
-            self.chansync.data_in0.eq(self.data0_decod.output),
-            self.chansync.data_in1.eq(self.data1_decod.output),
-            self.chansync.data_in2.eq(self.data2_decod.output),
-        ]
-
-        self.submodules.syncpol = SyncPolarity()
-        self.comb += [
-            self.syncpol.valid_i.eq(self.chansync.chan_synced),
-            self.syncpol.data_in0.eq(self.chansync.data_out0),
-            self.syncpol.data_in1.eq(self.chansync.data_out1),
-            self.syncpol.data_in2.eq(self.chansync.data_out2)
-        ]
-
-        self.submodules.resdetection = ResolutionDetection()
-        self.comb += [
-            self.resdetection.valid_i.eq(self.syncpol.valid_o),
-            self.resdetection.de.eq(self.syncpol.de),
-            self.resdetection.vsync.eq(self.syncpol.vsync)
-        ]
-
-        self.submodules.frame = FrameExtraction(24*lasmim.dw//32, fifo_depth)
-        self.comb += [
-            self.frame.valid_i.eq(self.syncpol.valid_o),
-            self.frame.de.eq(self.syncpol.de),
-            self.frame.vsync.eq(self.syncpol.vsync),
-            self.frame.r.eq(self.syncpol.r),
-            self.frame.g.eq(self.syncpol.g),
-            self.frame.b.eq(self.syncpol.b)
-        ]
-
-        self.submodules.dma = DMA(lasmim, n_dma_slots)
-        self.comb += self.frame.frame.connect(self.dma.frame)
-        self.ev = self.dma.ev
-
-    autocsr_exclude = {"ev"}
diff --git a/misoclib/video/dvisampler/analysis.py b/misoclib/video/dvisampler/analysis.py
deleted file mode 100644 (file)
index ccc7667..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg, PulseSynchronizer
-from migen.genlib.fifo import AsyncFIFO
-from migen.genlib.record import Record
-from migen.bank.description import *
-from migen.flow.actor import *
-
-from misoclib.video.dvisampler.common import channel_layout
-
-
-class SyncPolarity(Module):
-    def __init__(self):
-        self.valid_i = Signal()
-        self.data_in0 = Record(channel_layout)
-        self.data_in1 = Record(channel_layout)
-        self.data_in2 = Record(channel_layout)
-
-        self.valid_o = Signal()
-        self.de = Signal()
-        self.hsync = Signal()
-        self.vsync = Signal()
-        self.r = Signal(8)
-        self.g = Signal(8)
-        self.b = Signal(8)
-
-        ###
-
-        de = self.data_in0.de
-        de_r = Signal()
-        c = self.data_in0.c
-        c_polarity = Signal(2)
-        c_out = Signal(2)
-
-        self.comb += [
-            self.de.eq(de_r),
-            self.hsync.eq(c_out[0]),
-            self.vsync.eq(c_out[1])
-        ]
-
-        self.sync.pix += [
-            self.valid_o.eq(self.valid_i),
-            self.r.eq(self.data_in2.d),
-            self.g.eq(self.data_in1.d),
-            self.b.eq(self.data_in0.d),
-
-            de_r.eq(de),
-            If(de_r & ~de,
-                c_polarity.eq(c),
-                c_out.eq(0)
-            ).Else(
-                c_out.eq(c ^ c_polarity)
-            )
-        ]
-
-
-class ResolutionDetection(Module, AutoCSR):
-    def __init__(self, nbits=11):
-        self.valid_i = Signal()
-        self.vsync = Signal()
-        self.de = Signal()
-
-        self._hres = CSRStatus(nbits)
-        self._vres = CSRStatus(nbits)
-
-        ###
-
-        # Detect DE transitions
-        de_r = Signal()
-        pn_de = Signal()
-        self.sync.pix += de_r.eq(self.de)
-        self.comb += pn_de.eq(~self.de & de_r)
-
-        # HRES
-        hcounter = Signal(nbits)
-        self.sync.pix += If(self.valid_i & self.de,
-                hcounter.eq(hcounter + 1)
-            ).Else(
-                hcounter.eq(0)
-            )
-
-        hcounter_st = Signal(nbits)
-        self.sync.pix += If(self.valid_i,
-                If(pn_de, hcounter_st.eq(hcounter))
-            ).Else(
-                hcounter_st.eq(0)
-            )
-        self.specials += MultiReg(hcounter_st, self._hres.status)
-
-        # VRES
-        vsync_r = Signal()
-        p_vsync = Signal()
-        self.sync.pix += vsync_r.eq(self.vsync),
-        self.comb += p_vsync.eq(self.vsync & ~vsync_r)
-
-        vcounter = Signal(nbits)
-        self.sync.pix += If(self.valid_i & p_vsync,
-                vcounter.eq(0)
-            ).Elif(pn_de,
-                vcounter.eq(vcounter + 1)
-            )
-
-        vcounter_st = Signal(nbits)
-        self.sync.pix += If(self.valid_i,
-                If(p_vsync, vcounter_st.eq(vcounter))
-            ).Else(
-                vcounter_st.eq(0)
-            )
-        self.specials += MultiReg(vcounter_st, self._vres.status)
-
-
-class FrameExtraction(Module, AutoCSR):
-    def __init__(self, word_width, fifo_depth):
-        # in pix clock domain
-        self.valid_i = Signal()
-        self.vsync = Signal()
-        self.de = Signal()
-        self.r = Signal(8)
-        self.g = Signal(8)
-        self.b = Signal(8)
-
-        # in sys clock domain
-        word_layout = [("sof", 1), ("pixels", word_width)]
-        self.frame = Source(word_layout)
-        self.busy = Signal()
-
-        self._overflow = CSR()
-
-        ###
-
-        # start of frame detection
-        vsync_r = Signal()
-        new_frame = Signal()
-        self.comb += new_frame.eq(self.vsync & ~vsync_r)
-        self.sync.pix += vsync_r.eq(self.vsync)
-
-        # pack pixels into words
-        cur_word = Signal(word_width)
-        cur_word_valid = Signal()
-        encoded_pixel = Signal(24)
-        self.comb += encoded_pixel.eq(Cat(self.b, self.g, self.r))
-        pack_factor = word_width//24
-        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
-        pack_counter = Signal(max=pack_factor)
-        self.sync.pix += [
-            cur_word_valid.eq(0),
-            If(new_frame,
-                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
-                pack_counter.eq(0),
-            ).Elif(self.valid_i & self.de,
-                [If(pack_counter == (pack_factor-i-1),
-                    cur_word[24*i:24*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)],
-                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
-                pack_counter.eq(pack_counter + 1)
-            )
-        ]
-
-        # FIFO
-        fifo = RenameClockDomains(AsyncFIFO(word_layout, fifo_depth),
-            {"write": "pix", "read": "sys"})
-        self.submodules += fifo
-        self.comb += [
-            fifo.din.pixels.eq(cur_word),
-            fifo.we.eq(cur_word_valid)
-        ]
-        self.sync.pix += \
-            If(new_frame,
-                fifo.din.sof.eq(1)
-            ).Elif(cur_word_valid,
-                fifo.din.sof.eq(0)
-            )
-        self.comb += [
-            self.frame.stb.eq(fifo.readable),
-            self.frame.payload.eq(fifo.dout),
-            fifo.re.eq(self.frame.ack),
-            self.busy.eq(0)
-        ]
-
-        # overflow detection
-        pix_overflow = Signal()
-        pix_overflow_reset = Signal()
-        self.sync.pix += [
-            If(fifo.we & ~fifo.writable,
-                pix_overflow.eq(1)
-            ).Elif(pix_overflow_reset,
-                pix_overflow.eq(0)
-            )
-        ]
-
-        sys_overflow = Signal()
-        self.specials += MultiReg(pix_overflow, sys_overflow)
-        self.submodules.overflow_reset = PulseSynchronizer("sys", "pix")
-        self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys")
-        self.comb += [
-            pix_overflow_reset.eq(self.overflow_reset.o),
-            self.overflow_reset_ack.i.eq(pix_overflow_reset)
-        ]
-
-        overflow_mask = Signal()
-        self.comb += [
-            self._overflow.w.eq(sys_overflow & ~overflow_mask),
-            self.overflow_reset.i.eq(self._overflow.re)
-        ]
-        self.sync += \
-            If(self._overflow.re,
-                overflow_mask.eq(1)
-            ).Elif(self.overflow_reset_ack.o,
-                overflow_mask.eq(0)
-            )
diff --git a/misoclib/video/dvisampler/chansync.py b/misoclib/video/dvisampler/chansync.py
deleted file mode 100644 (file)
index 0e5d0d6..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.genlib.fifo import _inc
-from migen.genlib.record import Record, layout_len
-from migen.genlib.misc import optree
-from migen.bank.description import *
-
-from misoclib.video.dvisampler.common import channel_layout
-
-
-class _SyncBuffer(Module):
-    def __init__(self, width, depth):
-        self.din = Signal(width)
-        self.dout = Signal(width)
-        self.re = Signal()
-
-        ###
-
-        produce = Signal(max=depth)
-        consume = Signal(max=depth)
-        storage = Memory(width, depth)
-        self.specials += storage
-
-        wrport = storage.get_port(write_capable=True)
-        self.specials += wrport
-        self.comb += [
-            wrport.adr.eq(produce),
-            wrport.dat_w.eq(self.din),
-            wrport.we.eq(1)
-        ]
-        self.sync += _inc(produce, depth)
-
-        rdport = storage.get_port(async_read=True)
-        self.specials += rdport
-        self.comb += [
-            rdport.adr.eq(consume),
-            self.dout.eq(rdport.dat_r)
-        ]
-        self.sync += If(self.re, _inc(consume, depth))
-
-
-class ChanSync(Module, AutoCSR):
-    def __init__(self, nchan=3, depth=8):
-        self.valid_i = Signal()
-        self.chan_synced = Signal()
-
-        self._channels_synced = CSRStatus()
-
-        lst_control = []
-        all_control = Signal()
-        for i in range(nchan):
-            name = "data_in" + str(i)
-            data_in = Record(channel_layout, name=name)
-            setattr(self, name, data_in)
-            name = "data_out" + str(i)
-            data_out = Record(channel_layout, name=name)
-            setattr(self, name, data_out)
-
-            ###
-
-            syncbuffer = RenameClockDomains(_SyncBuffer(layout_len(channel_layout), depth), "pix")
-            self.submodules += syncbuffer
-            self.comb += [
-                syncbuffer.din.eq(data_in.raw_bits()),
-                data_out.raw_bits().eq(syncbuffer.dout)
-            ]
-            is_control = Signal()
-            self.comb += [
-                is_control.eq(~data_out.de),
-                syncbuffer.re.eq(~is_control | all_control)
-            ]
-            lst_control.append(is_control)
-
-        some_control = Signal()
-        self.comb += [
-            all_control.eq(optree("&", lst_control)),
-            some_control.eq(optree("|", lst_control))
-        ]
-        self.sync.pix += If(~self.valid_i,
-                self.chan_synced.eq(0)
-            ).Else(
-                If(some_control,
-                    If(all_control,
-                        self.chan_synced.eq(1)
-                    ).Else(
-                        self.chan_synced.eq(0)
-                    )
-                )
-            )
-        self.specials += MultiReg(self.chan_synced, self._channels_synced.status)
-
-
-class _TB(Module):
-    def __init__(self, test_seq_it):
-        self.test_seq_it = test_seq_it
-
-        self.submodules.chansync = RenameClockDomains(ChanSync(), {"pix": "sys"})
-        self.comb += self.chansync.valid_i.eq(1)
-
-    def do_simulation(self, selfp):
-        try:
-            de0, de1, de2 = next(self.test_seq_it)
-        except StopIteration:
-            raise StopSimulation
-
-        selfp.chansync.data_in0.de = de0
-        selfp.chansync.data_in1.de = de1
-        selfp.chansync.data_in2.de = de2
-        selfp.chansync.data_in0.d = selfp.simulator.cycle_counter
-        selfp.chansync.data_in1.d = selfp.simulator.cycle_counter
-        selfp.chansync.data_in2.d = selfp.simulator.cycle_counter
-
-        out0 = selfp.chansync.data_out0.d
-        out1 = selfp.chansync.data_out1.d
-        out2 = selfp.chansync.data_out2.d
-
-        print("{0:5} {1:5} {2:5}".format(out0, out1, out2))
-
-if __name__ == "__main__":
-    from migen.sim.generic import run_simulation
-
-    test_seq = [
-        (1, 1, 1),
-        (1, 1, 0),
-        (0, 0, 0),
-        (0, 0, 0),
-        (0, 0, 1),
-        (1, 1, 1),
-        (1, 1, 1),
-    ]
-    tb = _TB(iter(test_seq*2))
-    run_simulation(tb)
diff --git a/misoclib/video/dvisampler/charsync.py b/misoclib/video/dvisampler/charsync.py
deleted file mode 100644 (file)
index 343303e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.genlib.misc import optree
-from migen.bank.description import *
-
-from misoclib.video.dvisampler.common import control_tokens
-
-
-class CharSync(Module, AutoCSR):
-    def __init__(self, required_controls=8):
-        self.raw_data = Signal(10)
-        self.synced = Signal()
-        self.data = Signal(10)
-
-        self._char_synced = CSRStatus()
-        self._ctl_pos = CSRStatus(bits_for(9))
-
-        ###
-
-        raw_data1 = Signal(10)
-        self.sync.pix += raw_data1.eq(self.raw_data)
-        raw = Signal(20)
-        self.comb += raw.eq(Cat(raw_data1, self.raw_data))
-
-        found_control = Signal()
-        control_position = Signal(max=10)
-        self.sync.pix += found_control.eq(0)
-        for i in range(10):
-            self.sync.pix += If(optree("|", [raw[i:i+10] == t for t in control_tokens]),
-                  found_control.eq(1),
-                  control_position.eq(i)
-            )
-
-        control_counter = Signal(max=required_controls)
-        previous_control_position = Signal(max=10)
-        word_sel = Signal(max=10)
-        self.sync.pix += [
-            If(found_control & (control_position == previous_control_position),
-                If(control_counter == (required_controls - 1),
-                    control_counter.eq(0),
-                    self.synced.eq(1),
-                    word_sel.eq(control_position)
-                ).Else(
-                    control_counter.eq(control_counter + 1)
-                )
-            ).Else(
-                control_counter.eq(0)
-            ),
-            previous_control_position.eq(control_position)
-        ]
-        self.specials += MultiReg(self.synced, self._char_synced.status)
-        self.specials += MultiReg(word_sel, self._ctl_pos.status)
-
-        self.sync.pix += self.data.eq(raw >> word_sel)
diff --git a/misoclib/video/dvisampler/clocking.py b/misoclib/video/dvisampler/clocking.py
deleted file mode 100644 (file)
index d13b1fb..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-
-
-class Clocking(Module, AutoCSR):
-    def __init__(self, pads):
-        self._pll_reset = CSRStorage(reset=1)
-        self._locked = CSRStatus()
-
-        # DRP
-        self._pll_adr = CSRStorage(5)
-        self._pll_dat_r = CSRStatus(16)
-        self._pll_dat_w = CSRStorage(16)
-        self._pll_read = CSR()
-        self._pll_write = CSR()
-        self._pll_drdy = CSRStatus()
-
-        self.locked = Signal()
-        self.serdesstrobe = Signal()
-        self.clock_domains._cd_pix = ClockDomain()
-        self.clock_domains._cd_pix2x = ClockDomain()
-        self.clock_domains._cd_pix10x = ClockDomain(reset_less=True)
-
-        ###
-
-        clk_se = Signal()
-        self.specials += Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_se)
-
-        clkfbout = Signal()
-        pll_locked = Signal()
-        pll_clk0 = Signal()
-        pll_clk1 = Signal()
-        pll_clk2 = Signal()
-        pll_drdy = Signal()
-        self.sync += If(self._pll_read.re | self._pll_write.re,
-            self._pll_drdy.status.eq(0)
-        ).Elif(pll_drdy,
-            self._pll_drdy.status.eq(1)
-        )
-        self.specials += Instance("PLL_ADV",
-                                  p_CLKFBOUT_MULT=10,
-                                  p_CLKOUT0_DIVIDE=1,   # pix10x
-                                  p_CLKOUT1_DIVIDE=5,   # pix2x
-                                  p_CLKOUT2_DIVIDE=10,  # pix
-                                  p_COMPENSATION="INTERNAL",
-
-                                  i_CLKINSEL=1,
-                                  i_CLKIN1=clk_se,
-                                  o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
-                                  o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
-                                  o_LOCKED=pll_locked, i_RST=self._pll_reset.storage,
-
-                                  i_DADDR=self._pll_adr.storage,
-                                  o_DO=self._pll_dat_r.status,
-                                  i_DI=self._pll_dat_w.storage,
-                                  i_DEN=self._pll_read.re | self._pll_write.re,
-                                  i_DWE=self._pll_write.re,
-                                  o_DRDY=pll_drdy,
-                                  i_DCLK=ClockSignal())
-
-        locked_async = Signal()
-        self.specials += [
-            Instance("BUFPLL", p_DIVIDE=5,
-                     i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
-                     o_IOCLK=self._cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
-            Instance("BUFG", i_I=pll_clk1, o_O=self._cd_pix2x.clk),
-            Instance("BUFG", i_I=pll_clk2, o_O=self._cd_pix.clk),
-            MultiReg(locked_async, self.locked, "sys")
-        ]
-        self.comb += self._locked.status.eq(self.locked)
-
-        # sychronize pix+pix2x reset
-        pix_rst_n = 1
-        for i in range(2):
-            new_pix_rst_n = Signal()
-            self.specials += Instance("FDCE", i_D=pix_rst_n, i_CE=1, i_C=ClockSignal("pix"),
-                i_CLR=~locked_async, o_Q=new_pix_rst_n)
-            pix_rst_n = new_pix_rst_n
-        self.comb += self._cd_pix.rst.eq(~pix_rst_n), self._cd_pix2x.rst.eq(~pix_rst_n)
diff --git a/misoclib/video/dvisampler/common.py b/misoclib/video/dvisampler/common.py
deleted file mode 100644 (file)
index 7fb9a42..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
-channel_layout = [("d", 8), ("c", 2), ("de", 1)]
diff --git a/misoclib/video/dvisampler/datacapture.py b/misoclib/video/dvisampler/datacapture.py
deleted file mode 100644 (file)
index 8e91ad0..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.cdc import MultiReg, PulseSynchronizer
-from migen.bank.description import *
-
-
-class DataCapture(Module, AutoCSR):
-    def __init__(self, pad_p, pad_n, ntbits):
-        self.serdesstrobe = Signal()
-        self.d = Signal(10)
-
-        self._dly_ctl = CSR(6)
-        self._dly_busy = CSRStatus(2)
-        self._phase = CSRStatus(2)
-        self._phase_reset = CSR()
-
-        ###
-
-        # IO
-        pad_se = Signal()
-        self.specials += Instance("IBUFDS", i_I=pad_p, i_IB=pad_n, o_O=pad_se)
-
-        pad_delayed_master = Signal()
-        pad_delayed_slave = Signal()
-        delay_inc = Signal()
-        delay_ce = Signal()
-        delay_master_cal = Signal()
-        delay_master_rst = Signal()
-        delay_master_busy = Signal()
-        delay_slave_cal = Signal()
-        delay_slave_rst = Signal()
-        delay_slave_busy = Signal()
-        self.specials += Instance("IODELAY2",
-                                  p_SERDES_MODE="MASTER",
-                                  p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
-                                  p_COUNTER_WRAPAROUND="STAY_AT_LIMIT", p_DATA_RATE="SDR",
-
-                                  i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_master,
-                                  i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
-
-                                  i_INC=delay_inc, i_CE=delay_ce,
-                                  i_CAL=delay_master_cal, i_RST=delay_master_rst, o_BUSY=delay_master_busy,
-                                  i_T=1)
-        self.specials += Instance("IODELAY2",
-                                  p_SERDES_MODE="SLAVE",
-                                  p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
-                                  p_COUNTER_WRAPAROUND="WRAPAROUND", p_DATA_RATE="SDR",
-
-                                  i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_slave,
-                                  i_CLK=ClockSignal("pix2x"), i_IOCLK0=ClockSignal("pix10x"),
-
-                                  i_INC=delay_inc, i_CE=delay_ce,
-                                  i_CAL=delay_slave_cal, i_RST=delay_slave_rst, o_BUSY=delay_slave_busy,
-                                  i_T=1)
-
-        dsr2 = Signal(5)
-        pd_valid = Signal()
-        pd_incdec = Signal()
-        pd_edge = Signal()
-        pd_cascade = Signal()
-        self.specials += Instance("ISERDES2",
-                                  p_SERDES_MODE="MASTER",
-                                  p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
-                                  p_INTERFACE_TYPE="RETIMED",
-
-                                  i_D=pad_delayed_master,
-                                  o_Q4=dsr2[4], o_Q3=dsr2[3], o_Q2=dsr2[2], o_Q1=dsr2[1],
-
-                                  i_BITSLIP=0, i_CE0=1, i_RST=0,
-                                  i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
-                                  i_IOCE=self.serdesstrobe,
-
-                                  o_VALID=pd_valid, o_INCDEC=pd_incdec,
-                                  i_SHIFTIN=pd_edge, o_SHIFTOUT=pd_cascade)
-        self.specials += Instance("ISERDES2",
-                                  p_SERDES_MODE="SLAVE",
-                                  p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=5,
-                                  p_INTERFACE_TYPE="RETIMED",
-
-                                  i_D=pad_delayed_slave,
-                                  o_Q4=dsr2[0],
-
-                                  i_BITSLIP=0, i_CE0=1, i_RST=0,
-                                  i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix2x"),
-                                  i_IOCE=self.serdesstrobe,
-
-                                  i_SHIFTIN=pd_cascade, o_SHIFTOUT=pd_edge)
-
-        # Phase error accumulator
-        lateness = Signal(ntbits, reset=2**(ntbits - 1))
-        too_late = Signal()
-        too_early = Signal()
-        reset_lateness = Signal()
-        self.comb += [
-            too_late.eq(lateness == (2**ntbits - 1)),
-            too_early.eq(lateness == 0)
-        ]
-        self.sync.pix2x += [
-            If(reset_lateness,
-                lateness.eq(2**(ntbits - 1))
-            ).Elif(~delay_master_busy & ~delay_slave_busy & ~too_late & ~too_early,
-                If(pd_valid & pd_incdec, lateness.eq(lateness - 1)),
-                If(pd_valid & ~pd_incdec, lateness.eq(lateness + 1))
-            )
-        ]
-
-        # Delay control
-        self.submodules.delay_master_done = PulseSynchronizer("pix2x", "sys")
-        delay_master_pending = Signal()
-        self.sync.pix2x += [
-            self.delay_master_done.i.eq(0),
-            If(~delay_master_pending,
-                If(delay_master_cal | delay_ce, delay_master_pending.eq(1))
-            ).Else(
-                If(~delay_master_busy,
-                    self.delay_master_done.i.eq(1),
-                    delay_master_pending.eq(0)
-                )
-            )
-        ]
-        self.submodules.delay_slave_done = PulseSynchronizer("pix2x", "sys")
-        delay_slave_pending = Signal()
-        self.sync.pix2x += [
-            self.delay_slave_done.i.eq(0),
-            If(~delay_slave_pending,
-                If(delay_slave_cal | delay_ce, delay_slave_pending.eq(1))
-            ).Else(
-                If(~delay_slave_busy,
-                    self.delay_slave_done.i.eq(1),
-                    delay_slave_pending.eq(0)
-                )
-            )
-        ]
-
-        self.submodules.do_delay_master_cal = PulseSynchronizer("sys", "pix2x")
-        self.submodules.do_delay_master_rst = PulseSynchronizer("sys", "pix2x")
-        self.submodules.do_delay_slave_cal = PulseSynchronizer("sys", "pix2x")
-        self.submodules.do_delay_slave_rst = PulseSynchronizer("sys", "pix2x")
-        self.submodules.do_delay_inc = PulseSynchronizer("sys", "pix2x")
-        self.submodules.do_delay_dec = PulseSynchronizer("sys", "pix2x")
-        self.comb += [
-            delay_master_cal.eq(self.do_delay_master_cal.o),
-            delay_master_rst.eq(self.do_delay_master_rst.o),
-            delay_slave_cal.eq(self.do_delay_slave_cal.o),
-            delay_slave_rst.eq(self.do_delay_slave_rst.o),
-            delay_inc.eq(self.do_delay_inc.o),
-            delay_ce.eq(self.do_delay_inc.o | self.do_delay_dec.o),
-        ]
-
-        sys_delay_master_pending = Signal()
-        self.sync += [
-            If(self.do_delay_master_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
-                sys_delay_master_pending.eq(1)
-            ).Elif(self.delay_master_done.o,
-                sys_delay_master_pending.eq(0)
-            )
-        ]
-        sys_delay_slave_pending = Signal()
-        self.sync += [
-            If(self.do_delay_slave_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
-                sys_delay_slave_pending.eq(1)
-            ).Elif(self.delay_slave_done.o,
-                sys_delay_slave_pending.eq(0)
-            )
-        ]
-
-        self.comb += [
-            self.do_delay_master_cal.i.eq(self._dly_ctl.re & self._dly_ctl.r[0]),
-            self.do_delay_master_rst.i.eq(self._dly_ctl.re & self._dly_ctl.r[1]),
-            self.do_delay_slave_cal.i.eq(self._dly_ctl.re & self._dly_ctl.r[2]),
-            self.do_delay_slave_rst.i.eq(self._dly_ctl.re & self._dly_ctl.r[3]),
-            self.do_delay_inc.i.eq(self._dly_ctl.re & self._dly_ctl.r[4]),
-            self.do_delay_dec.i.eq(self._dly_ctl.re & self._dly_ctl.r[5]),
-            self._dly_busy.status.eq(Cat(sys_delay_master_pending, sys_delay_slave_pending))
-        ]
-
-        # Phase detector control
-        self.specials += MultiReg(Cat(too_late, too_early), self._phase.status)
-        self.submodules.do_reset_lateness = PulseSynchronizer("sys", "pix2x")
-        self.comb += [
-            reset_lateness.eq(self.do_reset_lateness.o),
-            self.do_reset_lateness.i.eq(self._phase_reset.re)
-        ]
-
-        # 5:10 deserialization
-        dsr = Signal(10)
-        self.sync.pix2x += dsr.eq(Cat(dsr[5:], dsr2))
-        self.sync.pix += self.d.eq(dsr)
diff --git a/misoclib/video/dvisampler/debug.py b/misoclib/video/dvisampler/debug.py
deleted file mode 100644 (file)
index 6cbc5a3..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.fifo import AsyncFIFO
-from migen.genlib.record import layout_len
-from migen.bank.description import AutoCSR
-from migen.actorlib import structuring, spi
-
-from misoclib.mem.sdram.frontend import dma_lasmi
-from misoclib.video.dvisampler.edid import EDID
-from misoclib.video.dvisampler.clocking import Clocking
-from misoclib.video.dvisampler.datacapture import DataCapture
-
-
-class RawDVISampler(Module, AutoCSR):
-    def __init__(self, pads, asmiport):
-        self.submodules.edid = EDID(pads)
-        self.submodules.clocking = Clocking(pads)
-
-        invert = False
-        try:
-            s = getattr(pads, "data0")
-        except AttributeError:
-            s = getattr(pads, "data0_n")
-            invert = True
-        self.submodules.data0_cap = DataCapture(8, invert)
-        self.comb += [
-            self.data0_cap.pad.eq(s),
-            self.data0_cap.serdesstrobe.eq(self.clocking.serdesstrobe)
-        ]
-
-        fifo = RenameClockDomains(AsyncFIFO(10, 256),
-            {"write": "pix", "read": "sys"})
-        self.submodules += fifo
-        self.comb += [
-            fifo.din.eq(self.data0_cap.d),
-            fifo.we.eq(1)
-        ]
-
-        pack_factor = asmiport.hub.dw//16
-        self.submodules.packer = structuring.Pack([("word", 10), ("pad", 6)], pack_factor)
-        self.submodules.cast = structuring.Cast(self.packer.source.payload.layout, asmiport.hub.dw)
-        self.submodules.dma = spi.DMAWriteController(dma_lasmi.Writer(lasmim), spi.MODE_SINGLE_SHOT)
-        self.comb += [
-            self.packer.sink.stb.eq(fifo.readable),
-            fifo.re.eq(self.packer.sink.ack),
-            self.packer.sink.word.eq(fifo.dout),
-            self.packer.source.connect_flat(self.cast.sink),
-            self.cast.source.connect_flat(self.dma.data)
-        ]
diff --git a/misoclib/video/dvisampler/decoding.py b/misoclib/video/dvisampler/decoding.py
deleted file mode 100644 (file)
index db0b48e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.record import Record
-
-from misoclib.video.dvisampler.common import control_tokens, channel_layout
-
-
-class Decoding(Module):
-    def __init__(self):
-        self.valid_i = Signal()
-        self.input = Signal(10)
-        self.valid_o = Signal()
-        self.output = Record(channel_layout)
-
-        ###
-
-        self.sync.pix += self.output.de.eq(1)
-        for i, t in enumerate(control_tokens):
-            self.sync.pix += If(self.input == t,
-                self.output.de.eq(0),
-                self.output.c.eq(i)
-            )
-        self.sync.pix += self.output.d[0].eq(self.input[0] ^ self.input[9])
-        for i in range(1, 8):
-            self.sync.pix += self.output.d[i].eq(self.input[i] ^ self.input[i-1] ^ ~self.input[8])
-        self.sync.pix += self.valid_o.eq(self.valid_i)
diff --git a/misoclib/video/dvisampler/dma.py b/misoclib/video/dvisampler/dma.py
deleted file mode 100644 (file)
index 5f47752..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.fsm import FSM, NextState
-from migen.bank.description import *
-from migen.bank.eventmanager import *
-from migen.flow.actor import *
-
-from misoclib.mem.sdram.frontend import dma_lasmi
-
-
-# Slot status: EMPTY=0 LOADED=1 PENDING=2
-class _Slot(Module, AutoCSR):
-    def __init__(self, addr_bits, alignment_bits):
-        self.ev_source = EventSourceLevel()
-        self.address = Signal(addr_bits)
-        self.address_reached = Signal(addr_bits)
-        self.address_valid = Signal()
-        self.address_done = Signal()
-
-        self._status = CSRStorage(2, write_from_dev=True)
-        self._address = CSRStorage(addr_bits + alignment_bits, alignment_bits=alignment_bits, write_from_dev=True)
-
-        ###
-
-        self.comb += [
-            self.address.eq(self._address.storage),
-            self.address_valid.eq(self._status.storage[0]),
-            self._status.dat_w.eq(2),
-            self._status.we.eq(self.address_done),
-            self._address.dat_w.eq(self.address_reached),
-            self._address.we.eq(self.address_done),
-            self.ev_source.trigger.eq(self._status.storage[1])
-        ]
-
-
-class _SlotArray(Module, AutoCSR):
-    def __init__(self, nslots, addr_bits, alignment_bits):
-        self.submodules.ev = EventManager()
-        self.address = Signal(addr_bits)
-        self.address_reached = Signal(addr_bits)
-        self.address_valid = Signal()
-        self.address_done = Signal()
-
-        ###
-
-        slots = [_Slot(addr_bits, alignment_bits) for i in range(nslots)]
-        for n, slot in enumerate(slots):
-            setattr(self.submodules, "slot"+str(n), slot)
-            setattr(self.ev, "slot"+str(n), slot.ev_source)
-        self.ev.finalize()
-
-        change_slot = Signal()
-        current_slot = Signal(max=nslots)
-        self.sync += If(change_slot, [If(slot.address_valid, current_slot.eq(n)) for n, slot in reversed(list(enumerate(slots)))])
-        self.comb += change_slot.eq(~self.address_valid | self.address_done)
-
-        self.comb += [
-            self.address.eq(Array(slot.address for slot in slots)[current_slot]),
-            self.address_valid.eq(Array(slot.address_valid for slot in slots)[current_slot])
-        ]
-        self.comb += [slot.address_reached.eq(self.address_reached) for slot in slots]
-        self.comb += [slot.address_done.eq(self.address_done & (current_slot == n)) for n, slot in enumerate(slots)]
-
-
-class DMA(Module):
-    def __init__(self, lasmim, nslots):
-        bus_aw = lasmim.aw
-        bus_dw = lasmim.dw
-        alignment_bits = bits_for(bus_dw//8) - 1
-
-        fifo_word_width = 24*bus_dw//32
-        self.frame = Sink([("sof", 1), ("pixels", fifo_word_width)])
-        self._frame_size = CSRStorage(bus_aw + alignment_bits, alignment_bits=alignment_bits)
-        self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits)
-        self.ev = self._slot_array.ev
-
-        ###
-
-        # address generator + maximum memory word count to prevent DMA buffer overrun
-        reset_words = Signal()
-        count_word = Signal()
-        last_word = Signal()
-        current_address = Signal(bus_aw)
-        mwords_remaining = Signal(bus_aw)
-        self.comb += [
-            self._slot_array.address_reached.eq(current_address),
-            last_word.eq(mwords_remaining == 1)
-        ]
-        self.sync += [
-            If(reset_words,
-                current_address.eq(self._slot_array.address),
-                mwords_remaining.eq(self._frame_size.storage)
-            ).Elif(count_word,
-                current_address.eq(current_address + 1),
-                mwords_remaining.eq(mwords_remaining - 1)
-            )
-        ]
-
-        # 24bpp -> 32bpp
-        memory_word = Signal(bus_dw)
-        pixbits = []
-        for i in range(bus_dw//32):
-            for j in range(3):
-                b = (i*3+j)*8
-                pixbits.append(self.frame.pixels[b+6:b+8])
-                pixbits.append(self.frame.pixels[b:b+8])
-            pixbits.append(0)
-            pixbits.append(0)
-        self.comb += memory_word.eq(Cat(*pixbits))
-
-        # bus accessor
-        self.submodules._bus_accessor = dma_lasmi.Writer(lasmim)
-        self.comb += [
-            self._bus_accessor.address_data.a.eq(current_address),
-            self._bus_accessor.address_data.d.eq(memory_word)
-        ]
-
-        # control FSM
-        fsm = FSM()
-        self.submodules += fsm
-
-        fsm.act("WAIT_SOF",
-            reset_words.eq(1),
-            self.frame.ack.eq(~self._slot_array.address_valid | ~self.frame.sof),
-            If(self._slot_array.address_valid & self.frame.sof & self.frame.stb, NextState("TRANSFER_PIXELS"))
-        )
-        fsm.act("TRANSFER_PIXELS",
-            self.frame.ack.eq(self._bus_accessor.address_data.ack),
-            If(self.frame.stb,
-                self._bus_accessor.address_data.stb.eq(1),
-                If(self._bus_accessor.address_data.ack,
-                    count_word.eq(1),
-                    If(last_word, NextState("EOF"))
-                )
-            )
-        )
-        fsm.act("EOF",
-            If(~self._bus_accessor.busy,
-                self._slot_array.address_done.eq(1),
-                NextState("WAIT_SOF")
-            )
-        )
-
-    def get_csrs(self):
-        return [self._frame_size] + self._slot_array.get_csrs()
diff --git a/misoclib/video/dvisampler/edid.py b/misoclib/video/dvisampler/edid.py
deleted file mode 100644 (file)
index 2a8e8b0..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-from migen.fhdl.std import *
-from migen.fhdl.specials import Tristate
-from migen.genlib.cdc import MultiReg
-from migen.genlib.fsm import FSM, NextState
-from migen.genlib.misc import chooser
-from migen.bank.description import CSRStorage, CSRStatus, AutoCSR
-
-_default_edid = [
-    0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3D, 0x17, 0x32, 0x12, 0x2A, 0x6A, 0xBF, 0x00,
-    0x05, 0x17, 0x01, 0x03, 0x80, 0x28, 0x1E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-    0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xB2, 0x0C, 0x00, 0x40, 0x41, 0x00, 0x26, 0x30, 0x18, 0x88,
-    0x36, 0x00, 0x28, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x4D, 0x31, 0x20,
-    0x44, 0x56, 0x49, 0x20, 0x6D, 0x69, 0x78, 0x65, 0x72, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34,
-]
-
-
-class EDID(Module, AutoCSR):
-    def __init__(self, pads, default=_default_edid):
-        self._hpd_notif = CSRStatus()
-        self._hpd_en = CSRStorage()
-        self.specials.mem = Memory(8, 128, init=default)
-
-        ###
-
-        # HPD
-        if hasattr(pads, "hpd_notif"):
-            self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status)
-        else:
-            self.comb += self._hpd_notif.status.eq(1)
-        if hasattr(pads, "hpd_en"):
-            self.comb += pads.hpd_en.eq(self._hpd_en.storage)
-
-        # EDID
-        scl_raw = Signal()
-        sda_i = Signal()
-        sda_raw = Signal()
-        sda_drv = Signal()
-        _sda_drv_reg = Signal()
-        _sda_i_async = Signal()
-        self.sync += _sda_drv_reg.eq(sda_drv)
-        self.specials += [
-            MultiReg(pads.scl, scl_raw),
-            Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
-            MultiReg(_sda_i_async, sda_raw)
-        ]
-
-        scl_i = Signal()
-        samp_count = Signal(6)
-        samp_carry = Signal()
-        self.sync += [
-            Cat(samp_count, samp_carry).eq(samp_count + 1),
-            If(samp_carry,
-                scl_i.eq(scl_raw),
-                sda_i.eq(sda_raw)
-            )
-        ]
-
-        scl_r = Signal()
-        sda_r = Signal()
-        scl_rising = Signal()
-        sda_rising = Signal()
-        sda_falling = Signal()
-        self.sync += [
-            scl_r.eq(scl_i),
-            sda_r.eq(sda_i)
-        ]
-        self.comb += [
-            scl_rising.eq(scl_i & ~scl_r),
-            sda_rising.eq(sda_i & ~sda_r),
-            sda_falling.eq(~sda_i & sda_r)
-        ]
-
-        start = Signal()
-        self.comb += start.eq(scl_i & sda_falling)
-
-        din = Signal(8)
-        counter = Signal(max=9)
-        self.sync += [
-            If(start, counter.eq(0)),
-            If(scl_rising,
-                If(counter == 8,
-                    counter.eq(0)
-                ).Else(
-                    counter.eq(counter + 1),
-                    din.eq(Cat(sda_i, din[:7]))
-                )
-            )
-        ]
-
-        is_read = Signal()
-        update_is_read = Signal()
-        self.sync += If(update_is_read, is_read.eq(din[0]))
-
-        offset_counter = Signal(max=128)
-        oc_load = Signal()
-        oc_inc = Signal()
-        self.sync += [
-            If(oc_load,
-                offset_counter.eq(din)
-            ).Elif(oc_inc,
-                offset_counter.eq(offset_counter + 1)
-            )
-        ]
-        rdport = self.mem.get_port()
-        self.specials += rdport
-        self.comb += rdport.adr.eq(offset_counter)
-        data_bit = Signal()
-
-        zero_drv = Signal()
-        data_drv = Signal()
-        self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))
-
-        data_drv_en = Signal()
-        data_drv_stop = Signal()
-        self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
-        self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))
-
-        fsm = FSM()
-        self.submodules += fsm
-
-        fsm.act("WAIT_START")
-        fsm.act("RCV_ADDRESS",
-            If(counter == 8,
-                If(din[1:] == 0x50,
-                    update_is_read.eq(1),
-                    NextState("ACK_ADDRESS0")
-                ).Else(
-                    NextState("WAIT_START")
-                )
-            )
-        )
-        fsm.act("ACK_ADDRESS0",
-            If(~scl_i, NextState("ACK_ADDRESS1"))
-        )
-        fsm.act("ACK_ADDRESS1",
-            zero_drv.eq(1),
-            If(scl_i, NextState("ACK_ADDRESS2"))
-        )
-        fsm.act("ACK_ADDRESS2",
-            zero_drv.eq(1),
-            If(~scl_i,
-                If(is_read,
-                    NextState("READ")
-                ).Else(
-                    NextState("RCV_OFFSET")
-                )
-            )
-        )
-
-        fsm.act("RCV_OFFSET",
-            If(counter == 8,
-                oc_load.eq(1),
-                NextState("ACK_OFFSET0")
-            )
-        )
-        fsm.act("ACK_OFFSET0",
-            If(~scl_i, NextState("ACK_OFFSET1"))
-        )
-        fsm.act("ACK_OFFSET1",
-            zero_drv.eq(1),
-            If(scl_i, NextState("ACK_OFFSET2"))
-        )
-        fsm.act("ACK_OFFSET2",
-            zero_drv.eq(1),
-            If(~scl_i, NextState("RCV_ADDRESS"))
-        )
-
-        fsm.act("READ",
-            If(~scl_i,
-                If(counter == 8,
-                    data_drv_stop.eq(1),
-                    NextState("ACK_READ")
-                ).Else(
-                    data_drv_en.eq(1)
-                )
-            )
-        )
-        fsm.act("ACK_READ",
-            If(scl_rising,
-                oc_inc.eq(1),
-                If(sda_i,
-                    NextState("WAIT_START")
-                ).Else(
-                    NextState("READ")
-                )
-            )
-        )
-
-        for state in fsm.actions.keys():
-            fsm.act(state, If(start, NextState("RCV_ADDRESS")))
-            fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
diff --git a/misoclib/video/dvisampler/wer.py b/misoclib/video/dvisampler/wer.py
deleted file mode 100644 (file)
index 17399c2..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-from migen.fhdl.std import *
-from migen.bank.description import *
-from migen.genlib.misc import optree
-from migen.genlib.cdc import PulseSynchronizer
-
-from misoclib.video.dvisampler.common import control_tokens
-
-
-class WER(Module, AutoCSR):
-    def __init__(self, period_bits=24):
-        self.data = Signal(10)
-        self._update = CSR()
-        self._value = CSRStatus(period_bits)
-
-        ###
-
-        # pipeline stage 1
-        # we ignore the 10th (inversion) bit, as it is independent of the transition minimization
-        data_r = Signal(9)
-        self.sync.pix += data_r.eq(self.data[:9])
-
-        # pipeline stage 2
-        transitions = Signal(8)
-        self.comb += [transitions[i].eq(data_r[i] ^ data_r[i+1]) for i in range(8)]
-        transition_count = Signal(max=9)
-        self.sync.pix += transition_count.eq(optree("+", [transitions[i] for i in range(8)]))
-
-        is_control = Signal()
-        self.sync.pix += is_control.eq(optree("|", [data_r == ct for ct in control_tokens]))
-
-        # pipeline stage 3
-        is_error = Signal()
-        self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)
-
-        # counter
-        period_counter = Signal(period_bits)
-        period_done = Signal()
-        self.sync.pix += Cat(period_counter, period_done).eq(period_counter + 1)
-
-        wer_counter = Signal(period_bits)
-        wer_counter_r = Signal(period_bits)
-        wer_counter_r_updated = Signal()
-        self.sync.pix += [
-            wer_counter_r_updated.eq(period_done),
-            If(period_done,
-                wer_counter_r.eq(wer_counter),
-                wer_counter.eq(0)
-            ).Elif(is_error,
-                wer_counter.eq(wer_counter + 1)
-            )
-        ]
-
-        # sync to system clock domain
-        wer_counter_sys = Signal(period_bits)
-        self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
-        self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
-        self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))
-
-        # register interface
-        self.sync += If(self._update.re, self._value.status.eq(wer_counter_sys))
diff --git a/misoclib/video/framebuffer/__init__.py b/misoclib/video/framebuffer/__init__.py
deleted file mode 100644 (file)
index 10ea201..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-from migen.fhdl.std import *
-from migen.flow.network import *
-from migen.flow import plumbing
-from migen.bank.description import AutoCSR
-from migen.actorlib import structuring, misc
-
-from misoclib.mem.sdram.frontend import dma_lasmi
-from misoclib.video.framebuffer.format import bpp, pixel_layout, FrameInitiator, VTG
-from misoclib.video.framebuffer.phy import Driver
-
-
-class Framebuffer(Module, AutoCSR):
-    def __init__(self, pads_vga, pads_dvi, lasmim):
-        pack_factor = lasmim.dw//bpp
-
-        g = DataFlowGraph()
-
-        self.fi = FrameInitiator(lasmim.aw, pack_factor)
-
-        intseq = misc.IntSequence(lasmim.aw, lasmim.aw)
-        dma_out = AbstractActor(plumbing.Buffer)
-        g.add_connection(self.fi, intseq, source_subr=self.fi.dma_subr())
-        g.add_pipeline(intseq, AbstractActor(plumbing.Buffer), dma_lasmi.Reader(lasmim), dma_out)
-
-        cast = structuring.Cast(lasmim.dw, pixel_layout(pack_factor), reverse_to=True)
-        vtg = VTG(pack_factor)
-        self.driver = Driver(pack_factor, pads_vga, pads_dvi)
-
-        g.add_connection(self.fi, vtg, source_subr=self.fi.timing_subr, sink_ep="timing")
-        g.add_connection(dma_out, cast)
-        g.add_connection(cast, vtg, sink_ep="pixels")
-        g.add_connection(vtg, self.driver)
-        self.submodules += CompositeActor(g)
diff --git a/misoclib/video/framebuffer/dvi.py b/misoclib/video/framebuffer/dvi.py
deleted file mode 100644 (file)
index 0ba8b4b..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.misc import optree
-
-control_tokens = [0b1101010100, 0b0010101011, 0b0101010100, 0b1010101011]
-
-
-class Encoder(Module):
-    def __init__(self):
-        self.d = Signal(8)
-        self.c = Signal(2)
-        self.de = Signal()
-
-        self.out = Signal(10)
-
-        ###
-
-        # stage 1 - count number of 1s in data
-        d = Signal(8)
-        n1d = Signal(max=9)
-        self.sync += [
-            n1d.eq(optree("+", [self.d[i] for i in range(8)])),
-            d.eq(self.d)
-        ]
-
-        # stage 2 - add 9th bit
-        q_m = Signal(9)
-        q_m8_n = Signal()
-        self.comb += q_m8_n.eq((n1d > 4) | ((n1d == 4) & ~d[0]))
-        for i in range(8):
-            if i:
-                curval = curval ^ d[i] ^ q_m8_n
-            else:
-                curval = d[0]
-            self.sync += q_m[i].eq(curval)
-        self.sync += q_m[8].eq(~q_m8_n)
-
-        # stage 3 - count number of 1s and 0s in q_m[:8]
-        q_m_r = Signal(9)
-        n0q_m = Signal(max=9)
-        n1q_m = Signal(max=9)
-        self.sync += [
-            n0q_m.eq(optree("+", [~q_m[i] for i in range(8)])),
-            n1q_m.eq(optree("+", [q_m[i] for i in range(8)])),
-            q_m_r.eq(q_m)
-        ]
-
-        # stage 4 - final encoding
-        cnt = Signal((6, True))
-
-        s_c = self.c
-        s_de = self.de
-        for p in range(3):
-            new_c = Signal(2)
-            new_de = Signal()
-            self.sync += new_c.eq(s_c), new_de.eq(s_de)
-            s_c, s_de = new_c, new_de
-
-        self.sync += If(s_de,
-                If((cnt == 0) | (n1q_m == n0q_m),
-                    self.out[9].eq(~q_m_r[8]),
-                    self.out[8].eq(q_m_r[8]),
-                    If(q_m_r[8],
-                        self.out[:8].eq(q_m_r[:8]),
-                        cnt.eq(cnt + n1q_m - n0q_m)
-                    ).Else(
-                        self.out[:8].eq(~q_m_r[:8]),
-                        cnt.eq(cnt + n0q_m - n1q_m)
-                    )
-                ).Else(
-                    If((~cnt[5] & (n1q_m > n0q_m)) | (cnt[5] & (n0q_m > n1q_m)),
-                        self.out[9].eq(1),
-                        self.out[8].eq(q_m_r[8]),
-                        self.out[:8].eq(~q_m_r[:8]),
-                        cnt.eq(cnt + Cat(0, q_m_r[8]) + n0q_m - n1q_m)
-                    ).Else(
-                        self.out[9].eq(0),
-                        self.out[8].eq(q_m_r[8]),
-                        self.out[:8].eq(q_m_r[:8]),
-                        cnt.eq(cnt - Cat(0, ~q_m_r[8]) + n1q_m - n0q_m)
-                    )
-                )
-            ).Else(
-                self.out.eq(Array(control_tokens)[s_c]),
-                cnt.eq(0)
-            )
-
-
-class _EncoderSerializer(Module):
-    def __init__(self, serdesstrobe, pad_p, pad_n):
-        self.submodules.encoder = RenameClockDomains(Encoder(), "pix")
-        self.d, self.c, self.de = self.encoder.d, self.encoder.c, self.encoder.de
-
-        ###
-
-        # 2X soft serialization
-        ed_2x = Signal(5)
-        self.sync.pix2x += ed_2x.eq(Mux(ClockSignal("pix"), self.encoder.out[:5], self.encoder.out[5:]))
-
-        # 5X hard serialization
-        cascade_di = Signal()
-        cascade_do = Signal()
-        cascade_ti = Signal()
-        cascade_to = Signal()
-        pad_se = Signal()
-        self.specials += [
-            Instance("OSERDES2",
-                     p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
-                     p_SERDES_MODE="MASTER", p_OUTPUT_MODE="DIFFERENTIAL",
-
-                     o_OQ=pad_se,
-                     i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
-                     i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
-                     i_D1=ed_2x[4], i_D2=0, i_D3=0, i_D4=0,
-                     i_T1=0, i_T2=0, i_T3=0, i_T4=0,
-                     i_TRAIN=0, i_TCE=1,
-                     i_SHIFTIN1=1, i_SHIFTIN2=1,
-                     i_SHIFTIN3=cascade_do, i_SHIFTIN4=cascade_to,
-                     o_SHIFTOUT1=cascade_di, o_SHIFTOUT2=cascade_ti),
-            Instance("OSERDES2",
-                     p_DATA_WIDTH=5, p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
-                     p_SERDES_MODE="SLAVE", p_OUTPUT_MODE="DIFFERENTIAL",
-
-                     i_OCE=1, i_IOCE=serdesstrobe, i_RST=0,
-                     i_CLK0=ClockSignal("pix10x"), i_CLK1=0, i_CLKDIV=ClockSignal("pix2x"),
-                     i_D1=ed_2x[0], i_D2=ed_2x[1], i_D3=ed_2x[2], i_D4=ed_2x[3],
-                     i_T1=0, i_T2=0, i_T3=0, i_T4=0,
-                     i_TRAIN=0, i_TCE=1,
-                     i_SHIFTIN1=cascade_di, i_SHIFTIN2=cascade_ti,
-                     i_SHIFTIN3=1, i_SHIFTIN4=1,
-                     o_SHIFTOUT3=cascade_do, o_SHIFTOUT4=cascade_to),
-            Instance("OBUFDS", i_I=pad_se, o_O=pad_p, o_OB=pad_n)
-        ]
-
-
-class PHY(Module):
-    def __init__(self, serdesstrobe, pads):
-        self.hsync = Signal()
-        self.vsync = Signal()
-        self.de = Signal()
-        self.r = Signal(8)
-        self.g = Signal(8)
-        self.b = Signal(8)
-
-        ###
-
-        self.submodules.es0 = _EncoderSerializer(serdesstrobe, pads.data0_p, pads.data0_n)
-        self.submodules.es1 = _EncoderSerializer(serdesstrobe, pads.data1_p, pads.data1_n)
-        self.submodules.es2 = _EncoderSerializer(serdesstrobe, pads.data2_p, pads.data2_n)
-        self.comb += [
-            self.es0.d.eq(self.r),
-            self.es1.d.eq(self.g),
-            self.es2.d.eq(self.b),
-            self.es0.c.eq(Cat(self.hsync, self.vsync)),
-            self.es1.c.eq(0),
-            self.es2.c.eq(0),
-            self.es0.de.eq(self.de),
-            self.es1.de.eq(self.de),
-            self.es2.de.eq(self.de),
-        ]
-
-
-class _EncoderTB(Module):
-    def __init__(self, inputs):
-        self.outs = []
-        self._iter_inputs = iter(inputs)
-        self._end_cycle = None
-        self.submodules.dut = Encoder()
-        self.comb += self.dut.de.eq(1)
-
-    def do_simulation(self, selfp):
-        if self._end_cycle is None:
-            try:
-                nv = next(self._iter_inputs)
-            except StopIteration:
-                self._end_cycle = selfp.simulator.cycle_counter + 4
-            else:
-                selfp.dut.d = nv
-        if selfp.simulator.cycle_counter == self._end_cycle:
-            raise StopSimulation
-        if selfp.simulator.cycle_counter > 4:
-            self.outs.append(selfp.dut.out)
-
-
-def _bit(i, n):
-    return (i >> n) & 1
-
-
-def _decode_tmds(b):
-    try:
-        c = control_tokens.index(b)
-        de = False
-    except ValueError:
-        c = 0
-        de = True
-    vsync = bool(c & 2)
-    hsync = bool(c & 1)
-
-    value = _bit(b, 0) ^ _bit(b, 9)
-    for i in range(1, 8):
-        value |= (_bit(b, i) ^ _bit(b, i-1) ^ (~_bit(b, 8) & 1)) << i
-
-    return de, hsync, vsync, value
-
-if __name__ == "__main__":
-    from migen.sim.generic import run_simulation
-    from random import Random
-
-    rng = Random(788)
-    test_list = [rng.randrange(256) for i in range(500)]
-    tb = _EncoderTB(test_list)
-    run_simulation(tb)
-
-    check = [_decode_tmds(out)[3] for out in tb.outs]
-    assert(check == test_list)
-
-    nb0 = 0
-    nb1 = 0
-    for out in tb.outs:
-        for i in range(10):
-            if _bit(out, i):
-                nb1 += 1
-            else:
-                nb0 += 1
-    print("0/1: {}/{} ({:.2f})".format(nb0, nb1, nb0/nb1))
diff --git a/misoclib/video/framebuffer/format.py b/misoclib/video/framebuffer/format.py
deleted file mode 100644 (file)
index e3a3931..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-from migen.fhdl.std import *
-from migen.flow.actor import *
-from migen.bank.description import CSRStorage
-from migen.genlib.record import Record
-from migen.genlib.fsm import FSM, NextState
-from migen.actorlib import spi
-
-_hbits = 12
-_vbits = 12
-
-bpp = 32
-bpc = 10
-pixel_layout_s = [
-    ("pad", bpp-3*bpc),
-    ("r", bpc),
-    ("g", bpc),
-    ("b", bpc)
-]
-
-
-def pixel_layout(pack_factor):
-    return [("p"+str(i), pixel_layout_s) for i in range(pack_factor)]
-
-bpc_phy = 8
-phy_layout_s = [
-    ("r", bpc_phy),
-    ("g", bpc_phy),
-    ("b", bpc_phy)
-]
-
-
-def phy_layout(pack_factor):
-    r = [("hsync", 1), ("vsync", 1), ("de", 1)]
-    for i in range(pack_factor):
-        r.append(("p"+str(i), phy_layout_s))
-    return r
-
-
-class FrameInitiator(spi.SingleGenerator):
-    def __init__(self, bus_aw, pack_factor, ndmas=1):
-        h_alignment_bits = log2_int(pack_factor)
-        hbits_dyn = _hbits - h_alignment_bits
-        bus_alignment_bits = h_alignment_bits + log2_int(bpp//8)
-        layout = [
-            ("hres", hbits_dyn, 640, h_alignment_bits),
-            ("hsync_start", hbits_dyn, 656, h_alignment_bits),
-            ("hsync_end", hbits_dyn, 752, h_alignment_bits),
-            ("hscan", hbits_dyn, 800, h_alignment_bits),
-
-            ("vres", _vbits, 480),
-            ("vsync_start", _vbits, 492),
-            ("vsync_end", _vbits, 494),
-            ("vscan", _vbits, 525),
-
-            ("length", bus_aw + bus_alignment_bits, 640*480*bpp//8, bus_alignment_bits)
-        ]
-        layout += [("base"+str(i), bus_aw + bus_alignment_bits, 0, bus_alignment_bits)
-            for i in range(ndmas)]
-        spi.SingleGenerator.__init__(self, layout, spi.MODE_CONTINUOUS)
-
-    timing_subr = ["hres", "hsync_start", "hsync_end", "hscan",
-        "vres", "vsync_start", "vsync_end", "vscan"]
-
-    def dma_subr(self, i=0):
-        return ["length", "base"+str(i)]
-
-
-class VTG(Module):
-    def __init__(self, pack_factor):
-        hbits_dyn = _hbits - log2_int(pack_factor)
-        timing_layout = [
-            ("hres", hbits_dyn),
-            ("hsync_start", hbits_dyn),
-            ("hsync_end", hbits_dyn),
-            ("hscan", hbits_dyn),
-            ("vres", _vbits),
-            ("vsync_start", _vbits),
-            ("vsync_end", _vbits),
-            ("vscan", _vbits)]
-        self.timing = Sink(timing_layout)
-        self.pixels = Sink(pixel_layout(pack_factor))
-        self.phy = Source(phy_layout(pack_factor))
-        self.busy = Signal()
-
-        ###
-
-        hactive = Signal()
-        vactive = Signal()
-        active = Signal()
-
-        hcounter = Signal(hbits_dyn)
-        vcounter = Signal(_vbits)
-
-        skip = bpc - bpc_phy
-        self.comb += [
-            active.eq(hactive & vactive),
-            If(active,
-                [getattr(getattr(self.phy.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
-                    for p in ["p"+str(i) for i in range(pack_factor)] for c in ["r", "g", "b"]],
-                self.phy.de.eq(1)
-            ),
-            self.pixels.ack.eq(self.phy.ack & active)
-        ]
-
-        load_timing = Signal()
-        tr = Record(timing_layout)
-        self.sync += If(load_timing, tr.eq(self.timing.payload))
-
-        generate_en = Signal()
-        generate_frame_done = Signal()
-        self.sync += [
-            generate_frame_done.eq(0),
-            If(generate_en,
-                hcounter.eq(hcounter + 1),
-
-                If(hcounter == 0, hactive.eq(1)),
-                If(hcounter == tr.hres, hactive.eq(0)),
-                If(hcounter == tr.hsync_start, self.phy.hsync.eq(1)),
-                If(hcounter == tr.hsync_end, self.phy.hsync.eq(0)),
-                If(hcounter == tr.hscan,
-                    hcounter.eq(0),
-                    If(vcounter == tr.vscan,
-                        vcounter.eq(0),
-                        generate_frame_done.eq(1)
-                    ).Else(
-                        vcounter.eq(vcounter + 1)
-                    )
-                ),
-
-                If(vcounter == 0, vactive.eq(1)),
-                If(vcounter == tr.vres, vactive.eq(0)),
-                If(vcounter == tr.vsync_start, self.phy.vsync.eq(1)),
-                If(vcounter == tr.vsync_end, self.phy.vsync.eq(0))
-            )
-        ]
-
-        self.submodules.fsm = FSM()
-        self.fsm.act("GET_TIMING",
-            self.timing.ack.eq(1),
-            load_timing.eq(1),
-            If(self.timing.stb, NextState("GENERATE"))
-        )
-        self.fsm.act("GENERATE",
-            self.busy.eq(1),
-            If(~active | self.pixels.stb,
-                self.phy.stb.eq(1),
-                If(self.phy.ack, generate_en.eq(1))
-            ),
-            If(generate_frame_done,    NextState("GET_TIMING"))
-        )
diff --git a/misoclib/video/framebuffer/phy.py b/misoclib/video/framebuffer/phy.py
deleted file mode 100644 (file)
index d4958ff..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-from migen.fhdl.std import *
-from migen.genlib.fifo import AsyncFIFO
-from migen.genlib.cdc import MultiReg
-from migen.bank.description import *
-from migen.flow.actor import *
-
-from misoclib.video.framebuffer.format import bpc_phy, phy_layout
-from misoclib.video.framebuffer import dvi
-
-
-class _FIFO(Module):
-    def __init__(self, pack_factor):
-        self.phy = Sink(phy_layout(pack_factor))
-        self.busy = Signal()
-
-        self.pix_hsync = Signal()
-        self.pix_vsync = Signal()
-        self.pix_de = Signal()
-        self.pix_r = Signal(bpc_phy)
-        self.pix_g = Signal(bpc_phy)
-        self.pix_b = Signal(bpc_phy)
-
-        ###
-
-        fifo = RenameClockDomains(AsyncFIFO(phy_layout(pack_factor), 512),
-            {"write": "sys", "read": "pix"})
-        self.submodules += fifo
-        self.comb += [
-            self.phy.ack.eq(fifo.writable),
-            fifo.we.eq(self.phy.stb),
-            fifo.din.eq(self.phy.payload),
-            self.busy.eq(0)
-        ]
-
-        unpack_counter = Signal(max=pack_factor)
-        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
-        self.sync.pix += [
-            unpack_counter.eq(unpack_counter + 1),
-            self.pix_hsync.eq(fifo.dout.hsync),
-            self.pix_vsync.eq(fifo.dout.vsync),
-            self.pix_de.eq(fifo.dout.de)
-        ]
-        for i in range(pack_factor):
-            pixel = getattr(fifo.dout, "p"+str(i))
-            self.sync.pix += If(unpack_counter == i,
-                self.pix_r.eq(pixel.r),
-                self.pix_g.eq(pixel.g),
-                self.pix_b.eq(pixel.b)
-            )
-        self.comb += fifo.re.eq(unpack_counter == (pack_factor - 1))
-
-
-# This assumes a 50MHz base clock
-class _Clocking(Module, AutoCSR):
-    def __init__(self, pads_vga, pads_dvi):
-        self._cmd_data = CSRStorage(10)
-        self._send_cmd_data = CSR()
-        self._send_go = CSR()
-        self._status = CSRStatus(4)
-
-        self.clock_domains.cd_pix = ClockDomain(reset_less=True)
-        if pads_dvi is not None:
-            self._pll_reset = CSRStorage()
-            self._pll_adr = CSRStorage(5)
-            self._pll_dat_r = CSRStatus(16)
-            self._pll_dat_w = CSRStorage(16)
-            self._pll_read = CSR()
-            self._pll_write = CSR()
-            self._pll_drdy = CSRStatus()
-
-            self.clock_domains.cd_pix2x = ClockDomain(reset_less=True)
-            self.clock_domains.cd_pix10x = ClockDomain(reset_less=True)
-            self.serdesstrobe = Signal()
-
-        ###
-
-        # Generate 1x pixel clock
-        clk_pix_unbuffered = Signal()
-        pix_progdata = Signal()
-        pix_progen = Signal()
-        pix_progdone = Signal()
-        pix_locked = Signal()
-        self.specials += Instance("DCM_CLKGEN",
-                                  p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=1.0, p_CLKFX_MULTIPLY=2,
-                                  p_CLKIN_PERIOD=20.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
-
-                                  i_CLKIN=ClockSignal("base50"), o_CLKFX=clk_pix_unbuffered,
-                                  i_PROGCLK=ClockSignal(), i_PROGDATA=pix_progdata, i_PROGEN=pix_progen,
-                                  o_PROGDONE=pix_progdone, o_LOCKED=pix_locked,
-                                  i_FREEZEDCM=0, i_RST=ResetSignal())
-
-        remaining_bits = Signal(max=11)
-        transmitting = Signal()
-        self.comb += transmitting.eq(remaining_bits != 0)
-        sr = Signal(10)
-        self.sync += [
-            If(self._send_cmd_data.re,
-                remaining_bits.eq(10),
-                sr.eq(self._cmd_data.storage)
-            ).Elif(transmitting,
-                remaining_bits.eq(remaining_bits - 1),
-                sr.eq(sr[1:])
-            )
-        ]
-        self.comb += [
-            pix_progdata.eq(transmitting & sr[0]),
-            pix_progen.eq(transmitting | self._send_go.re)
-        ]
-
-        # enforce gap between commands
-        busy_counter = Signal(max=14)
-        busy = Signal()
-        self.comb += busy.eq(busy_counter != 0)
-        self.sync += If(self._send_cmd_data.re,
-                busy_counter.eq(13)
-            ).Elif(busy,
-                busy_counter.eq(busy_counter - 1)
-            )
-
-        mult_locked = Signal()
-        self.comb += self._status.status.eq(Cat(busy, pix_progdone, pix_locked, mult_locked))
-
-        # Clock multiplication and buffering
-        if pads_dvi is None:
-            # Just buffer 1x pixel clock
-            self.specials += Instance("BUFG", i_I=clk_pix_unbuffered, o_O=self.cd_pix.clk)
-            self.comb += mult_locked.eq(pix_locked)
-        else:
-            # Route unbuffered 1x pixel clock to PLL
-            # Generate 1x, 2x and 10x IO pixel clocks
-            clkfbout = Signal()
-            pll_locked = Signal()
-            pll_clk0 = Signal()
-            pll_clk1 = Signal()
-            pll_clk2 = Signal()
-            locked_async = Signal()
-            pll_drdy = Signal()
-            self.sync += If(self._pll_read.re | self._pll_write.re,
-                self._pll_drdy.status.eq(0)
-            ).Elif(pll_drdy,
-                self._pll_drdy.status.eq(1)
-            )
-            self.specials += [
-                Instance("PLL_ADV",
-                         p_CLKFBOUT_MULT=10,
-                         p_CLKOUT0_DIVIDE=1,   # pix10x
-                         p_CLKOUT1_DIVIDE=5,   # pix2x
-                         p_CLKOUT2_DIVIDE=10,  # pix
-                         p_COMPENSATION="INTERNAL",
-
-                         i_CLKINSEL=1,
-                         i_CLKIN1=clk_pix_unbuffered,
-                         o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
-                         o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
-                         o_LOCKED=pll_locked,
-                         i_RST=~pix_locked | self._pll_reset.storage,
-
-                         i_DADDR=self._pll_adr.storage,
-                         o_DO=self._pll_dat_r.status,
-                         i_DI=self._pll_dat_w.storage,
-                         i_DEN=self._pll_read.re | self._pll_write.re,
-                         i_DWE=self._pll_write.re,
-                         o_DRDY=pll_drdy,
-                         i_DCLK=ClockSignal()),
-                Instance("BUFPLL", p_DIVIDE=5,
-                         i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked,
-                         o_IOCLK=self.cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
-                Instance("BUFG", i_I=pll_clk1, o_O=self.cd_pix2x.clk),
-                Instance("BUFG", name="dviout_pix_bufg", i_I=pll_clk2, o_O=self.cd_pix.clk),
-                MultiReg(locked_async, mult_locked, "sys")
-            ]
-
-        # Drive VGA/DVI clock pads
-        if pads_vga is not None:
-            self.specials += Instance("ODDR2",
-                                      p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
-                                      o_Q=pads_vga.clk,
-                                      i_C0=ClockSignal("pix"),
-                                      i_C1=~ClockSignal("pix"),
-                                      i_CE=1, i_D0=1, i_D1=0,
-                                      i_R=0, i_S=0)
-        if pads_dvi is not None:
-            dvi_clk_se = Signal()
-            self.specials += Instance("ODDR2",
-                                      p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC",
-                                      o_Q=dvi_clk_se,
-                                      i_C0=ClockSignal("pix"),
-                                      i_C1=~ClockSignal("pix"),
-                                      i_CE=1, i_D0=1, i_D1=0,
-                                      i_R=0, i_S=0)
-            self.specials += Instance("OBUFDS", i_I=dvi_clk_se,
-                                      o_O=pads_dvi.clk_p, o_OB=pads_dvi.clk_n)
-
-
-class Driver(Module, AutoCSR):
-    def __init__(self, pack_factor, pads_vga, pads_dvi):
-        fifo = _FIFO(pack_factor)
-        self.submodules += fifo
-        self.phy = fifo.phy
-        self.busy = fifo.busy
-
-        self.submodules.clocking = _Clocking(pads_vga, pads_dvi)
-
-        if pads_vga is not None:
-            self.comb += [
-                pads_vga.hsync_n.eq(~fifo.pix_hsync),
-                pads_vga.vsync_n.eq(~fifo.pix_vsync),
-                pads_vga.r.eq(fifo.pix_r),
-                pads_vga.g.eq(fifo.pix_g),
-                pads_vga.b.eq(fifo.pix_b),
-                pads_vga.psave_n.eq(1)
-            ]
-        if pads_dvi is not None:
-            self.submodules.dvi_phy = dvi.PHY(self.clocking.serdesstrobe, pads_dvi)
-            self.comb += [
-                self.dvi_phy.hsync.eq(fifo.pix_hsync),
-                self.dvi_phy.vsync.eq(fifo.pix_vsync),
-                self.dvi_phy.de.eq(fifo.pix_de),
-                self.dvi_phy.r.eq(fifo.pix_r),
-                self.dvi_phy.g.eq(fifo.pix_g),
-                self.dvi_phy.b.eq(fifo.pix_b)
-            ]
index 41af6c81c4f2f2f4b23784457555277f1085f544..52fd0aa59dd79b01db1829d58e5db9cd6085f674 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -1,38 +1,38 @@
-#!/usr/bin/env python3\r
-\r
-import sys\r
-import os\r
-from setuptools import setup\r
-from setuptools import find_packages\r
-\r
-here = os.path.abspath(os.path.dirname(__file__))\r
-README = open(os.path.join(here, "README")).read()\r
-\r
-required_version = (3, 3)\r
-if sys.version_info < required_version:\r
-    raise SystemExit("MiSoC requires python {0} or greater".format(\r
-        ".".join(map(str, required_version))))\r
-\r
-setup(\r
-    name="misoclib",\r
-    version="unknown",\r
-    description="a high performance and small footprint SoC based on Migen",\r
-    long_description=README,\r
-    author="Sebastien Bourdeauducq",\r
-    author_email="sb@m-labs.hk",\r
-    url="http://m-labs.hk",\r
-    download_url="https://github.com/m-labs/misoc",\r
-    packages=find_packages(here),\r
-    license="BSD",\r
-    platforms=["Any"],\r
-    keywords="HDL ASIC FPGA hardware design",\r
-    classifiers=[\r
-        "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",\r
-        "Environment :: Console",\r
-        "Development Status :: Alpha",\r
-        "Intended Audience :: Developers",\r
-        "License :: OSI Approved :: BSD License",\r
-        "Operating System :: OS Independent",\r
-        "Programming Language :: Python",\r
-    ],\r
-)\r
+#!/usr/bin/env python3
+
+import sys
+import os
+from setuptools import setup
+from setuptools import find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, "README")).read()
+
+required_version = (3, 3)
+if sys.version_info < required_version:
+    raise SystemExit("MiSoC requires python {0} or greater".format(
+        ".".join(map(str, required_version))))
+
+setup(
+    name="misoc",
+    version="unknown",
+    description="a high performance and small footprint SoC based on Migen",
+    long_description=README,
+    author="Sebastien Bourdeauducq",
+    author_email="sb@m-labs.hk",
+    url="http://m-labs.hk",
+    download_url="https://github.com/m-labs/misoc",
+    packages=find_packages(here),
+    license="BSD",
+    platforms=["Any"],
+    keywords="HDL ASIC FPGA hardware design",
+    classifiers=[
+        "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
+        "Environment :: Console",
+        "Development Status :: Alpha",
+        "Intended Audience :: Developers",
+        "License :: OSI Approved :: BSD License",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python",
+    ],
+)
index 72f42fcbf7a01bda0a4d70e9d8a0288af5036a35..cff9bbd3a3fedf3f30bb37d2d78f78fff93ee6a1 100644 (file)
@@ -21,7 +21,7 @@ AR_quiet      = @echo " AR      " $@ && $(AR_normal)
 LD_quiet      = @echo " LD      " $@ && $(LD_normal)
 OBJCOPY_quiet = @echo " OBJCOPY " $@ && $(OBJCOPY_normal)
 
-MSC_GIT_ID := $(shell cd $(MSCDIR) && $(PYTHON) -c "from misoclib.cpu.identifier import get_id; print(hex(get_id()), end='')")
+MSC_GIT_ID := $(shell cd $(MSCDIR) && $(PYTHON) -c "from misoc.cpu.identifier import get_id; print(hex(get_id()), end='')")
 
 ifeq ($(V),1)
        CC = $(CC_normal)
index c6f733d3cd0d41e8c77fafaa5e843c4d548697b4..d823b0a67879089fb12a6de4f14406a990fe2b69 100644 (file)
@@ -1,9 +1,9 @@
 from migen.fhdl.std import *
 
-from misoclib.mem.sdram.module import IS42S16160
-from misoclib.mem.sdram.phy import gensdrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.soc.sdram import SDRAMSoC
+from misoc.mem.sdram.module import IS42S16160
+from misoc.mem.sdram.phy import gensdrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.soc.sdram import SDRAMSoC
 
 
 class _PLL(Module):
index 2604ae94d3ae9d2c3d393b244d4bfb5eaa0cd34f..e9cf70e48aadfeb600f31881420118d26886bc2f 100644 (file)
@@ -1,15 +1,15 @@
 from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 
-from misoclib.mem.sdram.module import MT8JTF12864
-from misoclib.mem.sdram.phy import k7ddrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.mem.flash import spiflash
-from misoclib.soc import mem_decoder
-from misoclib.soc.sdram import SDRAMSoC
-
-from misoclib.com.liteethmini.phy import LiteEthPHY
-from misoclib.com.liteethmini.mac import LiteEthMAC
+from misoc.mem.sdram.module import MT8JTF12864
+from misoc.mem.sdram.phy import k7ddrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.mem.flash import spiflash
+from misoc.soc import mem_decoder
+from misoc.soc.sdram import SDRAMSoC
+
+from misoc.com.liteethmini.phy import LiteEthPHY
+from misoc.com.liteethmini.mac import LiteEthMAC
 
 
 class _CRG(Module):
index ffea2f354e68f4990bb13ce078af41bc5032826e..ff5e4b8271d5761db82cb4961d5f171126c02b10 100644 (file)
@@ -4,10 +4,10 @@ from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 from migen.actorlib.fifo import SyncFIFO
 
-from misoclib.mem.sdram.module import AS4C16M16
-from misoclib.mem.sdram.phy import gensdrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.soc.sdram import SDRAMSoC
+from misoc.mem.sdram.module import AS4C16M16
+from misoc.mem.sdram.phy import gensdrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.soc.sdram import SDRAMSoC
 
 class _CRG(Module):
     def __init__(self, platform, clk_freq):
index 0602ac467e9908deed8d04283c605faa8b2bdb65..fcd8481c4a6bbee5c66e00adc8754110485bf0fb 100644 (file)
@@ -5,16 +5,16 @@ from math import ceil
 from migen.fhdl.std import *
 from mibuild.generic_platform import ConstraintError
 
-from misoclib.mem.sdram.module import MT46V32M16
-from misoclib.mem.sdram.phy import s6ddrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.mem.flash import norflash16
-from misoclib.video import framebuffer
-from misoclib.soc import mem_decoder
-from misoclib.soc.sdram import SDRAMSoC
-from misoclib.com import gpio
-from misoclib.com.liteethmini.phy import LiteEthPHY
-from misoclib.com.liteethmini.mac import LiteEthMAC
+from misoc.mem.sdram.module import MT46V32M16
+from misoc.mem.sdram.phy import s6ddrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.mem.flash import norflash16
+from misoc.video import framebuffer
+from misoc.soc import mem_decoder
+from misoc.soc.sdram import SDRAMSoC
+from misoc.com import gpio
+from misoc.com.liteethmini.phy import LiteEthPHY
+from misoc.com.liteethmini.mac import LiteEthMAC
 
 
 class _MXCRG(Module):
@@ -104,7 +104,7 @@ class BaseSoC(SDRAMSoC):
 INST "mxcrg/wr_bufpll" LOC = "BUFPLL_X0Y2";
 INST "mxcrg/rd_bufpll" LOC = "BUFPLL_X0Y3";
 """)
-        platform.add_source(os.path.join("misoclib", "mxcrg.v"))
+        platform.add_source(os.path.join("misoc", "mxcrg.v"))
 
 
 class MiniSoC(BaseSoC):
index fd9bd1cbe678ddffb2ca9a193acd27be80bb6edd..668be1de057b2f8635cdd8213a5da48ee546a633 100644 (file)
@@ -3,11 +3,11 @@ from fractions import Fraction
 from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 
-from misoclib.mem.sdram.module import MT46H32M16
-from misoclib.mem.sdram.phy import s6ddrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.mem.flash import spiflash
-from misoclib.soc.sdram import SDRAMSoC
+from misoc.mem.sdram.module import MT46H32M16
+from misoc.mem.sdram.phy import s6ddrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.mem.flash import spiflash
+from misoc.soc.sdram import SDRAMSoC
 
 
 class _CRG(Module):
index 96eaf221b903944b2f6679ae2037d72375038f8e..1b5f43bf0e8357f20e3da75d59b3a62ee8663771 100644 (file)
@@ -3,11 +3,11 @@ from fractions import Fraction
 from migen.fhdl.std import *
 from migen.genlib.resetsync import AsyncResetSynchronizer
 
-from misoclib.mem.sdram.module import MT48LC4M16
-from misoclib.mem.sdram.phy import gensdrphy
-from misoclib.mem.sdram.core.lasmicon import LASMIconSettings
-from misoclib.mem.flash import spiflash
-from misoclib.soc.sdram import SDRAMSoC
+from misoc.mem.sdram.module import MT48LC4M16
+from misoc.mem.sdram.phy import gensdrphy
+from misoc.mem.sdram.core.lasmicon import LASMIconSettings
+from misoc.mem.flash import spiflash
+from misoc.soc.sdram import SDRAMSoC
 
 
 class _CRG(Module):
index ffa0415210ef5cd86a5c4a901aef8026230a71e0..b28d5917fb31776443b2394e112cc08acf33249e 100644 (file)
@@ -2,9 +2,9 @@ from migen.fhdl.std import *
 from migen.bus import wishbone
 from migen.genlib.io import CRG
 
-from misoclib.soc import SoC, mem_decoder
-from misoclib.com.liteethmini.phy import LiteEthPHY
-from misoclib.com.liteethmini.mac import LiteEthMAC
+from misoc.soc import SoC, mem_decoder
+from misoc.com.liteethmini.phy import LiteEthPHY
+from misoc.com.liteethmini.mac import LiteEthMAC
 
 
 class BaseSoC(SoC):
index e1c376efae3b8e938aa15e892c893ccd3070a899..fd787476a4c0edfd833c47bd8594beb304c28dfd 100644 (file)
@@ -2,7 +2,7 @@ from migen.fhdl.std import *
 from migen.bus import wishbone
 from migen.genlib.io import CRG
 
-from misoclib.soc import SoC
+from misoc.soc import SoC
 
 
 class BaseSoC(SoC):