From 4423a46ba20ecbf9a424ba67393590a5dd3ecdbb Mon Sep 17 00:00:00 2001 From: Jan Kowalewski Date: Tue, 17 Sep 2019 21:35:53 +0200 Subject: [PATCH] soc: cores: support sending custom bitstream to ICAP This adds FIFO that can be used to send any sequence of commands to the ICAP controller. --- litex/soc/cores/icap.py | 71 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/litex/soc/cores/icap.py b/litex/soc/cores/icap.py index d607e3566..e841e7c72 100644 --- a/litex/soc/cores/icap.py +++ b/litex/soc/cores/icap.py @@ -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