Merge pull request #269 from antmicro/rework_icap
soc: cores: support sending custom bitstream to ICAP
This commit is contained in:
commit
4bb2827e05
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue