From ad7671f81168c69fa54e217e9ae2450f23b04abb Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 6 Oct 2020 15:18:05 +0200 Subject: [PATCH] soc/cores/icap/ICAP: add with_csr parameter and add_reload method to allow reloading the FPGA from the logic. --- litex/soc/cores/icap.py | 58 ++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/litex/soc/cores/icap.py b/litex/soc/cores/icap.py index d743d174d..c59180047 100644 --- a/litex/soc/cores/icap.py +++ b/litex/soc/cores/icap.py @@ -20,11 +20,11 @@ class ICAP(Module, AutoCSR): 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. """ - def __init__(self, simulation=False): - self.addr = CSRStorage(5, reset_less=True, description="ICAP Write Address.") - self.data = CSRStorage(32, reset_less=True, description="ICAP Write Data.") - self.send = CSRStorage(description="ICAP Control.\n\n Write ``1`` send a write command to the ICAP.") - self.done = CSRStatus(reset=1, description="ICAP Status.\n\n Write command done when read as ``1``.") + def __init__(self, with_csr=True, simulation=False): + self.addr = Signal(5) + self.data = Signal(32) + self.send = Signal() + self.done = Signal() # # # @@ -37,17 +37,17 @@ class ICAP(Module, AutoCSR): # Resynchronize send pulse to icap domain --------------------------------------------------- ps_send = PulseSynchronizer("sys", "icap") self.submodules += ps_send - self.comb += [ps_send.i.eq(self.send.re)] + self.comb += ps_send.i.eq(self.send) # Generate icap bitstream write sequence self._csib = _csib = Signal(reset=1) self._i = _i = Signal(32) - _addr = self.addr.storage << 13 - _data = self.data.storage + _addr = self.addr << 13 + _data = self.data self.sync.icap += [ _i.eq(0xffffffff), # dummy timeline(ps_send.o, [ - (1, [_csib.eq(1), self.done.status.eq(0)]), + (1, [_csib.eq(1), self.done.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 @@ -60,7 +60,7 @@ class ICAP(Module, AutoCSR): (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)]), + (14, [_csib.eq(1), self.done.eq(1)]), ]) ] @@ -68,14 +68,42 @@ class ICAP(Module, AutoCSR): if not simulation: self.specials += [ Instance("ICAPE2", - p_ICAP_WIDTH="X32", - i_CLK=ClockSignal("icap"), - i_CSIB=_csib, - i_RDWRB=0, - i_I=Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]), + p_ICAP_WIDTH = "X32", + i_CLK = ClockSignal("icap"), + i_CSIB = _csib, + i_RDWRB = 0, + i_I = Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]), ) ] + def add_csr(self): + self._addr = CSRStorage(5, reset_less=True, description="ICAP Write Address.") + self._data = CSRStorage(32, reset_less=True, description="ICAP Write Data.") + self._send = CSRStorage(description="ICAP Control.\n\n Write ``1`` send a write command to the ICAP.") + self._done = CSRStatus(reset=1, description="ICAP Status.\n\n Write command done when read as ``1``.") + + self.comb += [ + self.addr.eq(self._addr.storage), + self.data.eq(self._data.storage), + self.send.eq(self._send.re), + self._done.status.eq(self.done) + ] + + def add_reload(self): + self.reload = Signal() # Set to 1 to reload FPGA from logic. + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + fsm.act("IDLE", + If(self.reload, + NextState("RELOAD") + ) + ) + fsm.act("RELOAD", + self.addr.eq(0x4), + self.data.eq(0xf), + self.send.eq(1), + ) + def add_timing_constraints(self, platform, sys_clk_freq, sys_clk): platform.add_period_constraint(self.cd_icap.clk, 16*1e9/sys_clk_freq) platform.add_false_path_constraints(self.cd_icap.clk, sys_clk)