lib.io: allow dir="oe".
Although a dir="oe" pin is generally equivalent to dir="io" pin with the i* signal(s) disconnected, they are not equivalent, because some pins may not be able to support input buffers at all, either because there are no input buffers, or because the input buffers are consumed by some other resource. E.g. this can happen on iCE40 when the input buffer is consumed by a PLL.
This commit is contained in:
parent
9ba2efd86b
commit
1eee7cd76f
|
@ -15,8 +15,8 @@ def pin_layout(width, dir, xdr=1):
|
||||||
if not isinstance(width, int) or width < 1:
|
if not isinstance(width, int) or width < 1:
|
||||||
raise TypeError("Width must be a positive integer, not '{!r}'"
|
raise TypeError("Width must be a positive integer, not '{!r}'"
|
||||||
.format(width))
|
.format(width))
|
||||||
if dir not in ("i", "o", "io"):
|
if dir not in ("i", "o", "oe", "io"):
|
||||||
raise TypeError("Direction must be one of \"i\", \"o\" or \"io\", not '{!r}'"""
|
raise TypeError("Direction must be one of \"i\", \"o\", \"io\", or \"oe\", not '{!r}'"""
|
||||||
.format(dir))
|
.format(dir))
|
||||||
if not isinstance(xdr, int) or xdr < 0:
|
if not isinstance(xdr, int) or xdr < 0:
|
||||||
raise TypeError("Gearing ratio must be a non-negative integer, not '{!r}'"
|
raise TypeError("Gearing ratio must be a non-negative integer, not '{!r}'"
|
||||||
|
@ -29,13 +29,13 @@ def pin_layout(width, dir, xdr=1):
|
||||||
else:
|
else:
|
||||||
for n in range(xdr):
|
for n in range(xdr):
|
||||||
fields.append(("i{}".format(n), width))
|
fields.append(("i{}".format(n), width))
|
||||||
if dir in ("o", "io"):
|
if dir in ("o", "oe", "io"):
|
||||||
if xdr in (0, 1):
|
if xdr in (0, 1):
|
||||||
fields.append(("o", width))
|
fields.append(("o", width))
|
||||||
else:
|
else:
|
||||||
for n in range(xdr):
|
for n in range(xdr):
|
||||||
fields.append(("o{}".format(n), width))
|
fields.append(("o{}".format(n), width))
|
||||||
if dir == "io":
|
if dir in ("oe", "io"):
|
||||||
fields.append(("oe", 1))
|
fields.append(("oe", 1))
|
||||||
return Layout(fields)
|
return Layout(fields)
|
||||||
|
|
||||||
|
@ -54,11 +54,12 @@ class Pin(Record):
|
||||||
----------
|
----------
|
||||||
width : int
|
width : int
|
||||||
Width of the ``i``/``iN`` and ``o``/``oN`` signals.
|
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
|
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"``
|
present. If ``"o"`` is specified, only the ``o``/``oN`` signals are present. If ``"oe"`` is
|
||||||
is specified, both the ``i``/``iN`` and ``o``/``oN`` signals are present, and an ``oe``
|
specified, the ``o``/``oN`` signals are present, and an ``oe`` signal is present.
|
||||||
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
|
xdr : int
|
||||||
Gearbox ratio. If equal to 0, the I/O buffer is combinatorial, and only ``i``/``o``
|
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
|
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
|
I/O buffer outputs, with gearing. Present if ``dir="o"`` or ``dir="io"``, and ``xdr`` is
|
||||||
greater than 1.
|
greater than 1.
|
||||||
oe : Signal, in
|
oe : Signal, in
|
||||||
I/O buffer output enable. Present if ``dir="io"``. Buffers generally cannot change
|
I/O buffer output enable. Present if ``dir="io"`` or ``dir="oe"``. Buffers generally
|
||||||
direction more than once per cycle, so at most one output enable signal is present.
|
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):
|
def __init__(self, width, dir, xdr=0, name=None):
|
||||||
self.width = width
|
self.width = width
|
||||||
|
|
|
@ -27,6 +27,19 @@ class PinLayoutCombTestCase(FHDLTestCase):
|
||||||
"o": ((2, False), DIR_NONE),
|
"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):
|
def test_pin_layout_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io")
|
layout_1 = pin_layout(1, dir="io")
|
||||||
self.assertEqual(layout_1.fields, {
|
self.assertEqual(layout_1.fields, {
|
||||||
|
@ -66,6 +79,19 @@ class PinLayoutSDRTestCase(FHDLTestCase):
|
||||||
"o": ((2, False), DIR_NONE),
|
"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):
|
def test_pin_layout_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io", xdr=1)
|
layout_1 = pin_layout(1, dir="io", xdr=1)
|
||||||
self.assertEqual(layout_1.fields, {
|
self.assertEqual(layout_1.fields, {
|
||||||
|
@ -109,6 +135,21 @@ class PinLayoutDDRTestCase(FHDLTestCase):
|
||||||
"o1": ((2, False), DIR_NONE),
|
"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):
|
def test_pin_layout_io(self):
|
||||||
layout_1 = pin_layout(1, dir="io", xdr=2)
|
layout_1 = pin_layout(1, dir="io", xdr=2)
|
||||||
self.assertEqual(layout_1.fields, {
|
self.assertEqual(layout_1.fields, {
|
||||||
|
|
Loading…
Reference in a new issue