--- /dev/null
+# Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
+# Copyright (c) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+#
+# Based on code from LambaConcept, from the gram example which is BSD-2-License
+# https://github.com/jeanthom/gram/tree/master/examples
+#
+# Modifications for the Libre-SOC Project funded by NLnet and NGI POINTER
+# under EU Grants 871528 and 957073, under the LGPLv3+ License
+
+from nmigen import (Module, Elaboratable, DomainRenamer)
+from nmigen.lib.cdc import ResetSynchronizer
+from nmigen_soc import wishbone, memory
+from nmigen_soc.memory import MemoryMap
+from nmigen_stdio.serial import AsyncSerial
+
+from lambdasoc.cpu.minerva import MinervaCPU
+from lambdasoc.periph.intc import GenericInterruptController
+from lambdasoc.periph.sram import SRAMPeripheral
+from lambdasoc.periph.timer import TimerPeripheral
+from lambdasoc.periph import Peripheral
+from lambdasoc.soc.base import SoC
+from soc.bus.uart_16550 import UART16550 # opencores 16550 uart
+
+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 nmigen_boards.ulx3s import ULX3S_85F_Platform
+from nmigen_boards.arty_a7 import ArtyA7_100Platform
+from nmigen_boards.test.blinky import Blinky
+
+from crg import ECPIX5CRG
+
+import sys
+import os
+
+
+class DDR3SoC(SoC, Elaboratable):
+ def __init__(self, *,
+ uart_pins, ddr_pins,
+ ddrphy_addr, dramcore_addr,
+ ddr_addr, fw_addr=0x0000_0000,
+ firmware=None,
+ clk_freq=40e6):
+
+ # set up wishbone bus arbiter and decoder. arbiter routes,
+ # decoder maps local-relative addressed satellites to global addresses
+ 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"})
+
+ # default firmware name
+ if firmware is None:
+ firmware = "firmware/main.bin"
+
+ # set up clock request generator
+ self.crg = ECPIX5CRG()
+
+ # set up CPU, and interrupt interface
+ if False:
+ self.cpu = MinervaCPU(reset_address=0)
+ self._arbiter.add(self.cpu.ibus) # I-Cache Master
+ self._arbiter.add(self.cpu.dbus) # D-Cache Master. TODO JTAG master
+ self.intc = GenericInterruptController(width=len(self.cpu.ip))
+
+ # SRAM (but actually a ROM, for firmware), at address 0x0
+ if fw_addr is not None:
+ self.rom = SRAMPeripheral(size=4096, writable=False)
+ with open(firmware, "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=fw_addr) # ROM at fw_addr
+
+ # SRAM (read-writeable BRAM)
+ self.ram = SRAMPeripheral(size=4096)
+ self._decoder.add(self.ram.bus, addr=0x8000000) # SRAM at 0x8000_000
+
+ # UART
+ opencores_16550 = "../../uart16550/rtl/verilog"
+ pth = os.path.split(__file__)[0]
+ pth = os.path.join(pth, opencores_16550)
+ fname = os.path.abspath(pth)
+ print (fname)
+ self.uart = UART16550(verilog_src_dir=fname)
+ umap = MemoryMap(addr_width=7, data_width=8, name="uart_map")
+ #umap.add_resource(self._mem, name="mem", size=1<<5)
+ self.uart.bus.memory_map = umap
+
+ self._decoder.add(self.uart.bus, addr=0xc0002000) # 16550 UART address
+
+ # DRAM Module
+ self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins,
+ sys_clk_freq=100e6))
+ self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
+
+ ddrmodule = MT41K256M16(clk_freq, "1:2") # match DDR3 ASIC P/N
+
+ drs = DomainRenamer("dramsync")
+ dramcore = gramCore(phy=self.ddrphy,
+ geom_settings=ddrmodule.geom_settings,
+ timing_settings=ddrmodule.timing_settings,
+ clk_freq=clk_freq)
+ self.dramcore = drs(dramcore)
+ self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
+
+ # map the DRAM onto Wishbone
+ self.drambone = drs(gramWishbone(self.dramcore))
+ self._decoder.add(self.drambone.bus, addr=ddr_addr)
+
+ self.memory_map = self._decoder.bus.memory_map
+
+ self.clk_freq = clk_freq
+
+ def elaborate(self, platform):
+ m = Module()
+ comb = m.d.comb
+
+ # add the peripherals and clock-reset-generator
+ m.submodules.sysclk = self.crg
+
+ if hasattr(self, "rom"):
+ m.submodules.rom = self.rom
+ m.submodules.ram = self.ram
+ m.submodules.uart = self.uart
+ if False:
+ 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
+
+ # add blinky lights so we know FPGA is alive
+ m.submodules.blinky = Blinky()
+
+ # connect the arbiter (of wishbone masters)
+ # to the decoder (addressing wishbone slaves)
+ comb += self._arbiter.bus.connect(self._decoder.bus)
+
+ if False:
+ # wire up the CPU interrupts
+ comb += self.cpu.ip.eq(self.intc.ip)
+
+ return m
+
+
+if __name__ == "__main__":
+
+ # create a platform selected from the toolchain. defaults to VERSA_ECP5
+ # only VERSA_ECP5 will work for now because of the DDR3 module
+ fpga = "versa_ecp5"
+ if len(sys.argv) >= 2:
+ fpga = sys.argv[1]
+ platform_kls = {'versa_ecp5': VersaECP5Platform,
+ 'ulx3s': ULX3S_85F_Platform,
+ 'arty_a7': ArtyA7_100Platform,
+ }[fpga]
+ toolchain = {'arty_a7': "yosys_nextpnr",
+ 'versa_ecp5': 'Trellis',
+ 'ulx3s': 'Trellis'
+ }.get(fpga, None)
+ platform = platform_kls(toolchain=toolchain)
+
+ # select a firmware file
+ firmware = None
+ fw_addr = None
+ if len(sys.argv) >= 3:
+ firmware = sys.argv[2]
+ fw_addr = 0x0000_0000
+
+ # get DDR and UART resource pins
+ 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)
+
+ # set up the SOC
+ soc = DDR3SoC(ddrphy_addr=0xff000000, # DRAM firmware init base
+ dramcore_addr=0x80000000,
+ ddr_addr=0x10000000,
+ fw_addr=fw_addr,
+ ddr_pins=ddr_pins,
+ uart_pins=uart_pins,
+ firmware=firmware)
+
+ # build and upload it
+ platform.build(soc, do_program=True)
+++ /dev/null
-# Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
-# Copyright (c) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-#
-# Based on code from LambaConcept, from the gram example which is BSD-2-License
-# https://github.com/jeanthom/gram/tree/master/examples
-#
-# Modifications for the Libre-SOC Project funded by NLnet and NGI POINTER
-# under EU Grants 871528 and 957073, under the LGPLv3+ License
-
-from soc.bus.uart_16550 import UART16550 # opencores 16550 uart
-from nmigen import (Module, Elaboratable, DomainRenamer)
-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.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 nmigen_boards.ulx3s import ULX3S_85F_Platform
-from nmigen_boards.arty_a7 import ArtyA7_100Platform
-from nmigen_boards.test.blinky import Blinky
-
-from crg import ECPIX5CRG
-
-import sys
-import os
-
-
-class DDR3SoC(SoC, Elaboratable):
- def __init__(self, *,
- uart_pins, ddr_pins,
- ddrphy_addr, dramcore_addr,
- ddr_addr, fw_addr=0x0000_0000,
- firmware=None,
- clk_freq=40e6):
-
- # set up wishbone bus arbiter and decoder. arbiter routes,
- # decoder maps local-relative addressed satellites to global addresses
- 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"})
-
- # default firmware name
- if firmware is None:
- firmware = "firmware/main.bin"
-
- # set up clock request generator
- self.crg = ECPIX5CRG()
-
- if False:
- # set up CPU, and interrupt interface
- self.cpu = MinervaCPU(reset_address=0)
- self._arbiter.add(self.cpu.ibus) # I-Cache Master
- self._arbiter.add(self.cpu.dbus) # D-Cache Master. TODO JTAG master
- self.intc = GenericInterruptController(width=len(self.cpu.ip))
-
- # SRAM (but actually a ROM, for firmware), at address 0x0
- if fw_addr is not None:
- self.rom = SRAMPeripheral(size=4096, writable=False)
- with open(firmware, "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=fw_addr) # ROM at fw_addr
-
- # SRAM (read-writeable BRAM)
- self.ram = SRAMPeripheral(size=4096)
- self._decoder.add(self.ram.bus, addr=0x8000000) # SRAM at 0x8000_000
-
- # UART
- opencores_16550 = "../../uart16550/rtl/verilog"
- pth = __file__
- print (pth)
- self.uart = UART16550(verilog_src_dir=opencores_16550)
- self._decoder.add(self.uart.bus, addr=0xc0002000) # 16550 UART address
-
- # DRAM Module
- self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins,
- sys_clk_freq=100e6))
- self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
-
- ddrmodule = MT41K256M16(clk_freq, "1:2") # match DDR3 ASIC P/N
-
- drs = DomainRenamer("dramsync")
- dramcore = gramCore(phy=self.ddrphy,
- geom_settings=ddrmodule.geom_settings,
- timing_settings=ddrmodule.timing_settings,
- clk_freq=clk_freq)
- self.dramcore = drs(dramcore)
- self._decoder.add(self.dramcore.bus, addr=dramcore_addr)
-
- # map the DRAM onto Wishbone
- self.drambone = drs(gramWishbone(self.dramcore))
- self._decoder.add(self.drambone.bus, addr=ddr_addr)
-
- self.memory_map = self._decoder.bus.memory_map
-
- self.clk_freq = clk_freq
-
- def elaborate(self, platform):
- m = Module()
- comb = m.d.comb
-
- # add the peripherals and clock-reset-generator
- m.submodules.sysclk = self.crg
-
- if hasattr(self, "rom"):
- m.submodules.rom = self.rom
- m.submodules.ram = self.ram
- m.submodules.uart = self.uart
- if False:
- 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
-
- # add blinky lights so we know FPGA is alive
- m.submodules.blinky = Blinky()
-
- # connect the arbiter (of wishbone masters)
- # to the decoder (addressing wishbone slaves)
- comb += self._arbiter.bus.connect(self._decoder.bus)
-
- if False:
- # wire up the CPU interrupts
- comb += self.cpu.ip.eq(self.intc.ip)
-
- return m
-
-
-if __name__ == "__main__":
-
- # create a platform selected from the toolchain. defaults to VERSA_ECP5
- # only VERSA_ECP5 will work for now because of the DDR3 module
- fpga = "versa_ecp5"
- if len(sys.argv) >= 2:
- fpga = sys.argv[1]
- platform_kls = {'versa_ecp5': VersaECP5Platform,
- 'ulx3s': ULX3S_85F_Platform,
- 'arty_a7': ArtyA7_100Platform,
- }[fpga]
- toolchain = {'arty_a7': "yosys_nextpnr",
- 'versa_ecp5': 'Trellis',
- 'ulx3s': 'Trellis'
- }.get(fpga, None)
- platform = platform_kls(toolchain=toolchain)
-
- # select a firmware file
- firmware = None
- fw_addr = None
- if len(sys.argv) >= 3:
- firmware = sys.argv[2]
- fw_addr = 0x0000_0000
-
- # get DDR and UART resource pins
- 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)
-
- # set up the SOC
- soc = DDR3SoC(ddrphy_addr=0xff000000, # DRAM firmware init base
- dramcore_addr=0x80000000,
- ddr_addr=0x10000000,
- fw_addr=fw_addr,
- ddr_pins=ddr_pins,
- uart_pins=uart_pins,
- firmware=firmware)
-
- # build and upload it
- platform.build(soc, do_program=True)