文章摘要:藉助於QuartusII PLL_IP核產生一個任意頻率被測時鐘訊號,設計一個等精度測量模組,透過其處理後,再數碼管上顯示出六位的測量頻率數值,驗證測量的準確度。
關鍵詞:Verilog HDL;等精度頻率測量;數碼管;PLL_IP核
最終框圖:
頻率計,即頻率計數器,專用於測量被測訊號頻率,基本工作原理就是當被測訊號在特定時間段T內的週期個數為N時,則被測訊號的頻率freq可以透過公式freq=N/T計算得出。
在EDA設計中,常見的頻率測量方法包括頻率測量法(適合高頻被測訊號)、週期測量法(適合低頻被測訊號)和等精度測量法。頻率測量法是透過統計單位時間內上升沿(或下降沿等)來計算頻率,而週期測量法是透過測量上升沿(或下降沿等)的時間間隔來計算頻率。等精度測量法與前兩種不同,其在於門控時間的設定。
【基礎原理】
在等精度測量法中,門控時間的長度並非固定,而會根據被測時鐘訊號的週期進行調整,保證其為被測時鐘訊號週期的整數倍。在這樣的參考門限範圍內,同時記錄標準時鍾和被測時鐘訊號的週期數,隨後透過計算兩者的比例關係,得到被測訊號的時脈頻率。
預先設定一個軟體門限,在此門限劃定測量參考範圍,透過對測量訊號Measured_sig
上升沿觸發,可得到一個相對的參考門限REF_threshold
,其是被測時鐘週期的整數倍,消除了被測訊號存在的±1個時鐘週期誤差。
測量方法:
參考門限範圍內,計數被測訊號週期個數為N;給一個高頻(固定頻率Fs)標準訊號,並計數得到其在同樣門限下週期個數為Y;藉助 N * 1 / Fn = Y * 1/Fs 可知被測訊號頻率 Fn = Fs * N / Y。
f為被測訊號頻率的測量值,f'為實際頻率,參考門限T;
測量誤差β = | f'-f | / f' * 100%,若忽略標準訊號的誤差,可得到f' = N / (Y ± ΔY)* Fs;
聯立得到 β = ΔY/Y *100% ≤ 1/Y = 1/(Fs * T)
結論:被測訊號的頻率接近或高於標準訊號,測量的誤差會大,就是說,增大標準訊號頻率,或者擴大軟體門限,這樣可提高測量精度。
【時序邏輯設計】
系統時鐘sys_clk
為50Mhz訊號,sys_rst
為系統復位。被測訊號Measured_sig
設定任意頻率,thres_cnt
門限計數週期定位1.5s(可調),前0.25s為訊號保持,在中間的1.00s內是軟體門限測量範圍,後0.25s為計算時間。actual_thres
是參考門限範圍,也就是被測訊號的實際測量範圍,是被測時鐘週期的整數倍。
meas_clk_cnt
到act_cnt_reg
是被測時鐘訊號相對於參考門限的週期個數測量,最終得到計數N。由被測時鐘訊號上升沿觸發,act_thres_reg
對actual_thres
做了一個延後保持(打拍),得到計數結束訊號act_reg_flag
,透過其高電平觸發計數值轉移值act_cnt_reg
保持。std_clk_cnt
到std_cnt_reg
原理同樣如此,是標準高頻訊號相對於參考門限的週期個數測量,最終得到計數Y,透過公式計算得到被測訊號頻率。
對上述時序圖中的訊號,編寫Verilog程式:(注意不同的訊號觸發型別)
parameter THRES_CNT_MAX = 27'd75_000_000;
parameter THRES_CNT_250MS = 27'd12_500_000;
parameter CNT_STAND_FREP = 27'd100_000_000;
assign Std_flag = (Std_reg)&&(!act_thres)?1'b1:1'b0;
assign act_reg_flag = (act_thres_reg)&&(!act_thres)?1'b1:1'b0;
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst) thres_cnt <= 27'd0;
else if(thres_cnt == THRES_CNT_MAX -1'b1) thres_cnt <= 27'd0;
else thres_cnt <= thres_cnt + 1'b1;
end
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst) thres_range <= 1'b0;
else if((thres_cnt > (THRES_CNT_250MS-1'b1))&&(thres_cnt < (THRES_CNT_MAX-THRES_CNT_250MS-1'b1))) thres_range <= 1'b1;
else thres_range <= 1'b0;
end
always @(posedge measured_sig or negedge sys_rst)begin
if(!sys_rst) act_thres <= 1'b0;
else act_thres <= thres_range;
end
always @(posedge measured_sig or negedge sys_rst)begin
if(!sys_rst) meas_clk_cnt <= 48'd0;
else if(!act_thres) meas_clk_cnt <= 48'd0;
else meas_clk_cnt <= meas_clk_cnt + 1'b1;
end
always @(posedge measured_sig or negedge sys_rst)begin
if(!sys_rst) act_thres_reg <= 1'b0;
else act_thres_reg <= act_thres;
end
always @(posedge measured_sig or negedge sys_rst)begin
if(!sys_rst)act_cnt_reg <= 48'd0;
else if(act_reg_flag) act_cnt_reg <= meas_clk_cnt;
end
always @(posedge clk_stand or negedge sys_rst)begin
if(!sys_rst) std_clk_cnt <= 48'd0;
else if(!act_thres)std_clk_cnt <= 48'd0;
else std_clk_cnt <= std_clk_cnt + 1'b1;
end
always @(posedge clk_stand or negedge sys_rst)begin
if(!sys_rst) Std_reg <= 1'd0;
else Std_reg <= act_thres;
end
always @(posedge clk_stand or negedge sys_rst)begin
if(!sys_rst) std_cnt_reg <= 48'd0;
else if(Std_flag) std_cnt_reg <= std_clk_cnt;
end
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst) calc_flag <= 1'd0;
else if(thres_cnt == THRES_CNT_MAX-1)calc_flag <= 1'd1;
else calc_flag <= 1'd0;
end
always @(posedge sys_clk or negedge sys_rst)begin
if(!sys_rst)frep_result <= 32'd0;
else if(calc_flag)frep_result <= (CNT_STAND_FREP/ std_cnt_reg* act_cnt_reg);
end
其中的標準高頻訊號clk_stand
需要藉助於QuartusII的PLL_IP核產生,模組例項化其中。
//Stand_clk from PLL_IP_core
clk_stand clk_stand_inst (
.areset ( !sys_rst ),//Hign Level take effect
.inclk0 ( sys_clk ),
.c0 ( clk_stand ) );
【頻測模組模擬驗證】
在模擬程式及模擬現象中,設定系統時鐘20ns,即50Mhz,而被測時鐘週期216ns,即1 / 216 * 10e9 ≈ 4.6296Mhz。並且,為方便觀察波形變化,將軟體門限縮小了10e5倍(精度減小),最終得到被測訊號頻率 32'h46a806 ≈ 4.6305Mhz,誤差0.9khz,模擬上的時序變化均達到時序邏輯要求。
always #10 sys_clk =~sys_clk;
always #108 clk_test =~clk_test;
defparam frep_calc_inst.THRES_CNT_MAX = 750;
defparam frep_calc_inst.THRES_CNT_250MS = 125;
【部署其他模組】
考慮到最後的板級驗證,沒有訊號源和示波器透過,在此再建立一個PLL_IP核產生一個“任意時鐘訊號”,作為被測訊號,並且將最終的結果輸入到六位數碼管上顯示出來觀察,該被測訊號的實際頻率為3.580097Mhz。
其次,例項化數碼管顯示模組,這裡還是存在問題的,測訊號的實際頻率十六進位制顯示採用六位即可,這裡圖個方便,用assign直接賦值了。
digital digital_inst(
.sys_clk (sys_clk ),
.sys_rst (sys_rst ),
.clk_2khz (clk_2khz ),
.num6 (num6 ), //assign num6 = frep_result[23:20];
.num5 (num5 ), //assign num5 = frep_result[19:16];
.num4 (num4 ), //......
.num3 (num3 ),
.num2 (num2 ),
.num1 (num1 ),
.sel_cnt (sel_cnt ), //所使用到的位數
.dp_cnt (dp_cnt ), //小數點所在位號
.seg_sel (seg_sel ), //數碼管位選
.seg_led (seg_led ) //數碼管段選
);
【板級驗證方案】
從下圖可以看到,程式碼裡採用了除法運算。在FPGA或ASIC設計中,除法運算本身是一種複雜的算術操作,相比於加法、減法和乘法,它需要更多的計算步驟和邏輯單元來完成,除法操作往往需要專門的硬體除法器。
上機測試後,燒錄至EP4CE10F17C8開發板,數碼管顯示十六進位制36A0C1,剛好是3,580,097hz。軟體門限範圍為1.00s,標準訊號設定100Mhz,測量準確度還是比較高的。
文獻參考:
[1]基於Altera EP4CE10 征途Mini開發板文件(https://doc.embedfire.com/fpga/altera/ep4ce10_mini/zh/latest/fpga/Frequency_Meter.html)
[2]王立華,周松江,高世皓,等. 基於內嵌Cortex-M3核心FPGA的等精度頻率計設計[J]. 實驗室研究與探索,2017,36(7):139-143,181. DOI:10.3969/j.issn.1006-7167.2017.07.033.
本篇文章中使用的Verilog程式模組,若有需見網頁左欄Gitee倉庫連結:https://gitee.com/silly-big-head/little-mouse-funnyhouse/tree/FPGA-Verilog/