Meeting timing constraints is a crucial necessary condition for guaranteeing that the logic will reliably behave as designed. Even so, the common convention for logic design tools is that a failure to meet timing is conveyed to the user only as a warning, possibly a critical warning. Other indications are often given in GUI tools, and yet, there is nothing stopping the user from creating a bitstream file with the flawed implementation, which may or may not work. Or maybe work occasionally.

Proper design practices require checking the reports and build logs on every implementation. But FPGA designers being humans after all, it’s easy to forget looking for this confirmation. Some don’t even know that they should.

So the idea is to make Vivado fail the implementation if timing wasn’t met, in addition to the critical warning it issues in this case.

The script

Vivado allows running Tcl scripts on certain stages in the implementation (”hooks”). This script can be used to turn a timing failure into an error. This doesn’t only draw the user’s attention properly, but also prevents the generation of a bitstream. There’s no need to check the timing report anymore — if a bitstream file is created, it’s fine. Assuming that the timing constraints are in effect, of course.

This is the script:

# Halt the flow with an error if the timing constraints weren't met

set minireport [report_timing_summary -no_header -no_detailed_paths -return_string]

if {! [string match -nocase {*timing constraints are met*} $minireport]} {
    send_msg_id showstopper-0 error "Timing constraints weren't met. Please check your design."
    return -code error

This script should run when Vivado has exhausted its efforts to meet timing. By default, this last phase is routing, in which case the hook should be made after routing has completed, as follows.

Assuming that the script is stored in a file named showstopper.tcl, it’s easily added as a hook on the current project’s implementation run (impl_1) with the following command in the Tcl console:

set_property STEPS.ROUTE_DESIGN.TCL.POST "/path/to/showstopper.tcl" [get_runs impl_1]

If (and only if) post-route physical optimization is enabled (not the default on Vivado 2014.1), the hook should be put on that last stage instead:

set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.TCL.POST "/path/to/showstopper.tcl" [get_runs impl_1]

The post-route optimization will be useless otherwise, as it won’t get the chance to improve the timing if it wasn’t good enough after routing.

On the other hand, if the script is hooked on a phase that isn’t enabled, it’s never called.

The name “impl_1″ is the one that appears in the “Design runs” tabs at the bottom of Vivado. If you haven’t made modifications on the project’s runs, this is the one in effect by default.

To set this up (or remove the hook) with the GUI interface, click “Project Settings” under “Project Manager” in the Flow Navigator. Choose the “Implementation” button, and scroll down to the settings for “Route design”. The hooked script is related to for this implementation phase.

Verifying that the script is executed

In order to verify that the check indeed takes place during an implementation, the following line should be found in the build’s log when the design is implemented:

source /path/to/showstopper.tcl

This line appears in the Log tab, but not in the Message tab.

How it works

The script itself generates a minimal timing report by calling report_timing_summary, and stores it as a string in the variable $minireport. It searches the string for the substring “timing constraints are met”. If that substring doesn’t exist in the file, a timing failure error is reported on the Message tab, and the script quits with a failure status, making Vivado fail the implementation.