vendor.xilinx_{7series,ultrascale}: add (*keep*) on constrained clocks.

If the clock signal is not a top-level port and has aliases, it can
be optimized out, and then the constraint will no longer apply.
To prevent this, make sure the constrained signal is preferred over
any aliases by using the `keep` attribute.

Vivado does not parse attributes like (* keep = 32'd1 *) as valid
even though, AFAICT, they are equivalent to (* keep = 1 *) or simply
(* keep *) per IEEE 1364. To work around this, use the solution we
currently use for Quartus, which is `write_verilog -decimal`.

Fixes #373.
This commit is contained in:
whitequark 2020-05-20 04:58:03 +00:00
parent 7ea81f5f06
commit 892cff059b
3 changed files with 16 additions and 6 deletions

View file

@ -146,8 +146,6 @@ class IntelPlatform(TemplatedPlatform):
def add_clock_constraint(self, clock, frequency):
super().add_clock_constraint(clock, frequency)
# Make sure the net constrained in the SDC file is kept through synthesis; it is redundant
# after Quartus flattens the hierarchy and will be eliminated if not explicitly kept.
clock.attrs["keep"] = 1
# The altiobuf_* and altddio_* primitives are explained in the following Intel documents:

View file

@ -66,13 +66,15 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
[ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
{{emit_commands("sh")}}
""",
# Vivado doesn't like constructs like (* keep = 32'd1 *), even though they mean the same
# thing as (* keep = 1 *); use -decimal to work around that.
"{{name}}.v": r"""
/* {{autogenerated}} */
{{emit_verilog()}}
{{emit_verilog(["-decimal"])}}
""",
"{{name}}.debug.v": r"""
/* {{autogenerated}} */
{{emit_debug_verilog()}}
{{emit_debug_verilog(["-decimal"])}}
""",
"{{name}}.tcl": r"""
# {{autogenerated}}
@ -177,6 +179,10 @@ class Xilinx7SeriesPlatform(TemplatedPlatform):
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"] = 1
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.

View file

@ -66,13 +66,15 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
[ -n "${{platform._toolchain_env_var}}" ] && . "${{platform._toolchain_env_var}}"
{{emit_commands("sh")}}
""",
# Vivado doesn't like constructs like (* keep = 32'd1 *), even though they mean the same
# thing as (* keep = 1 *); use -decimal to work around that.
"{{name}}.v": r"""
/* {{autogenerated}} */
{{emit_verilog()}}
{{emit_verilog(["-decimal"])}}
""",
"{{name}}.debug.v": r"""
/* {{autogenerated}} */
{{emit_debug_verilog()}}
{{emit_debug_verilog(["-decimal"])}}
""",
"{{name}}.tcl": r"""
# {{autogenerated}}
@ -177,6 +179,10 @@ class XilinxUltraScalePlatform(TemplatedPlatform):
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"] = 1
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.