+++ /dev/null
-# Copyright (c) 2020 LambdaConcept <contact@lambdaconcept.com>
-# Copyright (c) 2021 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
-
-from nmigen import (Module, Elaboratable, Instance, Signal, ClockDomain,
- ClockSignal, ResetSignal)
-
-__ALL__ = ["ECPIX5CRG"]
-
-
-class PLL(Elaboratable):
- def __init__(self, clkin, clksel=Signal(shape=2, reset=2),
- clkout1=Signal(), clkout2=Signal(),
- clkout3=Signal(), clkout4=Signal(), lock=Signal(),
- CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=3, CLK2_DIV=24):
- self.clkin = clkin
- self.clkout1 = clkout1
- self.clkout2 = clkout2
- self.clkout3 = clkout3
- self.clkout4 = clkout4
- self.clksel = clksel
- self.lock = lock
- self.CLKI_DIV = CLKI_DIV
- self.CLKFB_DIV = CLKFB_DIV
- self.CLKOP_DIV = CLK1_DIV
- self.CLKOS_DIV = CLK2_DIV
- self.ports = [
- self.clkin,
- self.clkout1,
- self.clkout2,
- self.clkout3,
- self.clkout4,
- self.clksel,
- self.lock,
- ]
-
- def elaborate(self, platform):
- clkfb = Signal()
- pll = Instance("EHXPLLL",
- p_OUTDIVIDER_MUXA='DIVA',
- p_OUTDIVIDER_MUXB='DIVB',
- p_CLKOP_ENABLE='ENABLED',
- p_CLKOS_ENABLE='ENABLED',
- p_CLKOS2_ENABLE='DISABLED',
- p_CLKOS3_ENABLE='DISABLED',
- p_CLKOP_DIV=self.CLKOP_DIV,
- p_CLKOS_DIV=self.CLKOS_DIV,
- p_CLKFB_DIV=self.CLKFB_DIV,
- p_CLKI_DIV=self.CLKI_DIV,
- p_FEEDBK_PATH='INT_OP',
- p_CLKOP_TRIM_POL="FALLING",
- p_CLKOP_TRIM_DELAY=0,
- p_CLKOS_TRIM_POL="FALLING",
- p_CLKOS_TRIM_DELAY=0,
- i_CLKI=self.clkin,
- i_RST=0,
- i_STDBY=0,
- i_PHASESEL0=0,
- i_PHASESEL1=0,
- i_PHASEDIR=0,
- i_PHASESTEP=0,
- i_PHASELOADREG=0,
- i_PLLWAKESYNC=0,
- i_ENCLKOP=1,
- i_ENCLKOS=1,
- i_ENCLKOS2=0,
- i_ENCLKOS3=0,
- o_CLKOP=self.clkout1,
- o_CLKOS=self.clkout2,
- o_CLKOS2=self.clkout3,
- o_CLKOS3=self.clkout4,
- o_LOCK=self.lock,
- )
- m = Module()
- m.submodules += pll
- return m
-
-
-class ECPIX5CRG(Elaboratable):
- def __init__(self):
- ...
-
- def elaborate(self, platform):
- m = Module()
-
- # Get 100Mhz from oscillator
- clk100 = platform.request("clk100")
- cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
- m.d.comb += cd_rawclk.clk.eq(clk100)
- m.domains += cd_rawclk
-
- # Reset
- reset = platform.request(platform.default_rst).i
- gsr0 = Signal()
- gsr1 = Signal()
-
- m.submodules += [
- Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"),
- i_D=~reset, o_Q=gsr0),
- Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"),
- i_D=gsr0, o_Q=gsr1),
- Instance("SGSR", i_CLK=ClockSignal("rawclk"), i_GSR=gsr1),
- ]
-
- # Power-on delay (655us)
- podcnt = Signal(16, reset=2**16-1)
- pod_done = Signal()
- with m.If(podcnt != 0):
- m.d.rawclk += podcnt.eq(podcnt-1)
- m.d.rawclk += pod_done.eq(podcnt == 0)
-
- # Generating sync2x (200Mhz) and init (25Mhz) from clk100
- cd_sync2x = ClockDomain("sync2x", local=False)
- cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=False,
- reset_less=True)
- cd_init = ClockDomain("init", local=False)
- cd_sync = ClockDomain("sync", local=False)
- cd_dramsync = ClockDomain("dramsync", local=False)
- m.submodules.pll = pll = PLL(ClockSignal("rawclk"),
- CLKI_DIV=1, CLKFB_DIV=2,
- CLK1_DIV=3, CLK2_DIV=24,
- clkout1=ClockSignal("sync2x_unbuf"),
- clkout2=ClockSignal("init"))
- m.submodules += Instance("ECLKSYNCB",
- i_ECLKI = ClockSignal("sync2x_unbuf"),
- i_STOP = 0,
- o_ECLKO = ClockSignal("sync2x"))
- m.domains += cd_sync2x_unbuf
- m.domains += cd_sync2x
- m.domains += cd_init
- m.domains += cd_sync
- m.domains += cd_dramsync
- m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
- m.d.comb += ResetSignal("sync").eq(~pll.lock|~pod_done)
- m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
-
- # # Generating sync (100Mhz) from sync2x
-
- m.submodules += Instance("CLKDIVF",
- p_DIV="2.0",
- i_ALIGNWD=0,
- i_CLKI=ClockSignal("sync2x"),
- i_RST=0,
- o_CDIVX=ClockSignal("sync"))
- m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
-
- return m
+++ /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
- self.uart = UART16550()
- 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)
-
- # add uart16550 verilog source. assumes a directory
- # structure where ls2 has been checked out in a common
- # subdirectory as https://github.com/freecores/uart16550
- 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.add_verilog_source(fname, platform)
-
- 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>
+
+from nmigen import (Module, Elaboratable, Instance, Signal, ClockDomain,
+ ClockSignal, ResetSignal)
+
+__ALL__ = ["ECPIX5CRG"]
+
+
+class PLL(Elaboratable):
+ def __init__(self, clkin, clksel=Signal(shape=2, reset=2),
+ clkout1=Signal(), clkout2=Signal(),
+ clkout3=Signal(), clkout4=Signal(), lock=Signal(),
+ CLKI_DIV=1, CLKFB_DIV=2, CLK1_DIV=3, CLK2_DIV=24):
+ self.clkin = clkin
+ self.clkout1 = clkout1
+ self.clkout2 = clkout2
+ self.clkout3 = clkout3
+ self.clkout4 = clkout4
+ self.clksel = clksel
+ self.lock = lock
+ self.CLKI_DIV = CLKI_DIV
+ self.CLKFB_DIV = CLKFB_DIV
+ self.CLKOP_DIV = CLK1_DIV
+ self.CLKOS_DIV = CLK2_DIV
+ self.ports = [
+ self.clkin,
+ self.clkout1,
+ self.clkout2,
+ self.clkout3,
+ self.clkout4,
+ self.clksel,
+ self.lock,
+ ]
+
+ def elaborate(self, platform):
+ clkfb = Signal()
+ pll = Instance("EHXPLLL",
+ p_OUTDIVIDER_MUXA='DIVA',
+ p_OUTDIVIDER_MUXB='DIVB',
+ p_CLKOP_ENABLE='ENABLED',
+ p_CLKOS_ENABLE='ENABLED',
+ p_CLKOS2_ENABLE='DISABLED',
+ p_CLKOS3_ENABLE='DISABLED',
+ p_CLKOP_DIV=self.CLKOP_DIV,
+ p_CLKOS_DIV=self.CLKOS_DIV,
+ p_CLKFB_DIV=self.CLKFB_DIV,
+ p_CLKI_DIV=self.CLKI_DIV,
+ p_FEEDBK_PATH='INT_OP',
+ p_CLKOP_TRIM_POL="FALLING",
+ p_CLKOP_TRIM_DELAY=0,
+ p_CLKOS_TRIM_POL="FALLING",
+ p_CLKOS_TRIM_DELAY=0,
+ i_CLKI=self.clkin,
+ i_RST=0,
+ i_STDBY=0,
+ i_PHASESEL0=0,
+ i_PHASESEL1=0,
+ i_PHASEDIR=0,
+ i_PHASESTEP=0,
+ i_PHASELOADREG=0,
+ i_PLLWAKESYNC=0,
+ i_ENCLKOP=1,
+ i_ENCLKOS=1,
+ i_ENCLKOS2=0,
+ i_ENCLKOS3=0,
+ o_CLKOP=self.clkout1,
+ o_CLKOS=self.clkout2,
+ o_CLKOS2=self.clkout3,
+ o_CLKOS3=self.clkout4,
+ o_LOCK=self.lock,
+ )
+ m = Module()
+ m.submodules += pll
+ return m
+
+
+class ECPIX5CRG(Elaboratable):
+ def __init__(self):
+ ...
+
+ def elaborate(self, platform):
+ m = Module()
+
+ # Get 100Mhz from oscillator
+ clk100 = platform.request("clk100")
+ cd_rawclk = ClockDomain("rawclk", local=True, reset_less=True)
+ m.d.comb += cd_rawclk.clk.eq(clk100)
+ m.domains += cd_rawclk
+
+ # Reset
+ reset = platform.request(platform.default_rst).i
+ gsr0 = Signal()
+ gsr1 = Signal()
+
+ m.submodules += [
+ Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"),
+ i_D=~reset, o_Q=gsr0),
+ Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"),
+ i_D=gsr0, o_Q=gsr1),
+ Instance("SGSR", i_CLK=ClockSignal("rawclk"), i_GSR=gsr1),
+ ]
+
+ # Power-on delay (655us)
+ podcnt = Signal(16, reset=2**16-1)
+ pod_done = Signal()
+ with m.If(podcnt != 0):
+ m.d.rawclk += podcnt.eq(podcnt-1)
+ m.d.rawclk += pod_done.eq(podcnt == 0)
+
+ # Generating sync2x (200Mhz) and init (25Mhz) from clk100
+ cd_sync2x = ClockDomain("sync2x", local=False)
+ cd_sync2x_unbuf = ClockDomain("sync2x_unbuf", local=False,
+ reset_less=True)
+ cd_init = ClockDomain("init", local=False)
+ cd_sync = ClockDomain("sync", local=False)
+ cd_dramsync = ClockDomain("dramsync", local=False)
+ m.submodules.pll = pll = PLL(ClockSignal("rawclk"),
+ CLKI_DIV=1, CLKFB_DIV=2,
+ CLK1_DIV=3, CLK2_DIV=24,
+ clkout1=ClockSignal("sync2x_unbuf"),
+ clkout2=ClockSignal("init"))
+ m.submodules += Instance("ECLKSYNCB",
+ i_ECLKI = ClockSignal("sync2x_unbuf"),
+ i_STOP = 0,
+ o_ECLKO = ClockSignal("sync2x"))
+ m.domains += cd_sync2x_unbuf
+ m.domains += cd_sync2x
+ m.domains += cd_init
+ m.domains += cd_sync
+ m.domains += cd_dramsync
+ m.d.comb += ResetSignal("init").eq(~pll.lock|~pod_done)
+ m.d.comb += ResetSignal("sync").eq(~pll.lock|~pod_done)
+ m.d.comb += ResetSignal("dramsync").eq(~pll.lock|~pod_done)
+
+ # # Generating sync (100Mhz) from sync2x
+
+ m.submodules += Instance("CLKDIVF",
+ p_DIV="2.0",
+ i_ALIGNWD=0,
+ i_CLKI=ClockSignal("sync2x"),
+ i_RST=0,
+ o_CDIVX=ClockSignal("sync"))
+ m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
+
+ return m
--- /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
+ self.uart = UART16550()
+ 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)
+
+ # add uart16550 verilog source. assumes a directory
+ # structure where ls2 has been checked out in a common
+ # subdirectory as https://github.com/freecores/uart16550
+ 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.add_verilog_source(fname, platform)
+
+ 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)