对于数字系统而言,建立时间(setup time)和保持时间(hold time)是数字电路时序的基础。数字电路系统的稳定性,基本取决于时序是否满足建立时间和保持时间。所以,这里用一整节的篇幅,来详细的说明建立时间和保持时间的概念。
建立时间就是时钟触发事件来临之前,数据需要保持稳定的最小时间,以便数据能够被时钟正确的采样。
保持时间就是时钟触发事件来临之后,数据需要保持稳定的最小时间,以便数据能够被电路准确的传输。
可以通俗的理解为:时钟到来之前,数据需要提前准备好;时钟到来之后,数据还要稳定一段时间。建立时间和保持时间组成了数据稳定的窗口,如下图所示。

《1.3 门延迟》中已经介绍过一种简单的 D 触发器。下面再看一种典型的上升沿 D 触发器,来说明建立时间和保持时间的由来。

G1~G4 与非门是维持阻塞电路,G5~G6 组成 RS 触发器。
时钟直接作用在 G2/G3 门上,时钟为低时 G2/G3 通道关闭,为高时通道打开,进行数据的采样传输。
但数据传输到 G2/G3 门之前,会经过 G4/G1 与非门,将引入时间延迟。引入建立时间的概念,就是为了补偿数据在 G4/G1 门上的延迟。即时钟到来之前,G2/G3 端的输入数据需要准备好,以便数据能够被正确的采样。
数据被时钟采样完毕后,传输到 RS 触发器进行锁存之前,也需要经过 G2/G3 门,也会引入延迟。保持时间就是为了补偿数据在 G2/G3 门上的延迟。即时钟到来之后,要保证数据能够正确的传输到 G6/G5 与非门输入端。
如果数据在传输中不满足建立时间或保持时间,则会处于亚稳态,导致传输出错。
下图是一个典型的触发器到触发器之间的数据传输示意图。其中 "Comb" 代表组合逻辑延迟,"Clock Skew" 表示时钟偏移,数据均在时钟上升沿触发。

时钟到来之前,数据需要提前准备好,才能被时钟正确采样,要求数据路径 (data path) 比时钟路径 (clock path)更快,即数据到达时间(data arrival time)小于数据要求时间(data required time)。则建立时间需要满足的表达式为:
Tcq + Tcomb + Tsu <= Tclk + Tskew (1)
各个时间参数说明如下:
对上式进行变换,则理论上电路能够承载的最小时钟周期和最快时钟频率分别为:
最小时钟周期 = Tcq + Tcomb + Tsu - Tskew 最快时钟频率 = 1 / (Tcq + Tcomb + Tsu - Tskew)
时钟到来之后,数据还要稳定一段时间,这就要求前一级的数据延迟(data delay time)不要大于触发器的保持时间,以免数据被冲刷掉。则保持时间需要满足的表达式为:
Tcq + Tcomb >= Thd + Tskew (2)
各个时间参数说明如下:
由式 (1) (2) 可以推导出时钟偏移、组合逻辑延迟及时钟周期的约束。
建议大家只需要记住这 2 个最基本的约束条件表达式,需要求取其他参数约束时,再进行推导,以免各种推导造成记忆混乱。
一个关于建立时间和保持时间的复杂时序图如下所示。
其中,绿色部分表示建立时间的裕量(margin),蓝色部分表示保持时间的裕量。时间裕量,其实就是电路在满足时序约束的条件下,不等式 (1) 或 (2) 两边时间的差值。
建立时间裕量为:(时钟路径时间)-(数据路径时间) 保持时间裕量为:(数据延迟时间) - (保持时间 + 时钟偏移)
该图只是便于理解建立时间和保持时间约束条件的推导。如果这里会造成记忆混乱,建议不要深究(^_^)。

为更好的理解建立时间和保持时间的概念,也为面试或工作提供方便,这里列举一些典型的建立时间和保持时间的试题,以供参考。
例1:
考虑线网延迟,某电路各种延迟值(单位:ns)如下,时钟周期为 15ns,请判断该电路的建立时间和保持时间是否存在 violation ?

解:
这里涉及了延迟值的最大值和最小值。
因为要求时序约束恒成立,所以式 (1) (2) 的变形为:
max (data path time) <= min (clock path time) min (data delay time) >= max (Thd + Tskew)
建立时间检查:
max (data path time) = 2 + 11 + 2 + 9 + 2 + 2 = 28ns min (clock path time) = 15 + 2 + 5 + 2 = 24ns
因此建立时间存在 violation。
保持时间检查:
min (data delay time) = 1 + 9 + 1 + 6 + 1 = 18ns max (Thd + Tskew) = 3 + 3 + 9 + 2 = 17ns
因此保持时间不存在 violation,裕量(margin)为 1ns。
此例不能生硬的去照搬建立时间和保持时间的表达式,而要从数据路径、时间路径、数据延迟等概念去建立约束条件。所以,各种时序约束条件还要根据实际电路去分析。
例2:
一道知名公司的面试题:时钟周期为 T, 第一级触发器 D1 建立时间最大值为 T1max,最小值为 T1min。组合逻辑最大延迟为 T2max, 最小值为 T2min。问:第二级触发器 D2 的建立时间和保持时间应该满足什么条件?
解:
第二级的建立时间和保持时间和第一级触发器没有直接关系,所以这里的 T1max 和 T1min 是迷惑项。
例题中也没有给出时钟到 Q 端的延迟和时钟偏移,这里也不用考虑。
结合例 1 的指示,所以 D2 建立时间 Tsu 和保持时间 Thd 应该满足:
T2max + Tsu <= T T2min >= Thold
即
Tsu <= T - T2max Thold <= T2min
此例中很多延迟类型没有考虑。建立时序约束条件时,还需要根据已知条件懂得取舍。
例3:
一种简单的分频电路如下所示。该触发器建立时间为 3ns, 保持时间为 3ns, 逻辑延迟为 6ns,两个反相器延迟为 1ns,连线延迟为0。则该电路的最高工作频率是多少?

解:
这里的逻辑延迟要理解为时钟端到 Q 端的延迟,一定要注意不是电路中的组合逻辑延迟。
因为触发器 Q 端和 D 端连接,可以理解为两个触发器直接进行传输,所以 data path 没有组合逻辑延迟,只有一个反相器延迟。
因为只有一个钟,所以也没有时钟偏移,clock path 的反相器延迟也是迷惑项。
所以,时序约束条件为:
Tcq + Tbuf + Tsu <= Tclk
可得该电路最高工作频率为:
1 / (6ns + 1ns + 3ns) = 100Mhz。
此例是一个触发器自身到自身的反馈,一定要分析好数据路径和时钟路径,下面再看一道此类型的扩展例题。
例4:

解:
该电路数据路径和时钟路径上均有延迟,为达到与触发器相同建立时间和保持时间的条件约束,则触发器 D 端和时钟端 CK,以及等效的数据端 Data 和时钟端 Clock 时序图如下(我已经很努力在往简洁的方向上画了~_~):

(1) 由图可知:
该电路固有的建立时间为:2.1 + 2 - 1.2 = 2.9ns
固有的保持时间为:1.2 + 1.5 - 2.1 = 0.6ns
由此可知,数据路径的延迟会增加电路固有的建立时间,但是会减少电路固有的保持时间。而时钟偏移会减少电路固有的建立时间,增加电路固有的保持时间。
偷偷告诉你,求取电路固有的建立时间和保持时间,其实就是求取时间裕量的过程。
(2) 此电路仍然是自身到自身的反馈电路。所以没有时钟偏移,也无需考虑 T1= 0.9ns 的延迟。所以最高工作频率为: 1 / (1.8 + 1.2 + 2)ns = 200MHz
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查
这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build
我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实
在Ruby中,以毫秒为单位获取自纪元(1970)以来的当前系统时间的正确方法是什么?我试过了Time.now.to_i,好像不是我想要的结果。我需要结果显示毫秒并且使用long类型,而不是float或double。 最佳答案 (Time.now.to_f*1000).to_iTime.now.to_f显示包含十进制数字的时间。要获得毫秒数,只需将时间乘以1000。 关于ruby-以毫秒为单位获取当前系统时间,我们在StackOverflow上找到一个类似的问题:
我想知道我应该如何着手这个项目。我需要每周向人们发送一次电子邮件。但是,这必须在每周的特定时间自动生成并发送。编码有多难?我需要知道是否有任何书籍可以提供帮助,或者你们中的任何人是否可以指导我。它必须使用rubyonrails进行编程。因此有一个网络服务和数据库集成。干杯 最佳答案 为什么这么复杂?您只需安排工作。您可以使用Delayed::Job例如。Delayed::Job让您可以使用run_at符号在特定时间安排作业,如下所示:Delayed::Job.enqueue(SendEmailJob.new(...),:run_
我在ruby1.9.3p0上运行rails3.2.1和rspec2.8.1,在运行我的测试时它显示负时间值。这很烦人,因为我正在尝试优化我的测试。Running:spec/models/transaction_spec.rb................................................Finishedin-7603162.49414seconds我已经尝试将rspec更新到2.9.0,但这没有帮助。 最佳答案 你在使用timecopgem吗?确保在卡住后Timecop.return。或者你在某处
在我的场景中,Logstash收到的系统日志行的“时间戳”是UTC,我们在Elasticsearch输出中使用事件“时间戳”:output{elasticsearch{embedded=>falsehost=>localhostport=>9200protocol=>httpcluster=>'elasticsearch'index=>"syslog-%{+YYYY.MM.dd}"}}我的问题是,在UTC午夜,Logstash在外时区(GMT-4=>America/Montreal)结束前将日志发送到不同的索引,并且索引在20小时(晚上8点)之后没有日志,因为“时间戳”是UTC。我们已
关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭11年前。Improvethisquestion我不经常使用ruby-通常它加起来相当于每两个月或更长时间编写一次脚本。我的大部分编程都是使用C++进行的,这与ruby有很大不同。由于我与ruby之间的差距如此之大,我总是忘记语言的基本方面(比如解析文本文件和其他简单的东西)。我想每天练习一些基本的东西,我想知道是否有一些我可以订阅的网站,并且会向我发送当天的Ruby问题或类似的东西。有人知道这样的站点/Internet服务吗?