diff --git a/litex/build/efinix/common.py b/litex/build/efinix/common.py index 8229d816b8..ca9b73d997 100644 --- a/litex/build/efinix/common.py +++ b/litex/build/efinix/common.py @@ -294,7 +294,7 @@ def lower(dr): class EfinixDDRTristateImpl(LiteXModule): def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): - assert oe1 == oe2 + assert oe2 is None assert_is_signal_or_clocksignal(clk) platform = LiteXContext.platform io_name = platform.get_pin_name(io) diff --git a/litex/build/generic_toolchain.py b/litex/build/generic_toolchain.py index 488b92178f..fd1c0af37c 100644 --- a/litex/build/generic_toolchain.py +++ b/litex/build/generic_toolchain.py @@ -8,7 +8,7 @@ import os import math -from migen.fhdl.structure import _Fragment +from migen.fhdl.structure import Signal, _Fragment from litex.gen import LiteXContext @@ -178,7 +178,9 @@ def add_period_constraint(self, platform, clk, period, keep=True, name=None): def add_false_path_constraint(self, platform, from_, to, keep=True): if keep: - from_.attr.add("keep") - to.attr.add("keep") + if isinstance(from_, Signal): + from_.attr.add("keep") + if isinstance(to, Signal): + to.attr.add("keep") if (to, from_) not in self.false_paths: self.false_paths.add((from_, to)) diff --git a/litex/build/io.py b/litex/build/io.py index 9ca21baeb7..9c593795ea 100644 --- a/litex/build/io.py +++ b/litex/build/io.py @@ -190,20 +190,20 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): _oe = Signal() _i = Signal() self.specials += DDROutput(o1, o2, _o, clk) - self.specials += DDROutput(oe1, oe2, _oe, clk) + self.specials += DDROutput(oe1, oe2, _oe, clk) if oe2 is not None else SDROutput(oe1, _oe, clk) self.specials += DDRInput(_i, i1, i2, clk) self.specials += Tristate(io, _o, _oe, _i) class DDRTristate(Special): - def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk=None): + def __init__(self, io, o1, o2, oe1, oe2=None, i1=None, i2=None, clk=None): Special.__init__(self) self.io = io self.o1 = o1 self.o2 = o2 self.oe1 = oe1 self.oe2 = oe2 - self.i1 = i1 - self.i2 = i2 + self.i1 = i1 if i1 is not None else Signal() + self.i2 = i2 if i2 is not None else Signal() self.clk = clk if clk is not None else ClockSignal() def iter_expressions(self): diff --git a/litex/build/lattice/common.py b/litex/build/lattice/common.py index 917b5af0ce..28bf247ad4 100644 --- a/litex/build/lattice/common.py +++ b/litex/build/lattice/common.py @@ -324,11 +324,12 @@ def lower(dr): class LatticeNXDDRTristateImpl(Module): def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): + assert oe2 is None _o = Signal() _oe = Signal() _i = Signal() self.specials += DDROutput(o1, o2, _o, clk) - self.specials += SDROutput(oe1 | oe2, _oe, clk) + self.specials += SDROutput(oe1, _oe, clk) self.specials += DDRInput(_i, i1, i2, clk) self.specials += Tristate(io, _o, _oe, _i) _oe.attr.add("syn_useioff") diff --git a/litex/build/vhd2v_converter.py b/litex/build/vhd2v_converter.py index 1fb2bd647c..9e378b493f 100644 --- a/litex/build/vhd2v_converter.py +++ b/litex/build/vhd2v_converter.py @@ -152,6 +152,11 @@ def do_finalize(self): if len(v_list) != 0: inst_name += f"_{len(v_list)}" + + # Create build_dir if not existing. + if not os.path.exists(self._build_dir): + os.makedirs(self._build_dir) + verilog_out = os.path.join(self._build_dir, f"{inst_name}.v") ip_params = dict() diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index d0d6bf0f63..0f2231f70b 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -164,7 +164,7 @@ def __init__(self, io, o1, o2, oe1, oe2, i1, i2, clk): _oe_n = Signal() _i = Signal() self.specials += DDROutput(o1, o2, _o, clk) - self.specials += DDROutput(~oe1, ~oe2, _oe_n, clk) + self.specials += DDROutput(~oe1, ~oe2, _oe_n, clk) if oe2 is not None else SDROutput(~oe1, _oe_n, clk) self.specials += DDRInput(_i, i1, i2, clk) self.specials += Instance("IOBUF", io_IO = io, diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index a9f3e4f18f..2292b0918e 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -164,51 +164,83 @@ def build_io_constraints(self): # Timing Constraints (in xdc file) ------------------------------------------------------------- def _build_clock_constraints(self): + # Add clock constraints to the XDC file. self.platform.add_platform_command(_xdc_separator("Clock constraints")) + + # Determine whether a clock is defined as a net or a port. def get_clk_type(clk): return { - False : "nets", + False : "nets", True : "ports", }[hasattr(clk, "port")] + + # Add create_clock commands for each clock in the design. for clk, [period, name] in sorted(self.clocks.items(), key=lambda x: x[0].duid): if name is None: name = clk self.platform.add_platform_command( "create_clock -name {name} -period " + str(period) + " [get_" + get_clk_type(clk) + " {clk}]", name=name, clk=clk) - for _from, _to in sorted(self.false_paths, key=lambda x: (x[0].duid, x[1].duid)): - self.platform.add_platform_command( - "set_clock_groups " - "-group [get_clocks -include_generated_clocks -of [get_" + get_clk_type(_from) + " {_from}]] " - "-group [get_clocks -include_generated_clocks -of [get_" + get_clk_type(_to) + " {_to}]] " - "-asynchronous", - _from=_from, _to=_to) - # Make sure add_*_constraint cannot be used again + + # Clear clock constraints after generation. self.clocks.clear() - self.false_paths.clear() def _build_false_path_constraints(self): + # Add false path constraints to the XDC file. self.platform.add_platform_command(_xdc_separator("False path constraints")) - # The asynchronous input to a MultiReg is a false path + + # Mark asynchronous inputs to MultiReg as false paths. self.platform.add_platform_command( "set_false_path -quiet " "-through [get_nets -hierarchical -filter {{mr_ff == TRUE}}]" ) - # The asychronous reset input to the AsyncResetSynchronizer is a false path + + # Mark asynchronous reset inputs to AsyncResetSynchronizer as false paths. self.platform.add_platform_command( "set_false_path -quiet " "-to [get_pins -filter {{REF_PIN_NAME == PRE}} " - "-of_objects [get_cells -hierarchical -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]" + "-of_objects [get_cells -hierarchical -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]" ) - # clock_period-2ns to resolve metastability on the wire between the AsyncResetSynchronizer FFs + + # Set a maximum delay for metastability resolution in AsyncResetSynchronizer. self.platform.add_platform_command( "set_max_delay 2 -quiet " "-from [get_pins -filter {{REF_PIN_NAME == C}} " - "-of_objects [get_cells -hierarchical -filter {{ars_ff1 == TRUE}}]] " + "-of_objects [get_cells -hierarchical -filter {{ars_ff1 == TRUE}}]] " "-to [get_pins -filter {{REF_PIN_NAME == D}} " - "-of_objects [get_cells -hierarchical -filter {{ars_ff2 == TRUE}}]]" + "-of_objects [get_cells -hierarchical -filter {{ars_ff2 == TRUE}}]]" ) + # Add false paths between asynchronous clock domains. + def get_clk_type(clk): + return { + False: "nets", + True: "ports", + }[hasattr(clk, "port")] + + for _from, _to in sorted(self.false_paths, key=lambda x: (str(x[0]), str(x[1]))): + if isinstance(_from, str): + _from_cmd = f"[get_clocks {_from}]" + else: + _from_cmd = f"[get_clocks -include_generated_clocks -of [get_{get_clk_type(_from)} {{_from}}]]" + + if isinstance(_to, str): + _to_cmd = f"[get_clocks {_to}]" + else: + _to_cmd = f"[get_clocks -include_generated_clocks -of [get_{get_clk_type(_to)} {{_to}}]]" + + self.platform.add_platform_command( + "set_clock_groups " + f"-group {_from_cmd} " + f"-group {_to_cmd} " + "-asynchronous", + _from = _from if not isinstance(_from, str) else None, + _to = _to if not isinstance(_to, str) else None, + ) + + # Clear false path constraints after generation. + self.false_paths.clear() + def build_timing_constraints(self, vns): # FIXME: -> self ? self._vns = vns diff --git a/litex/gen/fhdl/namer.py b/litex/gen/fhdl/namer.py index 3db8606a2c..fea8458ca4 100644 --- a/litex/gen/fhdl/namer.py +++ b/litex/gen/fhdl/namer.py @@ -413,6 +413,11 @@ def __init__(self, name_dict, reserved_keywords=set()): self.clock_domains = dict() def get_name(self, sig): + # Return None if sig is None. + # --------------------------- + if sig is None: + return None + # Handle Clock and Reset Signals. # ------------------------------- if isinstance(sig, (ClockSignal, ResetSignal)): diff --git a/litex/soc/cores/cpu/vexiiriscv/core.py b/litex/soc/cores/cpu/vexiiriscv/core.py index 5a97c46421..d3cbbe090f 100755 --- a/litex/soc/cores/cpu/vexiiriscv/core.py +++ b/litex/soc/cores/cpu/vexiiriscv/core.py @@ -156,7 +156,7 @@ def args_read(args): vdir = get_data_mod("cpu", "vexiiriscv").data_location ndir = os.path.join(vdir, "ext", "VexiiRiscv") - NaxRiscv.git_setup("VexiiRiscv", ndir, "https://github.com/SpinalHDL/VexiiRiscv.git", "dev", "ca10ab58", args.update_repo) + NaxRiscv.git_setup("VexiiRiscv", ndir, "https://github.com/SpinalHDL/VexiiRiscv.git", "dev", "b4269ddc", args.update_repo) if not args.cpu_variant: args.cpu_variant = "standard" diff --git a/litex/soc/software/liblitespi/spiram.c b/litex/soc/software/liblitespi/spiram.c index 7e49ab2a88..9de0bb5f6f 100644 --- a/litex/soc/software/liblitespi/spiram.c +++ b/litex/soc/software/liblitespi/spiram.c @@ -98,7 +98,7 @@ static void spiram_master_write(uint32_t val, size_t len, size_t width, uint32_t while (!spiram_rx_ready()); /* Clear RX queue. */ - spiflash_core_master_rxtx_read(); + spiram_core_master_rxtx_read(); /* Clear CS. */ spiram_core_master_cs_write(0);