簡易數字頻率計(verilog HDL設計)
阿新 • • 發佈:2019-01-05
簡易數字頻率計
原理:數字頻率計的原理十分簡單,簡單的就是一句話和一幅圖而已。一句話:測量被測訊號的頻率,要清楚頻率的定義,一言以蔽之,就是1s中訊號的週期數,這不就是週期的倒數嗎?根據頻率的定義,我們測量被測訊號1s中變化的次數即可,即1s中的週期數。首先我們設定一個基準時鐘訊號,頻率為1Hz,從第一個上升沿開始計數(被測訊號的上升沿數),直到下一個上升沿到達時停止計數,對資料進行鎖存,再到達下一個上升沿時,對計數器進行清零,準備下一次的測量。一幅圖: 本圖是簡易頻率計的工作時序圖,從圖中 可以看出:基準訊號的第一個上升沿到達時,計數使能訊號有效,計數器開始計數;第二上升沿到達時,計數結束,鎖存使能有效,計數資料開始鎖存;第三個上升沿到達時,清零訊號有效,對計數器的輸出清零,準備下一次的測量。一個測量過程需要3 sec(重要)。
- //簡易頻率計設計
- module freDetect(clk_1Hz, fin, rst, d0, d1, d2, d3, d4, d5, d6, d7);
- input clk_1Hz;//1Hz基準頻率
- input fin; //待測訊號
- input rst; //復位訊號
- output[3:0] d0, d1, d2, d3, d4, d5, d6, d7; //8位顯示測量資料
- wire[3:0] q0, q1, q2, q3, q4, q5, q6, q7; //中間資料
- wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
- //控制模組例項
- control u_control(.clk_1Hz(clk_1Hz), .rst(rst), .count_en(count_en),
- .latch_en(latch_en), .clear(clear));
- //計數器模組例項
- counter_10 counter0(.en_in(count_en), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out0), .q(q0));
- counter_10 counter1(.en_in(en_out0), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out1), .q(q1));
- counter_10 counter2(.en_in(en_out1), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out2), .q(q2));
- counter_10 counter3(.en_in(en_out2), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out3), .q(q3));
- counter_10 counter4(.en_in(en_out3), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out4), .q(q4));
- counter_10 counter5(.en_in(en_out4), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out5), .q(q5));
- counter_10 counter6(.en_in(en_out5), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out6), .q(q6));
- counter_10 counter7(.en_in(en_out6), .clear(clear), .rst(rst),
- .fin(fin), .en_out(en_out7), .q(q7));
- //鎖存器模組例項
- latch u_latch(.clk_1Hz(clk_1Hz), .rst(rst), .latch_en(latch_en),
- .q0(q0), .q1(q1), .q2(q2), .q3(q3), .q4(q4), .q5(q5),
- .q6(q6), .q7(q7), .d0(d0), .d1(d1), .d2(d2), .d3(d3),
- .d4(d4), .d5(d5), .d6(d6), .d7(d7));
- endmodule
- //控制模組
- //控制模組產生計數使能訊號、鎖存使能訊號和計數器清零訊號
- module control(clk_1Hz, rst, count_en, latch_en, clear);
- input clk_1Hz;
- input rst;
- output count_en;
- output latch_en;
- output clear;
- reg[1:0] state; //狀態訊號,用於控制各種使能訊號
- reg count_en;
- reg latch_en;
- reg clear;
- always @(posedge clk_1Hz or negedge rst)
- if(!rst) //復位訊號有效
- begin //各種使能訊號清零
- state <= 2'd0;
- count_en <= 1'b0;
- latch_en <=1'b0;
- clear <= 1'b0;
- end
- else//遇到基準訊號的下一個上升沿,狀態變化一次,每次變化後狀態持續1s
- begin
- case(state)
- 2'd0:
- begin //第一個上升沿到達,開始計數,計數1個基準訊號週期內待測訊號的上升沿個數,此個數即為待測訊號的頻率
- count_en <= 1'b1; //計數使能訊號有效
- latch_en <=1'b0;
- clear <= 1'b0;
- state <= 2'd1;
- end
- 2'd1:
- begin //第二個上升沿到達,計數完成,鎖存使能訊號有效,測得頻率鎖存至鎖存器中
- count_en <= 1'b0;
- latch_en <=1'b1;
- clear <= 1'b0;
- state <= 2'd2;
- end
- 2'd2:
- begin //第三個上升沿到達,清零使能訊號有效,計數器清零,為下一次計數做準備
- count_en <= 1'b0;
- latch_en <=1'b0;
- clear <= 1'b1;
- state <= 2'd0; //狀態清零,進入下一次測量
- end
- default:
- begin
- count_en <= 1'b0;
- latch_en <=1'b0;
- clear <= 1'b0;
- state <= 2'd0;
- end
- endcase
- end
- endmodule
- //計數模組
- //模10計數器,當計數使能時計數開始,當計數器到達4'b1001,即9時,輸出下一模式計數器的使能訊號並將計數器清零
- module counter_10(en_in, rst, clear, fin, en_out, q);
- input en_in; //輸入使能訊號
- input rst; //復位訊號
- input clear; //清零訊號
- input fin; //待測訊號
- output en_out; //輸出使能,用於控制下一個計數器的狀態,當輸出使能有效時,下一個模10計數器計數加1
- output[3:0] q; //計數器的輸出,4位BCD碼輸出
- reg en_out;
- reg[3:0] q;
- [email protected] (posedge fin or negedge rst) //輸入待測訊號的上升沿作為敏感訊號
- if(!rst) //復位訊號有效,計數器輸出清零
- begin
- en_out <= 1'b0;
- q <= 4'b0;
- end
- elseif(en_in) //進位輸入使能訊號有效
- begin
- if(q == 4'b1001) //若q = 4'b1001的話,q清零,同時進位輸出使能有效,即en_out 賦值為1'b1
- begin
- q <= 4'b0;
- en_out <= 1'b1;
- end
- else//若q未達到4'b1001時,每到達待測訊號的一個上升沿,q加1,同時輸出進位清零
- begin
- q <= q + 1'b1;
- en_out <=1'b0;
- end
- end
- elseif(clear) //若清零訊號有效,計數器清零,主要用於為下一次測量準備
- begin
- q <= 4'b0;
- en_out <= 1'b0;
- end
- else
- begin
- q <= q;
- en_out <=1'b0;
- end
- endmodule
- //鎖存器模組
- //當鎖存使能時,鎖存器將8個模10計數器的輸出值鎖存並輸出
- module latch(clk_1Hz, latch_en, rst, q0, q1, q2, q3, q4, q5, q6, q7,
- d0, d1, d2, d3, d4, d5, d6, d7);
- input clk_1Hz, latch_en, rst;
- input[3:0] q0, q1, q2, q3, q4, q5, q6, q7;
- output[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
- reg[3:0] d0, d1, d2, d3, d4, d5, d6, d7;
- [email protected] (posedge clk_1Hz or negedge rst)
- if(!rst) //復位訊號有效時輸出清零
- begin
- d0 <= 4'b0; d1 <= 4'b0; d2 <= 4'b0; d3 <= 4'b0; d4 <= 4'b0;
- d5 <= 4'b0; d6 <= 4'b0; d7 <= 4'b0;
- end
- elseif(latch_en) //鎖存訊號有效時,將計數器的輸出訊號鎖存至鎖存器
- begin
- d0 <= q0; d1 <= q1; d2 <= q2; d3 <= q3; d4 <= q4;
- d5 <= q5; d6 <= q6; d7 <= q7;
- end
- else//上面兩種情況均未發生時,輸入不變