From faf2dc1dfbdc0aec59bcc0766567637374b6ebcb Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 3 Jun 2019 03:29:27 +0000 Subject: [PATCH] lib.io: allow Pin(xdr=0), representing a combinatorial I/O buffer. --- nmigen/lib/io.py | 17 ++++++++-------- nmigen/test/test_lib_io.py | 41 +++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 9 deletions(-) diff --git a/nmigen/lib/io.py b/nmigen/lib/io.py index f77dde6..3b65f07 100644 --- a/nmigen/lib/io.py +++ b/nmigen/lib/io.py @@ -18,19 +18,19 @@ def pin_layout(width, dir, xdr=1): if dir not in ("i", "o", "io"): raise TypeError("Direction must be one of \"i\", \"o\" or \"io\", not '{!r}'""" .format(dir)) - if not isinstance(xdr, int) or xdr < 1: - raise TypeError("Gearing ratio must be a positive integer, not '{!r}'" + if not isinstance(xdr, int) or xdr < 0: + raise TypeError("Gearing ratio must be a non-negative integer, not '{!r}'" .format(xdr)) fields = [] if dir in ("i", "io"): - if xdr == 1: + if xdr in (0, 1): fields.append(("i", width)) else: for n in range(xdr): fields.append(("i{}".format(n), width)) if dir in ("o", "io"): - if xdr == 1: + if xdr in (0, 1): fields.append(("o", width)) else: for n in range(xdr): @@ -60,7 +60,8 @@ class Pin(Record): 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 1, the I/O buffer is SDR, and only ``i``/``o`` signals are + 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 present. If greater than 1, the I/O buffer includes a gearbox, and ``iN``/``oN`` signals are present instead, where ``N in range(0, N)``. For example, if ``xdr=2``, the I/O buffer is DDR; the signal ``i0`` reflects the value at the rising edge, and the signal ``i1`` @@ -72,13 +73,13 @@ class Pin(Record): ---------- i : Signal, out I/O buffer input, without gearing. Present if ``dir="i"`` or ``dir="io"``, and ``xdr`` is - equal to 1. + equal to 0 or 1. i0, i1, ... : Signal, out I/O buffer inputs, with gearing. Present if ``dir="i"`` or ``dir="io"``, and ``xdr`` is greater than 1. o : Signal, in I/O buffer output, without gearing. Present if ``dir="o"`` or ``dir="io"``, and ``xdr`` is - equal to 1. + equal to 0 or 1. o0, o1, ... : Signal, in I/O buffer outputs, with gearing. Present if ``dir="o"`` or ``dir="io"``, and ``xdr`` is greater than 1. @@ -86,7 +87,7 @@ class Pin(Record): 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. """ - def __init__(self, width, dir, xdr=1, name=None): + def __init__(self, width, dir, xdr=0, name=None): self.width = width self.dir = dir self.xdr = xdr diff --git a/nmigen/test/test_lib_io.py b/nmigen/test/test_lib_io.py index f2cfdef..1a91a29 100644 --- a/nmigen/test/test_lib_io.py +++ b/nmigen/test/test_lib_io.py @@ -4,7 +4,7 @@ from ..hdl.rec import * from ..lib.io import * -class PinLayoutSDRTestCase(FHDLTestCase): +class PinLayoutCombTestCase(FHDLTestCase): def test_pin_layout_i(self): layout_1 = pin_layout(1, dir="i") self.assertEqual(layout_1.fields, { @@ -43,6 +43,45 @@ class PinLayoutSDRTestCase(FHDLTestCase): }) +class PinLayoutSDRTestCase(FHDLTestCase): + def test_pin_layout_i(self): + layout_1 = pin_layout(1, dir="i", xdr=1) + self.assertEqual(layout_1.fields, { + "i": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="i", xdr=1) + self.assertEqual(layout_2.fields, { + "i": ((2, False), DIR_NONE), + }) + + def test_pin_layout_o(self): + layout_1 = pin_layout(1, dir="o", xdr=1) + self.assertEqual(layout_1.fields, { + "o": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="o", xdr=1) + self.assertEqual(layout_2.fields, { + "o": ((2, False), DIR_NONE), + }) + + def test_pin_layout_io(self): + layout_1 = pin_layout(1, dir="io", xdr=1) + self.assertEqual(layout_1.fields, { + "i": ((1, False), DIR_NONE), + "o": ((1, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + + layout_2 = pin_layout(2, dir="io", xdr=1) + self.assertEqual(layout_2.fields, { + "i": ((2, False), DIR_NONE), + "o": ((2, False), DIR_NONE), + "oe": ((1, False), DIR_NONE), + }) + + class PinLayoutDDRTestCase(FHDLTestCase): def test_pin_layout_i(self): layout_1 = pin_layout(1, dir="i", xdr=2) -- 2.30.2