from migen.fhdl.structure import * from migen.bank.description import * from migen.corelogic.misc import optree class EventSource: def __init__(self): self.trigger = Signal() class EventSourcePulse(EventSource): pass class EventSourceLevel(EventSource): pass class EventManager: def __init__(self, *sources): self.sources = sources self.irq = Signal() n = len(self.sources) self.status = RegisterRaw("status", n) self.pending = RegisterRaw("pending", n) self.enable = RegisterFields("enable", [Field("s" + str(i), access_bus=READ_WRITE, access_dev=READ_ONLY) for i in range(n)]) def get_registers(self): return [self.status, self.pending, self.enable] def get_fragment(self): comb = [] sync = [] # status for i, source in enumerate(self.sources): if isinstance(source, EventSourcePulse): comb.append(self.status.w[i].eq(0)) elif isinstance(source, EventSourceLevel): comb.append(self.status.w[i].eq(source.trigger)) else: raise TypeError # pending for i, source in enumerate(self.sources): pending = Signal() # W1C sync.append(If(self.pending.re & self.pending.r[i], pending.eq(0))) if isinstance(source, EventSourcePulse): # set on a positive trigger pulse sync.append(If(source.trigger, pending.eq(1))) elif isinstance(source, EventSourceLevel): # set on the falling edge of the trigger old_trigger = Signal() sync += [ old_trigger.eq(source.trigger), If(~source.trigger & old_trigger, pending.eq(1)) ] else: raise TypeError comb.append(self.pending.w[i].eq(pending)) # IRQ irqs = [self.pending.w[i] & field.r for i, field in enumerate(self.enable.fields)] comb.append(self.irq.eq(optree("|", irqs))) return Fragment(comb, sync)