|
| 1 | +from amaranth import Module, unsigned |
| 2 | +from amaranth.lib import wiring |
| 3 | +from amaranth.lib.wiring import In, Out, flipped, connect |
| 4 | + |
| 5 | +from amaranth_soc import csr, gpio |
| 6 | + |
| 7 | +from chipflow_lib.platforms import BidirPinSignature, PinSignature |
| 8 | + |
| 9 | +__all__ = ["GPIOPeripheral"] |
| 10 | + |
| 11 | + |
| 12 | +class GPIOPeripheral(wiring.Component): |
| 13 | + |
| 14 | + class Signature(wiring.Signature): |
| 15 | + def __init__(self, pin_count=1): |
| 16 | + if pin_count > 32: |
| 17 | + raise ValueError(f"Pin pin_count must be lesser than or equal to 32, not {pin_count}") |
| 18 | + self._pin_count = pin_count |
| 19 | + super().__init__({ |
| 20 | + "gpio": Out(BidirPinSignature(pin_count, all_have_oe=True)) |
| 21 | + }) |
| 22 | + |
| 23 | + @property |
| 24 | + def pin_count(self): |
| 25 | + return self._pin_count |
| 26 | + |
| 27 | + """Wrapper for amaranth_soc gpio with chipflow_lib.PinSignature support |
| 28 | +
|
| 29 | + Parameters |
| 30 | + ---------- |
| 31 | + pin_count : :class:`int` |
| 32 | + Number of GPIO pins. |
| 33 | + addr_width : :class:`int` |
| 34 | + CSR bus address width. Defaults to ``4``. |
| 35 | + data_width : :class:`int` |
| 36 | + CSR bus data width. Defaults to ``8``. |
| 37 | + input_stages : :class:`int` |
| 38 | + Number of synchronization stages between pin inputs and the :class:`~Peripheral.Input` |
| 39 | + register. Optional. Defaults to ``2``. |
| 40 | +
|
| 41 | + Attributes |
| 42 | + ---------- |
| 43 | + bus : :class:`csr.Interface` |
| 44 | + CSR bus interface providing access to registers. |
| 45 | + pins : :class:`list` of :class:`wiring.PureInterface` of :class:`PinSignature` |
| 46 | + GPIO pin interfaces. |
| 47 | + alt_mode : :class:`Signal` |
| 48 | + Indicates which members of the :attr:`Peripheral.pins` array are in alternate mode. |
| 49 | +
|
| 50 | + Raises |
| 51 | + ------ |
| 52 | + :exc:`TypeError` |
| 53 | + If ``pin_count`` is not a positive integer. |
| 54 | + :exc:`TypeError` |
| 55 | + If ``input_stages`` is not a non-negative integer. |
| 56 | + """ |
| 57 | + |
| 58 | + def __init__(self, *, pin_count, addr_width=4, data_width=8, input_stages=2): |
| 59 | + self._gpio = gpio.Peripheral(pin_count=pin_count, |
| 60 | + addr_width=addr_width, |
| 61 | + data_width=data_width, |
| 62 | + input_stages=input_stages) |
| 63 | + |
| 64 | + super().__init__({ |
| 65 | + "bus": In(csr.Signature(addr_width=addr_width, data_width=data_width)), |
| 66 | + "pins": Out(self.Signature(pin_count)), |
| 67 | + "alt_mode": Out(unsigned(pin_count)), |
| 68 | + }) |
| 69 | + self.bus.memory_map = self._gpio.bus.memory_map |
| 70 | + |
| 71 | + def elaborate(self, platform): |
| 72 | + m = Module() |
| 73 | + m.submodules._gpio = gpio = self._gpio |
| 74 | + |
| 75 | + connect(m, flipped(self.bus), self._gpio.bus) |
| 76 | + for i in range(self._gpio.pin_count): |
| 77 | + # m.d.comb += self.pins.gpio.i[i].eq(self._gpio.pins[i].i) |
| 78 | + # m.d.comb += self._gpio.pins[i].o.eq(self.pins.gpio.o[i]) |
| 79 | + # m.d.comb += self._gpio.pins[i].oe.eq(self.pins.gpio.oe[i]) |
| 80 | + m.d.comb += self._gpio.pins[i].i.eq(self.pins.gpio.i[i]) |
| 81 | + m.d.comb += self.pins.gpio.o[i].eq(self._gpio.pins[i].o) |
| 82 | + m.d.comb += self.pins.gpio.oe[i].eq(self._gpio.pins[i].oe) |
| 83 | + |
| 84 | + return m |
| 85 | + |
| 86 | + @property |
| 87 | + def pin_count(self): |
| 88 | + return self._gpio.pin_count |
| 89 | + |
| 90 | + @property |
| 91 | + def input_stages(self): |
| 92 | + return self._gpio.input_stages |
0 commit comments