需求说明:FPGA基本知识
内容 :第一部分 FPGA各个时钟说明
第二部分 FPGA时钟总结
第三部分 异步时钟同步化及门控时钟
来自 :时间的诗
1. FPGA的全局时钟是什么?
FPGA的全局时钟应该是从晶振分出来的,最原始的频率。其他需要的各种频率都是在这个基础上利用PLL或者其他分频手段得到的。
2. 全局时钟和BUFG:
BUFG,输入为固定管脚,输出为H型全铜全局高速网络,这样抖动和到任意触发器的延时差最小,这个也就是FPGA做同步设计可以不需要做后仿真的原因。
全局时钟:今天我们从另一个角度来看一下时钟的概念:时钟是D触发器的重要组成部分,一个有效边沿使得D触发器进行一次工作。而更多的时候,D触发器保持住上次的值。对于D触发器来说,可以将输入信号和时钟作比较。也许你会问,这么比较有什么意义。首先看我们比较得出什么东西:
翻转率:R=Dr/Crx100%
就是D触发器改变一次值与时钟有效沿个数的比值。
举例:你写了一个来一个时钟有效沿就取一次反的电路,那么他的翻转率就是100%,翻转率和你的FPGA的功率有很大关系,翻转率越高,FPGA功率越高。
3. 全局时钟不够用是什么意思?
因为全局时钟需要驱动很多模块,所以全局时钟引脚需要有很大的驱动能力,FPGA一般都有一些专门的引脚用于作为全局时钟用,他们的驱动能力比较强。但是如果这些引脚用完了,就只能用一般的引脚了,而他们的驱动能力不强,有可能不能满足你的时序要求。(驱动能力小的,产生的延迟会大一些)
理论上,FPGA的任意一个管脚都可以作为时钟输入端口,但是FPGA专门设计了全局时钟,全局时钟总线是一条专用总线,到达片内各部分触发器的时间最短,所以用全局时钟芯片工作最可靠,但是如果你设计的时候时钟太多,FPGA上的全局时钟管脚用完了就出现不够用的情况。
4. 什么是第二全局时钟?
比如我有一个同步使能信号,连接到FPGA内部80%的资源(但不是时钟),这个时候,你的信号走线到达各个D触发器的延迟差很大,或者翻转率比较大的时候(>40%),这个时候你就需要使用第二全局时钟资源。
第二全局时钟资源的驱动能力和时钟抖动延迟等指标仅次于全局时钟信号。第二全局时钟资源其实是通过片内的高速行列总线来实现的,而不像全局时钟总线是一条专用总线。第二全局时钟总线是通过软件布线得到的,所以硬指标肯定是拼不过全局时钟总线。特别是当你在已经有80%以上的布线率的情况下,可能会出现约束第二全局时钟资源失败的情况。
5. CCLK:
CCLK:FPGA同步配置时钟。如果配置模式为主模式,则该时钟由FPGA器件生成,并输出;如果配置模式为从模式,则该时钟由外部提供;
当所配置的数据存放在PROM中,即通过PROM来配置器件时,必须选择CCLK时钟;
USER CLOCK:用户定义的配置时钟信号,该配置时钟目前很少采用;
JTAG CLOCK:JTAG模式的配置时钟,该时钟提供给内部的JTAG控制逻辑。
默认值为:CCLK
6. CCLK是怎么产生的:
CCLK的产生根据配置模式不同而不同,如果设置为Master模式,则由内部的震荡电路产生,作为外部ROM的工作时钟,默认为6MHZ,可通过配置选项设置;如果设置为Slave模式,则由计算机(或其他下载设备)提供,作为芯片内部下载电路的工作时钟;在JTAG模式情况下,CCLK不输出,此时芯片内部下载电路时钟由内部震荡电路提供,TCK仅用作边界扫描相关电路时钟。
补充:FPGA的主配置模式中,CCLK信号是如何产生的?
CCLK是由FPGA内部一个晶振电路产生的,同时ISE的软件在生成BIT流文件时,有个CCLK CONFIG选项,这个选项只有在时钟为CCLK时才可以起作用,可以在4-60MHz选择,可以控制CCLK的频率。
在主从模式配置,配置数据的前60个字节导入FPGA之前,CCLK一直是2.5MHz,接下来由于前60个配置字节的作用,CCLK改为CONFIG设定的频率,直到结束,一般CONFIG默认的频率是4MHz.
7. FPGA中全局时钟怎么用啊? 是把时钟接到FPGA的全局时钟输入引脚后,就起到全局时钟的作用了,还是在编译时需要制定某个时钟为全局时钟阿?
其实全局时钟的使用关键在你的代码… 如果你的代码中只用了一个时钟作为所有的或者大部分触发器的时钟,编译器自然会把它编译为全局时钟。当然硬件连接上还是用全局时钟引脚较好,尤其是带PLL的,不是所有的全局时钟脚都能用PLL。
无沦是用离散逻辑、可编程逻辑,还是用全定制硅器件实现的任何数字设计,为了成功地操作,可靠的时钟是非常关键的。设计不良的时钟在极限的温度、电压或制造工艺的偏差情况下将导致错误的行为,并且调试困难、花销很大。 在设计PLD/FPGA时通常采用几种时钟类型。时钟可分为如下四种类型:全局时钟、门控时钟、多级逻辑时钟和波动式时钟。多时钟系统能够包括上述四种时钟类型的任意组合。
图6 给出一种可靠的全局钟控的电路,它是图5不可靠计数器电路的改进,RCO控制D触发器的使能输入。这个改进不需要增加PLD的逻辑单元。
来自:http://www.eefocus.com/karldada/blog/12-05/252437_66a55.html
通过双触发器接口,异步信号输入总是无法满足数据的建立保持时间,所以建议大家把所有异步输入都先经过双触发器进行同步化。如图所示,时钟域clk_s传给时钟域clk_d的数据经过了双触发器的同步处理,相同的,时钟域clk_d经双触发器传给时钟域clk_s的数据
通过高频时钟同步化,当在单个系统中有两个或两个以上非同源时钟的时候,数据的建立和保持时间很难得到保证,我们将面临复杂的时间问题,最好的方法是将所有非同源时钟同步化:选用一个频率是它们的时钟频率公倍数的高频主时钟将他们进行同步。
假设系统有两个不同源时钟,一个为3MHz,一个为5MHz,不同的触发器使用不同的时钟。为了系统稳定,假设我们引入一个20MHz时钟。
module orignal(clk,clk5m,clk3m,clk3men,clk5men); input clk; input clk3m; input clk5m; output clk3men; output clk5men; reg clk3mreg1; reg clk5mreg1; reg clk3mreg2; reg clk5mreg2; always @(posedge clk) begin clk3mreg1<=clk3m; clk3mreg2<=clk3mreg1; clk5mreg1<=clk5m; clk5mreg2<=clk5mreg1; end assign clk3men=clk3mreg1&(~clk3mreg2); assign clk5men=clk5mreg1&(~clk5mreg2); endmodule
用modelsim仿真后得到的时序图如图所示
门控时钟通过一个时能信号控制时钟的开关。当系统不工作时可以关闭时钟,整个系统处于非激活状态,这样就能够在某种程度上降低系统功耗。但是使用门控时钟并不符合同步设计的思想,它可能会影响设计的实现和验证,在FPGA设计中并不是很推荐使用时能时钟。
对于上升沿有效的系统时钟clk,他的下降沿先把门控时钟打一拍,然后再用这个使能信号和系统时钟clk相与后作为后续电路的门控时钟。
在方案一中由单独的组合逻辑来控制时钟的使能,容易产生毛刺。
在方案二中可以避免产生毛刺。
always @(negedge clk) enable<=gating_signal; assign clkout=enable&clk;
使能时钟
在前面提到门控时钟并不符合FPGA设计的思想,我们可以用时能时钟代替。在时能时钟的设计中,用原来的系统时钟作为触发器时钟,而让分频后的时钟作为信号的使能端。但是使能时钟在使能信号关闭时,时钟信号仍然在工作,它无法像门控时钟那样降低系统的功耗。
Verilog 代码: always @(posedge clk) if(!rst_n)…; else if(en)…; //en为是时能时钟,寄存器使能端的输入
使能时钟例子
在某系统中,前级数据输入位宽为8,而后级的数据输出位宽32,我们需要将8bit的数据转换成32bit的数据,因此后级处理的时钟频率为前级的 1/4,若不使用时钟时能,则就要将前级时钟进行4分频来作为后级处理的时钟,这种设计方法会引入新的时钟域,为了避免这种情况,我们采用了时钟时能的方 法来减少设计的复杂度。
module gray ( input clk, input rst_n, input [7:0] data_in, output reg [31:0] data_out, output reg clk1x_en ); reg [1:0] cnt; reg [31:0] shift_reg; always @ (posedge clk,negedge rst_n) begin if(!rst_n) begin cnt <= 2'b0; clk1x_en <= 1'b0; shift_reg <= 32'b0; end else if(cnt ==2'b01) begin cnt <= cnt +1'b1; clk1x_en <= 1'b1; shift_reg <= {shift_reg[23:0],data_in}; end else begin cnt <= cnt +1'b1; clk1x_en <= 1'b0; shift_reg <= {shift_reg[23:0],data_in}; end end always @ (posedge clk,negedge rst_n) begin if(!rst_n) data_out<= 32'b0; else if(clk1x_en==1'b1)//仅在clk1x_en为1时才将shift_reg的值赋给data_out data_out<=shift_reg; end endmodule