litex/miscope/storage.py

115 lines
2.6 KiB
Python
Raw Normal View History

2013-09-21 07:04:07 -04:00
from migen.fhdl.std import *
from migen.bank.description import *
from migen.genlib.fifo import SyncFIFOBuffered as SyncFIFO
2014-05-13 15:30:32 -04:00
from migen.genlib.fsm import FSM, NextState
2014-08-03 02:38:37 -04:00
from migen.genlib.record import *
from miscope.std import *
2013-09-21 07:04:07 -04:00
2013-09-22 12:41:44 -04:00
class RunLengthEncoder(Module, AutoCSR):
2014-05-20 03:02:35 -04:00
def __init__(self, width, length=1024):
2013-09-22 06:35:46 -04:00
self.width = width
self.length = length
2014-08-03 02:38:37 -04:00
self.sink = Record(dat_layout(width))
self.source = Record(dat_layout(width))
2013-09-22 06:35:46 -04:00
self._r_enable = CSRStorage()
2014-05-13 15:30:32 -04:00
###
2014-05-20 03:02:35 -04:00
enable = self._r_enable.storage
2013-09-22 06:35:46 -04:00
2014-08-03 02:38:37 -04:00
sink_d = Record(dat_layout(width))
self.sync += If(self.sink.stb, sink_d.eq(self.sink))
2013-09-22 06:35:46 -04:00
cnt = Signal(max=length)
cnt_inc = Signal()
cnt_reset = Signal()
cnt_max = Signal()
2013-09-22 06:35:46 -04:00
2014-05-20 03:02:35 -04:00
self.sync += \
If(cnt_reset,
cnt.eq(1),
).Elif(cnt_inc,
cnt.eq(cnt+1)
2013-09-22 06:35:46 -04:00
)
self.comb += cnt_max.eq(cnt == length)
2013-09-22 06:35:46 -04:00
change = Signal()
self.comb += change.eq(self.sink.stb & (self.sink.dat != sink_d.dat))
2014-05-22 12:14:03 -04:00
fsm = FSM(reset_state="BYPASS")
self.submodules += fsm
fsm.act("BYPASS",
sink_d.connect(self.source),
cnt_reset.eq(1),
If(enable & ~change & self.sink.stb, NextState("COUNT"))
)
fsm.act("COUNT",
cnt_inc.eq(self.sink.stb),
If(change | cnt_max | ~enable,
self.source.stb.eq(1),
self.source.dat[width-1].eq(1), # Set RLE bit
self.source.dat[:flen(cnt)].eq(cnt),
NextState("BYPASS")
2014-05-20 03:02:35 -04:00
)
),
2013-09-22 06:35:46 -04:00
2013-09-21 07:04:07 -04:00
class Recorder(Module, AutoCSR):
def __init__(self, width, depth):
self.width = width
2014-08-03 02:38:37 -04:00
self.trig_sink = Record(hit_layout())
self.dat_sink = Record(dat_layout(width))
2013-09-21 07:04:07 -04:00
self._r_trigger = CSR()
self._r_length = CSRStorage(bits_for(depth))
self._r_offset = CSRStorage(bits_for(depth))
self._r_done = CSRStatus()
self._r_read_en = CSR()
self._r_read_empty = CSRStatus()
self._r_read_dat = CSRStatus(width)
###
2014-08-01 04:36:15 -04:00
fifo = InsertReset(SyncFIFO(width, depth))
2013-09-21 07:04:07 -04:00
self.submodules += fifo
2014-05-13 15:30:32 -04:00
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
2013-09-21 07:04:07 -04:00
self.comb += [
self._r_read_empty.status.eq(~fifo.readable),
self._r_read_dat.status.eq(fifo.dout),
2013-09-21 07:04:07 -04:00
]
2014-05-13 15:30:32 -04:00
fsm.act("IDLE",
If(self._r_trigger.re & self._r_trigger.r,
NextState("PRE_HIT_RECORDING"),
2014-08-01 04:36:15 -04:00
fifo.reset.eq(1),
2014-05-13 15:30:32 -04:00
),
fifo.re.eq(self._r_read_en.re & self._r_read_en.r),
self._r_done.status.eq(1)
)
fsm.act("PRE_HIT_RECORDING",
fifo.we.eq(self.dat_sink.stb),
fifo.din.eq(self.dat_sink.dat),
fifo.re.eq(fifo.level >= self._r_offset.storage),
If(self.trig_sink.stb & self.trig_sink.hit, NextState("POST_HIT_RECORDING"))
)
fsm.act("POST_HIT_RECORDING",
fifo.we.eq(self.dat_sink.stb),
fifo.din.eq(self.dat_sink.dat),
If(~fifo.writable | (fifo.level >= self._r_length.storage), NextState("IDLE"))
)