嗨,你好啊,又见面了,既然来了,那就学点东西再走吧~
本文首发于微信公众号<FPGA学习者>
相信很多人在此之前对时序分析、时序约束、建立时间、保持时间等相关名词已经听过很多遍了,而且也几乎都认同时序约束对于保证一个系统的可靠运行起着至关重要的作用,那为什么时序约束能够解决这些问题?时序约束的原理又是什么呢?我们一起来,慢慢探讨。
FPGA即现场可编程门阵列,一个典型的FPGA内部通常包括三类基本资源:
①可编程逻辑功能块:是实现用户功能的基本单元,多个逻辑功能块通常规则地排成一个阵列结构,分布于整个芯片;Altera叫做LE(Logic Element),Xilinx叫做LC(Logic Cell)。
②可编程输入/输出(I/O)块:完成芯片内部逻辑与外部管脚之间的接口,围绕在逻辑单元阵列四周;
③可编程内部互连资源:包括各种长度的连线线段和一些可编程连接开关,它们将各个可编程逻辑块或输入/输出块连接起来,构成特定功能的电路。用户可以通过编程决定每个单元的功能以及它们的互连关系,从而实现所需的逻辑功能。
在之前的文章笔试|面试|FPGA知识点大全系列(5)中也有所提及;
除此之外,还增加了很多其他常用资源,如如时钟管理单元(PLL、DLL)、嵌入式存储器单元、DSP、硬件乘法器单元等等;FPGA的基本结构如图所示:
FPGA最主要的组成部分就是呈阵列分布的可编程逻辑单元,可编程逻辑单元包括查找表(通过查找表的方式来实现逻辑门的功能)、D触发器、选择器、进位链等等;
图示为Stratix10 FPGA的可编程逻辑单元的结构示意图
其中最主要的就是查找表(LUT)和D触发器,后面的分析中,将可编程逻辑单元简化为下图所示的样子。
图示是一个四输入的查找表(关于查找表的结构详见笔试|面试|FPGA知识点大全系列(5))和一个D触发器组成的可编程逻辑单元;使用查找表实现各种组合逻辑,配上D触发器便可实现时序逻辑。
如下图,就是我们利用可编程逻辑单元搭建的一个简单电路:
通过上图可以看出,FPGA中各种复杂的逻辑,都是使用基本的逻辑单元构建各种特定的简单的组合逻辑或时序逻辑功能,然后使用片上的可编程互联线
资源将这些独立的逻辑功能连接起来实现的。
上图所对应的代码如下:
module test(
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
通过Quartus II综合出的电路图为:
从上图中可以比较清楚的看出使用了7个可编程逻辑单元,而通过查看资源利用率发现和我们分析的是一致的。
不过,如果将上述程序中第一级组合逻辑改变一下:
![//第一级组合逻辑
assign w_g = r_a | r_b | r_c | r_d;
//第二级组合逻辑
assign w_h = r_e | w_g;]
可以看到综合出的电路图,组合逻辑(此处指或运算)进行了整合,使我们不那么容易看出逻辑资源使用情况,不过通过查看资源利用率仍然是使用7个逻辑单元。
通过上述两段不同的编程只是想说明,一开始画的那个用逻辑单元组合成的电路图不止对应一段代码,因为LUT内部是可以实现不同的组合逻辑的。所以可以使用同样的资源根据不同的代码实现不同的功能。
上面我们了解了FPGA内部数据的传输形式,接下来可以提取归纳出一个通用的FPGA内部信号传输模型,如下图:
根据上图,可以看出
①数据从一个D触发器(REG1)传到另一个D触发器(REG2),即从源触发器到目的触发器;
②数据在传输过程中,可能经过多次的组合逻辑;
③数据在传输过程中,需要经过可编程互联线传递;
④分析信号在两个寄存器之间的传递时,需要保证这两个寄存器的时钟信号是同源时钟。
关于D触发器还有一些需要补充:
①D触发器具有记忆功能,具有两个稳定状态,是构成多种时序电路的最基本逻辑单元。
②D触发器在时钟脉冲的上升沿发生翻转,触发器的次态取决于时钟脉冲上升沿到来之前D端的状态,即Q(n+1)=D。D触发器在clk=1期间具有维持阻塞作用,此期间,D端的数据状态变化,不会影响触发器的输出状态。
所以,要想保证D端的数据能被正确地存起来,需要确保D端的数据在时钟上升沿时刻是稳定的,不能处于变化时期。
对于理想的D触发器,可以认为时钟信号从0到1的变化所需的时间无限短,但是在实际电路中,这个变化需要一定的时间;而且D触发器也不是真的就只需要在时钟上升沿的那一个时间点需要D端的数据是稳定即可,从实际的器件工作情况来看,任何一个D触发器要想在时钟的上升沿将D端的数据正确寄存并输出到Q 端,有2个关键的时间参数需要保证。
建立时间、保持时间<
对于实际的D触发器来说,为了保证在时钟的上升沿能够正确的将D端的数据寄存并输出到Q端,需要满足以下两点:
①D端的数据必须在时钟上升沿到来之前的一定时间内就已经保持稳定,该时间被称为D触发器的建立时间(Tsu);
②D端的数据必须在时钟上升沿到来之后的一定时间内继续保持稳定,该时间被称为D触发器的保持时间(Th);
不满足上述建立时间和保持时间会出现什么后果呢?那就会使得触发器进入亚稳态,直到一段时间后再恢复到稳态;关于亚稳态问题,后续会继续学习。
输出延迟
同时,对于D触发器来说, D端的数据也不可能会在时钟上升沿出现的那一刻就立即更新到Q端,从时钟的上升沿到D端的数据稳定出现在Q端,这段时间称为寄存器输出延迟(Tco)(clock to output delay)。
通过上面的分析,可以提出FPGA内数据传输的时序了,如下图所示:
其中Tdata是数据在传输过程中需要的时间。
值得注意的是,虽然FPGA的时钟信号在走全局时钟网络时,到达每个寄存器的时间几乎一样,但是仍存在一定的延迟,只不过这个延迟比较小罢了。
①CLK是时钟输入端输入的时钟信号;
②REG1.CLK为CLK到达REG1的波形,相对于CLK,有一个Tclk1延迟。
③REG1.Q为REG1的输出端数据值,从REG1.CLK上升沿到来到其值更新并稳定下来,存在一定的延迟,该延迟为Tco。
④REG2.D为REG2的输入端D端口上的数据波形,该信号由REG1.Q经过组合逻辑和内部连线传递后到达,因此REG1.Q到达REG2.D这个时间是数据传输时间,为Tdata。
⑤RERG2.CLK是CLK到达REG2的波形,相对于CLK有一个Tclk2延迟。
基于上述波形图,我们此处引出两个时序概念,数据需求时间(data require time)和数据到达时间(data arrival time)。
数据需求时间,指数据被存入目的寄存器所需要的最短时间(长度);
数据到达时间,指数据到达目的寄存器D端口的时间(长度)。
数据到达时间,完整的说法应该是数据到达时间长度,起始点一般以时钟上升沿从CLK的输入引脚输入开始算,具体到上面的波形图中,就是CLK的第一个上升沿,一般将其称为发射沿(launch edge)(注:此发射沿也可以认为是0时刻)。而结束时间,就是数据到达目的寄存器D端口的时间。
所以,数据到达时间为:
Data Arrival Time = launch edge + Tclk1 + Tco +Tdata
数据需求时间,数据被存入目的寄存器所需要的最短时间长度,那么怎样才能保证数据被稳稳地存入寄存器呢?之前说过了,需要满足建立时间(Tsu)。
这里,一般将目的寄存器的锁存数据的时钟沿称为锁存沿(Latch edge)。对于寄存器来说,上一个时钟周期上升沿对其赋值,其新的值只有下一个时钟周期的上升沿才能被其他寄存器存储。
所以,常规情况下Latch edge和Launch edge之间相差一个时钟周期,这个差值被称作relatitonship,常规情况下relationship的值就是CLK的周期。
再根据定义,数据被存入目的寄存器所需要的最短时间(长度)被称为数据需求时间,所以:
Data Required Time = latch edge + Tclk2 - Tsu
目的寄存器要想能够正确的接收数据,需要在Latch edge传输到该寄存器的Tsu时间之前,数据就稳定下来,即:
必须保证:Data Required Time > Data Arrival Time;
即:
latch edge + Tclk2 - Tsu > launch edge + Tclk1 + Tco + Tdata
对照上图,这个公式应该是比较容易理解的了,其实刚才说的什么数据需求时间、数据到达时间,仅仅是为了概念补充;单独看这个公式反而更容易理解一些。
(为了省得你来回翻看的麻烦,这里再放一次时序图)
下面对上述公式进行一系列的变形:
latch edge + Tclk2 - Tsu > launch edge + Tclk1 + Tco + Tdata
即:latch edge + Tclk2 - Tsu - launch edge - Tclk1 - Tco - Tdata > 0
即:Tclk +(Tclk2 - Tclk1) - Tsu - Tco - Tdata >0;
即:setup slack = Tclk + Tskew -Tsu - Tco - Tdata > 0
总结:目的寄存器能够正确的接收源寄存器发过来的数据,需要保证建立时间余量(setup slack)大于0,(当然了,至少是等于0)。
建立时间余量,在上述波形图中以绿色标出。如果这个时序余量值为正值,则表明目标寄存器能够正确地接收数据;如果时序余量值为负值,则说明目标寄存器无法正确接收数据, 设计失败。
好了,此处来总结一下上面出现过的各个名词:
名词 | 相关解释 |
---|---|
Tsu,建立时间 | 在时钟上升沿之前,D端口的数据必须保持稳定的最小时间 |
Th,保持时间 | 在时钟上升沿之后,D端口的数据必须保持稳定的最小时间 |
Tco,寄存器输出时间 | 时钟上升沿与输出端(Q端)数据稳定输出的时间差 |
Tclk,时钟周期 | 系统时钟的周期 |
Tdata | 数据从源寄存器的Q端出发,到达目的寄存器D端的时间 |
Tskew,时钟偏斜 | 时钟从源端口出发,到达目的寄存器和源寄存器时钟端口的时间差值,(Tclk2 - Tclk1) |
数据到达时间 | Tclk1 + Tco + Tdata;(发射沿视为0时刻) |
数据需求时间 | Tclk + Tclk2 - Tsu;(锁存沿视为一个时钟周期之后) |
setup slack,建立时间余量 | 数据需求时间与数据到达时间的差值 |
看了那么多,绕的也挺晕的,来做一个题目试试吧。
**【大疆逻辑岗】**假设时钟周期为T,寄存器时钟端到数据输出端的延迟为Tcq,时钟到第一级寄存器的时钟端的延迟为Tcd1,时钟到第二级寄存器时钟端的延迟为Tcd2,两级寄存器之间的组合逻辑延迟为Tpd,寄存器的建立时间为Tsetup,Tpd的最大延迟为( )。(大疆FPGA逻辑岗B卷)
A Tpd ≤ T - Tsetup - Tcq -(Tcd2 - Tcd1)
B Tpd ≤ T - Tsetup + Tcq -(Tcd2 - Tcd1)
C Tpd ≤ T - Tsetup + Tcq -(Tcd1 - Tcd2)
D Tpd ≤ T - Tsetup - Tcq -(Tcd1 - Tcd2)
【解析】
虽然题目中使用的各个名词的符合和我们今天说的不太一样,但是不影响我们做题;根据数据传输模型,可得以下图形:
要保证正确传输,必须有setup slack >= 0;
setup slack = T + Tcd2 - Tsetup - (Tcd1 + Tcq + Tpd) >= 0;
即:Tpd <= T - Tsetup - Tcq - (Tcd1 - Tcd2)
故答案选D。
时序分析确实是一个非常重要的问题,本篇文章仅仅是基于静态时序分析模型,一步一步的探讨时序分析相关问题,虽然可能不太深入,仍希望对你有所帮助。
笔试|面试|FPGA知识点大全系列(1)
笔试|面试|FPGA知识点大全系列(2)
笔试|面试|FPGA知识点大全系列(3)
笔试|面试|FPGA知识点大全系列(4)
笔试|面试|FPGA知识点大全系列(5)
笔试|面试|FPGA知识点大全系列(6)
笔试|面试|FPGA知识点大全系列(7)之异步FIFO设计