begin a tidyup on the example
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 12 Feb 2022 20:57:05 +0000 (20:57 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 12 Feb 2022 20:57:05 +0000 (20:57 +0000)
core, put addresses of peripherals at the microwatt-expected addresses

examples/soc.py

index 51136745fe2b02ffde13a23b78f812db7dc92ecc..889f2416952085572cf816df30af0a10a11d6c62 100644 (file)
@@ -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)