soc: cores: support sending custom bitstream to ICAP
authorJan Kowalewski <jkowalewski@antmicro.com>
Tue, 17 Sep 2019 19:35:53 +0000 (21:35 +0200)
committerMateusz Holenko <mholenko@antmicro.com>
Tue, 1 Oct 2019 11:44:45 +0000 (13:44 +0200)
This adds FIFO that can be used to send any
sequence of commands to the ICAP controller.

litex/soc/cores/icap.py

index d607e3566eb3daa08f2eea51940e3b6434a6420e..e841e7c728299a6f5293a0b2d030e2769b369c0b 100644 (file)
@@ -7,57 +7,62 @@ from migen.genlib.misc import timeline
 from migen.genlib.cdc import PulseSynchronizer
 
 from litex.soc.interconnect.csr import *
+from litex.soc.interconnect import stream
 
 # Xilinx 7-series ----------------------------------------------------------------------------------
 
 class ICAP(Module, AutoCSR):
     """ICAP
 
-    Allow sending commands to ICAPE2 of Xilinx 7-Series FPGAs, the bistream can for example be
-    reloaded from SPI Flash by writing 0x00000000 at address @0x4.
+    Allow sending bitstreams to ICAPE2 of Xilinx 7-Series FPGAs.
     """
     def __init__(self, simulation=False):
-        self.addr = CSRStorage(5)
-        self.data = CSRStorage(32)
-        self.send = CSR()
+        self.data = CSRStorage(32, reset=0xffffffff)
+        self.icap_en = CSRStorage(reset=0)
+        self.fifofull = CSRStatus()
         self.done = CSRStatus(reset=1)
 
         # # #
 
-        # Create slow icap clk (sys_clk/2) ---------------------------------------------------------
+        # Create slow icap clk (sys_clk/4) ---------------------------------------------------------
         self.clock_domains.cd_icap = ClockDomain()
         icap_clk_counter = Signal(4)
         self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
-        self.sync += self.cd_icap.clk.eq(icap_clk_counter[3])
+        self.sync += self.cd_icap.clk.eq(icap_clk_counter[1])
 
-        # Resychronize send pulse to icap domain ---------------------------------------------------
-        ps_send = PulseSynchronizer("sys", "icap")
-        self.submodules += ps_send
-        self.comb += [ps_send.i.eq(self.send.re)]
-
-        # generate icap bitstream write sequence
+        # Helper signals
         _csib = Signal(reset=1)
-        _i = Signal(32)
-        _addr = self.addr.storage << 13
-        _data = self.data.storage
+        _i = Signal(32, reset=0xffffffff)
+        acknext = Signal(reset=0)
+        syncdata = Signal(32, reset=0xffffffff)
+
+        # FIFO
+        fifo = stream.AsyncFIFO([("data", 32)], 8)
+        icapfifo = ClockDomainsRenamer({"write": "sys", "read": "icap"})(fifo)
+
+        # Connect to FIFO
+        self.comb += [
+            icapfifo.sink.valid.eq(self.data.re),
+            icapfifo.sink.data.eq(self.data.storage),
+            self.fifofull.status.eq(~icapfifo.sink.ready),
+            syncdata.eq(icapfifo.source.data),
+            icapfifo.source.ready.eq(acknext),
+        ]
+        self.submodules += icapfifo
+
         self.sync.icap += [
-            _i.eq(0xffffffff), # dummy
-            timeline(ps_send.o, [
-                (1,  [_csib.eq(1), self.done.status.eq(0)]),
-                (2,  [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (3,  [_csib.eq(0), _i.eq(0xaa995566)]),         # sync word
-                (4,  [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (5,  [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (6,  [_csib.eq(0), _i.eq(0x30000001 | _addr)]), # write command
-                (7,  [_csib.eq(0), _i.eq(_data)]),              # write value
-                (8,  [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (9,  [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (10, [_csib.eq(0), _i.eq(0x30008001)]),         # write to cmd register
-                (11, [_csib.eq(0), _i.eq(0x0000000d)]),         # desync command
-                (12, [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (13, [_csib.eq(0), _i.eq(0x20000000)]),         # noop
-                (14, [_csib.eq(1), self.done.status.eq(1)]),
-            ])
+            If(self.icap_en.storage & icapfifo.source.valid & ~acknext,
+                acknext.eq(1),
+                self.done.status.eq(0)
+            ).Elif(self.icap_en.storage & icapfifo.source.valid & acknext,
+                _i.eq(syncdata),
+                _csib.eq(0)
+            ).Else(
+                _i.eq(0xffffffff),
+                _csib.eq(1),
+                acknext.eq(0),
+                self.done.status.eq(1)
+            ),
         ]
 
         self._csib = _csib