cores/spi_flash: add SpiFlashCommon and use it to add clk primitives (7-Series/ECP5...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 22 Jul 2019 08:28:03 +0000 (10:28 +0200)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 22 Jul 2019 08:28:03 +0000 (10:28 +0200)
litex/soc/cores/spi_flash.py

index caf81b809f3cb73db06af2445cf2057eb2151516..2e40caa88524506dd763bea61118acfcdd3ba08a 100644 (file)
@@ -37,13 +37,50 @@ def _format_cmd(cmd, spi_width):
     return c
 
 
-class SpiFlashDualQuad(Module, AutoCSR):
+class SpiFlashCommon(Module):
+    def __init__(self, pads):
+        if not hasattr(pads, "clk"):
+            self.clk_primitive_needed = True
+            self.clk_primitive_registered = False
+            pads.clk = Signal()
+        self.pads = pads
+
+    def add_clk_primitive(self, device):
+        assert hasattr(self, "clk_primitive_needed")
+        # Xilinx 7-series
+        if device[:3] == "xc7":
+            self.specials += Instance("STARTUPE2",
+                i_CLK=0,
+                i_GSR=0,
+                i_GTS=0,
+                i_KEYCLEARB=0,
+                i_PACK=0,
+                i_USRCCLKO=self.pads.clk,
+                i_USRCCLKTS=0,
+                i_USRDONEO=1,
+                i_USRDONETS=1)
+        # Lattice ECP5
+        elif device[:4] == "LFE5":
+            self.specials += Instance("USRMCLK",
+                i_USRMCLKI=self.pads.clk,
+                i_USRMCLKTS=0)
+        else:
+            raise NotImplementedError
+        self.clk_primitive_registered = True
+
+    def do_finalize(self):
+        if hasattr(self, "clk_primitive_needed"):
+            assert self.clk_primitive_registered == True
+
+
+class SpiFlashDualQuad(SpiFlashCommon, AutoCSR):
     def __init__(self, pads, dummy=15, div=2, with_bitbang=True, endianness="big"):
         """
         Simple SPI flash.
         Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
         Read). Only supports mode0 (cpol=0, cpha=0).
         """
+        SpiFlashCommon.__init__(self, pads)
         self.bus = bus = wishbone.Interface()
         spi_width = len(pads.dq)
         assert spi_width >= 2
@@ -164,12 +201,13 @@ class SpiFlashDualQuad(Module, AutoCSR):
         self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
 
 
-class SpiFlashSingle(Module, AutoCSR):
+class SpiFlashSingle(SpiFlashCommon, AutoCSR):
     def __init__(self, pads, dummy=15, div=2, with_bitbang=True, endianness="big"):
         """
         Simple SPI flash.
         Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0).
         """
+        SpiFlashCommon.__init__(self, pads)
         self.bus = bus = wishbone.Interface()
 
         if with_bitbang:
@@ -272,12 +310,11 @@ class SpiFlashSingle(Module, AutoCSR):
         self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
 
 
-def SpiFlash(pads, *args, **kw):
+def SpiFlash(pads, *args, **kwargs):
     if hasattr(pads, "mosi"):
-        return SpiFlashSingle(pads, *args, **kw)
+       return SpiFlashSingle(pads, *args, **kwargs)
     else:
-        return SpiFlashDualQuad(pads, *args, **kw)
-
+        return SpiFlashDualQuad(pads, *args, **kwargs)
 
 # Xilinx 7-Series FPGAs SPI Flash (non-memory-mapped) ----------------------------------------------