--- /dev/null
+gram is based off the LiteDRAM project, a DRAM controller for LiteX SoCs.
+
+If you think you should be in this list and don't find yourself, please send a pull-request
+and we'll fix it!
+
+Contributors:
+Copyright (c) 2019 Ambroz Bizjak <abizjak.pro@gmail.com>
+Copyright (c) 2019 Antony Pavlov <antonynpavlov@gmail.com>
+Copyright (c) 2018 bunnie <bunnie@kosagi.com>
+Copyright (c) 2018-2019 David Shah <dave@ds0.me>
+Copyright (c) 2020 Drew Fustini <drew@pdp7.com>
+Copyright (c) 2019 Ewout ter Hoeven <E.M.terHoeven@student.tudelft.nl>
+Copyright (c) 2018 Felix Held <felix-github@felixheld.de>
+Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
+Copyright (c) 2019 Gabriel L. Somlo <gsomlo@gmail.com>
+Copyright (c) 2018 John Sully <john@csquare.ca>
+Copyright (c) 2019 Antmicro <www.antmicro.com>
+Copyright (c) 2020 Michael Welling <mwelling@ieee.org>
+Copyright (c) 2019 Pierre-Olivier Vauboin <po@lambdaconcept>
+Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
+Copyright (c) 2016-2016 Tim 'mithro' Ansell <me@mith.ro>
+Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
--- /dev/null
+Unless otherwise noted, Gram is Copyright 2020 / LambdaConcept
+
+Initial development is based on MiSoC's LASMICON / Copyright 2007-2016 / M-Labs
+ LiteDRAM / Copyright 2012-2018 / EnjoyDigital
+
+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.
--- /dev/null
+# This file is Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
+
+from nmigen import *
+from nmigen.lib.cdc import ResetSynchronizer
+from nmigen_soc import wishbone, memory
+from nmigen_stdio.serial import AsyncSerial
+
+from lambdasoc.cpu.minerva import MinervaCPU
+from lambdasoc.periph.intc import GenericInterruptController
+from lambdasoc.periph.serial import AsyncSerialPeripheral
+from lambdasoc.periph.sram import SRAMPeripheral
+from lambdasoc.periph.timer import TimerPeripheral
+from lambdasoc.periph import Peripheral
+from lambdasoc.soc.base import SoC
+
+from gram.core import gramCore
+from gram.phy.ecp5ddrphy import ECP5DDRPHY
+from gram.modules import MT41K256M16
+from gram.frontend.wishbone import gramWishbone
+
+from nmigen_boards.versa_ecp5 import VersaECP5Platform
+from uartbridge import UARTBridge
+from crg import *
+
+class DDR3SoC(SoC, Elaboratable):
+ def __init__(self, *,
+ uart_pins, ddr_pins,
+ ddrphy_addr, dramcore_addr,
+ ddr_addr):
+ self._arbiter = wishbone.Arbiter(addr_width=30, data_width=32, granularity=8,
+ features={"cti", "bte"})
+ self._decoder = wishbone.Decoder(addr_width=30, data_width=32, granularity=8,
+ features={"cti", "bte"})
+
+ freq = 100e6
+
+ self.crg = ECPIX5CRG()
+
+ self.cpu = MinervaCPU(reset_address=0)
+ self._arbiter.add(self.cpu.ibus)
+ self._arbiter.add(self.cpu.dbus)
+ self.intc = GenericInterruptController(width=len(self.cpu.ip))
+
+ self.rom = SRAMPeripheral(size=4096, writable=False)
+ with open("firmware/main.bin", "rb") as f:
+ words = iter(lambda: f.read(self.cpu.data_width // 8), b'')
+ bios = [int.from_bytes(w, self.cpu.byteorder) for w in words]
+ self.rom.init = bios
+ self._decoder.add(self.rom.bus, addr=0)
+
+ self.ram = SRAMPeripheral(size=4096)
+ self._decoder.add(self.ram.bus, addr=0x1000)
+
+ self.uart_phy = AsyncSerial(data_bits=8,
+ divisor=int(freq//115200),
+ pins=uart_pins)
+ self.uart = AsyncSerialPeripheral(core=self.uart_phy)
+ self._decoder.add(self.uart.bus, addr=0x2000)
+
+
+ self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins,
+ sys_clk_freq=100e6))
+ self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
+
+ ddrmodule = MT41K256M16(freq, "1:2")
+
+ self.dramcore = DomainRenamer("dramsync")(gramCore(
+ phy=self.ddrphy,
+ geom_settings=ddrmodule.geom_settings,
+ timing_settings=ddrmodule.timing_settings,
+ clk_freq=freq))
+ self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
+
+ self.drambone = DomainRenamer("dramsync")(gramWishbone(self.dramcore))
+ self._decoder.add(self.drambone.bus, addr=ddr_addr)
+
+ self.memory_map = self._decoder.bus.memory_map
+
+ self.clk_freq = freq
+
+ def elaborate(self, platform):
+ m = Module()
+
+ m.submodules.sysclk = self.crg
+
+ m.submodules.rom = self.rom
+ m.submodules.ram = self.ram
+ m.submodules.uart = self.uart
+ m.submodules.intc = self.intc
+ m.submodules.cpu = self.cpu
+ m.submodules.arbiter = self._arbiter
+ m.submodules.decoder = self._decoder
+ m.submodules.ddrphy = self.ddrphy
+ m.submodules.dramcore = self.dramcore
+ m.submodules.drambone = self.drambone
+
+ m.d.comb += [
+ self._arbiter.bus.connect(self._decoder.bus),
+ self.cpu.ip.eq(self.intc.ip),
+ ]
+
+ return m
+
+
+if __name__ == "__main__":
+ platform = VersaECP5Platform()
+
+ ddr_pins = platform.request("ddr3", 0, dir={"dq":"-", "dqs":"-"},
+ xdr={"clk":4, "a":4, "ba":4, "clk_en":4, "odt":4, "ras":4, "cas":4, "we":4})
+ uart_pins = platform.request("uart", 0)
+
+ soc = DDR3SoC(ddrphy_addr=0x00008000, dramcore_addr=0x00009000,
+ ddr_addr=0x10000000, ddr_pins=ddr_pins, uart_pins=uart_pins)
+
+ platform.build(soc, do_program=True)