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: # # Definition # 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() self.run = Signal() #Write Path self.put = Signal() self.put_dat = Signal(BV(self.width)) self._put_ptr = Signal(BV(self.depth_width)) self._put_ptr_stop = 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_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.run.eq(0), self._put_ptr.eq(0) ).Elif(self.start & ~self.run, self.run.eq(1), self._put_ptr_stop.eq(self._put_ptr + self.size - self.offset) ).Elif(self.done, self.run.eq(0) ), If(self.put & ~self.done, self._put_ptr.eq(self._put_ptr+1) ), If(self.rst, self.done.eq(0) ).Elif((self._put_ptr == self._put_ptr_stop) & self.run, self.done.eq(1) ), If(self.rst, self._get_ptr.eq(0) ).Elif(self.start & ~self.run, self._get_ptr.eq(self._put_ptr-self.offset-1) ).Elif(self.get, self._get_ptr.eq(self._get_ptr+1) ) ] return Fragment(comb=comb, sync=sync, memories=memories) class Sequencer: # # Definition # 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() self._ctl_arm_d = Signal() # Triggers interface self.trig_hit = Signal() self._trig_hit_d = 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._ctl_arm_d, self.enable.eq(1) ).Elif(self.rec_done, self.enable.eq(0) ), self._ctl_arm_d.eq(self.ctl_arm) ] sync += [self._trig_hit_d.eq(self.trig_hit)] 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._trig_hit_d)), self.ctl_done.eq(~self.enable) ] return Fragment(comb=comb, sync=sync) class Recorder: # # Definition # def __init__(self, width, depth, address = 0x0000, interface = None): self.address = address self.width = width self.depth = depth self.depth_width = bits_for(self.depth) self.interface = interface 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=0) self._get_dat = RegisterField("get_dat", self.width, reset=1, access_bus=READ_ONLY, access_dev=WRITE_ONLY) self.regs = [self._rst, self._arm, self._done, self._size, self._offset, self._get, self._get_dat] self.bank = csrgen.Bank(self.regs,address=self.address) # Trigger Interface self.trig_hit = Signal() self.trig_dat = Signal(BV(self.width)) def set_address(self, address): self.address = address self.bank = csrgen.Bank(self.regs,address=self.address) def set_interface(self, interface): self.interface = interface def get_fragment(self): comb = [] sync = [] _get_d = Signal() _get_rising = Signal() sync += [ _get_d.eq(self._get.field.r), _get_rising.eq(self._get.field.r & ~_get_d) ] #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), self.storage.get.eq(_get_rising), self._get_dat.field.w.eq(self.storage.get_dat) ] #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) # #Driver # def reset(self): self.interface.write(self.address + 0x00, 1) self.interface.write(self.address + 0x00, 0) def arm(self): self.interface.write(self.address + 0x01, 1) self.interface.write(self.address + 0x01, 0) def is_done(self): return self.interface.read(self.address + 0x02) == 1 def size(self, dat): self.size = dat self.interface.write_n(self.address + 0x03, dat, 16) def offset(self, dat): self.interface.write_n(self.address + 0x05, dat, 16) def read(self, size): r = [] for i in range(size): self.interface.write(self.address+7, 1) self.interface.write(self.address+7, 0) r.append(self.interface.read_n(self.address+8,self.width)) return r