在FPGA中实现频率计方案详解(等精度测量)
1.方案分析
1.1 频率测量法与周期测量法
常用的频率测量方法有两种,分别是频率测量法和周期测量法。
频率测量法:在时间t内对被测时钟信号时钟周期N计数,求出单位时间内的时钟周期数,即为被测
时钟信号的时钟频率。所以频率测量法适用于测量高频时钟信号。
周期测量法:先测量出被测时钟信号的时钟周期T,根据频率f = 1 / T 求出被测时钟信号的频率。
所以周期测量法适用于低频时钟信号的测量。
由定义可以知道,频率测量法在规定的时间测量周期的个数,当周期越小时,越容易测得周期的个数;周期测量法则是直接测一个周期的时间,当周期越大时,精度也就越高。
但是这两种方法都会产生±1个被测时钟周期的误差,在实际应用中会有一定的局限性。而且两者不能兼顾高低频率有同样精度的测量要求。以下是误差示意图


所以就有了等精度测量法的出现。
1.2 等精度测量法
等精度测量法与前两种方式不同,其最大的特点是,测量的实际门控时间不是一个固定值,它与被测时钟信号有关,是被测时钟信号周期的整数倍。在实际门控信号下,同时对标准时钟和被测时钟信号的时钟周期进行计数,再通过公式计算得到被测信号的时钟频率。
由于实际门控信号是被测时钟周期的整数倍,就消除了被测信号产生的±1时钟周期的误差,
但是会产生标准时钟信号±1时钟周期的误差。等精度测量原理示意图如下。

由等精度测量的原理和示意图可得:
①被测时钟信号的时钟频率fx的相对误差与被测时钟无关;
②增大“软件闸门”的有效范围或者提高“标准时钟信号”的时钟频率fs,可以减小误差,提高测量精度。
了解等精度测量原理之后,现在说明一下被测时钟信号的计算方法。
首先分别对实际闸门下被测时钟信号和标准时钟信号的时钟周期进行计数。
①实际闸门下被测时钟信号周期为X,设被测信号时钟周期为Tfx,其时钟频率fx=1 / Tfx,由此式可得等式:
②实际闸门下标准时钟信号周期数为Y,设被测信号时钟周期为Tfs,其时钟频率fx=1 / Tfs,由此式可得等式:
③将两等式结合得到只包含各自时钟周期计数和时钟频率的等式,得到被测时钟信号时钟频率计算公式为:
④将已知量标准时钟信号频率fs和测量值X,Y带入公式,即可得到被测时钟信号频率fx。
2.方案实现
2.1 整体方案
本次实验的硬件平台为小梅哥AC101-EDA,开发软件为Quartus13.1。

如下流程图也很简单,一共就大概分为两个模块(数码管驱动有几个子模块)。

整体的思路就是通过引脚直接测量信号发生器的输出的方波信号,通过频率计模块计算出频率,将结果输送给数码管进行显示。
频率计模块时序图如下:

频率计算模块的作用是:使用等精度测量法对输入的待检测时钟信号进行频率测量,并将测量结果输出。 模块内实例化一个PLL ip核,将50MHz的系统时钟倍频为100MHz。
提问:为什么要用100MHz的时钟信号作为标准信号呢?
在前文的分析中,被测时钟信号的时钟频率fx的相对误差与被测时钟信号无关;增大“软件闸门”的有效范围或者提高“标准时钟信号”的时钟频率fs,可以减小误差,提高测量精度。
使用100MHz时钟作为标准时钟信号,实际闸门时间大于或等于1s时,就可使测量的最大相对误差小于或等于10-8,即精度达到1/100MHz,大大提高测量精度。
接下来对时序图的各个波形进行详细说明。
第一部分:软件闸门gata_s及相关信号的设计与实现
由等精度测量原理可知,实现等精度测量必不可少的是实际闸门,而实际闸门是由软件闸门得来,所以现在先生成软件闸门。这里计划一个完整周期的软件闸门为1.5s,前0.25s保持低电平,中间1s保持高电平,最后0.25s保持低电平。高电平保持1s是为了提高测试精度。
低电平部分是为了将各计数器清0,并计算待测时钟信号的频率;高电平部分就是软件闸门的有效部分。
这里的软件闸门时间由50MHz系统时钟进行计数。最大值为74_999_999。

第二部分:实现闸门gata_a的设计与实现
生成软件闸门后,使用被测时钟对软件闸门进行同步生成实际闸门gata_a,波形图如下:

第三部分:实际闸门下,标准信号和被测信号时钟计数相关信号的波形设计与实现
在实际闸门下,分别用标准信号和被测信号的时钟进行计数。
cnt_clk_stand :使用clk_stand进行计数。
cnt_clk_test :使用clk_test进行时钟周期计数。

cnt_clk_stand 和 cnt_clk_test 这两个计数器在实际闸门下计数完成之后,需要对数据进行清零。所以这个时候需要对数据结果进行寄存,选择实际闸门的下降沿的时刻进行数据寄存。
cnt_clk_stand的寄存:通过将实际闸门gata_a打一拍后得到下降沿标志信号gata_a_fall_stand,当gata_a_fall_stand为高时,将数值寄存。
cnt_clk_test 的寄存 :与上同理,将clk_test打一拍,得到下降沿标志信号,进行寄存。

此时我们已经获取了所有需要知道的值,下一步就是计算结果并输出了。
第四部分:频率计算结果freq及输出
什么是时候对数据进行求解,这是一个关键的问题。这里选择在软件闸门计数器cnt_gata_s计数到最大值的时候进行结果计算。使用calc_flag作为计算标志信号。随后在系统时钟下对calc_flag打一拍得到calc_flag_reg作为结果输出信号。

以上,关于频率计模块的讲解就结束了。
最后将结果输送进数码管模块进行显示即可。
3.实验结果

可以看出精度还是很高的,能够在上百K的频率下,实现个位数的分辨率。至于上M后的频率,我就没有进行测试了,而且我使用的这台信号发生器最高只支持25M的方波输出,也不方便我进行测试。就这样吧。
后话
这部分与频率计实验原理是无关的,只是对我测试时遇到的现象的思考。
1.首先拿到这个开发板的时候,有一点是让我比较为难的——这块板子并没有单独的IO口。
我查看了开发板的原理图,最终发现左侧的排母是用于LCD的,其中每个引脚都是连接了一个上拉电阻,这让我感到很为难。我最开始尝试把电阻断开,这样就能形成短路,但是做这个实际上是给本科生做实验的,这样的话,每块板子都需要拆除电阻,这并不现实。

后来我导师让我查看一下VCC_LCD能否断开。我发现了P1是使用跳线帽来对VCC_LCD进行电压选择的,也就是说:当P1不接入跳线帽,那么VCC_LCD实际就为开路,这个时候可以视作有关LCD的引脚直接与FPGA芯片相连接,也就是说可以当作普通的IO使用。
2.关于信号发生器的设置
关于波形设置:这种测量方式只适用于对方波进行测试,原因有二:其一是等精度测量的实现原理,都是基于高低电平的;其二是FPGA的输入引脚只能感受高低电平变化,是不可能测量正弦波、三角波等波形的。如果想要测得正弦波这种波形的频率,一般有两种方式:1.通过过零比较器将正弦波转化为方波再进行等精度测量;2.使用fft进行测频,但这就需要使用ADC了。
关于幅度设置:最开始没有现象,我以为是程序有问题。找了挺久代码的错误但都没进展。后来我使用signal tap对一些寄存器和变量进行抓取,发现了问题所在:连输入信号都不正常。我以为是板子的问题,但也没找到。
最后我发现了幅度设置,信号发生器默认输出的是5Vpp的信号,而FPGA IO 口的电平标准一般是LVCMOS33,即输入幅度与标准不兼容,所以会出现,测量的值可能为实际值的2倍或1/2甚至根本就不对,这里测试2.5Vpp的输出信号是能够正确测量的。
