草庐IT

基于Xlinx的时序分析、约束和收敛(6)----如何读懂vivado下的时序报告?

孤独的单刀 2023-04-20 原文

写在前面

        全系列:《基于Xilinx的时序分析、约束和收敛》目录与传送门

        在《基于Xlinx的时序分析、约束和收敛(3)----基础概念(下)》文章中写了一些时序分析的基础概念,同时还说了文章中提到的公式根本就不需要记忆,因为综合工具vivado会帮你把所有时序路径都做详尽的分析,你所需要做的就是理解概念。

        光说不练云玩家,今天就通过一个简单的工程来看下如何在vivado软件中查看时序报告。


1、建立工程与添加时序约束

        首先新建一个vivado的RTL工程,再添加一个Verilog文件,内容如下:

module test
(
    input               sys_clk	,
    input               rst  	,
    output reg [7:0]	cnt
);

always @(posedge sys_clk)begin
    if(rst)
        cnt <= 0;
    else
        cnt <= cnt + 1'b1;
end

endmodule

        这个工程要实现的功能非常简单,就是一个8bit的循环计数器。这是生成的功能框图:

        然后再往工程里添加一个时序约束文件timing.xdc,内容如下:

create_clock -period 10.000 -name sys_clk -waveform {0.000 5.000} [get_ports sys_clk]

        这句约束的意思是将输入的主时钟频率约束在100MHz,如果你不懂主时钟约束,可以参考《基于Xlinx的时序分析、约束和收敛(4)----主时钟约束

        管脚的绑定因为只是看时序报表不涉及具体的开发,所以就省去了(vivado自动分配,不影响看查看时序)。


2、时序报表

        工程新建完成后,点击综合、实现(完成布局布线)。然后点击实现implementation下的report timing summary,弹出的界面如下:

        按上图设置,点击OK,然后就出现了timing界面:

        timing界面左侧是时序路径分类,右侧是时序的一个总览,其中一些参数的含义如WNS以及TNS,WHS以及THS是我们需要着重关注的:

  • WNS:最差负时序裕量 (Worst Negative Slack)
  • TNS :总的负时序裕量 (Total Negative Slack),也就是负时序裕量路径之和
  • WHS :最差保持时序裕量 (Worst Hold Slack)
  • THS :总的保持时序裕量 (Total Hold Slack),也就是负保持时序裕量路径之和

       

        可以看到WNS为8.370ns,这表示这个工程中最差的那条时序路径的建立时间裕量是8.370ns,所以该设计是时序收敛的。如果时序不收敛,那么肯定是有WNS为负。

        而TNS为0代表不存在建立时间裕量为负的时序路径,这也表示设计是收敛的。如果设计不收敛,那么必然存在1条或多条建立时间裕量为负的时序路径,作为路径之和的TNS也就一定是一个负数。

        所以WNS描述设计中最差的时序路径的裕量情况,而TNS则描述设计中所有不收敛的时序路径的裕量情况。保持路径的分析类似。

        我们最需要关注的是intra-clock paths下sys_clk的setup和hold,这把具体的时序路径都穷举出来了:

        其中一些参数的意义如下:

  • slack:建立时间裕量
  • level:逻辑级数,这里1就表示在两个寄存器之间仅存在1个组合逻辑器件
  • fanout:表示从这一点连接到了几个目的端点,fanout = 1就表示连接了1个目的端点
  • from to:表示是哪两者之间的时序

        点击schematic就会出现设计的原理图:

       

        此时,点击某条路径,就会在原理图上高亮该条路径:

        上图以路径9为例,源端是cnt_reg【1】,目的端则是cnt_reg【5】,中间的数据路径经过了2个CARRY4,所以逻辑级数levels为2。

        

        双击某条路径,则可以打开其具体的路径分析(仍以路径9为例),由于报表很长,分为3个部分讲解:

        第1部分--总览:

  • slack:裕量,具体到这条路径就是建立时间裕量,裕量为8.370ns,表示这条路径是满足时序要求的
  • source:源端寄存器,即时序分析的起点,发射沿(Launch Edge)
  • destination:目的端寄存器,即时序分析的终点,锁存沿(Latch Edge)
  • path group:时序分析的时钟来源
  • path type:路径类型,此路径为建立时间的分析
  • requirement:时序要求,设定为100MHz,所以就是10ns
  • data path delay:组合路径的数据延时,包括组合逻辑器件的延时(logic)和布线延时(route)
  • logic levels:逻辑级数,即两个寄存器之间存在多少级组合逻辑
  • clock path skew:时钟到达目的寄存器和源寄存器之间的时间差值
  • clock uncertainty :时钟的不确定度,包括skew和jitter

       

        在讲第2部分和第3部分之前,先把建立时间裕量计算的这张模型图请出来,对照着理解会比较方便。

Data Arrival Time = launch edge + Tclk1 + Tco +Tdata 

Data Required Time = latch edge + Tclk2 - Tsu

Setup Slack = Data Required Time – Data Arrival Time

        第2部分由源端的时钟路径和数据路径组成:

        时钟路径就是时钟从起点到达源端寄存器时钟端口的路径,也就是Tclk1,映射到路径9的具体路线则是:FPGA的时钟管脚--布线--IBUF(这个是缓冲的,每个管脚都会自动添加,增加驱动能力)--布线--BUFG(全局时钟网络,可以减少时钟到不同寄存器之间的Skew,一般时钟管脚都会添加)--布线--源端寄存器时钟端口。从上图可以看到,把每一条细小的路径叠加后,时钟从IO口到源端寄存器的时间是 4.392ns。

        数据路径则是数据从源端寄存器的D端到目的寄存器的D端的路径,也就是Tco +  Tdata。Tco等于0.379ns,接下来的所有net+2个CARRY4则是组合逻辑的延迟即Tdata,计算得到Tco +  Tdata = 1.625ns。

        那么Tclk1 + Tco +  Tdata不就是数据的到达时间吗?加起来就是6.017ns。

        第3部分是目的端的时钟路径,也就是Tclk2:

        时钟路径就是时钟从起点到达目的端寄存器时钟端口的路径,也就是Tclk2,映射到路径9的具体路线则是:FPGA的时钟管脚--布线--IBUF--布线--BUFG--布线--目的寄存器。这些时间参数统统加起来就构成了数据的要求到达时间,即14.387ns。

        最后就可以算出建立时间裕量slack =   数据要求到达时间Data Required Time – 数据实际到达时间Data Arrival Time = 14.387ns - 6.017ns = 8.370ns。

        如果你想查看某一条路径在FPGA内部的具体分布,可以按下面操作:

       

        这样就把该路径标成了紫色高亮,然后在device视图下就很快可以找到了:


3、参考

        ug903,Vivado Design Suite User Guide--Using Constraints

        ug949,适用于 FPGA 和 SoC 的 UltraFast 设计方法指南

        ug906,Vivado Design Suite 用户指南--设计分析与收敛技巧


  • 📣博客主页:wuzhikai.blog.csdn.net
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵
  • 📣您有任何问题,都可以在评论区和我交流📞!
  • 📣创作不易,您的支持是我持续更新的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

有关基于Xlinx的时序分析、约束和收敛(6)----如何读懂vivado下的时序报告?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  7. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  8. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

  9. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  10. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

随机推荐