add fake (sim) DRAM from gram library
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 20 Feb 2022 00:00:01 +0000 (00:00 +0000)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 20 Feb 2022 00:00:01 +0000 (00:00 +0000)
src/ls2.py

index 2d5807fca13472c7943695718968af91fef59780..f564b46aaca6272c4150083701da78a556ed2d9e 100644 (file)
@@ -25,8 +25,12 @@ from soc.bus.external_core import ExternalCore # external libresoc/microwatt
 from soc.bus.wb_downconvert import WishboneDownConvert
 from soc.bus.syscon import MicrowattSYSCON
 
+from gram.common import (PhySettings, get_cl_cw, get_sys_latency,
+                        get_sys_phases,)
+from nmigen.utils import log2_int
 from gram.core import gramCore
 from gram.phy.ecp5ddrphy import ECP5DDRPHY
+from gram.phy.fakephy import FakePHY, SDRAM_VERBOSE_STD, SDRAM_VERBOSE_DBG
 from gram.modules import MT41K256M16, MT41K64M16
 from gram.frontend.wishbone import gramWishbone
 
@@ -40,9 +44,41 @@ from crg import ECPIX5CRG
 import sys
 import os
 
+def sim_ddr3_settings(clk_freq=100e6):
+    tck = 2/(2*2*clk_freq)
+    nphases = 2
+    databits = 16
+    nranks = 1
+    addressbits = 14
+    bankbits = 3
+    cl, cwl = get_cl_cw("DDR3", tck)
+    cl_sys_latency = get_sys_latency(nphases, cl)
+    cwl_sys_latency = get_sys_latency(nphases, cwl)
+    rdcmdphase, rdphase = get_sys_phases(nphases, cl_sys_latency, cl)
+    wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl)
+    return PhySettings(
+        phytype="ECP5DDRPHY",
+        memtype="DDR3",
+        databits=databits,
+        dfi_databits=4*databits,
+        nranks=nranks,
+        nphases=nphases,
+        rdphase=rdphase,
+        wrphase=wrphase,
+        rdcmdphase=rdcmdphase,
+        wrcmdphase=wrcmdphase,
+        cl=cl,
+        cwl=cwl,
+        read_latency=2 + cl_sys_latency + 2 + log2_int(4//nphases) + 4,
+        write_latency=cwl_sys_latency
+    )
+
+
+
 
 class DDR3SoC(SoC, Elaboratable):
     def __init__(self, *,
+                 fpga,
                  dram_cls,
                  uart_pins, ddr_pins,
                  ddrphy_addr, dramcore_addr,
@@ -137,13 +173,18 @@ class DDR3SoC(SoC, Elaboratable):
         """
 
         # DRAM Module
-        if ddr_pins is not None:
-            self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins,
-                                                    sys_clk_freq=clk_freq))
-            self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
-
+        if ddr_pins is not None or fpga == 'sim':
             ddrmodule = MT41K256M16(clk_freq, "1:2") # match DDR3 ASIC P/N
 
+            if fpga == 'sim':
+                self.ddrphy = FakePHY(module=ddrmodule,
+                                      settings=sim_ddr3_settings(clk_freq),
+                                      verbosity=SDRAM_VERBOSE_DBG)
+            else:
+                self.ddrphy = DomainRenamer("dramsync")(ECP5DDRPHY(ddr_pins,
+                                                        sys_clk_freq=clk_freq))
+                self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr)
+
             drs = DomainRenamer("dramsync")
             dramcore = gramCore(phy=self.ddrphy,
                                 geom_settings=ddrmodule.geom_settings,
@@ -244,7 +285,7 @@ class DDR3SoC(SoC, Elaboratable):
         # and at the moment that's just UART tx/rx.
         ports = []
         ports += [self.uart.tx_o, self.uart.rx_i]
-        if hasattr(self, "ddrphy"):
+        if hasattr(self, "ddrphy") and hasattr(self.ddrphy, "pads"):
             ports += list(self.ddrphy.pads.fields.values())
         return ports
 
@@ -297,7 +338,7 @@ if __name__ == "__main__":
                                          "odt":4, "ras":4, "cas":4, "we":4})
 
     # set up the SOC
-    soc = DDR3SoC(dram_cls=dram_cls,
+    soc = DDR3SoC(fpga=fpga, dram_cls=dram_cls,
                   # check microwatt_soc.h for these
                   ddrphy_addr=0xff000000,   # DRAM_INIT_BASE firmware base
                   dramcore_addr=0xc8000000, # DRAM_CTRL_BASE