1、FPGA頻率測量?
頻率測量在電子設(shè)計和測量領(lǐng)域中經(jīng)常用到,因此對頻率測量方法的研究在實際工程應(yīng)用中具有重要意義。
通常的頻率測量方法有三種:直接測量法,間接測量法,等精度測量法。
2、直接測量法
2.1、方法
直接測量法也叫頻率測量法,即在固定在時間t內(nèi)對被測信號的脈沖數(shù)進(jìn)行計數(shù),然后求出單位時間內(nèi)的脈沖數(shù),即為被測信號的頻率。
下圖中的信號分別為:
sys_clk:系統(tǒng)的基準(zhǔn)時鐘
gate:根據(jù)基準(zhǔn)時鐘生成的閘門信號,用于生成一個固定的時間(例如1s,方便計算)
clk_fx:被測信號
gate是在基準(zhǔn)時鐘下生成的固定時間信號,它持續(xù)的時間 Tg = sys_clk 計數(shù)個數(shù)N(可設(shè)置);在gate持續(xù)為高的時間內(nèi),可使用被測信號clk_fx對其進(jìn)行計數(shù),計數(shù)個數(shù)為cnt(圖中為5),則cnt個被測信號的周期即為gate時長。
此種方法的本質(zhì)是:同樣的時間內(nèi)分別使用兩種時鐘計時,則有 Tg = Tfx---- Tsys_clk 計數(shù)個數(shù)N = Tclk_fx cnt,公式變換后:clk_fx = cnt sys_clk / 計數(shù)個數(shù)N (其中clk_fx為待測信號頻率,sys_clk為基準(zhǔn)時鐘頻率)
2.2、誤差分析
從圖可以看出,在gate為高電平期間,被測信號實際上差不多有六個周期被囊括在內(nèi),但是因為被測信號是相對與系統(tǒng)的異步信號,相位不同,第一個周期無法被采樣,所以實際采樣為5,這樣造成的誤差為一個被測信號周期。可以預(yù)見,這種測量方法帶來的測量誤差即為一個被測信號周期。
那么理論上測得的準(zhǔn)確頻率:clk_fxe = cnt sys_clk / 計數(shù)個數(shù)N----理論上cnt無誤差
實際上測量的頻率值:clk_fx= cnt±1 sys_clk / 計數(shù)個數(shù)N----cnt會存在一個周期的測量誤差
測量誤差 = |(clk_fxe -clk_fx)/clk_fxe | 100% = 1 / cnt 100%
所以測得的cnt越大,那么測出來的誤差值就小,而cnt越大則代表被測信號的頻率越高,所以可以推斷該種測量方法適合測量高頻信號;此外,選擇的閘門時間越長則被測信號的個數(shù)越多,同樣測量就越精確,但是增大閘門時間又會帶來測量時間過長的問題,需要依據(jù)具體需求進(jìn)行取舍。
2.3、Verilog代碼
Verilog源碼如下:
閘門時間設(shè)定為0.5s,非閘門時間也0.5s,則每1秒更新一次測量數(shù)據(jù)
使用計數(shù)器生成閘門時間,閘門時間取反得到非閘門時間
在閘門時間對被測信號計數(shù)
在非閘門時間更新測量數(shù)據(jù)
使用parameter定義參數(shù),方便調(diào)用修改
//直接測量法(高頻) modulecymometer_direct( input sys_clk,//基準(zhǔn)時鐘,設(shè)計為50M(可更改) input sys_rst_n,//復(fù)位信號,低電平有效 input clk_fx,//待測信號 output reg [31:0]fre//測量結(jié)果 ); parameterTIME_SYS = 20;//系統(tǒng)時鐘周期:20ns--頻率=50MHz parameterTIME_GATE = 500_000_000;//500ms閘門設(shè)置的時間,單位:ns localparamN = TIME_GATE /TIME_SYS;//生成閘門需要計數(shù)的個數(shù) reg gate;//閘門 reg [31:0] cnt_gate;//用于生成閘門的計數(shù)器 reg [31:0] cnt_fx;//閘門時間內(nèi)對被測信號計數(shù) wiregate_n;//閘門取反,用于在非閘門時輸出測得的頻率值 assigngate_n = ~gate;//閘門取反,用于在非閘門時輸出測得的頻率值 //分頻計數(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 //閘門時間內(nèi)對被測信號計數(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 //在非閘門時輸出測得的頻率值 always @(posedge gate_n or negedge sys_rst_n)begin if(!sys_rst_n) fre <= 0; else //TIME_GATE/cnt_fx=規(guī)定時間/被測信號個數(shù)=被測信號周期,取倒數(shù)即為頻率 fre <= 1000_000_000/TIME_GATE * cnt_fx; end endmodule
2.4、仿真分析
Testbench:
設(shè)計被測信號周期為489*2=978ns,則其理論頻率為1/978ns=1022494.88Hz;
`timescale 1ns/1ns//時間單位/精度 //------------<模塊及端口聲明>---------------------------------------- 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;//初始時鐘為0 sys_rst_n <= 1'b0;//初始復(fù)位 clk_fx<= 1'b0; #5//5個時鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) // #2500_000 // forever#2560 clk_fx = ~clk_fx; end //------------<設(shè)置時鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時鐘周期20ns always #489 clk_fx = ~clk_fx;//被測信號周期489*2ns = 978ns endmodule
仿真如下圖:
上圖在閘門時間內(nèi)測得的被測信號個數(shù)cnt_fx為511248,測得被測信號頻率為1022496Hz;理論頻率=1/978ns=1022494.88Hz(MHz級別)。
可以看出這個測量結(jié)果還是比較準(zhǔn)確的。因為閘門時間夠長,且被測信號自身頻率就比較高(約1Mhz)。
接下來更改一下Testbench,比較一下閘門時間對被測信號的影響以及被測信號自身頻率高低對測量的影響:
第1個模塊:被測信號頻率為1022494.88Hz(MHz級別),閘門時間0.5s
第2個模塊:被測信號頻率為1022494.88Hz(MHz級別),閘門時間0.5ms
第3個模塊:被測信號頻率為76103.5Hz(KHz級別),閘門時間0.5s
第4個模塊:被測信號頻率為21.217Hz(Hz級別),閘門時間0.5s
//多變量對比測試 `timescale 1ns/1ns//時間單位/精度 //------------<模塊及端口聲明>---------------------------------------- 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è)閘門時間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;//初始時鐘為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個時鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) end //------------<設(shè)置時鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時鐘周期20ns always #489 clk_fx1 = ~clk_fx1;//被測信號周期489*2ns,理論頻率1022494.88Hz(MHz級別) always #489 clk_fx2 = ~clk_fx2;//被測信號周期489*2ns,理論頻率1022494.88Hz(MHz級別) always #6570 clk_fx3 = ~clk_fx3;//被測信號周期6570*2ns,理論頻率76103.5Hz(KHz級別) always #23565678 clk_fx4 = ~clk_fx4;//被測信號周期23565678*2ns,理論頻率21.217Hz(Hz級別) endmodule
測量結(jié)果如下:
將測量結(jié)果整理成下表:
閘門時間 | 理論頻率(Hz) | 實際測量頻率(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é):
閘門時間越長,測量結(jié)果越精準(zhǔn),但是也會導(dǎo)致單次測量時間過長
直接測量法適合測量高頻信號,測量誤差與閘門時間及被測信號頻率相關(guān)
3、間接測量法
3.1、方法
間接測量法也叫周期測量法,即在一個被測信號的周期內(nèi),測量基準(zhǔn)時鐘的個數(shù),得到被測信號的周期,再將其轉(zhuǎn)化為頻率。
下圖中的信號分別為:
sys_clk:系統(tǒng)的基準(zhǔn)時鐘
clk_fx:被測信號
在被測信號clk_fx為高電平的時間內(nèi),使用基準(zhǔn)時鐘進(jìn)行計數(shù),計數(shù)個數(shù)為cnt(圖中為8),則cnt基準(zhǔn)時鐘周期=半個被測信號的周期。
所以cnt/ FERQ_SYS(基準(zhǔn)時鐘頻率)=(1/2) * (1/clk_fx),化簡后clk_fx =FERQ_SYS/(cnt*2)
此種方法適用于測量低頻信號,但同時也會帶來測量速度過慢的問題,誤差來自一個系統(tǒng)基準(zhǔn)時鐘。
3.2、誤差分析
從圖可以看出,在被測信號高電平期間,被測信號實際上差不多有8.5個周期被囊括在內(nèi),但是因為被測信號是相對與系統(tǒng)的異步信號,相位不同,所以實際采樣為8,這樣造成的誤差為1個基準(zhǔn)信號周期??梢灶A(yù)見,這種測量方法帶來的測量誤差即為一個基準(zhǔn)信號周期。
那么理論上測得的準(zhǔn)確頻率:clk_fx =FERQ_SYS/(cnt*2)----理論上cnt無誤差
實際上測量的頻率值:clk_fx =FERQ_SYS/((cnt±1)*2)----cnt會存在一個周期的測量誤差
測量誤差 = |(clk_fxe -clk_fx)/clk_fxe | 100% = 1 / cnt 100%
所以測得的cnt越大,那么測出來的誤差值就小,而cnt越大則代表被測信號的頻率越低(周期越高),所以可以推斷該種測量方法適合測量低頻信號。
2.3、Verilog代碼
Verilog源碼如下:
在被測信號計數(shù)高電平期間使用基準(zhǔn)時鐘計數(shù)
在被測信號計數(shù)低電平期間更新測量數(shù)據(jù)
使用parameter定義參數(shù),方便調(diào)用修改
//間接測量法(低頻) module cymometer_indirect( input sys_clk,//基準(zhǔn)時鐘,設(shè)計為50M(可更改) input sys_rst_n, //復(fù)位信號,低電平有效 //待測信號 input clk_fx,//測量結(jié)果 output reg [31:0]fre ); parameterTIME_SYS = 20;//系統(tǒng)時鐘周期:20ns--頻率=50MHz reg [31:0]cnt_fx;//對被測信號高電平進(jìn)行計數(shù)的計數(shù)器 //在測信號高電平期間進(jìn)行計數(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 //在測信號低電平期輸出測量數(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個頻率設(shè)置
模塊1被被測信號周期23565678*2ns,理論頻率21.217Hz(Hz級別)
模塊2被測信號周期6570*2ns,理論頻率76103.5Hz(KHz級別)
模塊3被測信號周期489*2ns,理論頻率1022494.88Hz(MHz級別)
`timescale 1ns/1ns//時間單位/精度 //------------<模塊及端口聲明>---------------------------------------- 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;//初始時鐘為0 sys_rst_n <= 1'b0;//初始復(fù)位 clk_fx1<= 1'b0; clk_fx2<= 1'b0; clk_fx3<= 1'b0; #5//5個時鐘周期后 sys_rst_n <= 1'b1;//拉高復(fù)位,系統(tǒng)進(jìn)入工作狀態(tài) end //------------<設(shè)置時鐘>---------------------------------------------- always #10 sys_clk = ~sys_clk;//系統(tǒng)時鐘周期20ns always #23565678 clk_fx1 = ~clk_fx1;//被測信號周期23565678*2ns,理論頻率21.217Hz(Hz級別) always #6570 clk_fx2 = ~clk_fx2;//被測信號周期6570*2ns,理論頻率76103.5Hz(KHz級別) always #489 clk_fx3 = ~clk_fx3;//被測信號周期489*2ns,理論頻率1022494.88Hz(MHz級別) endmodule
仿真如下圖1:
將測量結(jié)果整理成下表:
理論頻率(Hz) | 實際測量頻率(Hz) | 測量誤差 | |
模塊1 | 21.217297 | 21 | 1.02% |
模塊2 | 76103.5 | 75987 | 0.15% |
模塊3 | 1022494.88 | 1041666 | 1.87% |
從上表的測試結(jié)果可以對間接測量法做出如下總結(jié):間接測量法適合測量低頻信號,測量誤差與測信號頻率相關(guān)。
需要注意的是,輸出信號不能處理浮點數(shù),推薦的解決辦法是將其放大整數(shù)倍(100倍),以便實現(xiàn)小數(shù)點的頻率測量(不然小數(shù)點被截斷會帶來額外的誤差)。
將測量結(jié)果乘以1000,一定程度上消除小數(shù)截斷帶來的誤差,模塊1的測試結(jié)果為21.217Hz,測量誤差為1.9998e-3%,大大低于另外兩個高頻信號。(這里不給出具體的測試過程了,可以自己嘗試下)。
4、等精度測量法
4.1、概念
上述兩種方法都會產(chǎn)生±1 個被測時鐘周期的誤差,在實際應(yīng)用中有一定的局限 性;而且根據(jù)兩種方式的測量原理,很容易發(fā)現(xiàn)頻率測量法適合于測量高頻時鐘信號,而周期測量法適合于低頻時鐘信號的測量,但二者都不能兼顧高低頻率同樣精度的測量要求。
等精度測量法與前兩種方式不同,其最大的特點是,測量的實際門控時間不是一個固 定值,它與被測時鐘信號相關(guān),是被測時鐘信號周期的整數(shù)倍。在實際門控信號下,同時對標(biāo)準(zhǔn)時鐘和被測時鐘信號的時鐘周期進(jìn)行計數(shù),再通過公式計算得到被測信號的時鐘頻率。 由于實際門控信號是被測時鐘周期的整數(shù)倍,就消除了被測信號產(chǎn)生的±1 時鐘周期的誤差,但是會產(chǎn)生對標(biāo)準(zhǔn)時鐘信號±1時鐘周期的誤差,而標(biāo)準(zhǔn)時鐘通常又是頻率極高,所以誤差較之前兩種方法就大大降低。
此種測量方法相對誤差與被測信號頻率的大小無關(guān),僅與閘門時間和基準(zhǔn)時鐘頻率有關(guān),即實現(xiàn)了整個測試頻段的等精度測量。閘門時間越長,基準(zhǔn)時鐘頻率越高,測頻的相對誤差越小。需要注意的是,原則上門控時間越長,則精度越高,但測量低頻信號(Hz級別)時,建議將門控時間設(shè)置為被測信號的十幾倍即可,否則測量時間將會過長。
了解了等精度測量原理之后,我們來說明一下被測時鐘信號的計算方法:
首先通過被測信號生成實際閘門
分別對實際閘門下被測時鐘信號和標(biāo)準(zhǔn)時鐘信號的時鐘周期進(jìn)行計數(shù)。
實際閘門下被測時鐘信號周期數(shù)為 X,設(shè)被測信號時鐘周期為 Tfx,它的時鐘頻率 fx = 1/Tfx,由此可得等式:X * Tfx = X / fx = Tx(實際閘門)----這里無誤差。
實際閘門下標(biāo)準(zhǔn)時鐘信號周期數(shù)為 Y(誤差為1),設(shè)被測信號時鐘周期為 Tfs,它的時鐘頻率 fs = 1/Tfs,由此可得等式:Y * Tfs = Y / fs = Tx(實際閘門)----這里最大誤差為1個基準(zhǔn)時鐘周期。
將兩等式結(jié)合得到只包含各自時鐘周期計數(shù)和時鐘頻率的等式:X / fx = Y / fs = Tx(實際閘門),等式變換,得到被測時鐘信號時鐘頻率計算公式:fx = X * fs / Y。
將已知量標(biāo)準(zhǔn)時鐘信號時鐘頻率 fs 和測量量 X、Y 帶入計算公式,得到被測時鐘信號時鐘頻率 fx。
4.2、誤差分析
根據(jù)前文及上圖,不難發(fā)現(xiàn),誤差來源于使用基準(zhǔn)時鐘在閘門時間測量時會存在一個基準(zhǔn)時鐘周期的誤差。
那么理論上測得的準(zhǔn)確頻率:clk_fxe = X * fs / Y----理論上Y無誤差
實際上測量的頻率值:clk_fx = X * fs / Y----Y會存在1個周期的測量誤差
測量誤差 = |(clk_fxe - clk_fx)/ clk_fxe | 100% = 1 / Y 100%
所以測得的Y越大,那么測出來的誤差值就小。當(dāng)閘門時間越大,Y越大;基準(zhǔn)時鐘頻率越高,Y越大。所以通過提高基準(zhǔn)時鐘頻率或者增加閘門時間(但是會使測量過長,需要取舍),可以有效提高測量精度。
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; //門控時間,越大誤差越小,但測量時間也會變長 //reg define reg gate_fx; //門控信號,被測信號域下 reg gate_fs ; //同步到基準(zhǔn)時鐘的門控信號 reg gate_fs_r ; //用于同步gate信號的寄存器 reg gate_fs_d0 ; //用于采集基準(zhǔn)時鐘下gate下降沿 reg gate_fs_d1 ; //用于采集基準(zhǔn)時鐘下gate下降沿 reg gate_fx_d0 ; //用于采集被測時鐘下gate下降沿 reg gate_fx_d1 ; //用于采集被測時鐘下gate下降沿 reg [15:0] gate_cnt ; //門控計數(shù) reg [31:0] fs_cnt ; //門控時間內(nèi)基準(zhǔn)時鐘的計數(shù)值 reg [31:0] fs_cnt_temp ; //fs_cnt 臨時值 reg [31:0] fx_cnt ; //門控時間內(nèi)被測時鐘的計數(shù)值 reg [31:0] fx_cnt_temp ; //fx_cnt 臨時值 //wire define wire neg_gate_fs; //基準(zhǔn)時鐘下門控信號下降沿= wire neg_gate_fx; //被測時鐘下門控信號下降沿 //捕捉信號下降沿 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ù)器 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 //被測時鐘閘門生成 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 //把閘門從被測時鐘域同步到基準(zhǔn)時鐘域 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 //在被測時鐘域?qū)Ρ粶y信號計數(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)時鐘域?qū)鶞?zhǔn)時鐘計數(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)時鐘域輸出結(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è)計被測信號周期為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è)置時鐘>---------------------------------------------- always#10 clk_fs <= ~clk_fs; always #489 clk_fx <= ~clk_fx; endmodule
仿真結(jié)果如下所示
上圖的測量結(jié)果為1022494Hz,理論頻率為1/978ns=1022494.88Hz,可以看到這個結(jié)果相當(dāng)精確。
接下來更改一下Testbench,比較一下閘門時間對被測信號的影響以及被測信號自身頻率高低對測量的影響(為避免仿真時間過長,閘門時間均設(shè)為10個被測信號周期,因為基準(zhǔn)時鐘頻率較高,所以閘門時間少點不會有什么影響)
第1個模塊:被測信號頻率為1022494.88Hz(MHz級別)
第2個模塊:被測信號頻率為76103.5Hz(KHz級別)
第3個模塊:被測信號頻率為21.217Hz(Hz級別)
仿真結(jié)果如下:
將測量結(jié)果整理成下表:
理論頻率(Hz) | 實際測量頻率(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)等精度測量法同時適用于高低頻域,測量結(jié)果誤差只和基準(zhǔn)時鐘頻率有關(guān)。
這里需要注意的是,因為測量結(jié)果都是整數(shù)(FPGA自動截斷小數(shù)),如果被測頻率較低,那么因為小數(shù)被截斷,會使得誤差增大。一個比較方便的解決辦法是把計算公式都放大一定的倍數(shù),從而使得“小數(shù)點前移”。 將測量結(jié)果乘以1000,一定程度上消除小數(shù)截斷帶來的誤差,模塊3的測試結(jié)果為21.217Hz,測量誤差為1.9998e-3%,基本和另外兩個信號處于同一數(shù)量級。(這里不給出具體的測試過程了,可以自己嘗試下)。
5、總結(jié)
直接測量法適合測量高頻信號;頻率越高、測量時間越長,測量結(jié)果越精準(zhǔn);
間接測量法適合測量低頻信號,但測量精度取決于自身頻率;
等精度測量法相對誤差與被測信號頻率的大小無關(guān),僅與閘門時間和基準(zhǔn)時鐘頻率有關(guān),即實現(xiàn)了整個測試頻段的等精度測量。閘門時間越長,基準(zhǔn)時鐘頻率越高,測頻的相對誤差就越小。
-
FPGA
+關(guān)注
關(guān)注
1630文章
21759瀏覽量
604296 -
頻率
+關(guān)注
關(guān)注
4文章
1513瀏覽量
59268 -
測量
+關(guān)注
關(guān)注
10文章
4894瀏覽量
111490
原文標(biāo)題:FPGA頻率測量的三種方法
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設(shè)計論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論