{"id":299,"date":"2025-07-19T07:18:22","date_gmt":"2025-07-19T06:18:22","guid":{"rendered":"https:\/\/blog.edgesmart.co.uk\/?p=299"},"modified":"2025-07-26T19:53:39","modified_gmt":"2025-07-26T18:53:39","slug":"vivado-timing-report-demystified-why-you-should-never-see-inter-clock-violations","status":"publish","type":"post","link":"https:\/\/blog.edgesmart.co.uk\/index.php\/2025\/07\/19\/vivado-timing-report-demystified-why-you-should-never-see-inter-clock-violations\/","title":{"rendered":"CDC-101.3: Why You Should Never See Inter-Clock Violations"},"content":{"rendered":"\n<p>In a well-constrained FPGA design, Vivado&#8217;s timing report should tell a clean story. So, if you\u2019re seeing <strong>inter-clock violations<\/strong>, it\u2019s not just a design issue \u2014 it&#8217;s a <strong>constraint failure<\/strong>. <\/p>\n\n\n\n<p>This post will focus on the <strong>real reason<\/strong> inter-clock violations appear in Vivado:<\/p>\n\n\n\n<p><strong>Because you haven\u2019t told Vivado what it <em>shouldn\u2019t<\/em> be analyzing.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Intra-Clock vs Inter-Clock Paths: Quick Refresher<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Type<\/th><th>Launch Clock = Capture Clock?<\/th><th>Timed by Vivado?<\/th><th>Should Fail?<\/th><\/tr><\/thead><tbody><tr><td>Intra-Clock<\/td><td>\u2705 Yes<\/td><td>\u2705 Yes<\/td><td>\u274c Ideally Not<\/td><\/tr><tr><td>Inter-Clock<\/td><td>\u274c No<\/td><td>\u26a0\ufe0f Maybe<\/td><td>\u274c Should Not Appear<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Intra-clock paths<\/strong> are valid timing paths and must be analyzed for setup\/hold.<\/li>\n\n\n\n<li><strong>Inter-clock paths<\/strong> (i.e., CDC paths) <strong>must be excluded from STA<\/strong> using proper constraints.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Why Inter-Clock Violations Should Never Be in Your Timing Report<\/h2>\n\n\n\n<p>Vivado doesn&#8217;t inherently know whether two clocks are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Asynchronous<\/strong> (e.g., clk_a and clk_b from separate oscillators)<\/li>\n\n\n\n<li><strong>Synchronous but unrelated<\/strong> (e.g., clk_100MHz and clk_125MHz)<\/li>\n\n\n\n<li><strong>Synchronous and phase-aligned<\/strong> (e.g., derived from the same PLL)<\/li>\n<\/ul>\n\n\n\n<p>So by default, <strong>Vivado assumes every clock might be related<\/strong> \u2014 and tries to time all paths between them. That includes <strong>cross-domain paths<\/strong> that have no deterministic phase relationship.<\/p>\n\n\n\n<p>This results in <strong>inter-clock timing analysis that is meaningless<\/strong> \u2014 and potentially misleading.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example:<\/h3>\n\n\n\n<p>Say you transfer a signal from <code>clk_A<\/code> to <code>clk_B<\/code>, using a proper CDC synchronizer. If you haven\u2019t added constraints to tell Vivado that these clocks are asynchronous, Vivado will:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Try to time the path<\/li>\n\n\n\n<li>Generate invalid setup\/hold paths between unrelated clock domains<\/li>\n\n\n\n<li>Show artificial violations<\/li>\n\n\n\n<li>Waste build time analyzing these false paths<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How to Correctly Handle Inter-Clock Paths<\/h2>\n\n\n\n<p>We will cover this in detail in our next blog post.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Synchronous Clocks that Are Still Not Safe<\/h2>\n\n\n\n<p>Sometimes, two clocks are generated from the same PLL but have different phase offsets or frequencies. Vivado assumes a relationship unless told otherwise. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes That Cause Inter-Clock Violations<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Mistake<\/th><th>What Happens<\/th><\/tr><\/thead><tbody><tr><td>Missing Constraints<\/td><td>Vivado tries to time async paths<\/td><\/tr><tr><td>Assuming Vivado detects CDC<\/td><td>It doesn&#8217;t \u2014 it needs explicit constraints<\/td><\/tr><tr><td>Using synchronizers without constraints<\/td><td>False violations still show<\/td><\/tr><tr><td>Not isolating multi-bit crossings<\/td><td>Timing paths report glitches\/violations<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why This Matters: Build Time &amp; Design Clarity<\/h2>\n\n\n\n<p>Every time Vivado tries to analyze a cross-clock path, it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Computes false arrival\/requirement times<\/strong><\/li>\n\n\n\n<li><strong>Uses internal resources for invalid paths<\/strong><\/li>\n\n\n\n<li><strong>Increases implementation run time<\/strong><\/li>\n\n\n\n<li><strong>Fills timing reports with noise<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This makes it harder to see <strong>real issues<\/strong> (e.g., intra-clock violations), and bloats the design effort.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Should Be in a Clean Timing Report?<\/h2>\n\n\n\n<p><strong>Intra-clock violations only<\/strong> (and ideally, none!)<br><strong>No inter-clock setup\/hold violations<\/strong><br><strong>Proper CDC constraints present<\/strong><br><strong>Safe crossing mechanisms<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tools That Help<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Vivado CDC Report<\/strong>:<br>Use <code>report_cdc<\/code> to find unguarded crossings.<\/li>\n\n\n\n<li><strong>Xilinx IP Integrator XPM FIFO \/ CDC blocks<\/strong>:<br>These auto-instantiate proper constraints.<\/li>\n\n\n\n<li><strong>Hierarchy-aware constraints<\/strong>:<br>Use hierarchical names in XDC to cleanly cut paths.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Summary: What to Do<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Check every inter-clock path<\/strong> in your report.<br>\u279c If it\u2019s a CDC, it should be cut and should be dealt with &#8220;properly&#8221;.<\/li>\n\n\n\n<li><strong>Don\u2019t tolerate inter-clock violations.<\/strong><br>\u279c They&#8217;re not real issues \u2014 just warnings that you haven\u2019t constrained CDC.<\/li>\n\n\n\n<li><strong>Use Vivado XPM based CDC Schemes<\/strong>.<\/li>\n\n\n\n<li><strong>Educate your team<\/strong><br>\u279c Inter-clock violations \u2260 timing failure. They = constraint failure.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Final Word<\/h2>\n\n\n\n<p><strong>Static Timing Analysis is only as smart as the constraints you provide.<\/strong><br>If Vivado is reporting inter-clock violations, it&#8217;s because it\u2019s trying to help \u2014 but it\u2019s looking in the wrong places.<\/p>\n\n\n\n<p><em>Don&#8217;t let false timing paths distract you from real design issues. Cut the noise. Constrain your CDC properly.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a well-constrained FPGA design, Vivado&#8217;s timing report should tell a clean story. So, if you\u2019re seeing inter-clock violations, it\u2019s not just a design issue \u2014 it&#8217;s a constraint failure. This post will focus on the real reason inter-clock violations appear in Vivado: Because you haven\u2019t told Vivado what it shouldn\u2019t be analyzing. Intra-Clock vs &hellip;<br \/><a href=\"https:\/\/blog.edgesmart.co.uk\/index.php\/2025\/07\/19\/vivado-timing-report-demystified-why-you-should-never-see-inter-clock-violations\/\" class=\"more-link pen_button pen_element_default pen_icon_arrow_double\">Continue reading <span class=\"screen-reader-text\">CDC-101.3: Why You Should Never See Inter-Clock Violations<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-299","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/299","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/comments?post=299"}],"version-history":[{"count":9,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/299\/revisions"}],"predecessor-version":[{"id":317,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/299\/revisions\/317"}],"wp:attachment":[{"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/media?parent=299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/categories?post=299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.edgesmart.co.uk\/index.php\/wp-json\/wp\/v2\/tags?post=299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}