vendor.fpga.lattice_ice40: implement differential input buffers.
This commit is contained in:
parent
3116d4add2
commit
41adcc3f97
|
@ -134,13 +134,13 @@ class Platform(ConstraintManager, metaclass=ABCMeta):
|
||||||
|
|
||||||
for pin, p_port, n_port, extras in self.iter_differential_pins():
|
for pin, p_port, n_port, extras in self.iter_differential_pins():
|
||||||
if pin.dir == "i":
|
if pin.dir == "i":
|
||||||
add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port))
|
add_pin_fragment(pin, self.get_diff_input(pin, p_port, n_port, extras))
|
||||||
if pin.dir == "o":
|
if pin.dir == "o":
|
||||||
add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port))
|
add_pin_fragment(pin, self.get_diff_output(pin, p_port, n_port, extras))
|
||||||
if pin.dir == "oe":
|
if pin.dir == "oe":
|
||||||
add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port))
|
add_pin_fragment(pin, self.get_diff_tristate(pin, p_port, n_port, extras))
|
||||||
if pin.dir == "io":
|
if pin.dir == "io":
|
||||||
add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port))
|
add_pin_fragment(pin, self.get_diff_input_output(pin, p_port, n_port, extras))
|
||||||
|
|
||||||
return self.toolchain_prepare(fragment, name, **kwargs)
|
return self.toolchain_prepare(fragment, name, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -156,17 +156,13 @@ class ConstraintManager:
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def iter_port_constraints(self, diff_pins="pn"):
|
def iter_port_constraints(self):
|
||||||
for resource, pin, port in self._ports:
|
for resource, pin, port in self._ports:
|
||||||
if isinstance(resource.io[0], Pins):
|
if isinstance(resource.io[0], Pins):
|
||||||
yield port.io.name, resource.io[0].names, resource.extras
|
yield port.io.name, resource.io[0].names, resource.extras
|
||||||
elif isinstance(resource.io[0], DiffPairs):
|
elif isinstance(resource.io[0], DiffPairs):
|
||||||
# On some FPGAs like iCE40, only one pin out of two in a differential pair may be
|
yield port.p.name, resource.io[0].p.names, resource.extras
|
||||||
# constrained. The other has to be completely disconnected.
|
yield port.n.name, resource.io[0].n.names, resource.extras
|
||||||
if "p" in diff_pins:
|
|
||||||
yield port.p.name, resource.io[0].p.names, resource.extras
|
|
||||||
if "n" in diff_pins:
|
|
||||||
yield port.n.name, resource.io[0].n.names, resource.extras
|
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
|
@ -115,12 +115,6 @@ class ConstraintManagerTestCase(FHDLTestCase):
|
||||||
("clk100_0__p", ["H1"], {}),
|
("clk100_0__p", ["H1"], {}),
|
||||||
("clk100_0__n", ["H2"], {}),
|
("clk100_0__n", ["H2"], {}),
|
||||||
])
|
])
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="p")), [
|
|
||||||
("clk100_0__p", ["H1"], {}),
|
|
||||||
])
|
|
||||||
self.assertEqual(list(self.cm.iter_port_constraints(diff_pins="n")), [
|
|
||||||
("clk100_0__n", ["H2"], {}),
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_request_raw(self):
|
def test_request_raw(self):
|
||||||
clk50 = self.cm.request("clk50", 0, dir="-")
|
clk50 = self.cm.request("clk50", 0, dir="-")
|
||||||
|
|
36
nmigen/vendor/fpga/lattice_ice40.py
vendored
36
nmigen/vendor/fpga/lattice_ice40.py
vendored
|
@ -108,6 +108,32 @@ class LatticeICE40Platform(TemplatedPlatform):
|
||||||
"""
|
"""
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def iter_ports(self):
|
||||||
|
for resource, pin, port in self._ports:
|
||||||
|
if isinstance(resource.io[0], Pins):
|
||||||
|
yield port.io
|
||||||
|
elif isinstance(resource.io[0], DiffPairs):
|
||||||
|
if resource.extras.get("IO_STANDARD", "SB_LVCMOS") == "SB_LVDS_INPUT":
|
||||||
|
yield port.p
|
||||||
|
else:
|
||||||
|
yield port.p
|
||||||
|
yield port.n
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
|
def iter_port_constraints(self):
|
||||||
|
for resource, pin, port in self._ports:
|
||||||
|
if isinstance(resource.io[0], Pins):
|
||||||
|
yield port.io.name, resource.io[0].names, resource.extras
|
||||||
|
elif isinstance(resource.io[0], DiffPairs):
|
||||||
|
if resource.extras.get("IO_STANDARD", "SB_LVCMOS") == "SB_LVDS_INPUT":
|
||||||
|
yield port.p.name, resource.io[0].p.names, resource.extras
|
||||||
|
else:
|
||||||
|
yield port.p.name, resource.io[0].p.names, resource.extras
|
||||||
|
yield port.n.name, resource.io[0].n.names, resource.extras
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
def _get_dff(self, clk, d, q):
|
def _get_dff(self, clk, d, q):
|
||||||
return Instance("$dff",
|
return Instance("$dff",
|
||||||
p_CLK_POLARITY=0,
|
p_CLK_POLARITY=0,
|
||||||
|
@ -216,6 +242,16 @@ class LatticeICE40Platform(TemplatedPlatform):
|
||||||
valid_xdrs=(0, 1, 2), valid_extras=True)
|
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||||
return self._get_io_buffer(pin, port, extras)
|
return self._get_io_buffer(pin, port, extras)
|
||||||
|
|
||||||
|
def get_diff_input(self, pin, p_port, n_port, extras):
|
||||||
|
self._check_feature("differential input", pin, extras,
|
||||||
|
valid_xdrs=(0, 1, 2), valid_extras=True)
|
||||||
|
# On iCE40, a differential input is placed by only instantiating an SB_IO primitive for
|
||||||
|
# the pin with z=0, which is the non-inverting pin. The pinout unfortunately differs
|
||||||
|
# between LP/HX and UP series:
|
||||||
|
# * for LP/HX, z=0 is DPxxB (B is non-inverting, A is inverting)
|
||||||
|
# * for UP, z=0 is IOB_xxA (A is non-inverting, B is inverting)
|
||||||
|
return self._get_io_buffer(pin, p_port, extras)
|
||||||
|
|
||||||
|
|
||||||
class IceStormProgrammerMixin:
|
class IceStormProgrammerMixin:
|
||||||
def toolchain_program(self, products, name, *, mode=None):
|
def toolchain_program(self, products, name, *, mode=None):
|
||||||
|
|
Loading…
Reference in a new issue