1、FPGA頻率測量?
頻率測量在電子設(shè)計(jì)和測量領(lǐng)域中經(jīng)常用到,因此對頻率測量方法的研究在實(shí)際工程應(yīng)用中具有重要意義。
通常的頻率測量方法有三種:直接測量法,間接測量法,等精度測量法。
2、直接測量法
2.1、方法
直接測量法也叫頻率測量法,即在固定在時(shí)間t內(nèi)對被測信號(hào)的脈沖數(shù)進(jìn)行計(jì)數(shù),然后求出單位時(shí)間內(nèi)的脈沖數(shù),即為被測信號(hào)的頻率。
下圖中的信號(hào)分別為:
sys_clk:系統(tǒng)的基準(zhǔn)時(shí)鐘
gate:根據(jù)基準(zhǔn)時(shí)鐘生成的閘門信號(hào),用于生成一個(gè)固定的時(shí)間(例如1s,方便計(jì)算)
clk_fx:被測信號(hào)

gate是在基準(zhǔn)時(shí)鐘下生成的固定時(shí)間信號(hào),它持續(xù)的時(shí)間 Tg = sys_clk 計(jì)數(shù)個(gè)數(shù)N(可設(shè)置);在gate持續(xù)為高的時(shí)間內(nèi),可使用被測信號(hào)clk_fx對其進(jìn)行計(jì)數(shù),計(jì)數(shù)個(gè)數(shù)為cnt(圖中為5),則cnt個(gè)被測信號(hào)的周期即為gate時(shí)長。
此種方法的本質(zhì)是:同樣的時(shí)間內(nèi)分別使用兩種時(shí)鐘計(jì)時(shí),則有 Tg = Tfx---- Tsys_clk 計(jì)數(shù)個(gè)數(shù)N = Tclk_fx cnt,公式變換后:clk_fx = cnt sys_clk / 計(jì)數(shù)個(gè)數(shù)N (其中clk_fx為待測信號(hào)頻率,sys_clk為基準(zhǔn)時(shí)鐘頻率)
2.2、誤差分析
從圖可以看出,在gate為高電平期間,被測信號(hào)實(shí)際上差不多有六個(gè)周期被囊括在內(nèi),但是因?yàn)楸粶y信號(hào)是相對與系統(tǒng)的異步信號(hào),相位不同,第一個(gè)周期無法被采樣,所以實(shí)際采樣為5,這樣造成的誤差為一個(gè)被測信號(hào)周期??梢灶A(yù)見,這種測量方法帶來的測量誤差即為一個(gè)被測信號(hào)周期。
那么理論上測得的準(zhǔn)確頻率:clk_fxe = cnt sys_clk / 計(jì)數(shù)個(gè)數(shù)N----理論上cnt無誤差
實(shí)際上測量的頻率值:clk_fx= cnt±1 sys_clk / 計(jì)數(shù)個(gè)數(shù)N----cnt會(huì)存在一個(gè)周期的測量誤差
測量誤差 = |(clk_fxe -clk_fx)/clk_fxe | 100% = 1 / cnt 100%
所以測得的cnt越大,那么測出來的誤差值就小,而cnt越大則代表被測信號(hào)的頻率越高,所以可以推斷該種測量方法適合測量高頻信號(hào);此外,選擇的閘門時(shí)間越長則被測信號(hào)的個(gè)數(shù)越多,同樣測量就越精確,但是增大閘門時(shí)間又會(huì)帶來測量時(shí)間過長的問題,需要依據(jù)具體需求進(jìn)行取舍。
2.3、Verilog代碼
Verilog源碼如下:
閘門時(shí)間設(shè)定為0.5s,非閘門時(shí)間也0.5s,則每1秒更新一次測量數(shù)據(jù)
使用計(jì)數(shù)器生成閘門時(shí)間,閘門時(shí)間取反得到非閘門時(shí)間
在閘門時(shí)間對被測信號(hào)計(jì)數(shù)
在非閘門時(shí)間更新測量數(shù)據(jù)
使用parameter定義參數(shù),方便調(diào)用修改
//直接測量法(高頻) modulecymometer_direct( input sys_clk,//基準(zhǔn)時(shí)鐘,設(shè)計(jì)為50M(可更改) input sys_rst_n,//復(fù)位信號(hào),低電平有效 input clk_fx,//待測信號(hào) output reg [31:0]fre//測量結(jié)果 ); parameterTIME_SYS = 20;//系統(tǒng)時(shí)鐘周期:20ns--頻率=50MHz parameterTIME_GATE = 500_000_000;//500ms閘門設(shè)置的時(shí)間,單位:ns localparamN = TIME_GATE /TIME_SYS;//生成閘門需要計(jì)數(shù)的個(gè)數(shù) reg gate;//閘門 reg [31:0] cnt_gate;//用于生成閘門的計(jì)數(shù)器 reg [31:0] cnt_fx;//閘門時(shí)間內(nèi)對被測信號(hào)計(jì)數(shù) wiregate_n;//閘門取反,用于在非閘門時(shí)輸出測得的頻率值 assigngate_n = ~gate;//閘門取反,用于在非閘門時(shí)輸出測得的頻率值 //分頻計(jì)數(shù)器,閘門時(shí)間設(shè)定為1ms,則每2ms測量一次 always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n)begin cnt_gate <=0; gate <=0; end else begin if(cnt_gate == N-1)begin cnt_gate <= 0; gate <= ~gate; end else cnt_gate<=cnt_gate+1; end end //閘門時(shí)間內(nèi)對被測信號(hào)計(jì)數(shù) always @(posedge clk_fx or negedge sys_rst_n)begin if(!sys_rst_n) cnt_fx <= 0; else if(gate) cnt_fx <= cnt_fx + 1; else cnt_fx <= 0; end //在非閘門時(shí)輸出測得的頻率值 always @(posedge gate_n or negedge sys_rst_n)begin if(!sys_rst_n) fre <= 0; else //TIME_GATE/cnt_fx=規(guī)定時(shí)間/被測信號(hào)個(gè)數(shù)=被測信號(hào)周期,取倒數(shù)即為頻率 fre <= 1000_000_000/TIME_GATE * cnt_fx; end endmodule
2.4、仿真分析
Testbench:
設(shè)計(jì)被測信號(hào)周期為489*2=978ns,則其理論頻率為1/978ns=1022494.88Hz;
`timescale 1ns/1ns//時(shí)間單位/精度 //------------<模塊及端口聲明>---------------------------------------- module tb_cymometer_direct(); reg sys_clk; reg sys_rst_n; reg clk_fx; wire [31:0] fre; // defparam cymometer_direct_inst.TIME_GATE = 500_000; //地址位寬 //------------<例化被測試模塊>---------------------------------------- cymometer_directcymometer_direct_inst( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx), .fre (fre) ); //------------<設(shè)置初始測試條件>---------------------------------------- initial begin sys_clk = 1'b0;//初始時(shí)鐘為0 sys_rst_n <= 1'b0;//初始復(fù)位 clk_fx<= 1'b0; #5//5個(gè)時(shí)鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) // #2500_000 // forever#2560 clk_fx = ~clk_fx; end //------------<設(shè)置時(shí)鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時(shí)鐘周期20ns always #489 clk_fx = ~clk_fx;//被測信號(hào)周期489*2ns = 978ns endmodule
仿真如下圖:

上圖在閘門時(shí)間內(nèi)測得的被測信號(hào)個(gè)數(shù)cnt_fx為511248,測得被測信號(hào)頻率為1022496Hz;理論頻率=1/978ns=1022494.88Hz(MHz級別)。
可以看出這個(gè)測量結(jié)果還是比較準(zhǔn)確的。因?yàn)殚l門時(shí)間夠長,且被測信號(hào)自身頻率就比較高(約1Mhz)。
接下來更改一下Testbench,比較一下閘門時(shí)間對被測信號(hào)的影響以及被測信號(hào)自身頻率高低對測量的影響:
第1個(gè)模塊:被測信號(hào)頻率為1022494.88Hz(MHz級別),閘門時(shí)間0.5s
第2個(gè)模塊:被測信號(hào)頻率為1022494.88Hz(MHz級別),閘門時(shí)間0.5ms
第3個(gè)模塊:被測信號(hào)頻率為76103.5Hz(KHz級別),閘門時(shí)間0.5s
第4個(gè)模塊:被測信號(hào)頻率為21.217Hz(Hz級別),閘門時(shí)間0.5s
//多變量對比測試 `timescale 1ns/1ns//時(shí)間單位/精度 //------------<模塊及端口聲明>---------------------------------------- module tb_cymometer_direct(); reg sys_clk; reg sys_rst_n; reg clk_fx1; reg clk_fx2; reg clk_fx3; reg clk_fx4; wire [31:0]fre1; wire [31:0]fre2; wire [31:0]fre3; wire [31:0]fre4; defparam cymometer_direct_inst2.TIME_GATE = 500_000; //重設(shè)閘門時(shí)間1ms //------------<例化被測試模塊>---------------------------------------- cymometer_directcymometer_direct_inst1( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx1), .fre (fre1) ); cymometer_directcymometer_direct_inst2( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx2), .fre (fre2) ); cymometer_directcymometer_direct_inst3( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx3), .fre (fre3) ); cymometer_directcymometer_direct_inst4( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx4), .fre (fre4) ); //------------<例化被測試模塊>---------------------------------------- //------------<設(shè)置初始測試條件>---------------------------------------- initial begin sys_clk = 1'b0;//初始時(shí)鐘為0 sys_rst_n <= 1'b0;//初始復(fù)位 clk_fx1<= 1'b0; clk_fx2<= 1'b0; clk_fx3<= 1'b0; clk_fx4<= 1'b0; #5//5個(gè)時(shí)鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) end //------------<設(shè)置時(shí)鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時(shí)鐘周期20ns always #489 clk_fx1 = ~clk_fx1;//被測信號(hào)周期489*2ns,理論頻率1022494.88Hz(MHz級別) always #489 clk_fx2 = ~clk_fx2;//被測信號(hào)周期489*2ns,理論頻率1022494.88Hz(MHz級別) always #6570 clk_fx3 = ~clk_fx3;//被測信號(hào)周期6570*2ns,理論頻率76103.5Hz(KHz級別) always #23565678 clk_fx4 = ~clk_fx4;//被測信號(hào)周期23565678*2ns,理論頻率21.217Hz(Hz級別) endmodule
測量結(jié)果如下:

將測量結(jié)果整理成下表:
| 閘門時(shí)間 | 理論頻率(Hz) | 實(shí)際測量頻率(Hz) | 測量誤差 | |
| 模塊1 | 0.5s | 1022494.88 | 1022496 | 1.095e-4% |
| 模塊2 | 0.5ms | 1022494.88 | 1022000 | 4.840e-4% |
| 模塊3 | 0.5s | 76103.5 | 76104 | 6.570e-4% |
| 模塊4 | 0.5s | 21.217 | 20 | 5.736% |
從上表的測試結(jié)果可以對直接測量法做出如下總結(jié):
閘門時(shí)間越長,測量結(jié)果越精準(zhǔn),但是也會(huì)導(dǎo)致單次測量時(shí)間過長
直接測量法適合測量高頻信號(hào),測量誤差與閘門時(shí)間及被測信號(hào)頻率相關(guān)
3、間接測量法
3.1、方法
間接測量法也叫周期測量法,即在一個(gè)被測信號(hào)的周期內(nèi),測量基準(zhǔn)時(shí)鐘的個(gè)數(shù),得到被測信號(hào)的周期,再將其轉(zhuǎn)化為頻率。
下圖中的信號(hào)分別為:
sys_clk:系統(tǒng)的基準(zhǔn)時(shí)鐘
clk_fx:被測信號(hào)

在被測信號(hào)clk_fx為高電平的時(shí)間內(nèi),使用基準(zhǔn)時(shí)鐘進(jìn)行計(jì)數(shù),計(jì)數(shù)個(gè)數(shù)為cnt(圖中為8),則cnt基準(zhǔn)時(shí)鐘周期=半個(gè)被測信號(hào)的周期。
所以cnt/ FERQ_SYS(基準(zhǔn)時(shí)鐘頻率)=(1/2) * (1/clk_fx),化簡后clk_fx =FERQ_SYS/(cnt*2)
此種方法適用于測量低頻信號(hào),但同時(shí)也會(huì)帶來測量速度過慢的問題,誤差來自一個(gè)系統(tǒng)基準(zhǔn)時(shí)鐘。
3.2、誤差分析
從圖可以看出,在被測信號(hào)高電平期間,被測信號(hào)實(shí)際上差不多有8.5個(gè)周期被囊括在內(nèi),但是因?yàn)楸粶y信號(hào)是相對與系統(tǒng)的異步信號(hào),相位不同,所以實(shí)際采樣為8,這樣造成的誤差為1個(gè)基準(zhǔn)信號(hào)周期??梢灶A(yù)見,這種測量方法帶來的測量誤差即為一個(gè)基準(zhǔn)信號(hào)周期。
那么理論上測得的準(zhǔn)確頻率:clk_fx =FERQ_SYS/(cnt*2)----理論上cnt無誤差
實(shí)際上測量的頻率值:clk_fx =FERQ_SYS/((cnt±1)*2)----cnt會(huì)存在一個(gè)周期的測量誤差
測量誤差 = |(clk_fxe -clk_fx)/clk_fxe | 100% = 1 / cnt 100%
所以測得的cnt越大,那么測出來的誤差值就小,而cnt越大則代表被測信號(hào)的頻率越低(周期越高),所以可以推斷該種測量方法適合測量低頻信號(hào)。
2.3、Verilog代碼
Verilog源碼如下:
在被測信號(hào)計(jì)數(shù)高電平期間使用基準(zhǔn)時(shí)鐘計(jì)數(shù)
在被測信號(hào)計(jì)數(shù)低電平期間更新測量數(shù)據(jù)
使用parameter定義參數(shù),方便調(diào)用修改
//間接測量法(低頻)
module cymometer_indirect(
input sys_clk,//基準(zhǔn)時(shí)鐘,設(shè)計(jì)為50M(可更改)
input sys_rst_n, //復(fù)位信號(hào),低電平有效
//待測信號(hào)
input clk_fx,//測量結(jié)果
output reg [31:0]fre
);
parameterTIME_SYS = 20;//系統(tǒng)時(shí)鐘周期:20ns--頻率=50MHz
reg [31:0]cnt_fx;//對被測信號(hào)高電平進(jìn)行計(jì)數(shù)的計(jì)數(shù)器
//在測信號(hào)高電平期間進(jìn)行計(jì)數(shù)
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt_fx <= 0;
else if(clk_fx)
cnt_fx <= cnt_fx+1;
else
cnt_fx <= 0;
end
//在測信號(hào)低電平期輸出測量數(shù)據(jù)
always @(negedge clk_fx or negedge sys_rst_n )begin
if(!sys_rst_n)
fre<=0;
else
fre<=1000_000_000/(TIME_SYS*cnt_fx*2);
end
endmodule
3.4、仿真分析
Testbench依然采用在直接測量法測試用的3個(gè)頻率設(shè)置
模塊1被被測信號(hào)周期23565678*2ns,理論頻率21.217Hz(Hz級別)
模塊2被測信號(hào)周期6570*2ns,理論頻率76103.5Hz(KHz級別)
模塊3被測信號(hào)周期489*2ns,理論頻率1022494.88Hz(MHz級別)
`timescale 1ns/1ns//時(shí)間單位/精度 //------------<模塊及端口聲明>---------------------------------------- module tb_cymometer_indirect(); reg sys_clk; regsys_rst_n; regclk_fx1; regclk_fx2; regclk_fx3; wire [31:0]fre1; wire [31:0]fre2; wire [31:0]fre3; //------------<例化被測試模塊>---------------------------------------- cymometer_indirectcymometer_indirect_inst1( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx1), .fre (fre1) ); cymometer_indirectcymometer_indirect_inst2( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx2), .fre (fre2) ); cymometer_indirectcymometer_indirect_inst3( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .clk_fx(clk_fx3), .fre (fre3) ); //------------<設(shè)置初始測試條件>---------------------------------------- initial begin sys_clk = 1'b0;//初始時(shí)鐘為0 sys_rst_n <= 1'b0;//初始復(fù)位 clk_fx1<= 1'b0; clk_fx2<= 1'b0; clk_fx3<= 1'b0; #5//5個(gè)時(shí)鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) end //------------<設(shè)置時(shí)鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時(shí)鐘周期20ns always #23565678 clk_fx1 = ~clk_fx1;//被測信號(hào)周期23565678*2ns,理論頻率21.217Hz(Hz級別) always #6570 clk_fx2 = ~clk_fx2;//被測信號(hào)周期6570*2ns,理論頻率76103.5Hz(KHz級別) always #489 clk_fx3 = ~clk_fx3;//被測信號(hào)周期489*2ns,理論頻率1022494.88Hz(MHz級別) endmodule
仿真如下圖1:

將測量結(jié)果整理成下表:
| 理論頻率(Hz) | 實(shí)際測量頻率(Hz) | 測量誤差 | |
| 模塊1 | 21.217297 | 21 | 1.02% |
| 模塊2 | 76103.5 | 75987 | 0.15% |
| 模塊3 | 1022494.88 | 1041666 | 1.87% |
從上表的測試結(jié)果可以對間接測量法做出如下總結(jié):間接測量法適合測量低頻信號(hào),測量誤差與測信號(hào)頻率相關(guān)。
需要注意的是,輸出信號(hào)不能處理浮點(diǎn)數(shù),推薦的解決辦法是將其放大整數(shù)倍(100倍),以便實(shí)現(xiàn)小數(shù)點(diǎn)的頻率測量(不然小數(shù)點(diǎn)被截?cái)鄷?huì)帶來額外的誤差)。
將測量結(jié)果乘以1000,一定程度上消除小數(shù)截?cái)鄮淼恼`差,模塊1的測試結(jié)果為21.217Hz,測量誤差為1.9998e-3%,大大低于另外兩個(gè)高頻信號(hào)。(這里不給出具體的測試過程了,可以自己嘗試下)。
4、等精度測量法
4.1、概念
上述兩種方法都會(huì)產(chǎn)生±1 個(gè)被測時(shí)鐘周期的誤差,在實(shí)際應(yīng)用中有一定的局限 性;而且根據(jù)兩種方式的測量原理,很容易發(fā)現(xiàn)頻率測量法適合于測量高頻時(shí)鐘信號(hào),而周期測量法適合于低頻時(shí)鐘信號(hào)的測量,但二者都不能兼顧高低頻率同樣精度的測量要求。
等精度測量法與前兩種方式不同,其最大的特點(diǎn)是,測量的實(shí)際門控時(shí)間不是一個(gè)固 定值,它與被測時(shí)鐘信號(hào)相關(guān),是被測時(shí)鐘信號(hào)周期的整數(shù)倍。在實(shí)際門控信號(hào)下,同時(shí)對標(biāo)準(zhǔn)時(shí)鐘和被測時(shí)鐘信號(hào)的時(shí)鐘周期進(jìn)行計(jì)數(shù),再通過公式計(jì)算得到被測信號(hào)的時(shí)鐘頻率。 由于實(shí)際門控信號(hào)是被測時(shí)鐘周期的整數(shù)倍,就消除了被測信號(hào)產(chǎn)生的±1 時(shí)鐘周期的誤差,但是會(huì)產(chǎn)生對標(biāo)準(zhǔn)時(shí)鐘信號(hào)±1時(shí)鐘周期的誤差,而標(biāo)準(zhǔn)時(shí)鐘通常又是頻率極高,所以誤差較之前兩種方法就大大降低。
此種測量方法相對誤差與被測信號(hào)頻率的大小無關(guān),僅與閘門時(shí)間和基準(zhǔn)時(shí)鐘頻率有關(guān),即實(shí)現(xiàn)了整個(gè)測試頻段的等精度測量。閘門時(shí)間越長,基準(zhǔn)時(shí)鐘頻率越高,測頻的相對誤差越小。需要注意的是,原則上門控時(shí)間越長,則精度越高,但測量低頻信號(hào)(Hz級別)時(shí),建議將門控時(shí)間設(shè)置為被測信號(hào)的十幾倍即可,否則測量時(shí)間將會(huì)過長。

了解了等精度測量原理之后,我們來說明一下被測時(shí)鐘信號(hào)的計(jì)算方法:
首先通過被測信號(hào)生成實(shí)際閘門
分別對實(shí)際閘門下被測時(shí)鐘信號(hào)和標(biāo)準(zhǔn)時(shí)鐘信號(hào)的時(shí)鐘周期進(jìn)行計(jì)數(shù)。
實(shí)際閘門下被測時(shí)鐘信號(hào)周期數(shù)為 X,設(shè)被測信號(hào)時(shí)鐘周期為 Tfx,它的時(shí)鐘頻率 fx = 1/Tfx,由此可得等式:X * Tfx = X / fx = Tx(實(shí)際閘門)----這里無誤差。
實(shí)際閘門下標(biāo)準(zhǔn)時(shí)鐘信號(hào)周期數(shù)為 Y(誤差為1),設(shè)被測信號(hào)時(shí)鐘周期為 Tfs,它的時(shí)鐘頻率 fs = 1/Tfs,由此可得等式:Y * Tfs = Y / fs = Tx(實(shí)際閘門)----這里最大誤差為1個(gè)基準(zhǔn)時(shí)鐘周期。
將兩等式結(jié)合得到只包含各自時(shí)鐘周期計(jì)數(shù)和時(shí)鐘頻率的等式:X / fx = Y / fs = Tx(實(shí)際閘門),等式變換,得到被測時(shí)鐘信號(hào)時(shí)鐘頻率計(jì)算公式:fx = X * fs / Y。
將已知量標(biāo)準(zhǔn)時(shí)鐘信號(hào)時(shí)鐘頻率 fs 和測量量 X、Y 帶入計(jì)算公式,得到被測時(shí)鐘信號(hào)時(shí)鐘頻率 fx。
4.2、誤差分析
根據(jù)前文及上圖,不難發(fā)現(xiàn),誤差來源于使用基準(zhǔn)時(shí)鐘在閘門時(shí)間測量時(shí)會(huì)存在一個(gè)基準(zhǔn)時(shí)鐘周期的誤差。
那么理論上測得的準(zhǔn)確頻率:clk_fxe = X * fs / Y----理論上Y無誤差
實(shí)際上測量的頻率值:clk_fx = X * fs / Y----Y會(huì)存在1個(gè)周期的測量誤差
測量誤差 = |(clk_fxe - clk_fx)/ clk_fxe | 100% = 1 / Y 100%
所以測得的Y越大,那么測出來的誤差值就小。當(dāng)閘門時(shí)間越大,Y越大;基準(zhǔn)時(shí)鐘頻率越高,Y越大。所以通過提高基準(zhǔn)時(shí)鐘頻率或者增加閘門時(shí)間(但是會(huì)使測量過長,需要取舍),可以有效提高測量精度。
4.3、Verilog代碼
Verilog源碼如下:
//等精度測量法(低頻)
module cymometer_equal (
input clk_fs ,
input rst_n ,
input clk_fx ,
output reg [63:0] fre
);
parameterCLK_FS = 26'd50_000_000;
parameter GATE_TIME = 16'd100; //門控時(shí)間,越大誤差越小,但測量時(shí)間也會(huì)變長
//reg define
reg gate_fx; //門控信號(hào),被測信號(hào)域下
reg gate_fs ; //同步到基準(zhǔn)時(shí)鐘的門控信號(hào)
reg gate_fs_r ; //用于同步gate信號(hào)的寄存器
reg gate_fs_d0 ; //用于采集基準(zhǔn)時(shí)鐘下gate下降沿
reg gate_fs_d1 ; //用于采集基準(zhǔn)時(shí)鐘下gate下降沿
reg gate_fx_d0 ; //用于采集被測時(shí)鐘下gate下降沿
reg gate_fx_d1 ; //用于采集被測時(shí)鐘下gate下降沿
reg [15:0] gate_cnt ; //門控計(jì)數(shù)
reg [31:0] fs_cnt ; //門控時(shí)間內(nèi)基準(zhǔn)時(shí)鐘的計(jì)數(shù)值
reg [31:0] fs_cnt_temp ; //fs_cnt 臨時(shí)值
reg [31:0] fx_cnt ; //門控時(shí)間內(nèi)被測時(shí)鐘的計(jì)數(shù)值
reg [31:0] fx_cnt_temp ; //fx_cnt 臨時(shí)值
//wire define
wire neg_gate_fs; //基準(zhǔn)時(shí)鐘下門控信號(hào)下降沿=
wire neg_gate_fx; //被測時(shí)鐘下門控信號(hào)下降沿
//捕捉信號(hào)下降沿
assign neg_gate_fs = gate_fs_d1 & (~gate_fs_d0);
assign neg_gate_fx = gate_fx_d1 & (~gate_fx_d0);
//檢測gate_fx下降沿
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) begin
gate_fx_d0 <= 1'b0;
gate_fx_d1 <= 1'b0;
end
else begin
gate_fx_d0 <= gate_fx;
gate_fx_d1 <= gate_fx_d0;
end
end
//檢測gate_fs下降沿
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) begin
gate_fs_d0 <= 1'b0;
gate_fs_d1 <= 1'b0;
end
else begin
gate_fs_d0 <= gate_fs;
gate_fs_d1 <= gate_fs_d0;
end
end
//被測時(shí)鐘閘門計(jì)數(shù)器
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n)
gate_cnt <= 16'd0;
else if(gate_cnt == GATE_TIME*2)
gate_cnt <= 16'd0;
else
gate_cnt <= gate_cnt + 1'b1;
end
//被測時(shí)鐘閘門生成
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n)
gate_fx <= 1'b0;
else if(gate_cnt == GATE_TIME)
gate_fx <= 1'b1;
else if(gate_cnt == GATE_TIME*2)
gate_fx <= 1'b0;
else
gate_fx <= gate_fx;
end
//把閘門從被測時(shí)鐘域同步到基準(zhǔn)時(shí)鐘域
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) begin
gate_fs_r <= 1'b0;
gate_fs <= 1'b0;
end
else begin
gate_fs_r <= gate_fx;
gate_fs <= gate_fs_r;
end
end
//在被測時(shí)鐘域?qū)Ρ粶y信號(hào)計(jì)數(shù)
always @(posedge clk_fx or negedge rst_n) begin
if(!rst_n) begin
fx_cnt_temp <= 0;
fx_cnt <= 0;
end
else if(gate_fx)
fx_cnt_temp <= fx_cnt_temp + 1'b1;
else if(neg_gate_fx) begin
fx_cnt_temp <= 0;
fx_cnt <= fx_cnt_temp;
end
end
//在基準(zhǔn)時(shí)鐘域?qū)鶞?zhǔn)時(shí)鐘計(jì)數(shù)
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) begin
fs_cnt_temp <= 0;
fs_cnt <= 0;
end
else if(gate_fs)
fs_cnt_temp <= fs_cnt_temp + 1'b1;
else if(neg_gate_fs) begin
fs_cnt_temp <= 0;
fs_cnt <= fs_cnt_temp;
end
end
//在基準(zhǔn)時(shí)鐘域輸出結(jié)果
always @(posedge clk_fs or negedge rst_n) begin
if(!rst_n) begin
fre <= 0;
end
else if(gate_fs == 1'b0)
fre <= (CLK_FS * fx_cnt ) / fs_cnt;
end
endmodule
4.4、仿真分析
Testbench:
設(shè)計(jì)被測信號(hào)周期為489*2=978ns,則其理論頻率為1/978ns=1022494.88Hz
`timescale 1 ns/ 1 ns
//------------<模塊及端口聲明>----------------------------------------
module tb_cymometer_equal();
reg clk_fs;
reg clk_fx;
reg rst_n;
wire [63:0] fre;
//------------<例化被測試模塊>----------------------------------------
cymometer_equal cymometer_equal_inst (
.clk_fs(clk_fs),
.clk_fx(clk_fx),
.fre(fre),
.rst_n(rst_n)
);
//------------<設(shè)置初始測試條件>----------------------------------------
initialbegin
clk_fs = 1'b0;
clk_fx <= 1'b0;
rst_n <= 1'b0;
#116
rst_n <= 1'b1;
end
//------------<設(shè)置時(shí)鐘>----------------------------------------------
always#10 clk_fs <= ~clk_fs;
always #489 clk_fx <= ~clk_fx;
endmodule
仿真結(jié)果如下所示

上圖的測量結(jié)果為1022494Hz,理論頻率為1/978ns=1022494.88Hz,可以看到這個(gè)結(jié)果相當(dāng)精確。
接下來更改一下Testbench,比較一下閘門時(shí)間對被測信號(hào)的影響以及被測信號(hào)自身頻率高低對測量的影響(為避免仿真時(shí)間過長,閘門時(shí)間均設(shè)為10個(gè)被測信號(hào)周期,因?yàn)榛鶞?zhǔn)時(shí)鐘頻率較高,所以閘門時(shí)間少點(diǎn)不會(huì)有什么影響)
第1個(gè)模塊:被測信號(hào)頻率為1022494.88Hz(MHz級別)
第2個(gè)模塊:被測信號(hào)頻率為76103.5Hz(KHz級別)
第3個(gè)模塊:被測信號(hào)頻率為21.217Hz(Hz級別)
仿真結(jié)果如下:

將測量結(jié)果整理成下表:
| 理論頻率(Hz) | 實(shí)際測量頻率(Hz) | 測量誤差 | |
| 模塊1 | 1022494.88 | 1022494 | 8.60e-5% |
| 模塊2 | 76103.5 | 76103 | 6.57e-4% |
| 模塊3 | 21.217297 | 21 | 1.02% |
從上表的測試結(jié)果發(fā)現(xiàn)等精度測量法同時(shí)適用于高低頻域,測量結(jié)果誤差只和基準(zhǔn)時(shí)鐘頻率有關(guān)。
這里需要注意的是,因?yàn)闇y量結(jié)果都是整數(shù)(FPGA自動(dòng)截?cái)嘈?shù)),如果被測頻率較低,那么因?yàn)樾?shù)被截?cái)?,?huì)使得誤差增大。一個(gè)比較方便的解決辦法是把計(jì)算公式都放大一定的倍數(shù),從而使得“小數(shù)點(diǎn)前移”。 將測量結(jié)果乘以1000,一定程度上消除小數(shù)截?cái)鄮淼恼`差,模塊3的測試結(jié)果為21.217Hz,測量誤差為1.9998e-3%,基本和另外兩個(gè)信號(hào)處于同一數(shù)量級。(這里不給出具體的測試過程了,可以自己嘗試下)。
5、總結(jié)
直接測量法適合測量高頻信號(hào);頻率越高、測量時(shí)間越長,測量結(jié)果越精準(zhǔn);
間接測量法適合測量低頻信號(hào),但測量精度取決于自身頻率;
等精度測量法相對誤差與被測信號(hào)頻率的大小無關(guān),僅與閘門時(shí)間和基準(zhǔn)時(shí)鐘頻率有關(guān),即實(shí)現(xiàn)了整個(gè)測試頻段的等精度測量。閘門時(shí)間越長,基準(zhǔn)時(shí)鐘頻率越高,測頻的相對誤差就越小。
-
FPGA
+關(guān)注
關(guān)注
1650文章
22217瀏覽量
627864 -
頻率
+關(guān)注
關(guān)注
4文章
1571瀏覽量
61423 -
測量
+關(guān)注
關(guān)注
10文章
5428瀏覽量
115484
原文標(biāo)題:FPGA頻率測量的三種方法
文章出處:【微信號(hào):gh_9d70b445f494,微信公眾號(hào):FPGA設(shè)計(jì)論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
精選好文!噪聲系數(shù)測量的三種方法
啟動(dòng)Redis的三種方法
LwIP協(xié)議棧開發(fā)嵌入式網(wǎng)絡(luò)的三種方法有何關(guān)系
一種基于STM32F1 MCU測速的三種方法
解決電池問題有三種方法
臺(tái)式機(jī)CMOS放電三種方法
單片機(jī)測量PWM占空比的三種方法
【世說設(shè)計(jì)】噪聲系數(shù)測量的三種方法

FPGA頻率測量的三種方法
評論