Skip to content

Commit e8af949

Browse files
committed
wip (gpio)
1 parent 7f324ab commit e8af949

File tree

6 files changed

+157
-115
lines changed

6 files changed

+157
-115
lines changed

amaranth_soc/csr/reg.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -482,14 +482,14 @@ class Register(wiring.Component):
482482
_doc_template = """
483483
A CSR register.
484484
485-
Parameters
486-
----------
485+
Arguments
486+
---------
487487
fields : :class:`dict` or :class:`list` or :class:`Field`
488488
Collection of register fields. If ``None`` (default), a dict is populated from Python
489489
:term:`variable annotations <python:variable annotations>`. ``fields`` is used to create
490490
a :class:`FieldActionMap`, :class:`FieldActionArray`, or :class:`FieldAction`,
491491
depending on its type (:class:`dict`, :class:`list`, or :class:`Field`).
492-
{parameters}
492+
{arguments}
493493
494494
Attributes
495495
----------
@@ -515,7 +515,7 @@ class Register(wiring.Component):
515515
If ``element.access`` is not writable and at least one field is writable.
516516
"""
517517

518-
__doc__ = _doc_template.format(parameters="""
518+
__doc__ = _doc_template.format(arguments="""
519519
access : :class:`Element.Access`
520520
Element access mode.
521521
""")
@@ -529,7 +529,6 @@ def __init_subclass__(cls, *, access=None, **kwargs):
529529
cls._access = Element.Access(access)
530530
except ValueError as e:
531531
raise ValueError(f"{access!r} is not a valid Element.Access") from e
532-
cls.__doc__ = cls._doc_template.format(parameters="")
533532
super().__init_subclass__(**kwargs)
534533

535534
def __init__(self, fields=None, access=None):
@@ -893,7 +892,7 @@ class Bridge(wiring.Component):
893892
894893
Attributes
895894
----------
896-
bus : :class:`.Interface`
895+
bus : :class:`..bus.Interface`
897896
CSR bus providing access to the contents of ``memory_map``.
898897
899898
Raises

amaranth_soc/gpio.py

+135-109
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ class PinMode(enum.Enum, shape=unsigned(2)):
4343
class PinSignature(wiring.Signature):
4444
"""GPIO pin signature.
4545
46-
Interface attributes
47-
--------------------
48-
i : :class:`Signal`
46+
Attributes
47+
----------
48+
i : :pc:`unsigned(1)`
4949
Input.
50-
o : :class:`Signal`
50+
o : :pc:`unsigned(1)`
5151
Output.
52-
oe : :class:`Signal`
52+
oe : :pc:`unsigned(1)`
5353
Output enable.
5454
"""
5555
def __init__(self):
@@ -61,30 +61,70 @@ def __init__(self):
6161

6262

6363
class Peripheral(wiring.Component):
64+
"""GPIO peripheral.
65+
66+
Arguments
67+
---------
68+
pin_count : :class:`int`
69+
Number of GPIO pins.
70+
addr_width : :class:`int`
71+
CSR bus address width.
72+
data_width : :class:`int`
73+
CSR bus data width.
74+
name : :class:`str`
75+
CSR bus window name. Optional.
76+
input_stages : :class:`int`
77+
Number of synchronization stages between pin inputs and the :class:`~Peripheral.Input`
78+
register. Optional. Defaults to ``2``.
79+
80+
Attributes
81+
----------
82+
bus : :class:`.csr.bus.Interface`
83+
CSR bus interface providing access to registers.
84+
pins : :class:`list` of :class:`wiring.PureInterface` of :class:`PinSignature`
85+
GPIO pin interfaces.
86+
alt_mode : :pc:`unsigned(pin_count)`
87+
Indicates which members of the :attr:`Peripheral.pins` array are in alternate mode.
88+
89+
Raises
90+
------
91+
:exc:`TypeError`
92+
If ``pin_count`` is not a positive integer.
93+
:exc:`TypeError`
94+
If ``input_stages`` is not a non-negative integer.
95+
"""
96+
6497
class Mode(csr.Register, access="rw"):
65-
"""Mode register.
98+
__doc__ = """Mode register.
6699
67-
This :class:`csr.Register` contains an array of ``pin_count`` read/write fields. Each field
68-
is 2-bit wide and its possible values are defined by the :class:`PinMode` enumeration.
100+
This :class:`~.csr.reg.Register` contains an array of ``pin_count`` read/write fields.
101+
Each field is 2-bit wide and its possible values are defined by the :class:`PinMode`
102+
enumeration.
69103
70-
If ``pin_count`` is 8, then the register has the following fields:
104+
----
71105
72-
.. bitfield::
73-
:bits: 16
106+
If ``pin_count`` is 8, then the :class:`~.csr.reg.Register` has the following fields:
74107
75-
[
76-
{ "name": "pin[0]", "bits": 2, "attr": "RW" },
77-
{ "name": "pin[1]", "bits": 2, "attr": "RW" },
78-
{ "name": "pin[2]", "bits": 2, "attr": "RW" },
79-
{ "name": "pin[3]", "bits": 2, "attr": "RW" },
80-
{ "name": "pin[4]", "bits": 2, "attr": "RW" },
81-
{ "name": "pin[5]", "bits": 2, "attr": "RW" },
82-
{ "name": "pin[6]", "bits": 2, "attr": "RW" },
83-
{ "name": "pin[7]", "bits": 2, "attr": "RW" },
84-
]
108+
.. wavedrom:: gpio_mode
85109
86-
Parameters
87-
----------
110+
{
111+
"reg": [
112+
{ "name": "pin[0]", "bits": 2, "attr": "RW" },
113+
{ "name": "pin[1]", "bits": 2, "attr": "RW" },
114+
{ "name": "pin[2]", "bits": 2, "attr": "RW" },
115+
{ "name": "pin[3]", "bits": 2, "attr": "RW" },
116+
{ "name": "pin[4]", "bits": 2, "attr": "RW" },
117+
{ "name": "pin[5]", "bits": 2, "attr": "RW" },
118+
{ "name": "pin[6]", "bits": 2, "attr": "RW" },
119+
{ "name": "pin[7]", "bits": 2, "attr": "RW" }
120+
],
121+
"config": {"bits": 16}
122+
}
123+
124+
----
125+
126+
Arguments
127+
---------
88128
pin_count : :class:`int`
89129
Number of GPIO pins.
90130
"""
@@ -96,31 +136,37 @@ def __init__(self, pin_count):
96136
class Input(csr.Register, access="r"):
97137
"""Input register.
98138
99-
This :class:`csr.Register` contains an array of ``pin_count`` read-only fields. Each field
100-
is 1-bit wide and driven by the input of its associated pin in the :attr:`Peripheral.pins`
101-
array.
139+
This :class:`~.csr.reg.Register` contains an array of ``pin_count`` read-only fields. Each
140+
field is 1-bit wide and driven by the input of its associated pin in the
141+
:attr:`Peripheral.pins` array.
102142
103143
Values sampled from pin inputs go through :attr:`Peripheral.input_stages` synchronization
104144
stages (on a rising edge of ``ClockSignal("sync")``) before reaching the register.
105145
106-
If ``pin_count`` is 8, then the register has the following fields:
146+
----
107147
108-
.. bitfield::
109-
:bits: 8
148+
If ``pin_count`` is 8, then the :class:`~.csr.reg.Register` has the following fields:
110149
111-
[
112-
{ "name": "pin[0]", "bits": 1, "attr": "R" },
113-
{ "name": "pin[1]", "bits": 1, "attr": "R" },
114-
{ "name": "pin[2]", "bits": 1, "attr": "R" },
115-
{ "name": "pin[3]", "bits": 1, "attr": "R" },
116-
{ "name": "pin[4]", "bits": 1, "attr": "R" },
117-
{ "name": "pin[5]", "bits": 1, "attr": "R" },
118-
{ "name": "pin[6]", "bits": 1, "attr": "R" },
119-
{ "name": "pin[7]", "bits": 1, "attr": "R" },
120-
]
150+
.. wavedrom:: gpio_input
151+
152+
{
153+
"reg": [
154+
{ "name": "pin[0]", "bits": 1, "attr": "R" },
155+
{ "name": "pin[1]", "bits": 1, "attr": "R" },
156+
{ "name": "pin[2]", "bits": 1, "attr": "R" },
157+
{ "name": "pin[3]", "bits": 1, "attr": "R" },
158+
{ "name": "pin[4]", "bits": 1, "attr": "R" },
159+
{ "name": "pin[5]", "bits": 1, "attr": "R" },
160+
{ "name": "pin[6]", "bits": 1, "attr": "R" },
161+
{ "name": "pin[7]", "bits": 1, "attr": "R" }
162+
],
163+
"config": {"bits": 8}
164+
}
121165
122-
Parameters
123-
----------
166+
----
167+
168+
Arguments
169+
---------
124170
pin_count : :class:`int`
125171
Number of GPIO pins.
126172
"""
@@ -132,28 +178,34 @@ def __init__(self, pin_count):
132178
class Output(csr.Register, access="rw"):
133179
"""Output register.
134180
135-
This :class:`csr.Register` contains an array of ``pin_count`` read/write fields. Each field
136-
is 1-bit wide and drives the output of its associated pin in the :attr:`Peripheral.pins`
137-
array, depending on its associated :class:`~Peripheral.Mode` field.
181+
This :class:`~.csr.reg.Register` contains an array of ``pin_count`` read/write fields. Each
182+
field is 1-bit wide and drives the output of its associated pin in the
183+
:attr:`Peripheral.pins` array, depending on its associated :class:`~Peripheral.Mode` field.
138184
139-
If ``pin_count`` is 8, then the register has the following fields:
185+
----
140186
141-
.. bitfield::
142-
:bits: 8
187+
If ``pin_count`` is 8, then the :class:`~.csr.reg.Register` has the following fields:
143188
144-
[
145-
{ "name": "pin[0]", "bits": 1, "attr": "RW" },
146-
{ "name": "pin[1]", "bits": 1, "attr": "RW" },
147-
{ "name": "pin[2]", "bits": 1, "attr": "RW" },
148-
{ "name": "pin[3]", "bits": 1, "attr": "RW" },
149-
{ "name": "pin[4]", "bits": 1, "attr": "RW" },
150-
{ "name": "pin[5]", "bits": 1, "attr": "RW" },
151-
{ "name": "pin[6]", "bits": 1, "attr": "RW" },
152-
{ "name": "pin[7]", "bits": 1, "attr": "RW" },
153-
]
189+
.. wavedrom:: gpio_output
190+
191+
{
192+
"reg": [
193+
{ "name": "pin[0]", "bits": 1, "attr": "RW" },
194+
{ "name": "pin[1]", "bits": 1, "attr": "RW" },
195+
{ "name": "pin[2]", "bits": 1, "attr": "RW" },
196+
{ "name": "pin[3]", "bits": 1, "attr": "RW" },
197+
{ "name": "pin[4]", "bits": 1, "attr": "RW" },
198+
{ "name": "pin[5]", "bits": 1, "attr": "RW" },
199+
{ "name": "pin[6]", "bits": 1, "attr": "RW" },
200+
{ "name": "pin[7]", "bits": 1, "attr": "RW" }
201+
],
202+
"config": {"bits": 8}
203+
}
154204
155-
Parameters
156-
----------
205+
----
206+
207+
Arguments
208+
---------
157209
pin_count : :class:`int`
158210
Number of GPIO pins.
159211
"""
@@ -189,32 +241,38 @@ def __init__(self, pin_count):
189241
class SetClr(csr.Register, access="w"):
190242
"""Output set/clear register.
191243
192-
This :class:`csr.Register` contains an array of ``pin_count`` write-only fields. Each field
193-
is 2-bit wide; writing it can modify its associated :class:`~Peripheral.Output` field as a
194-
side-effect.
244+
This :class:`~.csr.reg.Register` contains an array of ``pin_count`` write-only fields. Each
245+
field is 2-bit wide; writing it can modify its associated :class:`~Peripheral.Output` field
246+
as a side-effect.
195247
196-
If ``pin_count`` is 8, then the register has the following fields:
248+
----
197249
198-
.. bitfield::
199-
:bits: 16
250+
If ``pin_count`` is 8, then the :class:`~.csr.reg.Register` has the following fields:
200251
201-
[
202-
{ "name": "pin[0]", "bits": 2, "attr": "W" },
203-
{ "name": "pin[1]", "bits": 2, "attr": "W" },
204-
{ "name": "pin[2]", "bits": 2, "attr": "W" },
205-
{ "name": "pin[3]", "bits": 2, "attr": "W" },
206-
{ "name": "pin[4]", "bits": 2, "attr": "W" },
207-
{ "name": "pin[5]", "bits": 2, "attr": "W" },
208-
{ "name": "pin[6]", "bits": 2, "attr": "W" },
209-
{ "name": "pin[7]", "bits": 2, "attr": "W" },
210-
]
252+
.. wavedrom:: gpio_setclr
253+
254+
{
255+
"reg": [
256+
{ "name": "pin[0]", "bits": 2, "attr": "W" },
257+
{ "name": "pin[1]", "bits": 2, "attr": "W" },
258+
{ "name": "pin[2]", "bits": 2, "attr": "W" },
259+
{ "name": "pin[3]", "bits": 2, "attr": "W" },
260+
{ "name": "pin[4]", "bits": 2, "attr": "W" },
261+
{ "name": "pin[5]", "bits": 2, "attr": "W" },
262+
{ "name": "pin[6]", "bits": 2, "attr": "W" },
263+
{ "name": "pin[7]", "bits": 2, "attr": "W" }
264+
],
265+
"config": {"bits": 16}
266+
}
211267
212268
- Writing `0b01` to a field sets its associated :class:`~Peripheral.Output` field.
213269
- Writing `0b10` to a field clears its associated :class:`~Peripheral.Output` field.
214270
- Writing `0b00` or `0b11` to a field has no side-effect.
215271
216-
Parameters
217-
----------
272+
----
273+
274+
Arguments
275+
---------
218276
pin_count : :class:`int`
219277
Number of GPIO pins.
220278
"""
@@ -227,38 +285,6 @@ def __init__(self, pin_count):
227285
"pin": [pin_fields for _ in range(pin_count)],
228286
})
229287

230-
"""GPIO peripheral.
231-
232-
Parameters
233-
----------
234-
pin_count : :class:`int`
235-
Number of GPIO pins.
236-
addr_width : :class:`int`
237-
CSR bus address width.
238-
data_width : :class:`int`
239-
CSR bus data width.
240-
name : :class:`str`
241-
CSR bus window name. Optional.
242-
input_stages : :class:`int`
243-
Number of synchronization stages between pin inputs and the :class:`~Peripheral.Input`
244-
register. Optional. Defaults to ``2``.
245-
246-
Attributes
247-
----------
248-
bus : :class:`csr.Interface`
249-
CSR bus interface providing access to registers.
250-
pins : :class:`list` of :class:`wiring.PureInterface` of :class:`PinSignature`
251-
GPIO pin interfaces.
252-
alt_mode : :class:`Signal`
253-
Indicates which members of the :attr:`Peripheral.pins` array are in alternate mode.
254-
255-
Raises
256-
------
257-
:exc:`TypeError`
258-
If ``pin_count`` is not a positive integer.
259-
:exc:`TypeError`
260-
If ``input_stages`` is not a non-negative integer.
261-
"""
262288
def __init__(self, *, pin_count, addr_width, data_width, name=None, input_stages=2):
263289
if not isinstance(pin_count, int) or pin_count <= 0:
264290
raise TypeError(f"Pin count must be a positive integer, not {pin_count!r}")

docs/conf.py

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"sphinx.ext.autodoc",
1717
"sphinx.ext.napoleon",
1818
"sphinx_rtd_theme",
19+
"sphinxcontrib.yowasp_wavedrom",
1920
]
2021

2122
with open(".gitignore") as f:

docs/gpio.rst

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
GPIO
2+
====
3+
4+
.. warning::
5+
6+
This manual is a work in progress and is seriously incomplete!
7+
8+
.. py:module:: amaranth_soc.gpio
9+
10+
The :mod:`amaranth_soc.gpio` module provides a basic GPIO peripheral.
11+
12+
.. autoclass:: PinMode()
13+
.. autoclass:: PinSignature()
14+
.. autoclass:: Peripheral()

docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ System on Chip toolkit
1111
memory
1212
wishbone
1313
csr
14+
gpio

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ test = [
3737
]
3838
docs = [
3939
"sphinx~=7.1",
40+
"sphinxcontrib-yowasp-wavedrom~=1.0",
4041
"sphinx-rtd-theme~=1.2",
4142
"sphinx-autobuild",
4243
]

0 commit comments

Comments
 (0)