cores/icap/ICAP: Rewrite using with an FSM instead of Timeline (will be easier to extend).
This commit is contained in:
parent
9416e30249
commit
3504904c09
|
@ -8,7 +8,6 @@ from enum import IntEnum
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
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 *
|
||||||
|
@ -97,50 +96,95 @@ class ICAP(Module, AutoCSR):
|
||||||
self.submodules += ps_send
|
self.submodules += ps_send
|
||||||
self.comb += ps_send.i.eq(self.send)
|
self.comb += ps_send.i.eq(self.send)
|
||||||
|
|
||||||
# Generate ICAP bitstream write sequence.
|
# Generate ICAP bitstream sequence.
|
||||||
self._csib = _csib = Signal(reset=1)
|
self._csib = _csib = Signal(reset=1)
|
||||||
self._rdwrb = _rdwrb = Signal()
|
self._rdwrb = _rdwrb = Signal()
|
||||||
self._i = _i = Signal(32)
|
self._i = _i = Signal(32)
|
||||||
self.sync.icap += [
|
|
||||||
_i.eq(ICAP_DUMMY), # Dummy (Default).
|
|
||||||
timeline(ps_send.o, [
|
|
||||||
# Clear Done.
|
|
||||||
(1, [_csib.eq(1), self.done.eq(0)]),
|
|
||||||
|
|
||||||
# Synchronize.
|
count = Signal(4)
|
||||||
(2, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
fsm = FSM(reset_state="WAIT")
|
||||||
(3, [_csib.eq(0), _i.eq(ICAP_SYNC)]), # Sync Word.
|
fsm = ClockDomainsRenamer("icap")(fsm)
|
||||||
(4, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
self.submodules += fsm
|
||||||
(5, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
|
||||||
|
|
||||||
# Write User's data to addr Register.
|
# Wait User Command.
|
||||||
(6, [_csib.eq(0), _i.eq(ICAP_WRITE | (self.addr << 13) | 1)]), # Set Register.
|
fsm.act("WAIT",
|
||||||
(7, [_csib.eq(0), _i.eq(self.data)]), # Set Register Data.
|
# Set ICAP in IDLE state.
|
||||||
(8, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
_csib.eq(1),
|
||||||
(9, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
_rdwrb.eq(0),
|
||||||
|
_i.eq(ICAP_DUMMY),
|
||||||
|
|
||||||
# De-Synchronize.
|
# Set Done.
|
||||||
(10, [_csib.eq(0), _i.eq(ICAP_WRITE | (ICAPRegisters.CMD << 13) | 1)]), # Write to CMD Register.
|
self.done.eq(1),
|
||||||
(11, [_csib.eq(0), _i.eq(ICAPCMDs.DESYNC)]), # DESYNC CMD.
|
|
||||||
(12, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
|
||||||
(13, [_csib.eq(0), _i.eq(ICAP_NOOP)]), # No Op.
|
|
||||||
|
|
||||||
# Set Done.
|
# Wait User Command.
|
||||||
(14, [_csib.eq(1), self.done.eq(1)]),
|
If(ps_send.o,
|
||||||
])
|
NextValue(count, 0),
|
||||||
]
|
NextState("SYNC")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# ICAP instance
|
# Send ICAP Synchronization sequence.
|
||||||
|
fsm.act("SYNC",
|
||||||
|
_csib.eq(0),
|
||||||
|
_rdwrb.eq(0),
|
||||||
|
Case(count, {
|
||||||
|
0 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
1 : _i.eq(ICAP_SYNC), # Sync Word.
|
||||||
|
2 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
3 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
}),
|
||||||
|
NextValue(count, count + 1),
|
||||||
|
If(count == (4-1),
|
||||||
|
NextValue(count, 0),
|
||||||
|
NextState("WRITE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send ICAP Write sequence.
|
||||||
|
fsm.act("WRITE",
|
||||||
|
_csib.eq(0),
|
||||||
|
_rdwrb.eq(0),
|
||||||
|
Case(count, {
|
||||||
|
0 : _i.eq(ICAP_WRITE | (self.addr << 13) | 1), # Set Register.
|
||||||
|
1 : _i.eq(self.data), # Set Register Data.
|
||||||
|
2 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
3 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
}),
|
||||||
|
NextValue(count, count + 1),
|
||||||
|
If(count == (4-1),
|
||||||
|
NextValue(count, 0),
|
||||||
|
NextState("DESYNC")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send ICAP Desynchronization sequence.
|
||||||
|
fsm.act("DESYNC",
|
||||||
|
_csib.eq(0),
|
||||||
|
_rdwrb.eq(0),
|
||||||
|
Case(count, {
|
||||||
|
0 : _i.eq(ICAP_WRITE | (ICAPRegisters.CMD << 13) | 1), # Write to CMD Register.
|
||||||
|
1 : _i.eq(ICAPCMDs.DESYNC), # DESYNC CMD.
|
||||||
|
2 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
3 : _i.eq(ICAP_NOOP), # No Op.
|
||||||
|
}),
|
||||||
|
NextValue(count, count + 1),
|
||||||
|
If(count == (4-1),
|
||||||
|
NextValue(count, 0),
|
||||||
|
NextState("WAIT")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# ICAP Instance.
|
||||||
if not simulation:
|
if not simulation:
|
||||||
self.specials += Instance("ICAPE2",
|
self.specials += Instance("ICAPE2",
|
||||||
p_ICAP_WIDTH = "X32",
|
p_ICAP_WIDTH = "X32",
|
||||||
i_CLK = ClockSignal("icap"),
|
i_CLK = ClockSignal("icap"),
|
||||||
i_CSIB = _csib,
|
i_CSIB = _csib,
|
||||||
i_RDWRB = 0,
|
i_RDWRB = _rdwrb,
|
||||||
i_I = Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]),
|
i_I = Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]),
|
||||||
)
|
)
|
||||||
|
|
||||||
# CSR
|
# CSR.
|
||||||
if with_csr:
|
if with_csr:
|
||||||
self.add_csr()
|
self.add_csr()
|
||||||
|
|
||||||
|
@ -167,8 +211,8 @@ class ICAP(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("RELOAD",
|
fsm.act("RELOAD",
|
||||||
self.addr.eq(0x4),
|
self.addr.eq(ICAPRegisters.CMD),
|
||||||
self.data.eq(0xf),
|
self.data.eq(ICAPCMDs.IPROG),
|
||||||
self.send.eq(1),
|
self.send.eq(1),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class TestICAP(unittest.TestCase):
|
||||||
for ref_w in iprog_sequence:
|
for ref_w in iprog_sequence:
|
||||||
cur_w = f"{(yield dut._csib)} {(yield dut._rdwrb)} 0x{(yield dut._i):08x}"
|
cur_w = f"{(yield dut._csib)} {(yield dut._rdwrb)} 0x{(yield dut._i):08x}"
|
||||||
self.assertEqual(ref_w, cur_w)
|
self.assertEqual(ref_w, cur_w)
|
||||||
# print(cur_w)
|
#print(cur_w)
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue