from collections import OrderedDict
-__all__ = ["Pins", "DiffPairs", "Attrs", "Clock", "Subsignal", "Resource", "Connector"]
+__all__ = ["Pins", "PinsN", "DiffPairs", "DiffPairsN",
+ "Attrs", "Clock", "Subsignal", "Resource", "Connector"]
class Pins:
raise TypeError("Direction must be one of \"i\", \"o\", \"oe\", or \"io\", not {!r}"
.format(dir))
- self.names = names
- self.dir = dir
+ self.names = names
+ self.dir = dir
+ self.invert = False
def __len__(self):
return len(self.names)
return mapped_names
def __repr__(self):
- return "(pins {} {})".format(self.dir, " ".join(self.names))
+ return "(pins{} {} {})".format("-n" if self.invert else "",
+ self.dir, " ".join(self.names))
+
+
+def PinsN(*args, **kwargs):
+ pins = Pins(*args, **kwargs)
+ pins.invert = True
+ return pins
class DiffPairs:
"and {!r} do not"
.format(self.p, self.n))
- self.dir = dir
+ self.dir = dir
+ self.invert = False
def __len__(self):
return len(self.p.names)
return zip(self.p.names, self.n.names)
def __repr__(self):
- return "(diffpairs {} (p {}) (n {}))".format(
+ return "(diffpairs{} {} (p {}) (n {}))".format("-n" if self.invert else "",
self.dir, " ".join(self.p.names), " ".join(self.n.names))
+def DiffPairsN(*args, **kwargs):
+ diff_pairs = DiffPairs(*args, **kwargs)
+ diff_pairs.invert = True
+ return diff_pairs
+
+
class Attrs(OrderedDict):
def __init__(self, **attrs):
for attr_key, attr_value in attrs.items():
pin_fragment.flatten = True
fragment.add_subfragment(pin_fragment, name="pin_{}".format(pin.name))
- for pin, port, attrs in self.iter_single_ended_pins():
+ for pin, port, attrs, invert in self.iter_single_ended_pins():
if pin.dir == "i":
- add_pin_fragment(pin, self.get_input(pin, port, attrs))
+ add_pin_fragment(pin, self.get_input(pin, port, attrs, invert))
if pin.dir == "o":
- add_pin_fragment(pin, self.get_output(pin, port, attrs))
+ add_pin_fragment(pin, self.get_output(pin, port, attrs, invert))
if pin.dir == "oe":
- add_pin_fragment(pin, self.get_tristate(pin, port, attrs))
+ add_pin_fragment(pin, self.get_tristate(pin, port, attrs, invert))
if pin.dir == "io":
- add_pin_fragment(pin, self.get_input_output(pin, port, attrs))
+ add_pin_fragment(pin, self.get_input_output(pin, port, attrs, invert))
- for pin, p_port, n_port, attrs in self.iter_differential_pins():
+ for pin, p_port, n_port, attrs, invert in self.iter_differential_pins():
if pin.dir == "i":
- add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, attrs))
+ add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, attrs, invert))
if pin.dir == "o":
- add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, attrs))
+ add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, attrs, invert))
if pin.dir == "oe":
- add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, attrs))
+ add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, attrs, invert))
if pin.dir == "io":
- add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port, attrs))
+ add_pin_fragment(pin,
+ self.get_diff_input_output(pin, p_port, n_port, attrs, invert))
return self.toolchain_prepare(fragment, name, **kwargs)
raise NotImplementedError("Platform {} does not support attributes for {}"
.format(self.__class__.__name__, feature))
- def get_input(self, pin, port, attrs):
+ @staticmethod
+ def _invert_if(invert, value):
+ if invert:
+ return ~value
+ else:
+ return value
+
+ def get_input(self, pin, port, attrs, invert):
self._check_feature("single-ended input", pin, attrs,
valid_xdrs=(0,), valid_attrs=None)
m = Module()
- m.d.comb += pin.i.eq(port)
+ m.d.comb += pin.i.eq(self._invert_if(invert, port))
return m
- def get_output(self, pin, port, attrs):
+ def get_output(self, pin, port, attrs, invert):
self._check_feature("single-ended output", pin, attrs,
valid_xdrs=(0,), valid_attrs=None)
m = Module()
- m.d.comb += port.eq(pin.o)
+ m.d.comb += port.eq(self._invert_if(invert, pin.o))
return m
- def get_tristate(self, pin, port, attrs):
+ def get_tristate(self, pin, port, attrs, invert):
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0,), valid_attrs=None)
m.submodules += Instance("$tribuf",
p_WIDTH=pin.width,
i_EN=pin.oe,
- i_A=pin.o,
+ i_A=self._invert_if(invert, pin.o),
o_Y=port,
)
return m
- def get_input_output(self, pin, port, attrs):
+ def get_input_output(self, pin, port, attrs, invert):
self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0,), valid_attrs=None)
m.submodules += Instance("$tribuf",
p_WIDTH=pin.width,
i_EN=pin.oe,
- i_A=pin.o,
+ i_A=self._invert_if(invert, pin.o),
o_Y=port,
)
- m.d.comb += pin.i.eq(port)
+ m.d.comb += pin.i.eq(self._invert_if(invert, port))
return m
- def get_diff_input(self, pin, p_port, n_port, attrs):
+ def get_diff_input(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential input", pin, attrs,
valid_xdrs=(), valid_attrs=None)
- def get_diff_output(self, pin, p_port, n_port, attrs):
+ def get_diff_output(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential output", pin, attrs,
valid_xdrs=(), valid_attrs=None)
- def get_diff_tristate(self, pin, p_port, n_port, attrs):
+ def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential tristate", pin, attrs,
valid_xdrs=(), valid_attrs=None)
- def get_diff_input_output(self, pin, p_port, n_port, attrs):
+ def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential input/output", pin, attrs,
valid_xdrs=(), valid_attrs=None)
if pin is None:
continue
if isinstance(res.ios[0], Pins):
- yield pin, port.io, attrs
+ yield pin, port.io, attrs, res.ios[0].invert
def iter_differential_pins(self):
for res, pin, port, attrs in self._ports:
if pin is None:
continue
if isinstance(res.ios[0], DiffPairs):
- yield pin, port.p, port.n, attrs
+ yield pin, port.p, port.n, attrs, res.ios[0].invert
def should_skip_port_component(self, port, attrs, component):
return False
self.assertEqual(repr(p), "(pins io A0 A1 A2)")
self.assertEqual(len(p.names), 3)
self.assertEqual(p.dir, "io")
+ self.assertEqual(p.invert, False)
self.assertEqual(list(p), ["A0", "A1", "A2"])
+ def test_invert(self):
+ p = PinsN("A0")
+ self.assertEqual(repr(p), "(pins-n io A0)")
+ self.assertEqual(p.invert, True)
+
def test_conn(self):
p = Pins("0 1 2", conn=("pmod", 0))
self.assertEqual(list(p), ["pmod_0:0", "pmod_0:1", "pmod_0:2"])
self.assertEqual(dp.dir, "io")
self.assertEqual(list(dp), [("A0", "B0"), ("A1", "B1")])
+ def test_invert(self):
+ dp = DiffPairsN(p="A0", n="B0")
+ self.assertEqual(repr(dp), "(diffpairs-n io (p A0) (n B0))")
+ self.assertEqual(dp.p.names, ["A0"])
+ self.assertEqual(dp.n.names, ["B0"])
+ self.assertEqual(dp.invert, True)
+
def test_conn(self):
dp = DiffPairs(p="0 1 2", n="3 4 5", conn=("pmod", 0))
self.assertEqual(list(dp), [
self.assertEqual(ports[1].nbits, 1)
self.assertEqual(list(self.cm.iter_single_ended_pins()), [
- (i2c.scl, scl, {}),
- (i2c.sda, sda, {}),
+ (i2c.scl, scl, {}, False),
+ (i2c.sda, sda, {}, False),
])
self.assertEqual(list(self.cm.iter_port_constraints()), [
("i2c_0__scl__io", ["N10"], {}),
self.assertEqual(n.nbits, clk100.width)
self.assertEqual(list(self.cm.iter_differential_pins()), [
- (clk100, p, n, {}),
+ (clk100, p, n, {}, False),
])
self.assertEqual(list(self.cm.iter_port_constraints()), [
("clk100_0__p", ["H1"], {}),
("clk100_0__n", ["H2"], {}),
])
+ def test_request_inverted(self):
+ new_resources = [
+ Resource("cs", 0, PinsN("X0")),
+ Resource("clk", 0, DiffPairsN("Y0", "Y1")),
+ ]
+ self.cm.add_resources(new_resources)
+
+ sig_cs = self.cm.request("cs")
+ sig_clk = self.cm.request("clk")
+ port_cs, port_clk_p, port_clk_n = self.cm.iter_ports()
+ self.assertEqual(list(self.cm.iter_single_ended_pins()), [
+ (sig_cs, port_cs, {}, True),
+ ])
+ self.assertEqual(list(self.cm.iter_differential_pins()), [
+ (sig_clk, port_clk_p, port_clk_n, {}, True),
+ ])
+
def test_request_raw(self):
clk50 = self.cm.request("clk50", 0, dir="-")
self.assertIsInstance(clk50, Record)
return True
return False
- def _get_io_buffer(self, m, pin, port, attrs, o_invert=None):
- def _get_dff(clk, d, q):
+ def _get_io_buffer(self, m, pin, port, attrs, i_invert=None, o_invert=None):
+ def get_dff(clk, d, q):
m.submodules += Instance("$dff",
p_CLK_POLARITY=0,
p_WIDTH=len(d),
i_D=d,
o_Q=q)
- def _get_inverter(a, invert):
+ def get_i_inverter(y, invert):
+ if invert is None:
+ return y
+ else:
+ a = Signal.like(y, name="{}_x{}".format(a.name, 1 if invert else 0))
+ for bit in range(len(y)):
+ m.submodules += Instance("SB_LUT4",
+ p_LUT_INIT=0b01 if invert else 0b10,
+ i_I0=a[bit],
+ i_I1=Const(0),
+ i_I2=Const(0),
+ i_I3=Const(0),
+ o_O=y[bit])
+ return a
+
+ def get_o_inverter(a, invert):
if invert is None:
return a
else:
else:
is_global_input = False
+ if "i" in pin.dir:
+ if pin.xdr < 2:
+ pin_i = get_i_inverter(pin.i, i_invert)
+ elif pin.xdr == 2:
+ pin_i0 = get_i_inverter(pin.i0, i_invert)
+ pin_i1 = get_i_inverter(pin.i1, i_invert)
if "o" in pin.dir:
if pin.xdr < 2:
- pin_o = _get_inverter(pin.o, o_invert)
+ pin_o = get_o_inverter(pin.o, o_invert)
elif pin.xdr == 2:
- pin_o0 = _get_inverter(pin.o0, o_invert)
- pin_o1 = _get_inverter(pin.o1, o_invert)
+ pin_o0 = get_o_inverter(pin.o0, o_invert)
+ pin_o1 = get_o_inverter(pin.o1, o_invert)
if "i" in pin.dir and pin.xdr == 2:
- i0_ff = Signal.like(pin.i0, name="{}_ff".format(pin.i0.name))
- i1_ff = Signal.like(pin.i1, name="{}_ff".format(pin.i1.name))
- _get_dff(pin.i_clk, i0_ff, pin.i0)
- _get_dff(pin.i_clk, i1_ff, pin.i1)
+ i0_ff = Signal.like(pin_i0, name="{}_ff".format(pin_i0.name))
+ i1_ff = Signal.like(pin_i1, name="{}_ff".format(pin_i1.name))
+ get_dff(pin.i_clk, i0_ff, pin_i0)
+ get_dff(pin.i_clk, i1_ff, pin_i1)
if "o" in pin.dir and pin.xdr == 2:
- o1_ff = Signal.like(pin.o1, name="{}_ff".format(pin.o1.name))
- _get_dff(pin.o_clk, pin_o1, o1_ff)
+ o1_ff = Signal.like(pin_o1, name="{}_ff".format(pin_o1.name))
+ get_dff(pin.o_clk, pin_o1, o1_ff)
for bit in range(len(port)):
io_args = [
if "i" in pin.dir:
if pin.xdr == 0 and is_global_input:
- io_args.append(("o", "GLOBAL_BUFFER_OUTPUT", pin.i[bit]))
+ io_args.append(("o", "GLOBAL_BUFFER_OUTPUT", pin_i[bit]))
elif pin.xdr < 2:
- io_args.append(("o", "D_IN_0", pin.i[bit]))
+ io_args.append(("o", "D_IN_0", pin_i[bit]))
elif pin.xdr == 2:
# Re-register both inputs before they enter fabric. This increases hold time
# to an entire cycle, and adds one cycle of latency.
else:
m.submodules += Instance("SB_IO", *io_args)
- def get_input(self, pin, port, attrs):
+ def get_input(self, pin, port, attrs, invert):
self._check_feature("single-ended input", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
- self._get_io_buffer(m, pin, port, attrs)
+ self._get_io_buffer(m, pin, port, attrs, i_invert=True if invert else None)
return m
- def get_output(self, pin, port, attrs):
+ def get_output(self, pin, port, attrs, invert):
self._check_feature("single-ended output", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
- self._get_io_buffer(m, pin, port, attrs)
+ self._get_io_buffer(m, pin, port, attrs, o_invert=True if invert else None)
return m
- def get_tristate(self, pin, port, attrs):
+ def get_tristate(self, pin, port, attrs, invert):
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
- self._get_io_buffer(m, pin, port, attrs)
+ self._get_io_buffer(m, pin, port, attrs, o_invert=True if invert else None)
return m
- def get_input_output(self, pin, port, attrs):
+ def get_input_output(self, pin, port, attrs, invert):
self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
- self._get_io_buffer(m, pin, port, attrs)
+ self._get_io_buffer(m, pin, port, attrs, i_invert=True if invert else None,
+ o_invert=True if invert else None)
return m
- def get_diff_input(self, pin, p_port, n_port, attrs):
+ def get_diff_input(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential input", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
# See comment in should_skip_port_component above.
- self._get_io_buffer(m, pin, p_port, attrs)
+ self._get_io_buffer(m, pin, p_port, attrs, i_invert=True if invert else None)
return m
- def get_diff_output(self, pin, p_port, n_port, attrs):
+ def get_diff_output(self, pin, p_port, n_port, attrs, invert):
self._check_feature("differential output", pin, attrs,
valid_xdrs=(0, 1, 2), valid_attrs=True)
m = Module()
# output pin. The inverter introduces a delay, so for a non-inverting output pin,
# an identical delay is introduced by instantiating a LUT. This makes the waveform
# perfectly symmetric in the xdr=0 case.
- self._get_io_buffer(m, pin, p_port, attrs, o_invert=False)
- self._get_io_buffer(m, pin, n_port, attrs, o_invert=True)
+ self._get_io_buffer(m, pin, p_port, attrs, o_invert=invert)
+ self._get_io_buffer(m, pin, n_port, attrs, o_invert=not invert)
return m
# Tristate and bidirectional buffers are not supported on iCE40 because it requires external
)
m.d.comb += q[bit].eq(_q)
- def get_input(self, pin, port, attrs):
+ def get_input(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended input", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
m.d.comb += pin.i.eq(port)
return m
- def get_output(self, pin, port, attrs):
+ def get_output(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
m.d.comb += port.eq(pin.o)
return m
- def get_tristate(self, pin, port, attrs):
+ def get_tristate(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_input_output(self, pin, port, attrs):
+ def get_input_output(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_input(self, pin, p_port, n_port, attrs):
+ def get_diff_input(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential input", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_output(self, pin, p_port, n_port, attrs):
+ def get_diff_output(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_tristate(self, pin, p_port, n_port, attrs):
+ def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential tristate", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_input_output(self, pin, p_port, n_port, attrs):
+ def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential input/output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
m.d.comb += q[bit].eq(_q)
- def get_input(self, pin, port, attrs):
+ def get_input(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended input", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
m.d.comb += pin.i.eq(port)
return m
- def get_output(self, pin, port, attrs):
+ def get_output(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
m.d.comb += port.eq(pin.o)
return m
- def get_tristate(self, pin, port, attrs):
+ def get_tristate(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended tristate", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_input_output(self, pin, port, attrs):
+ def get_input_output(self, pin, port, attrs, invert):
+ assert not invert
self._check_feature("single-ended input/output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_input(self, pin, p_port, n_port, attrs):
+ def get_diff_input(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential input", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_output(self, pin, p_port, n_port, attrs):
+ def get_diff_output(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_tristate(self, pin, p_port, n_port, attrs):
+ def get_diff_tristate(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential tristate", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()
)
return m
- def get_diff_input_output(self, pin, p_port, n_port, attrs):
+ def get_diff_input_output(self, pin, p_port, n_port, attrs, invert):
+ assert not invert
self._check_feature("differential input/output", pin, attrs,
valid_xdrs=(0, 1), valid_attrs=True)
m = Module()