2013-09-21 07:04:07 -04:00
|
|
|
from migen.fhdl.std import *
|
|
|
|
from migen.fhdl.specials import Memory
|
|
|
|
from migen.bank.description import *
|
2014-08-03 02:38:37 -04:00
|
|
|
from migen.genlib.record import *
|
2013-09-21 07:04:07 -04:00
|
|
|
|
2013-09-22 07:04:18 -04:00
|
|
|
from miscope.std import *
|
|
|
|
|
2013-09-21 07:04:07 -04:00
|
|
|
class Term(Module, AutoCSR):
|
|
|
|
def __init__(self, width):
|
|
|
|
self.width = width
|
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.sink = Record(dat_layout(width))
|
|
|
|
self.source = Record(hit_layout())
|
2013-09-21 07:04:07 -04:00
|
|
|
|
|
|
|
self._r_trig = CSRStorage(width)
|
|
|
|
self._r_mask = CSRStorage(width)
|
|
|
|
|
2013-09-22 12:41:44 -04:00
|
|
|
###
|
2013-09-21 07:04:07 -04:00
|
|
|
|
|
|
|
trig = self._r_trig.storage
|
|
|
|
mask = self._r_mask.storage
|
2013-09-22 07:04:18 -04:00
|
|
|
dat = self.sink.dat
|
|
|
|
hit = self.source.hit
|
2013-09-21 07:04:07 -04:00
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2013-09-22 06:15:11 -04:00
|
|
|
hit.eq((dat & mask) == trig),
|
2014-05-20 03:02:35 -04:00
|
|
|
self.source.stb.eq(self.sink.stb)
|
2013-09-21 07:04:07 -04:00
|
|
|
]
|
|
|
|
|
2013-09-22 06:15:11 -04:00
|
|
|
class RangeDetector(Module, AutoCSR):
|
|
|
|
def __init__(self, width):
|
|
|
|
self.width = width
|
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.sink = Record(dat_layout(width))
|
|
|
|
self.source = Record(hit_layout())
|
2013-09-22 06:15:11 -04:00
|
|
|
|
|
|
|
self._r_low = CSRStorage(width)
|
|
|
|
self._r_high = CSRStorage(width)
|
|
|
|
|
|
|
|
###
|
2014-05-20 03:02:35 -04:00
|
|
|
|
2013-09-22 06:15:11 -04:00
|
|
|
low = self._r_low.storage
|
|
|
|
high = self._r_high.storage
|
2013-09-22 07:04:18 -04:00
|
|
|
dat = self.sink.dat
|
|
|
|
hit = self.source.hit
|
2013-09-22 06:15:11 -04:00
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2013-09-22 06:15:11 -04:00
|
|
|
hit.eq((dat >= low) & (dat <= high)),
|
2014-05-20 03:02:35 -04:00
|
|
|
self.source.stb.eq(self.sink.stb)
|
2013-09-22 06:15:11 -04:00
|
|
|
]
|
|
|
|
|
|
|
|
class EdgeDetector(Module, AutoCSR):
|
|
|
|
def __init__(self, width):
|
|
|
|
self.width = width
|
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.sink = Record(dat_layout(width))
|
|
|
|
self.source = Record(hit_layout())
|
2013-09-22 06:15:11 -04:00
|
|
|
|
|
|
|
self._r_rising_mask = CSRStorage(width)
|
|
|
|
self._r_falling_mask = CSRStorage(width)
|
|
|
|
self._r_both_mask = CSRStorage(width)
|
|
|
|
|
|
|
|
###
|
2014-05-20 03:02:35 -04:00
|
|
|
|
2013-09-22 06:15:11 -04:00
|
|
|
rising_mask = self._r_rising_mask.storage
|
|
|
|
falling_mask = self._r_falling_mask.storage
|
|
|
|
both_mask = self._r_both_mask.storage
|
|
|
|
|
2013-09-22 07:04:18 -04:00
|
|
|
dat = self.sink.dat
|
2013-09-22 06:15:11 -04:00
|
|
|
dat_d = Signal(width)
|
|
|
|
rising_hit = Signal()
|
|
|
|
falling_hit = Signal()
|
|
|
|
both_hit = Signal()
|
2013-09-22 07:04:18 -04:00
|
|
|
hit = self.source.hit
|
2013-09-22 06:15:11 -04:00
|
|
|
|
|
|
|
self.sync += dat_d.eq(dat)
|
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2013-09-22 06:15:11 -04:00
|
|
|
rising_hit.eq(rising_mask & dat & ~dat_d),
|
|
|
|
falling_hit.eq(rising_mask & ~dat & dat_d),
|
|
|
|
both_hit.eq((both_mask & dat) != (both_mask & dat_d)),
|
|
|
|
hit.eq(rising_hit | falling_hit | both_hit),
|
2014-05-20 03:02:35 -04:00
|
|
|
self.source.stb.eq(self.sink.stb)
|
2013-09-22 06:15:11 -04:00
|
|
|
]
|
|
|
|
|
2013-09-21 07:04:07 -04:00
|
|
|
class Sum(Module, AutoCSR):
|
|
|
|
def __init__(self, ports=4):
|
2014-08-03 02:38:37 -04:00
|
|
|
|
|
|
|
self.sinks = [Record(hit_layout()) for p in range(ports)]
|
|
|
|
self.source = Record(hit_layout())
|
2013-09-21 07:04:07 -04:00
|
|
|
|
|
|
|
self._r_prog_we = CSRStorage()
|
|
|
|
self._r_prog_adr = CSRStorage(ports) #FIXME
|
|
|
|
self._r_prog_dat = CSRStorage()
|
|
|
|
|
|
|
|
mem = Memory(1, 2**ports)
|
|
|
|
lut_port = mem.get_port()
|
|
|
|
prog_port = mem.get_port(write_capable=True)
|
|
|
|
|
|
|
|
self.specials += mem, lut_port, prog_port
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
# Lut prog
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2013-09-21 07:04:07 -04:00
|
|
|
prog_port.we.eq(self._r_prog_we.storage),
|
|
|
|
prog_port.adr.eq(self._r_prog_adr.storage),
|
|
|
|
prog_port.dat_w.eq(self._r_prog_dat.storage)
|
|
|
|
]
|
|
|
|
|
|
|
|
# Lut read
|
|
|
|
for i, sink in enumerate(self.sinks):
|
2013-09-22 07:04:18 -04:00
|
|
|
self.comb += lut_port.adr[i].eq(sink.hit)
|
2013-09-21 07:04:07 -04:00
|
|
|
|
|
|
|
# Drive source
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2013-09-21 07:04:07 -04:00
|
|
|
self.source.stb.eq(optree("&", [sink.stb for sink in self.sinks])),
|
2013-09-22 07:04:18 -04:00
|
|
|
self.source.hit.eq(lut_port.dat_r),
|
2013-09-21 07:04:07 -04:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
class Trigger(Module, AutoCSR):
|
|
|
|
def __init__(self, width, ports):
|
|
|
|
self.width = width
|
|
|
|
self.ports = ports
|
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.submodules.sum = Sum(len(ports))
|
2013-09-21 07:04:07 -04:00
|
|
|
for i, port in enumerate(ports):
|
2014-08-03 02:38:37 -04:00
|
|
|
setattr(self.submodules, "port"+str(i), port)
|
2013-09-21 07:04:07 -04:00
|
|
|
|
2014-08-03 02:38:37 -04:00
|
|
|
self.sink = Record(dat_layout(width))
|
2013-09-21 07:04:07 -04:00
|
|
|
self.source = self.sum.source
|
|
|
|
|
|
|
|
###
|
2014-08-03 02:38:37 -04:00
|
|
|
|
2013-09-21 07:04:07 -04:00
|
|
|
for i, port in enumerate(ports):
|
2014-08-03 02:38:37 -04:00
|
|
|
self.comb += [
|
2014-05-20 03:02:35 -04:00
|
|
|
self.sink.connect(port.sink),
|
2013-09-21 07:04:07 -04:00
|
|
|
port.source.connect(self.sum.sinks[i])
|
2014-08-03 02:38:37 -04:00
|
|
|
]
|