mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
split migScope to trigger & recorder
This commit is contained in:
parent
a99a902fef
commit
d34c877401
5 changed files with 442 additions and 468 deletions
|
@ -1,440 +0,0 @@
|
|||
from migen.fhdl.structure import *
|
||||
from migen.bus import csr
|
||||
from migen.bank import description, csrgen
|
||||
from migen.bank.description import *
|
||||
from migen.corelogic.misc import optree
|
||||
|
||||
class Term:
|
||||
def __init__(self, width, pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.t = Signal(BV(self.width))
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
frag = [
|
||||
self.o.eq(self.i==self.t)
|
||||
]
|
||||
if self.pipe:
|
||||
return Fragment(sync=frag)
|
||||
else:
|
||||
return Fragment(comb=frag)
|
||||
|
||||
class RangeDetector:
|
||||
def __init__(self, width, pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.low = Signal(BV(self.width))
|
||||
self.high = Signal(BV(self.width))
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
frag = [
|
||||
self.o.eq((self.i >= self.low) & ((self.i <= self.high)))
|
||||
]
|
||||
if self.pipe:
|
||||
return Fragment(sync=frag)
|
||||
else:
|
||||
return Fragment(comb=frag)
|
||||
|
||||
class EdgeDetector:
|
||||
def __init__(self, width, pipe=False, mode = "RFB"):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
self.mode = mode
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.i_d = Signal(BV(self.width))
|
||||
if "R" in mode:
|
||||
self.r_mask = Signal(BV(self.width))
|
||||
self.ro = Signal()
|
||||
if "F" in mode:
|
||||
self.f_mask = Signal(BV(self.width))
|
||||
self.fo = Signal()
|
||||
if "B" in mode:
|
||||
self.b_mask = Signal(BV(self.width))
|
||||
self.bo = Signal()
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
sync += [self.i_d.eq(self.i)]
|
||||
# Rising Edge
|
||||
if "R" in self.mode:
|
||||
r_eq = [self.ro.eq(self.r_mask & self.i & (~self.i_d))]
|
||||
if self.pipe:
|
||||
sync += r_eq
|
||||
else:
|
||||
comb += r_eq
|
||||
else:
|
||||
comb += [self.ro.eq(0)]
|
||||
# Falling Edge
|
||||
if "F" in self.mode:
|
||||
f_eq = [self.fo.eq(self.f_mask & (~ self.i) & self.i_d)]
|
||||
if self.pipe:
|
||||
sync += f_eq
|
||||
else:
|
||||
comb += f_eq
|
||||
else:
|
||||
comb += [self.fo.eq(0)]
|
||||
# Both
|
||||
if "B" in self.mode:
|
||||
b_eq = [self.bo.eq(self.b_mask & self.i != self.i_d)]
|
||||
if self.pipe:
|
||||
sync += b_eq
|
||||
else:
|
||||
comb += b_eq
|
||||
else:
|
||||
comb += [self.bo.eq(0)]
|
||||
#Output
|
||||
comb += [self.o.eq(self.ro | self.fo | self.bo)]
|
||||
|
||||
return Fragment(comb, sync)
|
||||
|
||||
class Timer:
|
||||
def __init__(self, width):
|
||||
self.width = width
|
||||
|
||||
self.start = Signal()
|
||||
self.stop = Signal()
|
||||
self.clear = Signal()
|
||||
|
||||
self.enable = Signal()
|
||||
self.cnt = Signal(BV(self.width))
|
||||
self.cnt_max = Signal(BV(self.width))
|
||||
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
sync += [
|
||||
If(self.stop,
|
||||
self.enable.eq(0),
|
||||
self.cnt.eq(0),
|
||||
self.o.eq(0)
|
||||
).Elif(self.clear,
|
||||
self.cnt.eq(0),
|
||||
self.o.eq(0)
|
||||
).Elif(self.start,
|
||||
self.enable.eq(1)
|
||||
).Elif(self.enable,
|
||||
If(self.cnt <= self.cnt_max,
|
||||
self.cnt.eq(self.cnt+1)
|
||||
).Else(
|
||||
self.o.eq(1)
|
||||
)
|
||||
),
|
||||
If(self.enable,
|
||||
self.enable.eq(0),
|
||||
self.cnt.eq(0)
|
||||
).Elif(self.clear,
|
||||
self.cnt.eq(0)
|
||||
).Elif(self.start,
|
||||
self.enable.eq(1)
|
||||
)
|
||||
|
||||
]
|
||||
|
||||
return Fragment(comb, sync)
|
||||
|
||||
class Sum:
|
||||
def __init__(self,width=4,pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self._o = Signal()
|
||||
self.o = Signal()
|
||||
self._lut_port = MemoryPort(adr=self.i, dat_r=self._o)
|
||||
|
||||
self.prog = Signal()
|
||||
self.prog_adr = Signal(BV(width))
|
||||
self.prog_dat = Signal()
|
||||
self._prog_port = MemoryPort(adr=self.prog_adr, we=self.prog, dat_w=self.prog_dat)
|
||||
|
||||
self._mem = Memory(1, 2**self.width, self._lut_port, self._prog_port)
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
memories = [self._mem]
|
||||
if self.pipe:
|
||||
sync += [self.o.eq(self._o)]
|
||||
else:
|
||||
comb += [self.o.eq(self._o)]
|
||||
return Fragment(comb=comb,sync=sync,memories=memories)
|
||||
|
||||
|
||||
class Trigger:
|
||||
def __init__(self,address, trig_width, dat_width, ports):
|
||||
self.address = address
|
||||
self.trig_width = trig_width
|
||||
self.dat_width = dat_width
|
||||
self.ports = ports
|
||||
assert (len(self.ports) <= 4), "Nb Ports > 4 (This version support 4 ports Max)"
|
||||
self._sum = Sum(len(self.ports))
|
||||
|
||||
self.in_trig = Signal(BV(self.trig_width))
|
||||
self.in_dat = Signal(BV(self.dat_width))
|
||||
|
||||
self.hit = Signal()
|
||||
self.dat = Signal(BV(self.dat_width))
|
||||
|
||||
# Csr interface
|
||||
for i in range(len(self.ports)):
|
||||
if isinstance(self.ports[i],Term):
|
||||
setattr(self,"_term_reg%d"%i,RegisterField("rst", 1*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
elif isinstance(self.ports[i],EdgeDetector):
|
||||
setattr(self,"_edge_reg%d"%i,RegisterField("rst", 3*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
elif isinstance(self.ports[i],RangeDetector):
|
||||
setattr(self,"_range_reg%d"%i,RegisterField("rst", 2*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
self._sum_reg = RegisterField("_sum_reg", 32, reset=0,access_bus=WRITE_ONLY, access_dev=READ_ONLY)
|
||||
|
||||
regs = []
|
||||
objects = self.__dict__
|
||||
for object in sorted(objects):
|
||||
if "_reg" in object:
|
||||
print(object)
|
||||
regs.append(objects[object])
|
||||
self.bank = csrgen.Bank(regs,address=address)
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
# Connect in_trig to input of trig elements
|
||||
comb+= [port.i.eq(self.in_trig) for port in self.ports]
|
||||
|
||||
# Connect output of trig elements to sum
|
||||
comb+= [self._sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))]
|
||||
|
||||
# Connect sum ouput to hit
|
||||
comb+= [self.hit.eq(self._sum.o)]
|
||||
|
||||
# Add ports & sum to frag
|
||||
frag = self.bank.get_fragment()
|
||||
frag += self._sum.get_fragment()
|
||||
for port in self.ports:
|
||||
frag += port.get_fragment()
|
||||
comb+= [self.dat.eq(self.in_dat)]
|
||||
|
||||
#Connect Registers
|
||||
for i in range(len(self.ports)):
|
||||
if isinstance(self.ports[i],Term):
|
||||
comb += [self.ports[i].t.eq(getattr(self,"_term_reg%d"%i).field.r[0:self.trig_width])]
|
||||
elif isinstance(self.ports[i],EdgeDetector):
|
||||
comb += [self.ports[i].r_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[0:1*self.trig_width])]
|
||||
comb += [self.ports[i].f_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[1*self.trig_width:2*self.trig_width])]
|
||||
comb += [self.ports[i].b_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[2*self.trig_width:3*self.trig_width])]
|
||||
elif isinstance(self.ports[i],RangeDetector):
|
||||
comb += [self.ports[i].low.eq(getattr(self,"_range_reg%d"%i).field.r[0:1*self.trig_width])]
|
||||
comb += [self.ports[i].high.eq(getattr(self,"_range_reg%d"%i).field.r[1*self.trig_width:2*self.trig_width])]
|
||||
|
||||
comb += [
|
||||
self._sum.prog_adr.eq(self._sum_reg.field.r[0:16]),
|
||||
self._sum.prog_dat.eq(self._sum_reg.field.r[16]),
|
||||
self._sum.prog.eq(self._sum_reg.field.r[17])
|
||||
]
|
||||
return frag + Fragment(comb=comb, sync=sync)
|
||||
|
||||
|
||||
class Storage:
|
||||
def __init__(self, width, depth):
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
#Control
|
||||
self.rst = Signal()
|
||||
self.start = Signal()
|
||||
self.offset = Signal(BV(self.depth_width))
|
||||
self.size = Signal(BV(self.depth_width))
|
||||
self.done = Signal()
|
||||
#Write Path
|
||||
self.put = Signal()
|
||||
self.put_dat = Signal(BV(self.width))
|
||||
self._put_cnt = Signal(BV(self.depth_width))
|
||||
self._put_ptr = Signal(BV(self.depth_width))
|
||||
self._put_port = MemoryPort(adr=self._put_ptr, we=self.put, dat_w=self.put_dat)
|
||||
#Read Path
|
||||
self.get = Signal()
|
||||
self.get_dat = Signal(BV(self.width))
|
||||
self._get_cnt = Signal(BV(self.depth_width))
|
||||
self._get_ptr = Signal(BV(self.depth_width))
|
||||
self._get_port = MemoryPort(adr=self._get_ptr, re=self.get, dat_r=self.get_dat)
|
||||
#Others
|
||||
self._mem = Memory(self.width, self.depth, self._put_port, self._get_port)
|
||||
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
memories = [self._mem]
|
||||
size_minus_offset = Signal(BV(self.depth_width))
|
||||
comb += [size_minus_offset.eq(self.size-self.offset)]
|
||||
|
||||
#Control
|
||||
sync += [
|
||||
If(self.rst,
|
||||
self._put_cnt.eq(0),
|
||||
self._put_ptr.eq(0),
|
||||
self._get_cnt.eq(0),
|
||||
self._get_ptr.eq(0),
|
||||
self.done.eq(0)
|
||||
).Elif(self.start,
|
||||
self._put_cnt.eq(0),
|
||||
self._get_cnt.eq(0),
|
||||
self._get_ptr.eq(self._put_ptr-size_minus_offset)
|
||||
),
|
||||
If(self.put,
|
||||
self._put_cnt.eq(self._put_cnt+1),
|
||||
self._put_ptr.eq(self._put_ptr+1)
|
||||
),
|
||||
If(self.get,
|
||||
self._get_cnt.eq(self._get_cnt+1),
|
||||
self._get_ptr.eq(self._get_ptr+1)
|
||||
)
|
||||
]
|
||||
comb += [
|
||||
If(self._put_cnt == size_minus_offset-1,
|
||||
self.done.eq(1)
|
||||
).Elif(self._get_cnt == size_minus_offset-1,
|
||||
self.done.eq(1)
|
||||
).Else(
|
||||
self.done.eq(0)
|
||||
)
|
||||
]
|
||||
return Fragment(comb=comb, sync=sync, memories=memories)
|
||||
|
||||
class Sequencer:
|
||||
def __init__(self,depth):
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
# Controller interface
|
||||
self.ctl_rst = Signal()
|
||||
self.ctl_offset = Signal(BV(self.depth_width))
|
||||
self.ctl_size = Signal(BV(self.depth_width))
|
||||
self.ctl_arm = Signal()
|
||||
self.ctl_done = Signal()
|
||||
# Triggers interface
|
||||
self.trig_hit = Signal()
|
||||
# Recorder interface
|
||||
self.rec_offset = Signal(BV(self.depth_width))
|
||||
self.rec_size = Signal(BV(self.depth_width))
|
||||
self.rec_start = Signal()
|
||||
self.rec_done = Signal()
|
||||
# Others
|
||||
self.enable = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
#Control
|
||||
sync += [
|
||||
If(self.ctl_rst,
|
||||
self.enable.eq(0)
|
||||
).Elif(self.ctl_arm,
|
||||
self.enable.eq(1)
|
||||
).Elif(self.rec_done,
|
||||
self.enable.eq(0)
|
||||
)
|
||||
]
|
||||
comb += [
|
||||
self.rec_offset.eq(self.ctl_offset),
|
||||
self.rec_size.eq(self.ctl_size),
|
||||
self.rec_start.eq(self.enable & self.trig_hit),
|
||||
self.ctl_done.eq(~self.enable)
|
||||
]
|
||||
return Fragment(comb=comb, sync=sync)
|
||||
|
||||
class Recorder:
|
||||
def __init__(self,address, width, depth):
|
||||
self.address = address
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
|
||||
self.storage = Storage(self.width, self.depth)
|
||||
self.sequencer = Sequencer(self.depth)
|
||||
|
||||
# Csr interface
|
||||
self._rst = RegisterField("rst", reset=1)
|
||||
self._arm = RegisterField("arm", reset=0)
|
||||
self._done = RegisterField("done", reset=0, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
|
||||
|
||||
self._size = RegisterField("size", self.depth_width, reset=1)
|
||||
self._offset = RegisterField("offset", self.depth_width, reset=1)
|
||||
|
||||
self._get = RegisterField("get", reset=1)
|
||||
self._get_dat = RegisterField("get_dat", self.width, reset=1,access_bus=READ_ONLY, access_dev=WRITE_ONLY)
|
||||
|
||||
regs = [self._rst, self._arm, self._done,
|
||||
self._size, self._offset,
|
||||
self._get, self._get_dat]
|
||||
|
||||
self.bank = csrgen.Bank(regs,address=address)
|
||||
|
||||
# Trigger Interface
|
||||
self.trig_hit = Signal()
|
||||
self.trig_dat = Signal(BV(self.width))
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
#Bank <--> Storage / Sequencer
|
||||
comb += [
|
||||
self.sequencer.ctl_rst.eq(self._rst.field.r),
|
||||
self.storage.rst.eq(self._rst.field.r),
|
||||
self.sequencer.ctl_offset.eq(self._offset.field.r),
|
||||
self.sequencer.ctl_size.eq(self._size.field.r),
|
||||
self.sequencer.ctl_arm.eq(self._arm.field.r),
|
||||
self._done.field.w.eq(self.sequencer.ctl_done)
|
||||
]
|
||||
|
||||
#Storage <--> Sequencer <--> Trigger
|
||||
comb += [
|
||||
self.storage.offset.eq(self.sequencer.rec_offset),
|
||||
self.storage.size.eq(self.sequencer.rec_size),
|
||||
self.storage.start.eq(self.sequencer.rec_start),
|
||||
self.sequencer.rec_done.eq(self.storage.done),
|
||||
self.sequencer.trig_hit.eq(self.trig_hit),
|
||||
self.storage.put.eq(self.sequencer.enable),
|
||||
self.storage.put_dat.eq(self.trig_dat)
|
||||
|
||||
]
|
||||
|
||||
return self.bank.get_fragment()+\
|
||||
self.storage.get_fragment()+self.sequencer.get_fragment()+\
|
||||
Fragment(comb=comb, sync=sync)
|
||||
|
||||
class MigCon:
|
||||
pass
|
||||
|
||||
class MigLa:
|
||||
pass
|
||||
|
||||
class MigIo:
|
||||
def __init__(self, width, mode = "IO"):
|
||||
self.width = width
|
||||
self.mode = mode
|
||||
self.ireg = description.RegisterField("i", 0, READ_ONLY, WRITE_ONLY)
|
||||
self.oreg = description.RegisterField("o", 0)
|
||||
if "I" in self.mode:
|
||||
self.inputs = Signal(BV(self.width))
|
||||
self.ireg = description.RegisterField("i", self.width, READ_ONLY, WRITE_ONLY)
|
||||
self.ireg.field.w.name_override = "inputs"
|
||||
if "O" in self.mode:
|
||||
self.outputs = Signal(BV(self.width))
|
||||
self.oreg = description.RegisterField("o", self.width)
|
||||
self.oreg.field.r.name_override = "ouptuts"
|
||||
self.bank = csrgen.Bank([self.oreg, self.ireg])
|
||||
|
||||
def get_fragment(self):
|
||||
return self.bank.get_fragment()
|
173
migScope/recorder.py
Normal file
173
migScope/recorder.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
from migen.fhdl.structure import *
|
||||
from migen.bus import csr
|
||||
from migen.bank import description, csrgen
|
||||
from migen.bank.description import *
|
||||
from migen.corelogic.misc import optree
|
||||
|
||||
class Storage:
|
||||
def __init__(self, width, depth):
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
#Control
|
||||
self.rst = Signal()
|
||||
self.start = Signal()
|
||||
self.offset = Signal(BV(self.depth_width))
|
||||
self.size = Signal(BV(self.depth_width))
|
||||
self.done = Signal()
|
||||
#Write Path
|
||||
self.put = Signal()
|
||||
self.put_dat = Signal(BV(self.width))
|
||||
self._put_cnt = Signal(BV(self.depth_width))
|
||||
self._put_ptr = Signal(BV(self.depth_width))
|
||||
self._put_port = MemoryPort(adr=self._put_ptr, we=self.put, dat_w=self.put_dat)
|
||||
#Read Path
|
||||
self.get = Signal()
|
||||
self.get_dat = Signal(BV(self.width))
|
||||
self._get_cnt = Signal(BV(self.depth_width))
|
||||
self._get_ptr = Signal(BV(self.depth_width))
|
||||
self._get_port = MemoryPort(adr=self._get_ptr, re=self.get, dat_r=self.get_dat)
|
||||
#Others
|
||||
self._mem = Memory(self.width, self.depth, self._put_port, self._get_port)
|
||||
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
memories = [self._mem]
|
||||
size_minus_offset = Signal(BV(self.depth_width))
|
||||
comb += [size_minus_offset.eq(self.size-self.offset)]
|
||||
|
||||
#Control
|
||||
sync += [
|
||||
If(self.rst,
|
||||
self._put_cnt.eq(0),
|
||||
self._put_ptr.eq(0),
|
||||
self._get_cnt.eq(0),
|
||||
self._get_ptr.eq(0),
|
||||
self.done.eq(0)
|
||||
).Elif(self.start,
|
||||
self._put_cnt.eq(0),
|
||||
self._get_cnt.eq(0),
|
||||
self._get_ptr.eq(self._put_ptr-size_minus_offset)
|
||||
),
|
||||
If(self.put,
|
||||
self._put_cnt.eq(self._put_cnt+1),
|
||||
self._put_ptr.eq(self._put_ptr+1)
|
||||
),
|
||||
If(self.get,
|
||||
self._get_cnt.eq(self._get_cnt+1),
|
||||
self._get_ptr.eq(self._get_ptr+1)
|
||||
)
|
||||
]
|
||||
comb += [
|
||||
If(self._put_cnt == size_minus_offset-1,
|
||||
self.done.eq(1)
|
||||
).Elif(self._get_cnt == size_minus_offset-1,
|
||||
self.done.eq(1)
|
||||
).Else(
|
||||
self.done.eq(0)
|
||||
)
|
||||
]
|
||||
return Fragment(comb=comb, sync=sync, memories=memories)
|
||||
|
||||
class Sequencer:
|
||||
def __init__(self,depth):
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
# Controller interface
|
||||
self.ctl_rst = Signal()
|
||||
self.ctl_offset = Signal(BV(self.depth_width))
|
||||
self.ctl_size = Signal(BV(self.depth_width))
|
||||
self.ctl_arm = Signal()
|
||||
self.ctl_done = Signal()
|
||||
# Triggers interface
|
||||
self.trig_hit = Signal()
|
||||
# Recorder interface
|
||||
self.rec_offset = Signal(BV(self.depth_width))
|
||||
self.rec_size = Signal(BV(self.depth_width))
|
||||
self.rec_start = Signal()
|
||||
self.rec_done = Signal()
|
||||
# Others
|
||||
self.enable = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
#Control
|
||||
sync += [
|
||||
If(self.ctl_rst,
|
||||
self.enable.eq(0)
|
||||
).Elif(self.ctl_arm,
|
||||
self.enable.eq(1)
|
||||
).Elif(self.rec_done,
|
||||
self.enable.eq(0)
|
||||
)
|
||||
]
|
||||
comb += [
|
||||
self.rec_offset.eq(self.ctl_offset),
|
||||
self.rec_size.eq(self.ctl_size),
|
||||
self.rec_start.eq(self.enable & self.trig_hit),
|
||||
self.ctl_done.eq(~self.enable)
|
||||
]
|
||||
return Fragment(comb=comb, sync=sync)
|
||||
|
||||
class Recorder:
|
||||
def __init__(self,address, width, depth):
|
||||
self.address = address
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.depth_width = bits_for(self.depth)
|
||||
|
||||
self.storage = Storage(self.width, self.depth)
|
||||
self.sequencer = Sequencer(self.depth)
|
||||
|
||||
# Csr interface
|
||||
self._rst = RegisterField("rst", reset=1)
|
||||
self._arm = RegisterField("arm", reset=0)
|
||||
self._done = RegisterField("done", reset=0, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
|
||||
|
||||
self._size = RegisterField("size", self.depth_width, reset=1)
|
||||
self._offset = RegisterField("offset", self.depth_width, reset=1)
|
||||
|
||||
self._get = RegisterField("get", reset=1)
|
||||
self._get_dat = RegisterField("get_dat", self.width, reset=1,access_bus=READ_ONLY, access_dev=WRITE_ONLY)
|
||||
|
||||
regs = [self._rst, self._arm, self._done,
|
||||
self._size, self._offset,
|
||||
self._get, self._get_dat]
|
||||
|
||||
self.bank = csrgen.Bank(regs,address=address)
|
||||
|
||||
# Trigger Interface
|
||||
self.trig_hit = Signal()
|
||||
self.trig_dat = Signal(BV(self.width))
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
#Bank <--> Storage / Sequencer
|
||||
comb += [
|
||||
self.sequencer.ctl_rst.eq(self._rst.field.r),
|
||||
self.storage.rst.eq(self._rst.field.r),
|
||||
self.sequencer.ctl_offset.eq(self._offset.field.r),
|
||||
self.sequencer.ctl_size.eq(self._size.field.r),
|
||||
self.sequencer.ctl_arm.eq(self._arm.field.r),
|
||||
self._done.field.w.eq(self.sequencer.ctl_done)
|
||||
]
|
||||
|
||||
#Storage <--> Sequencer <--> Trigger
|
||||
comb += [
|
||||
self.storage.offset.eq(self.sequencer.rec_offset),
|
||||
self.storage.size.eq(self.sequencer.rec_size),
|
||||
self.storage.start.eq(self.sequencer.rec_start),
|
||||
self.sequencer.rec_done.eq(self.storage.done),
|
||||
self.sequencer.trig_hit.eq(self.trig_hit),
|
||||
self.storage.put.eq(self.sequencer.enable),
|
||||
self.storage.put_dat.eq(self.trig_dat)
|
||||
|
||||
]
|
||||
|
||||
return self.bank.get_fragment()+\
|
||||
self.storage.get_fragment()+self.sequencer.get_fragment()+\
|
||||
Fragment(comb=comb, sync=sync)
|
245
migScope/trigger.py
Normal file
245
migScope/trigger.py
Normal file
|
@ -0,0 +1,245 @@
|
|||
from migen.fhdl.structure import *
|
||||
from migen.bus import csr
|
||||
from migen.bank import description, csrgen
|
||||
from migen.bank.description import *
|
||||
from migen.corelogic.misc import optree
|
||||
|
||||
class Term:
|
||||
def __init__(self, width, pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.t = Signal(BV(self.width))
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
frag = [
|
||||
self.o.eq(self.i==self.t)
|
||||
]
|
||||
if self.pipe:
|
||||
return Fragment(sync=frag)
|
||||
else:
|
||||
return Fragment(comb=frag)
|
||||
|
||||
class RangeDetector:
|
||||
def __init__(self, width, pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.low = Signal(BV(self.width))
|
||||
self.high = Signal(BV(self.width))
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
frag = [
|
||||
self.o.eq((self.i >= self.low) & ((self.i <= self.high)))
|
||||
]
|
||||
if self.pipe:
|
||||
return Fragment(sync=frag)
|
||||
else:
|
||||
return Fragment(comb=frag)
|
||||
|
||||
class EdgeDetector:
|
||||
def __init__(self, width, pipe=False, mode = "RFB"):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
self.mode = mode
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self.i_d = Signal(BV(self.width))
|
||||
if "R" in mode:
|
||||
self.r_mask = Signal(BV(self.width))
|
||||
self.ro = Signal()
|
||||
if "F" in mode:
|
||||
self.f_mask = Signal(BV(self.width))
|
||||
self.fo = Signal()
|
||||
if "B" in mode:
|
||||
self.b_mask = Signal(BV(self.width))
|
||||
self.bo = Signal()
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
sync += [self.i_d.eq(self.i)]
|
||||
# Rising Edge
|
||||
if "R" in self.mode:
|
||||
r_eq = [self.ro.eq(self.r_mask & self.i & (~self.i_d))]
|
||||
if self.pipe:
|
||||
sync += r_eq
|
||||
else:
|
||||
comb += r_eq
|
||||
else:
|
||||
comb += [self.ro.eq(0)]
|
||||
# Falling Edge
|
||||
if "F" in self.mode:
|
||||
f_eq = [self.fo.eq(self.f_mask & (~ self.i) & self.i_d)]
|
||||
if self.pipe:
|
||||
sync += f_eq
|
||||
else:
|
||||
comb += f_eq
|
||||
else:
|
||||
comb += [self.fo.eq(0)]
|
||||
# Both
|
||||
if "B" in self.mode:
|
||||
b_eq = [self.bo.eq(self.b_mask & self.i != self.i_d)]
|
||||
if self.pipe:
|
||||
sync += b_eq
|
||||
else:
|
||||
comb += b_eq
|
||||
else:
|
||||
comb += [self.bo.eq(0)]
|
||||
#Output
|
||||
comb += [self.o.eq(self.ro | self.fo | self.bo)]
|
||||
|
||||
return Fragment(comb, sync)
|
||||
|
||||
class Timer:
|
||||
def __init__(self, width):
|
||||
self.width = width
|
||||
|
||||
self.start = Signal()
|
||||
self.stop = Signal()
|
||||
self.clear = Signal()
|
||||
|
||||
self.enable = Signal()
|
||||
self.cnt = Signal(BV(self.width))
|
||||
self.cnt_max = Signal(BV(self.width))
|
||||
|
||||
self.o = Signal()
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
sync += [
|
||||
If(self.stop,
|
||||
self.enable.eq(0),
|
||||
self.cnt.eq(0),
|
||||
self.o.eq(0)
|
||||
).Elif(self.clear,
|
||||
self.cnt.eq(0),
|
||||
self.o.eq(0)
|
||||
).Elif(self.start,
|
||||
self.enable.eq(1)
|
||||
).Elif(self.enable,
|
||||
If(self.cnt <= self.cnt_max,
|
||||
self.cnt.eq(self.cnt+1)
|
||||
).Else(
|
||||
self.o.eq(1)
|
||||
)
|
||||
),
|
||||
If(self.enable,
|
||||
self.enable.eq(0),
|
||||
self.cnt.eq(0)
|
||||
).Elif(self.clear,
|
||||
self.cnt.eq(0)
|
||||
).Elif(self.start,
|
||||
self.enable.eq(1)
|
||||
)
|
||||
|
||||
]
|
||||
|
||||
return Fragment(comb, sync)
|
||||
|
||||
class Sum:
|
||||
def __init__(self,width=4,pipe=False):
|
||||
self.width = width
|
||||
self.pipe = pipe
|
||||
|
||||
self.i = Signal(BV(self.width))
|
||||
self._o = Signal()
|
||||
self.o = Signal()
|
||||
self._lut_port = MemoryPort(adr=self.i, dat_r=self._o)
|
||||
|
||||
self.prog = Signal()
|
||||
self.prog_adr = Signal(BV(width))
|
||||
self.prog_dat = Signal()
|
||||
self._prog_port = MemoryPort(adr=self.prog_adr, we=self.prog, dat_w=self.prog_dat)
|
||||
|
||||
self._mem = Memory(1, 2**self.width, self._lut_port, self._prog_port)
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
memories = [self._mem]
|
||||
if self.pipe:
|
||||
sync += [self.o.eq(self._o)]
|
||||
else:
|
||||
comb += [self.o.eq(self._o)]
|
||||
return Fragment(comb=comb,sync=sync,memories=memories)
|
||||
|
||||
|
||||
class Trigger:
|
||||
def __init__(self,address, trig_width, dat_width, ports):
|
||||
self.address = address
|
||||
self.trig_width = trig_width
|
||||
self.dat_width = dat_width
|
||||
self.ports = ports
|
||||
assert (len(self.ports) <= 4), "Nb Ports > 4 (This version support 4 ports Max)"
|
||||
self._sum = Sum(len(self.ports))
|
||||
|
||||
self.in_trig = Signal(BV(self.trig_width))
|
||||
self.in_dat = Signal(BV(self.dat_width))
|
||||
|
||||
self.hit = Signal()
|
||||
self.dat = Signal(BV(self.dat_width))
|
||||
|
||||
# Csr interface
|
||||
for i in range(len(self.ports)):
|
||||
if isinstance(self.ports[i],Term):
|
||||
setattr(self,"_term_reg%d"%i,RegisterField("rst", 1*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
elif isinstance(self.ports[i],EdgeDetector):
|
||||
setattr(self,"_edge_reg%d"%i,RegisterField("rst", 3*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
elif isinstance(self.ports[i],RangeDetector):
|
||||
setattr(self,"_range_reg%d"%i,RegisterField("rst", 2*self.trig_width, reset=0,
|
||||
access_bus=WRITE_ONLY, access_dev=READ_ONLY))
|
||||
self._sum_reg = RegisterField("_sum_reg", 32, reset=0,access_bus=WRITE_ONLY, access_dev=READ_ONLY)
|
||||
|
||||
regs = []
|
||||
objects = self.__dict__
|
||||
for object in sorted(objects):
|
||||
if "_reg" in object:
|
||||
regs.append(objects[object])
|
||||
self.bank = csrgen.Bank(regs,address=address)
|
||||
|
||||
def get_fragment(self):
|
||||
comb = []
|
||||
sync = []
|
||||
# Connect in_trig to input of trig elements
|
||||
comb+= [port.i.eq(self.in_trig) for port in self.ports]
|
||||
|
||||
# Connect output of trig elements to sum
|
||||
comb+= [self._sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))]
|
||||
|
||||
# Connect sum ouput to hit
|
||||
comb+= [self.hit.eq(self._sum.o)]
|
||||
|
||||
# Add ports & sum to frag
|
||||
frag = self.bank.get_fragment()
|
||||
frag += self._sum.get_fragment()
|
||||
for port in self.ports:
|
||||
frag += port.get_fragment()
|
||||
comb+= [self.dat.eq(self.in_dat)]
|
||||
|
||||
#Connect Registers
|
||||
for i in range(len(self.ports)):
|
||||
if isinstance(self.ports[i],Term):
|
||||
comb += [self.ports[i].t.eq(getattr(self,"_term_reg%d"%i).field.r[0:self.trig_width])]
|
||||
elif isinstance(self.ports[i],EdgeDetector):
|
||||
comb += [self.ports[i].r_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[0:1*self.trig_width])]
|
||||
comb += [self.ports[i].f_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[1*self.trig_width:2*self.trig_width])]
|
||||
comb += [self.ports[i].b_mask.eq(getattr(self,"_edge_reg%d"%i).field.r[2*self.trig_width:3*self.trig_width])]
|
||||
elif isinstance(self.ports[i],RangeDetector):
|
||||
comb += [self.ports[i].low.eq(getattr(self,"_range_reg%d"%i).field.r[0:1*self.trig_width])]
|
||||
comb += [self.ports[i].high.eq(getattr(self,"_range_reg%d"%i).field.r[1*self.trig_width:2*self.trig_width])]
|
||||
|
||||
comb += [
|
||||
self._sum.prog_adr.eq(self._sum_reg.field.r[0:16]),
|
||||
self._sum.prog_dat.eq(self._sum_reg.field.r[16]),
|
||||
self._sum.prog.eq(self._sum_reg.field.r[17])
|
||||
]
|
||||
return frag + Fragment(comb=comb, sync=sync)
|
|
@ -7,7 +7,8 @@ from migen.bus.transactions import *
|
|||
|
||||
import sys
|
||||
sys.path.append("../")
|
||||
import migScope
|
||||
|
||||
from migScope import trigger
|
||||
|
||||
from migScope.tools.truthtable import *
|
||||
|
||||
|
@ -67,11 +68,11 @@ def main():
|
|||
csr_master0 = csr.Initiator(csr_transactions())
|
||||
|
||||
# Trigger
|
||||
term0 = migScope.Term(32)
|
||||
term1 = migScope.Term(32)
|
||||
term2 = migScope.Term(32)
|
||||
term3 = migScope.Term(32)
|
||||
trigger0 = migScope.Trigger(0, 32, 64, [term0, term1, term2, term3])
|
||||
term0 = trigger.Term(32)
|
||||
term1 = trigger.Term(32)
|
||||
term2 = trigger.Term(32)
|
||||
term3 = trigger.Term(32)
|
||||
trigger0 = trigger.Trigger(0, 32, 64, [term0, term1, term2, term3])
|
||||
|
||||
# Csr Interconnect
|
||||
csrcon0 = csr.Interconnect(csr_master0.bus,
|
||||
|
|
39
top.py
39
top.py
|
@ -5,7 +5,9 @@ from migen.fhdl.structure import *
|
|||
from migen.fhdl import verilog, autofragment
|
||||
from migen.bus import csr
|
||||
|
||||
import migScope
|
||||
from migScope import trigger
|
||||
from migScope import recorder
|
||||
|
||||
import spi2Csr
|
||||
|
||||
from migScope.tools.truthtable import *
|
||||
|
@ -13,76 +15,69 @@ from migScope.tools.truthtable import *
|
|||
#
|
||||
#Test Term
|
||||
#
|
||||
#term = migScope.Term(32,True)
|
||||
#term = trigger.Term(32,True)
|
||||
#v = verilog.convert(term.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test RangeDetector
|
||||
#
|
||||
#rangeDetector = migScope.RangeDetector (32,True)
|
||||
#rangeDetector = trigger.RangeDetector (32,True)
|
||||
#v = verilog.convert(rangeDetector.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test EdgeDetector
|
||||
#
|
||||
#edgeDetector = migScope.EdgeDetector (32,True,"RFB")
|
||||
#edgeDetector = trigger.EdgeDetector (32,True,"RFB")
|
||||
#v = verilog.convert(edgeDetector.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Timer
|
||||
#
|
||||
#timer = migScope.Timer(32)
|
||||
#timer = trigger.Timer(32)
|
||||
#v = verilog.convert(timer.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Sum
|
||||
#
|
||||
#sum = migScope.Sum(4,pipe=False)
|
||||
#sum = trigger.Sum(4,pipe=False)
|
||||
#v = verilog.convert(sum.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test MigIo
|
||||
#
|
||||
#migIo = migScope.MigIo(32,"IO")
|
||||
#v = verilog.convert(migIo.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Storage
|
||||
#
|
||||
#storage = migScope.Storage(32,1024)
|
||||
#storage = recorder.Storage(32,1024)
|
||||
#v = verilog.convert(storage.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Sequencer
|
||||
#
|
||||
#sequencer = migScope.Sequencer(1024)
|
||||
#sequencer = recorder.Sequencer(1024)
|
||||
#v = verilog.convert(sequencer.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Recorder
|
||||
#
|
||||
#recorder = migScope.Recorder(0,32,1024)
|
||||
#recorder = recorder.Recorder(0,32,1024)
|
||||
#v = verilog.convert(recorder.get_fragment())
|
||||
#print(v)
|
||||
|
||||
#
|
||||
#Test Trigger
|
||||
#
|
||||
term0 = migScope.Term(32)
|
||||
term1 = migScope.RangeDetector(32)
|
||||
term2 = migScope.EdgeDetector(32)
|
||||
term3 = migScope.Term(32)
|
||||
term0 = trigger.Term(32)
|
||||
term1 = trigger.RangeDetector(32)
|
||||
term2 = trigger.EdgeDetector(32)
|
||||
term3 = trigger.Term(32)
|
||||
|
||||
trigger0 = migScope.Trigger(0,32,64,[term0, term1, term2, term3])
|
||||
recorder0 = migScope.Recorder(0,32,1024)
|
||||
trigger0 = trigger.Trigger(0,32,64,[term0, term1, term2, term3])
|
||||
recorder0 = recorder.Recorder(0,32,1024)
|
||||
v = verilog.convert(trigger0.get_fragment()+recorder0.get_fragment())
|
||||
print(v)
|
||||
|
||||
|
|
Loading…
Reference in a new issue