diff --git a/litex/build/efinix/common.py b/litex/build/efinix/common.py index 0a3ef4bf91..8229d816b8 100644 --- a/litex/build/efinix/common.py +++ b/litex/build/efinix/common.py @@ -38,6 +38,20 @@ def assert_is_signal_or_clocksignal(obj): assert isinstance(obj, (ClockSignal, Signal)), f"Object {obj} is not a ClockSignal or Signal" +def const_output_calc(o, io): + if o.value == 0: + const_output = 0 + elif len(o) == 1: + const_output = 1 + else: + const_output = [] + for bit in range(len(io)): + if o.value & (1 << bit): + const_output.append(1) + else: + const_output.append(0) + return const_output + # Efinix AsyncResetSynchronizer -------------------------------------------------------------------- class EfinixAsyncResetSynchronizerImpl(LiteXModule): @@ -142,12 +156,16 @@ def __init__(self, io, o, oe, i=None): io_pad = platform.get_pins_location(io) io_prop = platform.get_pin_properties(io[0]) io_prop_dict = dict(io_prop) - io_data_i = platform.add_iface_io(io_name + "_OUT", len(io)) - io_data_o = platform.add_iface_io(io_name + "_IN", len(io)) + if isinstance(o, Constant): + const_output = const_output_calc(o, io) + else: + const_output = "NONE" + io_data_i = platform.add_iface_io(io_name + "_OUT", len(io)) + self.comb += io_data_i.eq(o) io_data_e = platform.add_iface_io(io_name + "_OE", len(io)) - self.comb += io_data_i.eq(o) self.comb += io_data_e.eq(oe) if i is not None: + io_data_o = platform.add_iface_io(io_name + "_IN", len(io)) self.comb += i.eq(io_data_o) block = { "type" : "GPIO", @@ -156,6 +174,7 @@ def __init__(self, io, o, oe, i=None): "location" : io_pad, "properties" : io_prop, "size" : len(io), + "const_output" : const_output, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } platform.toolchain.ifacewriter.blocks.append(block) @@ -326,10 +345,14 @@ def __init__(self, io, o, oe, i, clk): io_pad = platform.get_pin_location(io) io_prop = platform.get_pin_properties(io) io_prop_dict = dict(io_prop) - io_data_i = platform.add_iface_io(io_name + "_OUT") + if isinstance(o, Constant): + const_output = const_output_calc(o, io) + else: + const_output = "NONE" + io_data_i = platform.add_iface_io(io_name + "_OUT") + self.comb += io_data_i.eq(o) io_data_o = platform.add_iface_io(io_name + "_IN") io_data_e = platform.add_iface_io(io_name + "_OE") - self.comb += io_data_i.eq(o) self.comb += io_data_e.eq(oe) self.comb += i.eq(io_data_o) block = { @@ -343,6 +366,7 @@ def __init__(self, io, o, oe, i, clk): "in_clk_pin" : clk, "out_reg" : "REG", "out_clk_pin" : clk, + "const_output" : const_output, "oe_reg" : "REG", "in_clk_inv" : 0, "out_clk_inv" : 0, @@ -367,8 +391,12 @@ def __init__(self, i, o, clk): io_pad = platform.get_pin_location(o) io_prop = platform.get_pin_properties(o) io_prop_dict = dict(io_prop) - io_data_i = platform.add_iface_io(io_name) - self.comb += io_data_i.eq(i) + if isinstance(i, Constant): + const_output = const_output_calc(i, o) + else: + const_output = "NONE" + io_data_i = platform.add_iface_io(io_name) + self.comb += io_data_i.eq(i) block = { "type" : "GPIO", "mode" : "OUTPUT", @@ -378,6 +406,7 @@ def __init__(self, i, o, clk): "size" : 1, "out_reg" : "REG", "out_clk_pin" : clk, + "const_output" : const_output, "out_clk_inv" : 0, "drive_strength" : io_prop_dict.get("DRIVE_STRENGTH", "4") } diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py index a8bf638993..ef65fc21b0 100644 --- a/litex/build/efinix/ifacewriter.py +++ b/litex/build/efinix/ifacewriter.py @@ -169,38 +169,9 @@ def generate_gpio(self, block, verbose=True): for i, pad in enumerate(block["location"]): cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n' - if "out_reg" in block: - cmd += f'design.set_property("{name}","OUT_REG","{block["out_reg"]}")\n' - cmd += f'design.set_property("{name}","OUT_CLK_PIN","{block["out_clk_pin"]}")\n' - if "out_delay" in block: - cmd += f'design.set_property("{name}","OUTDELAY","{block["out_delay"]}")\n' - - if "out_clk_inv" in block: - cmd += f'design.set_property("{name}","IS_OUTCLK_INVERTED","{block["out_clk_inv"]}")\n' - - if "in_reg" in block: - cmd += f'design.set_property("{name}","IN_REG","{block["in_reg"]}")\n' - cmd += f'design.set_property("{name}","IN_CLK_PIN","{block["in_clk_pin"]}")\n' - if "in_delay" in block: - cmd += f'design.set_property("{name}","INDELAY","{block["in_delay"]}")\n' - - if "in_clk_inv" in block: - cmd += f'design.set_property("{name}","IS_INCLK_INVERTED","{block["in_clk_inv"]}")\n' - if "oe_reg" in block: cmd += f'design.set_property("{name}","OE_REG","{block["oe_reg"]}")\n' - if "drive_strength" in block: - cmd += 'design.set_property("{}","DRIVE_STRENGTH","{}")\n'.format(name, block["drive_strength"]) - if "slewrate" in block: - cmd += 'design.set_property("{}","SLEWRATE","{}")\n'.format(name, block["slewrate"]) - - if prop: - for p, val in prop: - cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val) - cmd += "\n" - return cmd - if mode == "INPUT": if len(block["location"]) == 1: cmd += f'design.create_input_gpio("{name}")\n' @@ -209,6 +180,8 @@ def generate_gpio(self, block, verbose=True): cmd += f'design.create_input_gpio("{name}",{block["size"]-1},0)\n' for i, pad in enumerate(block["location"]): cmd += f'design.assign_pkg_pin("{name}[{i}]","{pad}")\n' + + if mode == "INPUT" or mode == "INOUT": if "in_reg" in block: in_clk_pin = block["in_clk_pin"] if isinstance(in_clk_pin, ClockSignal): @@ -225,21 +198,17 @@ def generate_gpio(self, block, verbose=True): cmd += f'design.set_property("{name}","INDELAY","{block["in_delay"]}")\n' if "in_clk_inv" in block: cmd += f'design.set_property("{name}","IS_INCLK_INVERTED","{block["in_clk_inv"]}")\n' - if prop: - for p, val in prop: - cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val) - cmd += "\n" - return cmd if mode == "OUTPUT": if len(block["location"]) == 1: cmd += 'design.create_output_gpio("{}")\n'.format(name) cmd += 'design.assign_pkg_pin("{}","{}")\n'.format(name, block["location"][0]) else: - cmd += 'design.create_input_gpio("{}",{},0)\n'.format(name, block["size"]-1) + cmd += 'design.create_output_gpio("{}",{},0)\n'.format(name, block["size"]-1) for i, pad in enumerate(block["location"]): cmd += 'design.assign_pkg_pin("{}[{}]","{}")\n'.format(name, i, pad) + if mode == "OUTPUT" or mode == "INOUT": if "out_reg" in block: cmd += 'design.set_property("{}","OUT_REG","{}")\n'.format(name, block["out_reg"]) cmd += 'design.set_property("{}","OUT_CLK_PIN","{}")\n'.format(name, block["out_clk_pin"]) @@ -253,7 +222,14 @@ def generate_gpio(self, block, verbose=True): cmd += 'design.set_property("{}","DRIVE_STRENGTH","{}")\n'.format(name, block["drive_strength"]) if "slewrate" in block: cmd += 'design.set_property("{}","SLEWRATE","{}")\n'.format(name, block["slewrate"]) - + if "const_output" in block: + if not isinstance(block["const_output"], list): + cmd += f'design.set_property("{name}","CONST_OUTPUT","{block["const_output"]}")\n' + else: + for i, val in enumerate(block["const_output"]): + cmd += f'design.set_property("{name}[{i}]","CONST_OUTPUT","{val}")\n' + + if mode == "INOUT" or mode == "INPUT" or mode == "OUTPUT": if prop: for p, val in prop: cmd += 'design.set_property("{}","{}","{}")\n'.format(name, p, val) diff --git a/litex/build/io.py b/litex/build/io.py index b83cac4780..9ca21baeb7 100644 --- a/litex/build/io.py +++ b/litex/build/io.py @@ -120,13 +120,13 @@ def __init__(self, io, o, oe, i, clk): class SDRTristate(Special): def __init__(self, io, o, oe, i, clk=None): - assert len(i) == len(o) == len(oe) Special.__init__(self) self.io = wrap(io) self.o = wrap(o) self.oe = wrap(oe) self.i = wrap(i) self.clk = wrap(clk) if clk is not None else ClockSignal() + assert len(self.i) == len(self.o) == len(self.oe) def iter_expressions(self): yield self, "io" , SPECIAL_INOUT