基于FPGA的频率计
1 簡介
頻率計又稱為頻率計數器,是一種專門對被測信號頻率進行測量的電子測量儀器。
2 傳統測量法
傳統測量法有兩種:周期測量法 和 頻率測量法。
2.1 周期測量法
誤差:被測信號和基準時鐘存在一定的錯位 △t△t△t。但假如被測信號的頻率比較低,脈沖寬度很寬,當基準時鐘頻率很低,與被測時鐘頻率相差較大時,相對誤差比較小。
周期測量法適合低頻信號頻率測量。
2.2 頻率測量法
誤差:被測信號和基準時鐘存在一定的錯位。但假如被測信號的頻率比較高,每個脈沖寬度很窄,當采樣寬度足夠寬時,誤差就會比較小。
頻率測量法適合高頻信號頻率測量。
3 等精度測量法
3.1 原理:
圖中,gategategate 信號為門控信號,它的持續時間 GateGateGate_timetimetime 為整數倍的被測信號周期。clkclkclk _ fxf_xfx?為被測信號(公式中表示被測信號頻率),clkclkclk _ fsf_sfs?為基準時鐘(公式中表示基準時鐘信號頻率)。
由:
被測信號周期個數×被測信號周期長度被測信號周期個數 × 被測信號周期長度被測信號周期個數×被測信號周期長度
=基準時鐘周期個數×基準時鐘周期長度= 基準時鐘周期個數 × 基準時鐘周期長度=基準時鐘周期個數×基準時鐘周期長度
=Gate= Gate=Gate_timetimetime
可以推導出最終被測信號頻率的計算公式:
clkclkclk _ fxfxfx ===clk?fsfs?cnt?\frac{clk-fs}{fs-cnt}·fs?cntclk?fs?? fxfxfx _ cntcntcnt
誤差:只會差一個基準時鐘周期。只要 GateGateGate_timetimetime 足夠大,相對誤差就可以忽略。
3.2 代碼實現
頂層設計模塊:
module top_cymometer(//system clockinput sys_clk , // 時鐘信號(系統時鐘,50MHz)input sys_rst_n, // 復位信號input clk_fx , // 被測時鐘output [7:0] led0,output [7:0] led1,output [7:0] led2,output [7:0] led3,output [63:0]data_fx );//parameter define parameter CLK_FS = 26'd50000000; // 基準時鐘頻率值gate//生成門控信號 (.clk_fs (sys_clk ), // 基準時鐘信號.rst_n (sys_rst_n), // 復位信號//cymometer interface.clk_fx (clk_fx ), //待測信號.gate(gate ) , //門控信號.gate_fs(gate_fs) // 同步到基準時鐘的門控信號);pexg//邊沿捕獲 (.clk_fs (sys_clk ), // 基準時鐘信號.rst_n (sys_rst_n), // 復位信號.gate(gate ) , //門控信號.gate_fs(gate_fs), // 同步到基準時鐘的門控信號.clk_fx (clk_fx), //待測信號.neg_gate_fs(neg_gate_fs),.neg_gate_fx(neg_gate_fx));cnt (//system clock.clk_fs (sys_clk ), // 基準時鐘信號.rst_n (sys_rst_n), // 復位信號//cymometer interface.clk_fx (clk_fx ), //待測信號.gate(gate ) ,//門控信號.gate_fs(gate_fs) ,// 同步到基準時鐘的門控信號.neg_gate_fs(neg_gate_fs),.neg_gate_fx(neg_gate_fx),.fs_cnt(fs_cnt) , // 門控時間內基準時鐘的計數值.fx_cnt(fx_cnt) , // 門控時間內被測時鐘的計數值 .data_fx_temp(data_fx) ); endmodulegate模塊:產生周期是待測信號周期整數倍(代碼中為5000倍)的門信號gate
module gate (input clk_fs , // 基準時鐘信號input rst_n , // 復位信號//cymometer interfaceinput clk_fx ,//待測信號output reg gate , //門控信號output reg gate_fs // 同步到基準時鐘的門控信號);localparam GATE_TIME = 16'd5_000; // 門控時間設置 reg [15:0] gate_cnt ; // 門控計數reg gate_fs_r ; // 用于同步gate信號的寄存器//門控信號計數器,使用被測時鐘計數 always @(posedge clk_fx or negedge rst_n) beginif(!rst_n)gate_cnt <= 16'd0; else if(gate_cnt == GATE_TIME + 5'd20)gate_cnt <= 16'd0;elsegate_cnt <= gate_cnt + 1'b1; end//門控信號,拉高時間為GATE_TIME個實測時鐘周期 always @(posedge clk_fx or negedge rst_n) beginif(!rst_n)gate <= 1'b0;else if(gate_cnt < 4'd10)gate <= 1'b0; else if(gate_cnt < GATE_TIME + 4'd10)gate <= 1'b1;else if(gate_cnt <= GATE_TIME + 5'd20)gate <= 1'b0;else gate <= 1'b0; end//將門控信號同步到基準時鐘下 always @(posedge clk_fs or negedge rst_n) beginif(!rst_n) begingate_fs_r <= 1'b0;gate_fs <= 1'b0;endelse begingate_fs_r <= gate;gate_fs <= gate_fs_r;end end endmodulepexg模塊:用來捕獲gate信號和基準時鐘信號的低電平
module pexg (input clk_fs , // 基準時鐘信號input rst_n , // 復位信號input clk_fx , input gate,input gate_fs , output neg_gate_fs,output neg_gate_fx); reg gate_fs_d0 ; // 用于采集基準時鐘下gate下降沿 reg gate_fs_d1 ; // reg gate_fx_d0 ; // 用于采集被測時鐘下gate下降沿 reg gate_fx_d1 ; // //wire define//邊沿檢測,捕獲信號下降沿 assign neg_gate_fs = gate_fs_d1 & (~gate_fs_d0); assign neg_gate_fx = gate_fx_d1 & (~gate_fx_d0);//打拍采門控信號的下降沿(被測時鐘) always @(posedge clk_fx or negedge rst_n) beginif(!rst_n) begingate_fx_d0 <= 1'b0;gate_fx_d1 <= 1'b0;endelse begingate_fx_d0 <= gate;gate_fx_d1 <= gate_fx_d0;end end//打拍采門控信號的下降沿(基準時鐘) always @(posedge clk_fs or negedge rst_n) beginif(!rst_n) begingate_fs_d0 <= 1'b0;gate_fs_d1 <= 1'b0;endelse begingate_fs_d0 <= gate_fs;gate_fs_d1 <= gate_fs_d0;end end endmodulecnt模塊:用來計數,得到 fsfsfs _ cntcntcnt 和 fxfxfx _ cntcntcnt
module cnt#(parameter CLK_FS = 26'd50_000_000,// 基準時鐘頻率parameter MAX = 10'd64) // 定義數據位寬 ( //system clockinput clk_fs , // 時鐘信號input rst_n , // 復位信號//cymometer interfaceinput clk_fx , // 待測信號input gate, // 門控信號(與待測時鐘同步)input gate_fs, // 與基準時鐘同步的門控信號input neg_gate_fx,//input neg_gate_fs,//output reg [MAX-1:0] fs_cnt , //門控時間內基準時鐘信號的個數 output reg [MAX-1:0] fx_cnt , // 門控時間內待測信號的個數output reg [MAX-1:0] data_fx_temp // 待測信號的頻率值 );reg [MAX-1:0] fs_cnt_temp ; // fs_cnt 計數 reg [MAX-1:0] fx_cnt_temp ; // fx_cnt 計數//門控時間內待測信號的計數,設置的為5000個,這里重新計數,只是用于檢驗信號是否正確 always @(posedge clk_fx or negedge rst_n) beginif(!rst_n) beginfx_cnt_temp <= 32'd0;fx_cnt <= 32'd0;endelse if(gate)beginfx_cnt_temp <= fx_cnt_temp + 1'b1;end else if(neg_gate_fx) beginfx_cnt_temp <= 32'd0;fx_cnt <= fx_cnt_temp;end end//門控時間內基準時鐘的計數 always @(posedge clk_fs or negedge rst_n) beginif(!rst_n) beginfs_cnt_temp <= 32'd0;fs_cnt <= 32'd0;endelse if(gate_fs)beginfs_cnt_temp <= fs_cnt_temp + 1'b1;endelse if(neg_gate_fs) beginfs_cnt_temp <= 32'd0;fs_cnt <= fs_cnt_temp;end end //計算待測信號的頻率值 always @(posedge clk_fs or negedge rst_n) beginif(!rst_n) begindata_fx_temp <= 64'd0;endelse if(gate_fs == 1'b0)data_fx_temp <=CLK_FS*fx_cnt/fs_cnt; endendmoduleRTL視圖:
3.4 實際測量
按照DE0手冊分配管腳
(注意:Quartus 18.1中沒有DE0設備Cyclone III EP3C16F484,舊版Quartus 9.1中有,于是重新下載9.1版本。。)
分配管腳:
分配完成后,重新運行程序,然后將程序加載在開發板上。
將電腦、開發板和信號發生器連接:
100Hz:
500Hz:
1kHz:
signaltap結果:
10kHz:
1MHz:
出現了誤差。
總結
以上是生活随笔為你收集整理的基于FPGA的频率计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器操作系统tco的英文全称,云服务器
- 下一篇: ADS设计不等分功分器