Merge pull request #269 from antmicro/rework_icap

soc: cores: support sending custom bitstream to ICAP
This commit is contained in:
enjoy-digital 2019-10-01 20:55:28 +02:00 committed by GitHub
commit 4bb2827e05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 38 additions and 33 deletions

View File

@ -7,57 +7,62 @@ from migen.genlib.misc import timeline
from migen.genlib.cdc import PulseSynchronizer from migen.genlib.cdc import PulseSynchronizer
from litex.soc.interconnect.csr import * from litex.soc.interconnect.csr import *
from litex.soc.interconnect import stream
# Xilinx 7-series ---------------------------------------------------------------------------------- # Xilinx 7-series ----------------------------------------------------------------------------------
class ICAP(Module, AutoCSR): class ICAP(Module, AutoCSR):
"""ICAP """ICAP
Allow sending commands to ICAPE2 of Xilinx 7-Series FPGAs, the bistream can for example be Allow sending bitstreams to ICAPE2 of Xilinx 7-Series FPGAs.
reloaded from SPI Flash by writing 0x00000000 at address @0x4.
""" """
def __init__(self, simulation=False): def __init__(self, simulation=False):
self.addr = CSRStorage(5) self.data = CSRStorage(32, reset=0xffffffff)
self.data = CSRStorage(32) self.icap_en = CSRStorage(reset=0)
self.send = CSR() self.fifofull = CSRStatus()
self.done = CSRStatus(reset=1) 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() self.clock_domains.cd_icap = ClockDomain()
icap_clk_counter = Signal(4) icap_clk_counter = Signal(4)
self.sync += icap_clk_counter.eq(icap_clk_counter + 1) 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 --------------------------------------------------- # Helper signals
ps_send = PulseSynchronizer("sys", "icap")
self.submodules += ps_send
self.comb += [ps_send.i.eq(self.send.re)]
# generate icap bitstream write sequence
_csib = Signal(reset=1) _csib = Signal(reset=1)
_i = Signal(32) _i = Signal(32, reset=0xffffffff)
_addr = self.addr.storage << 13 acknext = Signal(reset=0)
_data = self.data.storage 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 += [ self.sync.icap += [
_i.eq(0xffffffff), # dummy If(self.icap_en.storage & icapfifo.source.valid & ~acknext,
timeline(ps_send.o, [ acknext.eq(1),
(1, [_csib.eq(1), self.done.status.eq(0)]), self.done.status.eq(0)
(2, [_csib.eq(0), _i.eq(0x20000000)]), # noop ).Elif(self.icap_en.storage & icapfifo.source.valid & acknext,
(3, [_csib.eq(0), _i.eq(0xaa995566)]), # sync word _i.eq(syncdata),
(4, [_csib.eq(0), _i.eq(0x20000000)]), # noop _csib.eq(0)
(5, [_csib.eq(0), _i.eq(0x20000000)]), # noop ).Else(
(6, [_csib.eq(0), _i.eq(0x30000001 | _addr)]), # write command _i.eq(0xffffffff),
(7, [_csib.eq(0), _i.eq(_data)]), # write value _csib.eq(1),
(8, [_csib.eq(0), _i.eq(0x20000000)]), # noop acknext.eq(0),
(9, [_csib.eq(0), _i.eq(0x20000000)]), # noop self.done.status.eq(1)
(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)]),
])
] ]
self._csib = _csib self._csib = _csib