From a0cb436467043cb487e8f0e1ddd4e962c3c0ccca Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 7 Nov 2023 20:15:07 +0100 Subject: [PATCH 1/2] build/gowin/common: adding Tristate support --- litex/build/gowin/common.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/litex/build/gowin/common.py b/litex/build/gowin/common.py index 395d8c66a..4510a1dc6 100644 --- a/litex/build/gowin/common.py +++ b/litex/build/gowin/common.py @@ -96,6 +96,25 @@ class GowinDifferentialOutput: def lower(dr): return GowinDifferentialOutputImpl(dr.i, dr.o_p, dr.o_n) +# Gowin Tristate ----------------------------------------------------------------------------------- + +class GowinTristateImpl(Module): + def __init__(self, io, o, oe, i): + nbits, _ = value_bits_sign(io) + for bit in range(nbits): + self.specials += Instance("IOBUF", + io_IO = io[bit] if nbits > 1 else io, + o_O = i[bit] if nbits > 1 else i, + i_I = o[bit] if nbits > 1 else o, + i_OEN = ~oe, + ) + +class GowinTristate: + @staticmethod + def lower(dr): + print(dr) + return GowinTristateImpl(dr.target, dr.o, dr.oe, dr.i) + # Gowin Special Overrides -------------------------------------------------------------------------- gowin_special_overrides = { @@ -104,4 +123,5 @@ gowin_special_overrides = { DDROutput: GowinDDROutput, DifferentialInput: GowinDifferentialInput, DifferentialOutput: GowinDifferentialOutput, + Tristate: GowinTristate, } From 93ce42f7819428d6fdc28bfe74a1aed019a17e7e Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 7 Nov 2023 20:20:33 +0100 Subject: [PATCH 2/2] build/gowin/gowin: rework constraints: IOStandard & Misc in one line, merge _p/_n and only write _p --- litex/build/gowin/gowin.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index a0e693e14..8ee97cecf 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -69,15 +69,41 @@ class GowinToolchain(GenericToolchain): else: flat_sc.append((name, pins[0], other)) + def _search_pin_entry(pin_lst, pin_name): + for name, pin, other in pin_lst: + if pin_name == name: + return (name, pin, other) + return (None, None, None) + for name, pin, other in flat_sc: if pin != "X": + t_name = name.split('[') # avoid index pins + tmp_name = t_name[0] + if tmp_name[-2:] == "_p": + pn = tmp_name[:-2] + "_n" + if len(t_name) > 1: + pn += '[' + t_name[1] + (_, n_pin, _) = _search_pin_entry(flat_sc, pn) + if n_pin is not None: + pin = f"{pin},{n_pin}" + elif tmp_name[-2:] == "_n": + pp = tmp_name[:-2] + "_p" + if len(t_name) > 1: + pp += '[' + t_name[1] + (p_name, _, _) = _search_pin_entry(flat_sc, pp) + if p_name is not None: + continue cst.append(f"IO_LOC \"{name}\" {pin};") + other_cst = [] for c in other: if isinstance(c, IOStandard): - cst.append(f"IO_PORT \"{name}\" IO_TYPE={c.name};") + other_cst.append(f"IO_TYPE={c.name}") elif isinstance(c, Misc): - cst.append(f"IO_PORT \"{name}\" {c.misc};") + other_cst.append(f"{c.misc}") + if len(other_cst): + t = " ".join(other_cst) + cst.append(f"IO_PORT \"{name}\" {t};") if self.named_pc: cst.extend(self.named_pc)