From ab5f0ee9f6bb8e5ebf2810cdcfa9a53718dd5b4e Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sat, 12 Feb 2022 20:57:05 +0000 Subject: [PATCH] begin a tidyup on the example core, put addresses of peripherals at the microwatt-expected addresses --- examples/soc.py | 89 +++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/examples/soc.py b/examples/soc.py index 5113674..889f241 100644 --- a/examples/soc.py +++ b/examples/soc.py @@ -7,8 +7,7 @@ # 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 * +from nmigen import (Module, Elaboratable, DomainRenamer) from nmigen.lib.cdc import ResetSynchronizer from nmigen_soc import wishbone, memory from nmigen_stdio.serial import AsyncSerial @@ -28,69 +27,86 @@ from gram.frontend.wishbone import gramWishbone from nmigen_boards.versa_ecp5 import VersaECP5Platform from uartbridge import UARTBridge -from crg import * +from crg import ECPIX5CRG + 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, + ddr_addr, + firmware=None, + clk_freq=10e6): + + # 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, + self._decoder = wishbone.Decoder(addr_width=30, data_width=32, + granularity=8, features={"cti", "bte"}) - freq = 100e6 + # default firmware name + if firmware is None: + firmware = "firmware/main.bin" + # set up clock request generator, CPU, and interrupt interface self.crg = ECPIX5CRG() - self.cpu = MinervaCPU(reset_address=0) - self._arbiter.add(self.cpu.ibus) - self._arbiter.add(self.cpu.dbus) + 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 self.rom = SRAMPeripheral(size=4096, writable=False) - with open("firmware/main.bin", "rb") as f: + with open(, "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._decoder.add(self.rom.bus, addr=0) # ROM is at 0x0000_0000 + # SRAM (read-writeable BRAM) self.ram = SRAMPeripheral(size=4096) - self._decoder.add(self.ram.bus, addr=0x1000) + self._decoder.add(self.ram.bus, addr=0x8000000) # SRAM at 0x8000_000 + # UART self.uart_phy = AsyncSerial(data_bits=8, - divisor=int(freq//115200), + divisor=int(clk_freq//115200), pins=uart_pins) self.uart = AsyncSerialPeripheral(core=self.uart_phy) - self._decoder.add(self.uart.bus, addr=0x2000) + 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(freq, "1:2") + ddrmodule = MT41K256M16(clk_freq, "1:2") # match DDR3 ASIC P/N - self.dramcore = DomainRenamer("dramsync")(gramCore( - phy=self.ddrphy, - geom_settings=ddrmodule.geom_settings, - timing_settings=ddrmodule.timing_settings, - clk_freq=freq)) + 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) - self.drambone = DomainRenamer("dramsync")(gramWishbone(self.dramcore)) + # 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 = freq + 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 - + m.submodules.rom = self.rom m.submodules.ram = self.ram m.submodules.uart = self.uart @@ -102,10 +118,12 @@ class DDR3SoC(SoC, Elaboratable): 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), - ] + # connect the arbiter (of wishbone masters) + # to the decoder (addressing wishbone slaves) + comb += self._arbiter.bus.connect(self._decoder.bus) + + # wire up the CPU interrupts + comb += self.cpu.ip.eq(self.intc.ip) return m @@ -113,11 +131,16 @@ class DDR3SoC(SoC, Elaboratable): 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}) + 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) + soc = DDR3SoC(ddrphy_addr=0xff000000, # DRAM firmware init base + dramcore_addr=0x40000000, + ddr_addr=0x10000000, + ddr_pins=ddr_pins, + uart_pins=uart_pins) platform.build(soc, do_program=True) -- 2.30.2