# Trellis templates
_nextpnr_device_options = {
- "LFE5U-12F": "--25k",
+ "LFE5U-12F": "--12k",
"LFE5U-25F": "--25k",
"LFE5U-45F": "--45k",
"LFE5U-85F": "--85k",
- "LFE5UM-12F": "--um-25k",
"LFE5UM-25F": "--um-25k",
"LFE5UM-45F": "--um-45k",
"LFE5UM-85F": "--um-85k",
- "LFE5UM5G-12F": "--um5g-25k",
"LFE5UM5G-25F": "--um5g-25k",
"LFE5UM5G-45F": "--um5g-45k",
"LFE5UM5G-85F": "--um5g-85k",
# {{autogenerated}}
{{emit_rtlil()}}
""",
+ "{{name}}.debug.v": r"""
+ /* {{autogenerated}} */
+ {{emit_debug_verilog()}}
+ """,
"{{name}}.ys": r"""
# {{autogenerated}}
{% for file in platform.iter_extra_files(".v") -%}
- read_verilog {{get_override("read_opts")|options}} {{file}}
+ read_verilog {{get_override("read_verilog_opts")|options}} {{file}}
{% endfor %}
{% for file in platform.iter_extra_files(".sv") -%}
- read_verilog -sv {{get_override("read_opts")|options}} {{file}}
+ read_verilog -sv {{get_override("read_verilog_opts")|options}} {{file}}
+ {% endfor %}
+ {% for file in platform.iter_extra_files(".il") -%}
+ read_ilang {{file}}
{% endfor %}
read_ilang {{name}}.il
{{get_override("script_after_read")|default("# (script_after_read placeholder)")}}
# {{autogenerated}}
BLOCK ASYNCPATHS;
BLOCK RESETPATHS;
- {% for port_name, pin_name, extras in platform.iter_port_constraints_bits() -%}
+ {% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
LOCATE COMP "{{port_name}}" SITE "{{pin_name}}";
- {% if extras -%}
+ {% if attrs -%}
IOBUF PORT "{{port_name}}"
- {%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
+ {%- for key, value in attrs.items() %} {{key}}={{value}}{% endfor %};
{% endif %}
{% endfor %}
- {% for signal, frequency in platform.iter_clock_constraints() -%}
- FREQUENCY NET "{{signal|hierarchy(".")}}" {{frequency}} HZ;
+ {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
+ {% if port_signal is not none -%}
+ FREQUENCY PORT "{{port_signal.name}}" {{frequency}} HZ;
+ {% else -%}
+ FREQUENCY NET "{{net_signal|hierarchy(".")}}" {{frequency}} HZ;
+ {% endif %}
{% endfor %}
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
"""
}
_trellis_command_templates = [
r"""
- {{get_tool("yosys")}}
+ {{invoke_tool("yosys")}}
{{quiet("-q")}}
{{get_override("yosys_opts")|options}}
-l {{name}}.rpt
{{name}}.ys
""",
r"""
- {{get_tool("nextpnr-ecp5")}}
+ {{invoke_tool("nextpnr-ecp5")}}
{{quiet("--quiet")}}
{{get_override("nextpnr_opts")|options}}
--log {{name}}.tim
--textcfg {{name}}.config
""",
r"""
- {{get_tool("ecppack")}}
+ {{invoke_tool("ecppack")}}
{{verbose("--verbose")}}
{{get_override("ecppack_opts")|options}}
--input {{name}}.config
# Diamond templates
_diamond_required_tools = [
- "yosys",
"pnmainc",
"ddtcmd"
]
-lpf {{name}}.lpf \
-synthesis synplify
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
- prj_src add "{{file}}"
+ prj_src add {{file|tcl_escape}}
{% endfor %}
prj_src add {{name}}.v
prj_impl option top {{name}}
prj_run Translate -impl impl -forceAll
prj_run Map -impl impl -forceAll
prj_run PAR -impl impl -forceAll
- prj_run Export -impl "impl" -forceAll -task Bitgen
+ prj_run Export -impl impl -forceAll -task Bitgen
{{get_override("script_after_export")|default("# (script_after_export placeholder)")}}
""",
"{{name}}.lpf": r"""
IOBUF PORT "{{port_name}}"
{%- for key, value in extras.items() %} {{key}}={{value}}{% endfor %};
{% endfor %}
- {% for signal, frequency in platform.iter_clock_constraints() -%}
- FREQUENCY NET "{{signal|hierarchy("/")}}" {{frequency/1000000}} MHZ;
- {% endfor %}
{{get_override("add_preferences")|default("# (add_preferences placeholder)")}}
""",
"{{name}}.sdc": r"""
- {% for signal, frequency in platform.iter_clock_constraints() -%}
- create_clock -period {{1000000000/frequency}} [get_nets {{signal|hierarchy("/")}}]
+ {% for net_signal, port_signal, frequency in platform.iter_clock_constraints() -%}
+ {% if port_signal is not none -%}
+ create_clock -name {{port_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
+ {% else -%}
+ create_clock -name {{net_signal.name|tcl_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
+ {% endif %}
{% endfor %}
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
""",
_diamond_command_templates = [
# These don't have any usable command-line option overrides.
r"""
- {{get_tool("pnmainc")}}
+ {{invoke_tool("pnmainc")}}
{{name}}.tcl
""",
r"""
- {{get_tool("ddtcmd")}}
+ {{invoke_tool("ddtcmd")}}
-oft -bit
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.bit
""",
r"""
- {{get_tool("ddtcmd")}}
+ {{invoke_tool("ddtcmd")}}
-oft -svfsingle -revd -op "Fast Program"
-if {{name}}_impl/{{name}}_impl.bit -of {{name}}.svf
""",
return self._diamond_command_templates
assert False
+ @property
+ def default_clk_constraint(self):
+ if self.default_clk == "OSCG":
+ return Clock(310e6 / self.oscg_div)
+ return super().default_clk_constraint
+
def create_missing_domain(self, name):
# Lattice ECP5 devices have two global set/reset signals: PUR, which is driven at startup
# by the configuration logic and unconditionally resets every storage element, and GSR,
# network, its deassertion may violate a setup/hold constraint with relation to a user
# clock. To avoid this, a GSR/SGSR instance should be driven synchronized to user clock.
if name == "sync" and self.default_clk is not None:
- clk_i = self.request(self.default_clk).i
+ m = Module()
+ if self.default_clk == "OSCG":
+ if not hasattr(self, "oscg_div"):
+ raise ValueError("OSCG divider (oscg_div) must be an integer between 2 "
+ "and 128")
+ if not isinstance(self.oscg_div, int) or self.oscg_div < 2 or self.oscg_div > 128:
+ raise ValueError("OSCG divider (oscg_div) must be an integer between 2 "
+ "and 128, not {!r}"
+ .format(self.oscg_div))
+ clk_i = Signal()
+ m.submodules += Instance("OSCG", p_DIV=self.oscg_div, o_OSC=clk_i)
+ else:
+ clk_i = self.request(self.default_clk).i
if self.default_rst is not None:
rst_i = self.request(self.default_rst).i
else:
gsr0 = Signal()
gsr1 = Signal()
- m = Module()
# There is no end-of-startup signal on ECP5, but PUR is released after IOB enable, so
# a simple reset synchronizer (with PUR as the asynchronous reset) does the job.
m.submodules += [