device = abstractproperty()
package = abstractproperty()
speed = abstractproperty()
- grade = None
- required_tools = [
- "yosys",
- "vivado"
- ]
+ required_tools = ["vivado"]
file_templates = {
**TemplatedPlatform.build_script_templates,
"build_{{name}}.sh": r"""
""",
"{{name}}.tcl": r"""
# {{autogenerated}}
- create_project -force -name {{name}} -part {{platform.device}}-{{platform.package}}-{{platform.speed}}{{"-" + platform.grade if platform.grade else ""}}
+ create_project -force -name {{name}} -part {{platform.device}}-{{platform.package}}-{{platform.speed}}
{% for file in platform.iter_extra_files(".v", ".sv", ".vhd", ".vhdl") -%}
- add_files {{file}}
+ add_files {{file|tcl_escape}}
{% endfor %}
add_files {{name}}.v
read_xdc {{name}}.xdc
{% for file in platform.iter_extra_files(".xdc") -%}
- read_xdc {{file}}
+ read_xdc {{file|tcl_escape}}
{% endfor %}
{{get_override("script_after_read")|default("# (script_after_read placeholder)")}}
synth_design -top {{name}}
"{{name}}.xdc": r"""
# {{autogenerated}}
{% for port_name, pin_name, attrs in platform.iter_port_constraints_bits() -%}
- set_property LOC {{pin_name}} [get_ports {{port_name}}]
+ set_property LOC {{pin_name}} [get_ports {{port_name|tcl_escape}}]
{% for attr_name, attr_value in attrs.items() -%}
- set_property {{attr_name}} {{attr_value}} [get_ports {{port_name}}]
+ set_property {{attr_name}} {{attr_value|tcl_escape}} [get_ports {{port_name|tcl_escape}}]
{% endfor %}
{% endfor %}
- {% for signal, frequency in platform.iter_clock_constraints() -%}
- create_clock -name {{signal.name}} -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|ascii_escape}} -period {{1000000000/frequency}} [get_ports {{port_signal.name|tcl_escape}}]
+ {% else -%}
+ create_clock -name {{net_signal.name|ascii_escape}} -period {{1000000000/frequency}} [get_nets {{net_signal|hierarchy("/")|tcl_escape}}]
+ {% endif %}
{% endfor %}
{{get_override("add_constraints")|default("# (add_constraints placeholder)")}}
"""
ready = Signal()
m.submodules += Instance("STARTUPE3", o_EOS=ready)
m.domains += ClockDomain("sync", reset_less=self.default_rst is None)
- m.submodules += Instance("BUFGCE", i_CE=ready, i_I=clk_i, o_O=ClockSignal("sync"))
+ # Actually use BUFGCTRL configured as BUFGCE, since using BUFGCE causes sim/synth
+ # mismatches with Vivado 2019.2, and the suggested workaround (SIM_DEVICE parameter)
+ # breaks Vivado 2017.4.
+ m.submodules += Instance("BUFGCTRL",
+ i_I0=clk_i, i_S0=C(1, 1), i_CE0=ready, i_IGNORE0=C(0, 1),
+ i_I1=C(1, 1), i_S1=C(0, 1), i_CE1=C(0, 1), i_IGNORE1=C(1, 1),
+ o_O=ClockSignal("sync")
+ )
if self.default_rst is not None:
m.submodules.reset_sync = ResetSynchronizer(rst_i, domain="sync")
return m
+ def add_clock_constraint(self, clock, frequency):
+ super().add_clock_constraint(clock, frequency)
+ clock.attrs["keep"] = "TRUE"
+
def _get_xdr_buffer(self, m, pin, *, i_invert=False, o_invert=False):
def get_dff(clk, d, q):
# SDR I/O is performed by packing a flip-flop into the pad IOB.
m.d.comb += ff_sync.o.eq(flops[-1])
return m
- def get_reset_sync(self, reset_sync):
+ def get_async_ff_sync(self, async_ff_sync):
m = Module()
- m.domains += ClockDomain("reset_sync", async_reset=True, local=True)
+ m.domains += ClockDomain("async_ff", async_reset=True, local=True)
flops = [Signal(1, name="stage{}".format(index), reset=1,
attrs={"ASYNC_REG": "TRUE"})
- for index in range(reset_sync._stages)]
- if reset_sync._max_input_delay is None:
+ for index in range(async_ff_sync._stages)]
+ if async_ff_sync._max_input_delay is None:
flops[0].attrs["nmigen.vivado.false_path"] = "TRUE"
else:
- flops[0].attrs["nmigen.vivado.max_delay"] = str(reset_sync._max_input_delay * 1e9)
+ flops[0].attrs["nmigen.vivado.max_delay"] = str(async_ff_sync._max_input_delay * 1e9)
for i, o in zip((0, *flops), flops):
- m.d.reset_sync += o.eq(i)
+ m.d.async_ff += o.eq(i)
+
+ if async_ff_sync._edge == "pos":
+ m.d.comb += ResetSignal("async_ff").eq(async_ff_sync.i)
+ else:
+ m.d.comb += ResetSignal("async_ff").eq(~async_ff_sync.i)
+
m.d.comb += [
- ClockSignal("reset_sync").eq(ClockSignal(reset_sync._domain)),
- ResetSignal("reset_sync").eq(reset_sync.arst),
- ResetSignal(reset_sync._domain).eq(flops[-1])
+ ClockSignal("async_ff").eq(ClockSignal(async_ff_sync._domain)),
+ async_ff_sync.o.eq(flops[-1])
]
+
return m