FPGA设计的心脏——时钟电路
用心脏来比喻硬件设计中的时钟,再合适不过了。
心脏跳动的节拍,频率,就好比时钟的频率大小,上升和下降;
时钟虽起伏有别,却周而复始。
本文内容出自《通信IC设计》一书,仅作整合用于学习。
时钟电路
设计不良的时钟再极限的温度,电压或制造工艺的偏差下将导致错误的行为,并且调试困难、花销很大。根据时钟的分类,可以分为逻辑时钟、接口时钟、外部存储器时钟等。
-
逻辑时钟
逻辑时钟取决于生成该时钟逻辑的关键路径,通常需要遵循一定的原则进行时钟设计。逻辑时钟进一步可细分为:全局时钟、门控时钟、多级逻辑时钟和波动式时钟。多时钟系统包括上述
4
种时钟类型的任意组合。 -
接口时钟
异步信号的时序一般也是通过
FPGA
片内同步逻辑产生,一般需要同步化,即接口的同步化采样。某些接口的同步时钟一般是固定而精确的,例如SerDes
的时钟尽量由该组的专用时钟引脚输入,这样可保证由一组SerDes
组成的高速接口的时钟偏斜一致。 -
外部存储器时钟
外部存储器时钟主要包括
LPDDR / DDR2 / DDR3
等器件的时钟。一般来书,FPGA
的接口不用工作在相应器件的最高频率,只要满足系统缓存数据的性能即可。但由于此类接口需要对外部存储器进行定时刷新,工作频率过低会造成数据丢失或者不稳定,因此外部存储时钟存在一个最小时钟频率的问题。 -
其余时钟
对于类似
SPI / IIC / MDIO /
等要输出低速时钟的电路,通常通过计数器或者内部寄存器逻辑输出。这类电路无需通过PLL / DCM
产生所需时钟,因为这类时钟的驱动负载都可以通过引脚配置设定,而且要求的抖动、建立 / 保持时间都基本能够满足需求。
逻辑时钟的时序模型
由于逻辑时钟会对每个寄存器单元进行时序控制,而这些单元是按照一定的组织构架排列在FPGA
内部的,所以将所有时钟连线串接在一起,就会形成一个逻辑树,即时钟树的概念。
时钟树同样可以按照建立 / 保持时间、抖动等概念建立时序模型。该模型还需要考虑传播中的偏斜、跳变和绝对垂直的偏差,以及其他一些不确定因素。不同的时钟组合对应不同的参数组合(如网络延迟、有效工作区等),因此组合时钟数量越多,参数组合数量就越多,每个参数都满足的几率就会变小。这就是组合时钟电路不受欢迎的根源。
全局时钟的设计
对于FPGA
设计而言,全局时钟是最简单和最可预测的时钟。在FPGA
设计中,最好的时钟方案是:由专用的全局时钟输入引脚驱动的单个主时钟去钟控设计项目中的每一个触发器。只要可能,就尽量在设计项目中采用全局时钟。FPGA
都具有专门的全局时钟引脚,它直接连接到器件的每一个寄存器上。这种全局时钟提供器件中最短的时钟到输出的延时。(前面的I / O
部分已经对此有详细的说明)
门控时钟设计
在许多应用中,整个项目都采用外部的全局时钟是不可能或不实际的。FPGA
中有专门的时钟逻辑,以用于控制各个触发器。驱动时钟的逻辑必须只包含一个‘与’门或一个‘或’们。如果下图的逻辑信号A
附加了额外的毛刺,必然会影响到门控时钟的输出,且会产生时钟毛刺,因此逻辑信号A
最好是D
锁存器的直接输出。
门控时钟波形如下图:
多级时钟设计
当产生门控时钟的组合逻辑超过一级时,即超过单个的‘与’门或‘或’门时,该时钟实际上会存在很多风险,因为组合电路与时钟结合往往会存在很多的毛刺,即使仿真结果中没有显现。多级时钟实际上是不适合在FPGA
中使用的,如果非要使用,最佳方法是将多级逻辑时钟进行转换。一种转换方法是将组合电路进行时钟锁存,然后再与标准时钟组合,形成最终时钟输出。
下图左侧是一个多级时钟例子,这个时钟电路必然会产生较多的毛刺,因此时钟1
与时钟2
以及组合电路1
会形成多种情况,必然也会有各种组合翻转出现。
下图右侧的电路,则是对上述电路进行优化的实现方案。对电路的逻辑进行梳理,并将单个时钟作为D
触发器的输入端,组合电路作为使能端,这种情况下的生成时钟非常稳定可靠,然后将两个电路的时钟通过FPGA
专用时钟选择逻辑输出最后的组合时钟。
行波时钟
行波时钟通常用于低速分频时钟,即讲一个触发器的输出用作另一个触发器的书中输入。通常情况下,行波时钟是触发器的Q
端输出,如果该时钟负载较小,且驱动电路能容忍的建立 / 保持时间较大,则可以像全局时钟一样可靠地工作。
如果行波时钟在行波链上各触发器的时钟之间产生较大的时间偏移,并且会超出最坏情况下的建立 / 保持时间以及组合电路延迟之和,则该时钟不能满足要求。
行波时钟的建立 / 保持时间不够的情况如下图:
由于行波时钟的时钟沿与标准时钟沿的关系较为复杂,通常在ASIC
电路中不提倡使用,FPGA
也不推荐使用。推荐的办法是采用同步计数器,并采用沿指示的方法产生时钟(这个短句没有理解)。例如:
module clock_div_new #(parameter cfactor=2,parameter cnt_len=8)(
input clk_in,
input rst,
output clk_out
);
reg clk_loc;
reg [cnt_len-1:0] cnt;//allowed maximum clock division factor is 256
assign clk_out = (cfactor==1)? clk_in : clk_loc;
always@(posedge clk_in) begin
if(rst==1) begin
cnt <= 'd0;
clk_loc = 1;
end else begin
cnt <= cnt + 1'b1;
if(cnt==cfactor/2-1)
clk_loc = 0;
else if(cnt==cfactor-1) begin
cnt <= 'd0;
clk_loc = 1;
end
end
end
endmodule
After
时钟的概念,是数字电路设计的基础,如果时钟噪声非常大,或者没有跟数据同步,对于设计来说,无疑是失败的。
好在FPGA平台,对时钟的设计考虑的非常周到。
一般来说,像笔者做FPGA设计,主时钟,那都是PLL来实现的;时钟约束起来也挺方便的,而且部分PLL的IP是自带时钟约束的。
关于时钟约束的文章,网上有一大堆,也做过收藏:
看完这个系列,就OK了。
以下是广告?
Python企业招聘百万级信息爬取