系列文章目录
文章目录
前言
最近由于不懂时序约束,在高速信号采集上面吃了很多亏,不知道系统工作异常的原因是什么。记录一下查到的资料,有些许自己的理解,可能有误。(主要是小梅哥及《FPGA时序约束与分析(吴厚航)》)
Quartus时序约束
不进行时序约束的后果
在程序编译之后,会出现时序约束标红
如果不自己编写时序约束文件,就会出现系统进行默认分配,这里如果没有自己编写sdc时序分析文件,quartus会自动分析潜在的时钟,如下图,在clock中查看
这个altera_reserved_tck是识别到JTAG 输出作为时钟。
可能我们的输入是50M的时钟,系统按照1000M时钟进行了约束,但是你的FPGA内部寄存器和连线导致的延时,它不能满足1000M的时钟,所以就会标红。一些简单的程序,系统按照1000M去优化是没有问题的,但是复杂的程序就会出错了,这里用1000M去优化不是说明它按照最优效果去约束吗,答案是不是的,即使最简单的系统,如果不加入时序约束也是可能出问题的。参考:小梅哥FPGA时序分析笔记(三)时钟约束真重要——事实说话
用欠约束和过约束来描述:
欠约束:约束设定的时序条件太低了,导致不满足我们要求工作的要求。
过约束:约束的比实际要求高,但是FPGA是一个系统的设计,不是局部最优,所以局部过优那么其他地方就会有比较差的地方。
(并不绝对,有时也需要适当的过约束)
在TimeQusst Timing Analyzer下,slow 1200mv 85C model和slow 1200mv 0C Model以及Fast 1200mv 0C model里,quartus根据代码程序,按照刚才的clock会进行分析。
Fmax表示当下条件下,该时钟驱动的所有寄存器中,最坏路径下能够运行的最大频率(小梅哥视频里介绍)
-
Clocks:这一项是显示当前的设计中有哪些时钟信号
-
Slow 1200mV 85C Model:芯片内核供电电压 1200mV,工作温度85度情况下的慢慢速传输模型。
-
Slow 1200mV 0C Model:芯片内核供电电压 1200mV,工作温度0度情况下的慢速传输模型。
-
Fast 1200mV 0C Model:芯片内核供电电压 1200mV,工作温度0度情况下的快速传输模型。
这里介绍如何计算Fmax里面的值:
比如这里的sys_clk前面的slack是余量,这里我的时钟是50Mhz,那么就是20ns一个周期,Fmax=1000/(20-14.667)Mhz=186.5Mhz。(单位都是ns)
这里的是To Node会因为From Node而变换,slack前面的标号1是最坏的路径情况
和Fmax中给出的值一样。
在TimeQuest time analysis里面也可也以看到:
Slack:建立或保持时间余量。
From Node:起点,源寄存器。
To Node: 终点,目标寄存器。
Launch Clock: 源寄存器发射数据的时钟
Latch Clock: 目的寄存器接收数据的时钟
Relationship:Launch Clock edge和 Latch Clock edge 的时间差。
(如果两个时钟非同一个信号,而是有一定相位关系的同源时钟,则 Relationship不再是时钟的周期值)
其他详细介绍
当FPGA内部送出数据给外部器件的时,有两个时钟launch clock 与latch clock,前者负责将数据从内部寄存器中送出,后者要在setup 与hold都满足的条件下,将数据锁入外部寄存器。在这个过程中,就是要保证在时钟到来时数据准备好,并让时钟有足够的时间将数据打入外部寄存器中。
clock skew:时钟偏斜,时钟从源端口出发,到达目的寄存和源寄存器的时间差值。(setup slack公式中一般是+clock skew)(如果 clock skew为正值,说明时钟到达目的寄存器比源寄存器的时间要长,所以要加上)
分析数据到达时间:
Incr:器件延时增量
时钟从T1输入后,通过走线到IOIBUF(引脚缓冲),控制的比较好,没有延时,到单元内部,产生了0.626ns的延时,之后再通过走线到全局时钟树…FF是D触发器
data require path - data arrival path =slack
所以也有可能出现负数。(负数即该路径时序失败了)
(小梅哥视频中根据最坏路径报告中将组合逻辑修改成时序逻辑代码,能够提高Fmax,因为组合逻辑驱动到寄存器了)
还可以利用IP核ALTCLKCTRL将铺铜IO分配到全局时钟上,提高稳定性
如何提高时钟质量在:小梅哥全局时钟
FPGA内部走线时间
这里的CLK到达REG1和REG2的时间是不确定的,不一定到达REG1比REG2的延时小
skew=Tclk2-Tclk1
时序约束的公式:Tclk1 + Tco + Tdata <= Tclk+Tclk2 -Tsu
(目的寄存器能正确接收源寄存器的值)
最后推导:
Slack = Tclk +Tskew -Tsu-Tco -Tdata;Slack >= 0;
Tclk1:时钟信号从时钟源端口出发,到达源寄存器时钟端口的时间。
Tco:时钟上升沿到达寄存器时钟端到数据输出到寄存器α端口的时间。
Tdata:数据从源寄存器α端出发,到达目的寄存器D端的时间。
Tclk:时钟周期。
Tclk2:时钟信号从时钟源端口出发,到达目的寄存器时钟端口的时间。
Tsu:寄存器要求的其数据端口的值必须提前于时钟上升沿达到其时钟端口的时间值。
Tskew:时钟从源端口出发,到达目的寄存器和源寄存器时钟端口的时间差值(Tclk2-Tclk1)。
Tclk+Tco+Tdata:数据到达时间
Tclk + Tclk2 - Tsu:数据需求时间
Slack :数据需求时间和数据到达时间的差值
在软件中,Data_Delay=Tco+Tdate
Tsu为负值是合理的,或者说,是Altera Cyclone lVE这个系列的FPGA的寄存器时序模型的一个等效值
软件中为了分析Slack的最小值:
Skew=Tclk2(按最快速度)-Tclk1(按最慢速度)+Clock Pessimism(Tclk1和Tclk2路径有重合部分的时间)
在软件中,Clock Uncertainty算在data require中,
slack=Talk +Tclk2 + Clock Pessimism + Clock Uncertainty - Tsu- Tclk1 - Data_Delay(Tco + Tdata)
IO约束方法
计算PCB板上电信号的传输时间,可以将电信号等效为光速,得到的电信号传输时间与长度关系的参数为5555mil/ns
1mil = 0.0254mm
5555mil/ns -> 141.097mm/ns
要看不同的模型:
白色背景线是PCB走线。
这里的Tdata=Tdata(Init)+Tdata(Pcb)(芯片和PCB总共的延时)
Tclk2=Tclk2(Init)+Tclk2(Pcb)
T(0)->(3) = Tclk1
T(3)->(4) = Tco
T(4)->(5) + T(5)->(6) = Tdata
T(4)->(5) = Tdata(Init)
T(5)->(6) = Tdata(Pcb)
T(5)->(6)
T(0)->(1) + T(1)->(7) = Tclk2
T(0)->(1) = Tclk2(Init)
T(1)->(7) = Tclk2(Pcb)
根据建立时间余量和保持时间余量分析:
- 建立时间余量
建立时间余量就是数据到达AD9767要满足建立时间(提前到达)
对应的就是output delay max(继续延时就导致数据来的太迟了)
Data Require Time(数据要求时间) = Tclk2 - Tsu(芯片数据建立时间) + Latch edge(接收沿) = Tclk2(Init) + Tclk2(Pcb) - Tsu + Latch edge(接收沿)
Data Arrival Time(数据到达时间) = Tclk1 + Tco + Tdata + Launch edge(发送沿) = Tclk1 + Tco + Tdata(Init) + Tdata(Pcb) + Launch edge(发送沿)
满足Data Require Time - Data Arrival Time >= 0
Tclk2(Init) - Tclk1 -Tco - Tdata(Init) + Tclk >= -Tclk2(Pcb) + Tsu +Tdata(Pcb)
(右边即output delay max,因为FPGA可以通过程序控制的是左边的这些量) - 保持时间余量
保持时间余量就是数据到达AD9767要保持的时间(不能提前结束)
对应的就是output delay min(继续缩短延时就导致数据提前结束)
Data Require Time(数据要求时间) = Tclk2 + Th(芯片数据保持时间) + Latch edge(接收沿) = Tclk2(Init) + Tclk2(Pcb) + Th + Latch edge(接收沿)
Data Arrival Time(数据到达时间) = Tclk1 + Tco + Tdata + Launch edge(发送沿) = Tclk1 + Tco + Tdata(Init) + Tdata(Pcb) + Launch edge(发送沿)
最后结果:
output delay max = Tdata(pcb) - Tclk2(pcb) + Tsu
Output delay min = Tdata(pcb) - Tclk2(pcb) - Th
如果,PCB板上的数据走线长度与时钟走线长度一样,即:(5)->(6) = (1)->(7)
那么,Tdata(pcb) = Tclk2(pcb)
output delay max = Tsu
Output delay min = -Th
时序约束方法
在上一篇文章已经简单介绍了一些时序约束的语法,现在介绍如何利用quaruts编写时序约束
- 熟悉了可以直接自己编写SDC文件
- 用 TimeQuest Timing Analyzer Wizard 软件按照向导的指引操作。
- 可以使用 TimeQuest Timing Analyzer 工具用图形化界面添加约束。
TimeQuest Timing Analyzer 工具来对工程添加约束。
菜单栏依次点击:Tools->TimeQuest Timing Analyzer 可以打开,也可以直接点击工具栏里的 TimeQuest Timing Analyzer 图标
创建网表
约束的对象就是网表,网表就是 Quartus 软件经过编译,布局布线后得到的实际电路信息,该电路信息就是对应下载到芯片中后实际在芯片中呈现的电路。直接双击 Create Timing Netlist 选项就可以创建网表。
读取SDC文件
时序约束文件可以指导EDA软件(Quartus)进行布局布线,还可以指导时序分析软件(TimeQuest Timing Analyzer)对EDA软件编译得到的网表进行分析报告。
如果用户没有编写,就是使用默认那个1000M约束的默认文件。
创建时钟(Create Clock)
创建时钟约束,就是为当前网表模型指定一个明确的时钟信号。这样时序分析软件就能够基于该时钟参数,对网表中的各信号进行分析了。
在这个界面筛选时钟以及选择时钟本体
*号是通配符,一般 * xxx *这样写
例如:
将代码中的 MISO信号重命名为dclkn进行约束,占空比为50%,周期是10ns。(上升沿和下降沿不填默认是50%占空比)
命令窗:
如果出现:
约束被忽略了,因为系统默认约束过了那么就不能创建了,只能更改
注意:clock name不能改,改了还是会被忽略
写入SDC文件
到这里就基本完成了,最后记得把SDC文件添加到工程里面就可以了
时序约束语法补充
上篇文章有一些简单的介绍语法,这次又学习了一些比较详细的,总共有13种约束命令。以下命令都可以在菜单的constraint里面找到,直接设置好参数让软件自动生成,当然也可以自己生成添加。(都是参考文章末尾的第二篇文章的,还有很多看不懂,慢慢加入东西吧)
-
Creat clock
约束外部进入FPGA的时钟,其他IC产生的给FPGA的类时钟信号 -
Creat generated clock
约束pLL(derive_pll_clocks)
约束FPGA输出到外部的时钟
时钟多路复用器(clock muxes)
涟漪时钟(ripple clocks),FPGA内部寄存器输出的时钟
phase:是偏移多少度
offset:是偏移多少ns
例子:create_generated_clock -name 起名字 -source [get_ports {原时钟}] [get_ports {生成的时钟}] -
set_clock_latency
对输入到FPGA的时钟及类时钟(其他芯片产生的时钟给FPGA)
可以自己选择延迟类型
late指最大时钟延迟,early指最小时钟延迟(第二篇参考文章里面有详细解释,没太看懂) -
Set_clock_uncertainty
对时钟出现的抖动进行约束,是一个时钟到另一个时钟的约束,用 derive_clock_uncertainty约束命令不需要确定uncertainy的时间,
-
Set_clock_groups
把相关的时钟分成一个组,与其它不相关的时钟区分开。 timequest只对这组内的时钟域进行分析,组间的时钟路径将不会分析。 -
set_input_delay
对外部IC输入到FPGA管脚的约束,这个约束命令中的延迟信息需要告诉timequest。
外部IC到FPGA输入管脚Din[3:0]的最大延时是4ns,最小延时是2ns,外部IC时钟是ext1_clk。add delay选项用于说明有另外的外部寄存器连接到端口,通常用于对双倍速率接口的约束。
-
set_output_delay
FPGA输出到IC的延迟,与输入延迟相似 -
set false path
不要分析某个路径或某组路径 -
set_multicycle_path
两个寄存器间的数据传输在一个周期内没法完成时,我们可以通过该约束命令来改变他的建立关系值和保持关系值让其满足时序要求。 -
set muximum delay和set minimum delay
一般建议不要用
补充
查看Ignored constraints也很重要,看看有没有被忽略的约束
对于不需要约束的路径可以在时序这里直接设置