diff --git a/nmigen/lib/io.py b/nmigen/lib/io.py index 3b65f07..81f16c5 100644 --- a/nmigen/lib/io.py +++ b/nmigen/lib/io.py @@ -15,8 +15,8 @@ def pin_layout(width, dir, xdr=1): if not isinstance(width, int) or width < 1: raise TypeError("Width must be a positive integer, not '{!r}'" .format(width)) - if dir not in ("i", "o", "io"): - raise TypeError("Direction must be one of \"i\", \"o\" or \"io\", not '{!r}'""" + if dir not in ("i", "o", "oe", "io"): + raise TypeError("Direction must be one of \"i\", \"o\", \"io\", or \"oe\", not '{!r}'""" .format(dir)) if not isinstance(xdr, int) or xdr < 0: raise TypeError("Gearing ratio must be a non-negative integer, not '{!r}'" @@ -29,13 +29,13 @@ def pin_layout(width, dir, xdr=1): else: for n in range(xdr): fields.append(("i{}".format(n), width)) - if dir in ("o", "io"): + if dir in ("o", "oe", "io"): if xdr in (0, 1): fields.append(("o", width)) else: for n in range(xdr): fields.append(("o{}".format(n), width)) - if dir == "io": + if dir in ("oe", "io"): fields.append(("oe", 1)) return Layout(fields) @@ -54,11 +54,12 @@ class Pin(Record): ---------- width : int Width of the ``i``/``iN`` and ``o``/``oN`` signals. - dir : ``"i"``, ``"o"``, ``"io"`` + dir : ``"i"``, ``"o"``, ``"io"``, ``"oe"`` Direction of the buffers. If ``"i"`` is specified, only the ``i``/``iN`` signals are - present. If ``"o"`` is specified, only the ``o``/``oN`` signals are present. If ``"io"`` - is specified, both the ``i``/``iN`` and ``o``/``oN`` signals are present, and an ``oe`` - signal is present. + present. If ``"o"`` is specified, only the ``o``/``oN`` signals are present. If ``"oe"`` is + specified, the ``o``/``oN`` signals are present, and an ``oe`` signal is present. + If ``"io"`` is specified, both the ``i``/``iN`` and ``o``/``oN`` signals are present, and + an ``oe`` signal is present. xdr : int Gearbox ratio. If equal to 0, the I/O buffer is combinatorial, and only ``i``/``o`` signals are present. If equal to 1, the I/O buffer is SDR, and only ``i``/``o`` signals are @@ -84,8 +85,9 @@ class Pin(Record): I/O buffer outputs, with gearing. Present if ``dir="o"`` or ``dir="io"``, and ``xdr`` is greater than 1. oe : Signal, in - I/O buffer output enable. Present if ``dir="io"``. Buffers generally cannot change - direction more than once per cycle, so at most one output enable signal is present. + I/O buffer output enable. Present if ``dir="io"`` or ``dir="oe"``. Buffers generally + cannot change direction more than once per cycle, so at most one output enable signal + is present. """ def __init__(self, width, dir, xdr=0, name=None): self.width = width diff --git a/nmigen/test/test_lib_io.py b/nmigen/test/test_lib_io.py index 1a91a29..0e05277 100644 --- a/nmigen/test/test_lib_io.py +++ b/nmigen/test/test_lib_io.py @@ -27,6 +27,19 @@ class PinLayoutCombTestCase(FHDLTestCase): "o": ((2, False), DIR_NONE), }) + def test_pin_layout_oe(self): + layout_1 = pin_layout(1, dir="oe") + self.assertEqual(layout_1.fields, { + "o": ((1, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="oe") + self.assertEqual(layout_2.fields, { + "o": ((2, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + def test_pin_layout_io(self): layout_1 = pin_layout(1, dir="io") self.assertEqual(layout_1.fields, { @@ -66,6 +79,19 @@ class PinLayoutSDRTestCase(FHDLTestCase): "o": ((2, False), DIR_NONE), }) + def test_pin_layout_oe(self): + layout_1 = pin_layout(1, dir="oe", xdr=1) + self.assertEqual(layout_1.fields, { + "o": ((1, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="oe", xdr=1) + self.assertEqual(layout_2.fields, { + "o": ((2, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + def test_pin_layout_io(self): layout_1 = pin_layout(1, dir="io", xdr=1) self.assertEqual(layout_1.fields, { @@ -109,6 +135,21 @@ class PinLayoutDDRTestCase(FHDLTestCase): "o1": ((2, False), DIR_NONE), }) + def test_pin_layout_oe(self): + layout_1 = pin_layout(1, dir="oe", xdr=2) + self.assertEqual(layout_1.fields, { + "o0": ((1, False), DIR_NONE), + "o1": ((1, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="oe", xdr=2) + self.assertEqual(layout_2.fields, { + "o0": ((2, False), DIR_NONE), + "o1": ((2, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + def test_pin_layout_io(self): layout_1 = pin_layout(1, dir="io", xdr=2) self.assertEqual(layout_1.fields, {