soc/cores/gpio: Simplify GPIOIn IRQ, make polarity configurable and also add optional IRQ to GPIOTristate.

Ex of instance:
from litex.soc.cores import gpio
gpio_in_pads = Signal(16)
self.submodules.gpio_in = gpio.GPIOIn(gpio_in_pads, with_irq=True)
self.add_csr("gpio_in")
This commit is contained in:
Florent Kermarrec 2021-03-09 13:57:48 +01:00
parent 0d8b6f8fbb
commit 0e7d8219ea
1 changed files with 20 additions and 25 deletions

View File

@ -17,36 +17,28 @@ from litex.soc.interconnect.csr_eventmanager import *
def _to_signal(obj): def _to_signal(obj):
return obj.raw_bits() if isinstance(obj, Record) else obj return obj.raw_bits() if isinstance(obj, Record) else obj
class _GPIOIRQ(Module, AutoCSR):
def __init__(self, in_pads):
self._polarity = CSRStorage(len(in_pads), description="GPIO IRQ Polarity: 0: Rising Edge, 1: Falling Edge.")
# # #
self.submodules.ev = EventManager()
for n in range(len(in_pads)):
esp = EventSourceProcess(name=f"i{n}", edge="rising")
self.comb += esp.trigger.eq(in_pads[n] ^ self._polarity.storage[n])
setattr(self.ev, f"i{n}", esp)
# GPIO Input --------------------------------------------------------------------------------------- # GPIO Input ---------------------------------------------------------------------------------------
class GPIOIn(Module, AutoCSR): class GPIOIn(Module, AutoCSR):
"""GPIO Input def __init__(self, pads, with_irq=False):
Provides a GPIO Input peripheral. An optional IRQ dict can be passed to add rising or falling
interrupts to pads.
Ex: pads=Signal(8), irqs={} : 8-bit Input, No IRQ.
pads=Signal(8), irqs={0: "rise", 7: "fall"}: 8-bit Input, rising IRQ on 0, falling IRQ on 1.
"""
def __init__(self, pads, irqs={}):
pads = _to_signal(pads) pads = _to_signal(pads)
# Inputs
self._in = CSRStatus(len(pads), description="GPIO Input(s) Status.") self._in = CSRStatus(len(pads), description="GPIO Input(s) Status.")
self.specials += MultiReg(pads, self._in.status) self.specials += MultiReg(pads, self._in.status)
if with_irq:
# IRQs self.submodules.irq = _GPIOIRQ(self._in.status)
if len(irqs):
self.submodules.ev = EventManager()
for n, irq_type in irqs.items():
assert irq_type in ["fall", "falling", "rise", "rising"]
assert len(pads) > n
name = f"i{n}"
if irq_type in ["rise", "rising"]:
setattr(self.ev, f"i{n}", EventSourcePulse())
if irq_type in ["fall", "falling"]:
setattr(self.ev, f"i{n}", EventSourceProcess())
self.comb += getattr(self.ev, f"i{n}").trigger.eq(pads[n])
# GPIO Output -------------------------------------------------------------------------------------- # GPIO Output --------------------------------------------------------------------------------------
@ -69,7 +61,7 @@ class GPIOInOut(Module):
# GPIO Tristate ------------------------------------------------------------------------------------ # GPIO Tristate ------------------------------------------------------------------------------------
class GPIOTristate(Module, AutoCSR): class GPIOTristate(Module, AutoCSR):
def __init__(self, pads): def __init__(self, pads, with_irq=False):
assert isinstance(pads, Signal) assert isinstance(pads, Signal)
nbits = len(pads) nbits = len(pads)
self._oe = CSRStorage(nbits, description="GPIO Tristate(s) Control.") self._oe = CSRStorage(nbits, description="GPIO Tristate(s) Control.")
@ -84,3 +76,6 @@ class GPIOTristate(Module, AutoCSR):
self.comb += t.oe.eq(self._oe.storage[i]) self.comb += t.oe.eq(self._oe.storage[i])
self.comb += t.o.eq(self._out.storage[i]) self.comb += t.o.eq(self._out.storage[i])
self.specials += MultiReg(t.i, self._in.status[i]) self.specials += MultiReg(t.i, self._in.status[i])
if with_irq:
self.submodules.irq = _GPIOIRQ(self._in.status)