tag 标签: 小梅哥

相关帖子
相关博文
  • 热度 10
    2019-9-4 22:10
    9591 次阅读|
    5 个评论
    小梅哥FPGA时序分析笔记(6.2)深入现象看本质——庖丁解牛之FPGA内数据传输模型
    通过上一节,我们了解了 FPGA 内部数据的传输形式,接下来我们就可以根据上一节的内容来总结一下 FPGA 内部的数据传输模型了。 时钟和数据传输路径 通过上一节内容中,我绘制的那个 FPGA 内部数据在逻辑单元间的传输模型,我们可以提取归纳出一个通用的 FPGA 内部信号传输模型,如下图所示: 根据上图,可以概括出以下几个关键点: 1、 数据总是从一个 D 触发器( REG1 )传到另一个 D 触发器( REG2 ),我们称数据发出 D 触发器为源寄存器,数据接收 D 触发器为目的寄存器 2、 数据在传输过程中,可能参与多次组合逻辑变换 3、 数据在传输过程中,需要经过可编程互联线传递 4、 分析信号在两个寄存器之间的传递时,需要保证这两个寄存器的时钟信号是同源时钟。 针对第四点,需要补充的是,虽然通过上图可以看到,源寄存器和目的寄存器的时钟为同一个,那为啥要说是同源时钟,不说同一个时钟呢。其实,相信很多人也都知道,在实际使用中,有可能两个寄存器的工作时钟信号并非同一个。典型的例如一个 PLL 输出的两个时钟分别作为目的寄存器和源寄存器的时钟,这种情况下看似时钟不同,但是实际上在分析时,起点都是从 PLL 的时钟输入端开始,而从时钟输入到 PLL 的两个输出时间会算入时钟路径,因此本质上还是同一个时钟,所以上面说的是要求两个时钟是同源即可。 D 触发器基本概念 好了,到此为止,我们已经引出了 FPGA 时序分析的基本模型,接下来,就有必要聊聊,这个模型里面的哪些内容和参数会影响到我们的设计质量。 在正式讲解这个模型之前,我们还是先来回顾一下什么是 D 触发器,下图为一个 D 触发器的典型符号图。 D 触发器概念: 1. D 触发器是一个具有记忆功能的,具有两个稳定状态的信息存储器件,是构成多种时序电路的最基本逻辑单元,也是数字逻辑电路中一种重要的单元电路。 2. D 触发器在数字系统和计算机中有着广泛的应用。触发器具有两个稳定状态,即 "0" 和 "1" ,在一定的外界信号作用下,可以从一个稳定状态翻转到另一个稳定状态。 3. D 触发器在 CP( 时钟脉冲 ) 的前沿(正跳变 0 → 1 )发生翻转,触发器的次态取决于 CK 的脉冲上升沿到来之前 D 端的状态,即次态 =D 。因此,它具有置 0 、置 1 两种功能。由于在 CK=1 期间电路具有维持阻塞作用,所以在 CK=1 期间, D 端的数据状态变化,不会影响触发器的输出状态。 在上面的介绍中,我们需要提取出以下几个关键信息: 1、 D 触发器具有 2 个稳定状态“ 0 ”和“ 1 ”,在时钟( CK )的上升沿, D 端的数据被更新到 Q 端。 2、 在时钟的高电平期间, D 端的数据变化。 Q 端的数据不会跟着变化。 针对第一条信息,我们可以知道 D 触发器在时钟的上升沿时将 D 端的数据存起来,所以,要想保证 D 端的数据能被正确的存起来,需要确保 D 端的数据在时钟上升沿时刻是稳定的,不能处于变化时期。假如在时钟上升沿的那个点,刚好 D 端的数据也在变化,那就真的不知道存储起来的究竟是 0 还是 1 和。而且,理想的 D 触发器,我们认为时钟信号从 0 到 1 的变化所需时间无限短,那么这个上升沿时间究竟是多长呢?理想的时钟上升沿可以被认为是从 0 到 1 这个变化的过程所需的时间是无限短的,但是实际在电路中,这个变化还是需要一定的时间的,不可能无限短。而且 D 触发器也不是真的就只需要在时钟上升沿的那一个时间点需要 D 端的数据是稳定即可,从实际的器件工作情况来看,任何一个 D 触发器要想在时钟的上升沿将 D 端的数据寄存并输出到 Q 端,有 2 个关键的时间参数需要保证。 建立时间,保持时间,输出延迟 为了更加直观的说明这个问题,还是先画一张图说明。 对于实际的 D 触发器来说,为了保证在时钟的上升沿能够正确的将 D 端的数据寄存并输出到 Q 端,需要满足以下两点: 1. D 端的数据必须在时钟上升沿到来之前的一定时间内就已经保持稳定,该时间被称为 D 触发器的建立时间 ( Tsu ) 2. D 端的数据必须在时钟上升沿到来之后的一定时间内继续保持稳定,该时间被称为 D 触发器的保持时间 ( Th ) 如果不能同时满足上述两个条件,那么 D 端的数据就可能无法正确的被寄存并输出至 Q 端。 同时,对于 D 触发器来说, D 端的数据也不可能会在时钟上升沿出现的那一刻就立即更新到 Q 端,从时钟的上升沿到 D 端的数据稳定出现在 Q 端,也有一个时间,该时间称为寄存器的时钟到输出延迟 ( Tco ) 为了防止有人钻牛角尖问为啥会是这样的情况,这里统一回复:这就是 D 触发器的实际电路结构决定的,你也可以认为是通过测量手段测量出来的经验值。而且,从更深次的来说,如果 D 触发器没有这个特性,而是真正理想的特性,那么 D 触发器将没有存在的意义。 FPGA 内数据传输典型时序 好了,通过上面的介绍,相信大家已经对 D 触发器的工作特性有了一个了解了。那么接下来,我们就继续来看,在 FPGA 中,信号从一个寄存器传到另一个寄存器时,其典型时序是哪样的。 下图就是 Altera 的手册中 FPGA 典型的数据从寄存器到寄存器的传输时序图。 按照惯例首先我们还是对该图进行分析,提取出几个我们应该关心的问题。 首先看时钟,上图中可以看到,两个寄存器的时钟脚都是连在一起的,且来自同一个外部 Pin ,只是,从外部 pin 到寄存器 1 ( REG1 )和寄存器 2 ( REG2 )的时钟端口,中间都是有一段路要走的。既然要走一段路,就必然需要花费时间,所以图中也可以看到,从外部 pin 到寄存器 1 ( REG1 )的时间被标记为了 Tclk1 ,同样的,从外部 pin 到寄存器 2 ( REG2 )的时间被标记为了 Tclk2 ,这两个时间都是真实存在的,且并不一定相等。 可能到这里,有些同学就要质疑了,不是说 FPGA 的时钟信号,如果走全局时钟网络,那么到达每一个寄存器的时间都是几乎一样的吗?其实,这种说法是不严谨的,全局时钟网络也不能保证该时钟到达每个寄存器的时钟脚的延迟都是严格一样的,只能保证到达各个寄存器的延迟都尽量的小,且时钟质量尽量的高。至于到达每个寄存器的延迟,肯定是存在,且没有任何一个地方能够保证是完全相同的,只是说可能差距不大。既然现在是在分析微观的信号传输,所以这些微小的差距也都是需要考虑的。 其次看数据传输路径,一开始,数据存在于 REG1 的 D 端口上,当时钟上升沿到达 REG1 时,经过 Tco 时间, D 端数据才会到达 REG1 的 Q 端。 最后, REG1 的 Q 端的数据还需要经过 FPGA 内部的可编程连线,还有可能需要参与各种逻辑运算,才能到达目标寄存器,也就是 REG2 的 D 端,在从 REG1 的 Q 端传到 REG2 的 D 端过程中经过的各种连线和组合逻辑功能,也都是需要耗费时间的,这些时间在分析时统称为组合逻辑延迟,标记为 Tdata 。 那么,在这样的传输模型中,这些参数又将怎样影响我们的设计呢?为了不让大家越看越迷糊,这里先按照笔者平常调试工程时候的感觉,使用典型值做一个假设的情形。 假设: a) CLK 信号的频率为 200MHz ,既周期为 5ns b) REG1 的 Tco 时间为 0.5ns c) REG1 的 Q 端到 REG2 的 D 端,组合路径延迟 Tdata 为 6ns d) REG2 的建立时间 Tsu 为 0.8ns 那么这个设计,能够保证 REG2 正确的接收 REG1 发出的数据吗? “ 不能 ” ,可能马上就会有人脱口喊出这个答案。理由为: 1. 从时钟到达 REG1 的时钟端口,到 REG1 的 D 端数据能够出现在 Q 端,首先要经过寄存器输出延迟 Tco , 2. 然后数据再从 REG1 的 Q 端传到 REG2 的 D 端需要经过组合逻辑延迟 Tdata , 3. 再然后,前面已经说了,要想 REG2 能够在时钟上升沿时寄存 D 端口上的数据,需要数据在时钟上升沿到来之前最少 Tsu 时间就稳定下来, 4. 而根据上述假设, Tco + Tdata + Tsu 的时间为 7.3ns ,已经远远超过了一个时钟周期 5ns ,也就是说,当时钟上升沿到达 REG2 的时钟端口时,数据还没有就绪,所以无法被正常接收 ” 。 上述回答有理有据,貌似很正确,不瞒大家说,我在很长一段时间内,也是这样认为的。但是,上述分析却忽略了关键的一点,那就是时钟信号传输也是有延时的。接下来,我们把上述假设完善一下:假设时钟信号从外部 pin 传输到 REG1 的时钟端需要 1ns ,而传输到 REG2 时钟端需要 3.5ns ,那么这个时候,这个设计能够保证 REG2 正确接收 REG1 发出的数据吗? 答案是肯定的,此种情况下, REG2 就能正确接收 REG1 发出的数据了,因为真实的传输路径中,不仅有数据传输延迟,还有时钟延迟,而时钟延迟,又是大家在分析时候非常容易忽略的一类。毕竟大家在刚开始学习 FPGA 的时候,一直潜移默化的认为,时钟信号到达所有寄存器的时间都是一样的。所以,在这里,通过这样一种打脸的方式,希望大家能够纠正这种错误的认识,在分析信号传输的时候,不仅要分析数据传输延迟,还要分析时钟传输延迟。 好了,借着强调时钟延迟重要性的便道,又凑了大半页篇幅。接下来,我们终于可以用最有说服力的波形说话了。 上图很好的展示了我们前面分析的模型中各个节点的时序波形。 l CLK 认为是时钟输入脚输入的时钟信号。 l REG1.CLK 为 CLK 到达 REG1 的波形,相对于 CLK ,有一个延迟,设为 Tclk1 。 l REG1.Q 为 REG1 的输出端数据值,从 REG1.CLK 上升沿到来,到其值更新并稳定下来,存在一定的延迟,该延迟值名为 Tco 。 l REG2.D 为 REG2 的输入端 D 端口上的数据波形,该信号由 REG1.Q 经过组合逻辑和内部连线传递后到达,因此 REG1.Q 到达 REG2.D 这个时间是数据传输时间,为 Tdata 。 l RERG2.CLK 是 CLK 到达 REG2 的波形,相对于 CLK ,有一个延迟,设为 Tclk2 。 好了,到此时,相信又有人要问了,嗯,不错,你说的我都明白了,那么,然后呢,你说的这一些,与我的设计和约束有什么关系呢?难道我需要用你这个图来指导我约束?我要约束什么呀?这个嘛,说来话长。欲知后事如何,且听下回扯淡。
  • 热度 12
    2019-9-1 21:28
    12691 次阅读|
    2 个评论
    小梅哥FPGA时序分析笔记(6.1)深入现象看本质——庖丁解牛之FPGA可编程原理
    上一次发博客,已经是2个月前了,这中间两个月,干了件很有意义的事情,尤其是对于自己来说,感觉学到了非常多的知识和经验,每天都很忙,忙到没时间逛网站博客,终于忙完闲下来了,连载的事情可不能忘,终于可以书接上回了。 经过前面的几节内容,相信大家已经对时序约束的魅力有了一个大致的印象,而且也都认同了时序约束对于保证一个系统能够可靠运行起着至关重要的作用。那么,为什么时序约束能够解决这些问题?时序约束的原理又是什么?我们又该如何正确的去进行时序约束,以达到想要的性能呢?接下来,我先把我学习时序约束的时候对于时序的理解笔记分享出来。 要把这些问题都研究清楚,不能急,我们首先得知道, FPGA 中是如何实现相应的逻辑功能的。 FPGA 可编程原理 FPGA 是如何实现现场可编程的?大家可能都知道, FPGA 是基于查找表原理实现任意组合逻辑的,那么时序逻辑呢?大家又都知道, FPGA 中有很多的 D 触发器,既然有了 D 触发器,加上时钟,就能实现时序逻辑了。那么不同的 D 触发器之间怎么连接起来呢?答案就是内部连线。 FPGA 内部有大量的长的短的连线,这些连线能够将不同的 LE 的输入和输出连接起来。这样,假设每个 LE 实现一个单独的功能,然后多个 LE 的输入输出按照一定的规则使用连线连接起来,就能实现复杂的功能了。光写文字估计大家越看越迷糊,那我就画图吧。 上图为一个最最基本的 FPGA 架构,且不包括 I/O 块。通过上图右半部分可以看到,一个 FPGA 中以阵列的形式分布着很多的小逻辑块,这个块就是我们熟知的逻辑单元( Logic Elements ,简称 LE ),这些所有的小块共同构成了 FPGA 的可编程逻辑门阵列,而为了把不同的逻辑单元连接起来, FPGA 中分布着大量的可编程互联资源,通过对这些可编程互联资源编程,就能够把各个不同的逻辑单元的输入输出连接起来,在上图的上半部分就演示了部分互联资源将多个逻辑单元按照一定的规则连接了起来。这样看起来,是不是和我们的电路板模型非常的相似,在电路板上有各种芯片,每个芯片都有很多的管脚,通过 PCB 板走线把这些管脚按照正确的方式连接到一起,就能够形成一个可以实现特定功能的电路板了。 那么,上面说到的逻辑单元又是什么呢?在上图的左半部分,绘制了一个逻辑单元的内部示意图(简化版),可以看到,一个逻辑单元由一个查找表( LUT )和 D 触发器( DFF )组成,当然,真实的逻辑单元里面可能还包含了很多其他辅助的电路,这里省略。 LUT 有 4 个输入端口( a 、 b 、 c 、 d ),一个输出端口( o )。 LUT 的输出 o 可以送给 D 触发器的数据输入端口 D ,也可以不经过 D 触发器直接输出。当然了,实际上 D 触发器的输入也可以不来自于 LUT 的输出,而来自于其他逻辑单元的输出。不经过 D 触发器输出,那这个 LE 实现的就是一个纯组合逻辑,经过 D 触发器输出,那这个 LE 实现的就是一个时序逻辑。 一个 LUT 里面可以实现各种组合逻辑,与门、或门、非门等等, LUT 里面实际有 16 个 1bit 的基于 SRAM 结构的存储器,能够对应 a 、 b 、 c 、 d 四个输入的逻辑组合的所有可能, Quartus 通过向这 16bit 的存储器里写入不同的初始值,就能使 a 、 b 、 c 、 d 四个输入在不同的状态下输出不同的逻辑结果,从而实现使用一个 LUT 实现各种组合逻辑的功能。 既然 FPGA 已经能够实现各种的基本逻辑门功能了,而且还有 D 触发器能够实现时序逻辑功能,那么,要实现复杂逻辑功能,无非就是把众多的基本逻辑功能联合起来,从而达到复杂逻辑功能的目的。所以,我们可以认为, FPGA 中实现复杂的逻辑功能,大概就是下面的样子(当然下图所示的逻辑远远算不上复杂逻辑,只是我自己简画的一个 FPGA 内部数据在逻辑单元间的传输模型图)。 我们先对上图进行一个简单的分析,从图中可以归纳出以下信息: l 整个设计有 6 个输入信号( a, b, c, d, e, clk )一个输出信号( out ) l 5 个输入信号 a, b, c, d, e 进入设计后先分别使用一个 LE ( LE0~LE4 )中的 D 触发器打了一拍(设经过 D 触发器后的信号分别为 r_a, r_b, r_c, r_d, r_e ) l D 触发器输出的 r_a, r_b, r_c, r_d 信号进入一个 LE ( LE-5 )中的 LUT 进行了相关的逻辑运算后直接输出,没有经过 LE 的 D 触发器 , 。设 LUT 的输出信号名称为( w_g ) l LE-5 的输出信号 w_g 与 LE-4 的输出信号 r_e 再送入一个 LE ( LE6 )中进行逻辑运算, LUT 的运算结果输出命名为 w_h l w_h 进入 LE6 的 D 触发器,经过该触发器寄存一拍后输出,输出信号命名为 r_o 所以,通过上图我们可以清楚的看到, FPGA 中各种复杂的逻辑,都是使用基本的逻辑单元( LE )构建各种特定的简单的组合逻辑或时序逻辑功能,然后使用片上的可编程互联线资源将这些独立的逻辑功能连接起来实现的。事实上,上图逻辑,可以对应下述使用 Verilog 描述的电路: module logic ( input clk , input a , input b , input c , input d , input e , output out ); // 定义 5 个内部寄存器 reg r_a , r_b , r_c , r_d , r_e ; wire w_g , w_h ; // 输出寄存器 reg r_o ; // 将 IO 输入信号首先使用 D 触发器寄存 always @( posedge clk ) begin r_a <= a ; r_b <= b ; r_c <= c ; r_d <= d ; r_e <= e ; end // 第一级组合逻辑 assign w_g = r_a & r_b | r_c | r_d ; // 第二级组合逻辑 assign w_h = r_e | w_g ; // 寄存器输出 always @( posedge clk ) r_o <= w_h ; // 将寄存器输出信号连接到输出端口 assign out = r_o ; endmodule 当然了,不是说上面的图只能对应这一段代码,毕竟 LUT 内部实现的组合逻辑功能是可以不同的,而组合逻辑功能不同,对应实现的功能也就不一样了。上述代码只是结构上符合上图。 好了, FPGA 的可编程原理讲到这里就 Over 了,这里所谓的 Over ,不是说知识点讲完了,而是有了这些内容,已经差不多可以辅助我们进行下一步的传输分析了,更多 FPGA 可编程原理性的知识,这里暂时没用到,也就不介绍了。 嗯哼,一本正经的敷衍完事了。下楼买泡面去罗。呲溜。
  • 热度 12
    2019-7-2 08:57
    11741 次阅读|
    5 个评论
    小梅哥FPGA时序分析笔记(五)I/O约束显神威——深入龙潭
    大家一定对我上一节的突然结尾表示一脸茫然:我是来学习时序约束的,然后你告诉我时序约束里面 IO 约束很重要,然我又跟着你的文章继续往下看,本以为你就要讲如何进行 IO 约束了,结果呢,你一个取反时钟就把我们打发了,不仁义呀。 不仁义那就不仁义吧,不过话又说回来,这种取反时钟的方式解决时序问题,貌似并非是个例,其他很多地方也都有这种操作,比如以太网 GMII 接口也有这么干的,高速 DAC 输出也有这么干的,不过有时候是将时钟取反了输出,而有时候则是在 FPGA 内部使用下降沿作为触发器的采样信号,形式不同,原理一样,效果一样。只是,这么干的人多了,貌似就成了公理,反而我写一个使用时钟上升沿触发寄存器,同时不给时钟取反就直接驱动 DAC 或者以太网 GMII 的程序,会被人质疑写错了。既然如此,那就让事实再次来说话吧。还是以第四节讲到的 VGA 显示的程序为例,这一次,我们不再用取反时钟的方法,而是使用时序约束这种理论上的正统方法来解决这个问题。 先介绍下整个系统吧。如下图所示,在 FPGA 中,编写了一个名为 disp_driver 的模块,用来产生 VGA 时序并将每个像素的三元色值分别输出。同时使用了 PLL 的 clk 端口输出 74.5MHz 的时钟信号,既提供给 disp_driver 驱动逻辑使用,也作为 Disp_CLK 引出,接到 ADV7123 芯片的 CLOCK 引脚上,作为数据同步时钟。 既然 Disp_CLK 是输出时钟信号,那么就需要对其加上约束。约束方法很简单,以 PLL 的 CLK 端口为主,创建一个生成时钟,并指定到 Disp_CLK 引脚上即可。约束命令如下所示: create_generated_clock -name {CLK_Display} -source }] -master_clock {pll|altpll_component|auto_generated|pll1|clk } 注意,由于 页面 排版问题,上面的代码是被自动换行了,实际在 sdc 文件中,是不存在换行的 既然定义了一个时钟且绑定到了具体的输出信号上,为了让 Quartus 能够对该信号进行分析,需要对该信号添加输出约束。约束命令如下所示: set_max_delay -from }] -to 5.000 set_min_delay -from }] -to 1.000 接下来,就是对输出给 ADV7123 的数据( R 、 G 、 B )和控制( HS 、 VS )信号进行输出约束了。约束内容如下: set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 set_output_delay -add_delay -min -clock -1.500 set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 set_output_delay -add_delay -min -clock -1.500 set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 ] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 }] set_output_delay -add_delay -min -clock -1.500 }] set_output_delay -add_delay -max -clock 0.200 set_output_delay -add_delay -min -clock -1.500 好了,到这里,对 FPGA 输出给 ADV7123 的信号的约束就算是 OK 了,接下来全编译工程,然后下载到开发板中,就可以观察到相应的现象了。 如果不出意外,通过此种约束过后。全编译得到的结果下载到开发板后, VGA 显示器上显示的摄像头采集的图像又是完全正常的了,不会再有发霉的迹象,和之前将 PLL 的 clk 信号取反后接给 Disp_CLK 的现象是一样 OK 的了。至此,验证了使用 IO 约束的方法是确实可以解决这个问题的,或者,也可以说是验证了前面说的图像异常问题确实是由 IO 时序不满足导致的。 好了,到这里,本节内容就算是结束了,深入龙潭并看到了真龙。 纳尼?起这么个让人热血沸腾的名字,结果你就让我看这个?眼看着你进深入龙潭,想象着你与恶龙搏斗的场景,本以为你德胜归来,好歹也让我们一睹真龙,结果你就拧条水蛇出来跟我们说你看到龙了?我们就这样静静的看着你给出一串代码,然后编译两次工程,你就告诉我们通过约束解决了?不,我们想看的不是这个,而是想看你如何一步一步进行约束的,更想知道你的约束中这些参数是怎么来的,最想知道你为啥要这样约束。 嘿嘿嘿,如果你真的有了上述疑问,我就真的是挺开心了,证明我真的提起了诸位对时序约束的兴趣和好奇心,并且展示出了时序约束的魅力,既然这样,那么接下来我再来和大家讲理论,讲步骤,大家也就能看的静静有味,能够边看边消化了。 好了,看着大家这么的急切的心情,我也就不卖关子了,预知后事如何,且听下回分解吧。 各位慢聊,我还有事,先走了。(隐约感觉昨天那伙要打我的人马上就要追上来了已经)
  • 热度 19
    2019-6-30 11:07
    13531 次阅读|
    1 个评论
    小梅哥FPGA时序分析笔记(四)I/O时序定成败——化险为夷
    小梅哥FPGA时序分析从遥望到领悟系列 没有遇见过 I/O 时序问题,没有通过 I/O 约束方式实际解决过 I/O 时序问题,就很难明白 I/O 约束的重要性,也很难相信各种 EDA 软件真的有那么的傻白甜。 我遇到的最典型的一个 I/O 不加约束导致设计异常,然后通过加入合理的 I/O 时序约束解决问题的例子,就是第一节里面提到的基于 ADV7123 芯片的 RGB 数字时序转 VGA 模拟时序的例子。 ADV7123 这个芯片,相信大凡接触过基于 FPGA 的 VGA 显示的网友都了解,无论是国际大厂友晶的 DE1 、 DE2 开发板,还是我们(小梅哥 FPGA )的 24 位高动态 VGA 输出模块,都是使用的该芯片实现的,这个芯片实际上就是一个集成 3 路 10bit 并行 DAC 的 DAC 芯片。其系统架构如下图所示: 通过结构图可以看到,该芯片的结构确实简单,总共 3 个 10 位的 DAC 芯片,分别对应 RGB 彩色数据的 RED 、 GREEN 、 BLUE 三元色,同时,每个元色的数据接入芯片后,会首先在数据寄存器上寄存一拍,然后再送给各自的 DAC 转换为模拟信号输出。其中,在数据寄存器上进行同步时,使用的是 FPGA 输出给 ADV7123 的 CLOCK 信号,下图为 FPGA 或处理器使用 RGB888 模式连接 ADV7123 芯片示意图。 好了,电路讲完了(貌似啥都没讲),接下来该说正事了。先让我们看看,不加任何处理直接将 FPGA 内部的时钟作为 CLOCK 提供给 ADV7123 芯片作为数据同步时钟的具体现象,以 OV5640 型 CMOS 摄像头采集 1280*720 分辨率的图像,经由 ADV7123 芯片送给 VGA 显示器为例。 以下为了原汁原味的展现图片的效果,不想因为网络压缩导致图片失真,所以图片统一用BMP格式了,对不住了,各位网友的流量,更对不住了,面包板社区的服务器。 ,如果您网速不行的,可能要等一会儿才能打得开图片。 上图为不加任何 I/O 约束,也不对 FPGA 输给 ADV7123 芯片的 CLOCK 时钟进行取反的情况下采集到的图像实拍(时钟约束这种基本的条件当然已经满足了),可以看到,在轮廓的边缘,有明显的杂色出现,例如电视墙右上角那个红色块的中间圆圈处,能够看到明显的杂色。如果上图看的还不是很清楚的话,那么下面图片为该照片中局部放大图,通过局部放大图,看到的现象更加明显。 从上图可以明显看到,在两个方块的边缘处,就像是发了霉一样的附着着很多杂色,如果还觉得不明显的话,换个角度,拍个更加明显的效果图,如下所示: 好了,问题确实是实际存在的,毋庸置疑,哪怕是同样的实验,放在友晶的 DE2-115 这种原厂开发板上也是同样的现象。那么这个问题该怎么去解决呢?在 DE2-115 开发板提供的一个名为“ DE2_115_TV ”的 Demo 里面,可以看到,友晶也是将 VGA 控制器逻辑代码的工作时钟 iCLK 取反后输出的,如下图所示。所以,也正是这样,网上能够找到的绝大部分基于 ADV7123 芯片的代码也都是使用的这种方法(那种基于电阻网络的 Low 成本 VGA 方案本身性能就很差,根本没有同步时钟信号,因此没有这个说法)。 那么这种将时钟取反的方法是否真的有效呢?答案是肯定的!该方案不仅有效,而且还良好的工作在各种开发板上,不论是友晶和 Altera 等原厂开发板,还是其他厂家出的一些实验箱或者学习板,无论是芯片直接通过高可靠性的 PCB 板直接和 FPGA 芯片连接,还是用 2.54mm 的排针接口经过各种转接插接,该方案都能近乎完美的解决问题。比如,在我们的代码中,按照这个思路,将该时钟信号取反后作为送给 ADV7123 芯片的 CLOCK 信号输出, VGA 显示器上显示的图像效果立马变正常了,如下图所示。 同样的,作为一个清晰的对比,下图为将上图中的局部区域放大,可以看到,细节位置依旧白白净净,没有发霉的样子。 换个角度,拍个更加明显的效果图,效果依旧也是美美哒,如下所示: 此刻,是不是有人差点笑出声来:噗嗤,原来就这样啊,那你扯那么复杂,又臭又长的,好了好了,别说了,我知道了。 如果单就解决这个问题来说,确实是按照上面的方法弄一下,又快又有效,而且放之四海而皆准。可是,从学习的角度来说,是不是达到这样的效果,我们就应该满足了呢?在这一个取反符号引发的惊天逆转的背后,究竟隐藏了多少不为人知的秘密,是代码设计的缺陷,还是硬件板卡的低劣,亦或是还有什么原因,是我们目前还不知道的呢?预知后事如何,且听下回分解。(捂头疯狂逃窜,因为我有一种被打的预感。)
  • 热度 21
    2019-6-22 10:32
    19319 次阅读|
    7 个评论
    小梅哥FPGA时序分析笔记(三)时钟约束真重要——事实说话
    小梅哥FPGA时序分析从遥望到领悟系列 以前,那是在以前,经常有网友(原谅我行文动不动就是网友说,网友问,毕竟我是卖开发板的,正面接触学 FPGA 的网友相对多一些,所以这些也都是事实存在的事情)问我:小梅哥,请问在什么情况下需要进行时序约束呢?我的系统跑 50M ,请问不加约束行不行?我的系统跑 100M ,一定需要加约束吗?怎么加呢?面对这样的提问,我一般都是比较官方的回答:一般你们学习中进行的简单的系统设计,比如跑跑 VGA 、 UART 、 SPI 等简单的系统,加不加都行, 100M 的情况,简单的系统也可以不用加,复杂的加个时钟约束就可以。然后,基本上对话到这里就结束了,我也就松了一口气,因为他们没有问为什么,如果问为什么,或者问怎么加,那就得费很多的力气去说明,当然人家还不一定马上就能理解。也是怕自己说的不准确,让人更加迷糊。这样的回答,一直到 2017 年暑期 FPGA 辅导的时候,有学员在学习 SOPC 课程的时,发现同样的工程,即使 Quartus 工程和 Qsys 中系统不做任何修改,重新编译一次 Quartus 工程得到的 sof 文件下载到开发板中,在 Eclipse 中执行 Run 操作(使用 Jtag 下载 elf 文件到 FPGA 中)时,有时候能正常下载并运行,但是有的时候下载都下载不成功,即使是我对该学员的工程进行了细致的分析,从 Qsys 中每个 IP 的每个信号的连线,到 Quartus 中工程文件,以及引脚分配,还有 Eclipse 中各种设置都进行了详细的检查,甚至更换了开发板进行测试,都是这种现象。在和众多学员进行了多番分析,挠破了几层头皮(请忽略漫天飞舞的雪花)之后,我突然灵光一闪,会不会是因为系统跑不到 100MHz 呢,换句话说,是不是这个系统在当前的布局布线的情况下,其 fmax 远低于实际工作的时钟频率 100MHz 呢?带着这样的疑问,我们马上对该学员的系统进行了时序分析。 首先可以确定,该学员并没有对该工程添加基本的时钟约束,查看时序报告,也没有报告有任何软件默认的时钟约束。所以,我们立即对该工程加入时钟约束。 第一步,加入时钟约束,操作很简单,就是下述界面了 第二步,派生 PLL 时钟。因为在该工程中,是将输入自外部 50MHz 晶振时钟信号作为 FPGA 片上 PLL 的参考时钟,经过倍频得到 100MHz 的时钟信号,该 100MHz 的信号再作为整个设计的时钟信号使用。所以,需要加入 PLL 的时钟约束。操作很简单,就是下述界面了,只需要执行 derive_pll_clocks 命令就可以了,如下图所示。 第三步,报告时钟约束。通过报告时钟约束命令,可以查看当前系统的所有时钟约束。可以看到,经过以上两步操作后,再执行报告时钟约束命令,发现系统中就有了 clk 和 pll|clk 和 pll|clk , 第四步,查看运行最大频率。通过报告最大频率命令,可以查看当前经过布局布线的网表能够运行的最大时钟频率,如下图 1 。可以看到,在本例中,作为最重要的所有寄存器的工作时钟的 pll7|clk 时钟,其最大运行频率竟然只有惊人的 68.76MHz 。这个工程还只是简单的在 Qsys 中加入了一个 NIOS II CPU 、一个 SDRAM 控制器、一个 LCD1602 模块呀,这么简单的一个系统,在不加时钟约束的情况下,居然只能最高运行到 68.79MHz ,可想而知,如果系统中再加入更多的外设,比如加入一些 PIO 、 SPI 、 FIFO 、 UART 等之后,系统的最高运行频率可能会进一步下降,更进一步,如果加入了那些本身都很复杂的 IP ,比如 DMA 、视频处理 IP 之后,整个系统的最高运行频率可能会低于 50MHz 。 上面说加入更多的 IP 之后,如果不加时钟约束,整个系统的最高运行频率可能会低于 50MHz 的事情绝对不是危言耸听,而是有众多网友见证的公开课现场演示分析的过程,详细可以参看小梅哥 2017 年时候录制的公开课 “ 基于 SOPC 的 2.8 寸液晶显示屏应用 ” 一课的第 1 小时 36 分到 1 小时 54 分的内容,该课程可以在我们的官网 网站上找到,下图为该视频中进行分析得到的报告,可以看到,时钟频率仅为 44.22MHz 。 看到这里,不知道大家是什么感受,反正我当时看到这个结果的时候是后背发凉。因为如果是这样的话,那么我之前回答网友的,系统频率跑 50MHz 的时候可以不加时序约束的说法就是不合适的。因为如果不注重代码设计,或者系统设计较为庞大,在不加约束的情况下,整个系统的运行频率可能真的连 50MHz 都不一定能达到。 第五步,使用约束文件指导 Quartus 工程进行编译。通过上面的例子,我们可以发现,在不加约束的情况下, Quartus 对设计的布局布线会比较随意,得到的编译结果的最高运行频率可能会比较低。然后我们将上述约束内容生成约束文件( sdc ),并添加到 Quartus 工程中(如下图 )之后,再次进行全编译。 第六步,查看加入约束后的编译时序报告,编译完成之后查看时序报告,发现整个系统的最高运行频率竟然能够达到 131.27MHz ,如下图 所示。 至此,石锤了如果不加入最基本的时钟约束, Quartus 软件可能真的不会按照最优秀的布局布线规划给我们进行编译的问题,同时也打脸了我之前给网友的不严谨的回答。所以此时,我必须要重新组织我对之前网友提问的答案了:无论什么样的系统,都建议加入完整的时序约束,以保证 Quartus 软件去按照我们明确的时序约束对设计进行必要的优化。即使是一个非常简单的系统,加入基本的约束也是有意义的,因为这能让我们养成无约束,不设计的良好习惯。 冷汗过后,相信大家也应该明白我在第一节里面说的,越来越不敢写教程的原因了。不过,不敢写教程,不等于不愿意分享,如果我自己写的笔记和分析之类的文章能够得到大家的认可,相信不用我自己喊口号,大家也愿意将其当成教程来学习,来推荐。 到此为止,可能大多数人以为时序约束就差不多了。曾经我也是这样认为的,因为在之前的网络上,能找到的资料大部分也都是详细介绍到这里就差不多了,其他的一些约束内容,大多一笔带过,让人误以为那些并不重要,实际上,从一个完整的 PCB 板级系统可靠性来讲,那些他们没有详细讲到的地方更加的重要,还记得我在第一节说过的 USB 的问题、 VGA 的问题吧,那些问题,单靠通过加入简单的时钟约束是无法解决问题的。因为时钟约束只能约束 FPGA 芯片内的各个路径,而对 FPGA 和其他芯片的连接,也就是 IO 口上的时序约束根本无能为力,所以,要想解决这些问题,就涉及到另一个更加重要的约束了—— IO 约束。什么是 IO 约束, IO 约束真的能解决这些问题?预知后事如何,且听下回分解。
相关资源