1. 程式人生 > >簡易數字頻率計(verilog HDL設計)

簡易數字頻率計(verilog HDL設計)

簡易數字頻率計

原理:數字頻率計的原理十分簡單,簡單的就是一句話和一幅圖而已。一句話:測量被測訊號的頻率,要清楚頻率的定義,一言以蔽之,就是1s中訊號的週期數,這不就是週期的倒數嗎?根據頻率的定義,我們測量被測訊號1s中變化的次數即可,即1s中的週期數。首先我們設定一個基準時鐘訊號,頻率為1Hz,從第一個上升沿開始計數(被測訊號的上升沿數),直到下一個上升沿到達時停止計數,對資料進行鎖存,再到達下一個上升沿時,對計數器進行清零,準備下一次的測量。一幅圖:

                             本圖是簡易頻率計的工作時序圖,從圖中 可以看出:基準訊號的第一個上升沿到達時,計數使能訊號有效,計數器開始計數;第二上升沿到達時,計數結束,鎖存使能有效,計數資料開始鎖存;第三個上升沿到達時,清零訊號有效,對計數器的輸出清零,準備下一次的測量。

一個測量過程需要3 sec(重要)。

下面是數字頻率計的原理圖:                 由此原理圖可以清晰的理解下面的verilog HDL程式:
  1. //簡易頻率計設計
  2. module freDetect(clk_1Hz, fin, rst, d0, d1, d2, d3, d4, d5, d6, d7);  
  3.   input clk_1Hz;//1Hz基準頻率
  4.   input fin; //待測訊號
  5.   input rst; //復位訊號
  6.   output[3:0] d0, d1, d2, d3, d4, d5, d6, d7; //8位顯示測量資料
  7.   wire[3:0] q0, q1, q2, q3, q4, q5, q6, q7;   //中間資料
  8.   wire[3:0] d0, d1, d2, d3, d4, d5, d6, d7;  
  9.   //控制模組例項
  10.   control u_control(.clk_1Hz(clk_1Hz), .rst(rst), .count_en(count_en),  
  11.                     .latch_en(latch_en), .clear(clear));  
  12.   //計數器模組例項
  13.   counter_10 counter0(.en_in(count_en), .clear(clear), .rst(rst),  
  14.                       .fin(fin), .en_out(en_out0), .q(q0));  
  15.   counter_10 counter1(.en_in(en_out0), .clear(clear), .rst(rst),  
  16.                       .fin(fin), .en_out(en_out1), .q(q1));  
  17.   counter_10 counter2(.en_in(en_out1), .clear(clear), .rst(rst),  
  18.                       .fin(fin), .en_out(en_out2), .q(q2));  
  19.   counter_10 counter3(.en_in(en_out2), .clear(clear), .rst(rst),  
  20.                       .fin(fin), .en_out(en_out3), .q(q3));  
  21.   counter_10 counter4(.en_in(en_out3), .clear(clear), .rst(rst),  
  22.                       .fin(fin), .en_out(en_out4), .q(q4));  
  23.   counter_10 counter5(.en_in(en_out4), .clear(clear), .rst(rst),  
  24.                       .fin(fin), .en_out(en_out5), .q(q5));  
  25.   counter_10 counter6(.en_in(en_out5), .clear(clear), .rst(rst),  
  26.                       .fin(fin), .en_out(en_out6), .q(q6));  
  27.   counter_10 counter7(.en_in(en_out6), .clear(clear), .rst(rst),  
  28.                       .fin(fin), .en_out(en_out7), .q(q7));  
  29.   //鎖存器模組例項
  30.   latch u_latch(.clk_1Hz(clk_1Hz), .rst(rst), .latch_en(latch_en),  
  31.                 .q0(q0), .q1(q1), .q2(q2), .q3(q3), .q4(q4), .q5(q5),  
  32.                 .q6(q6), .q7(q7), .d0(d0), .d1(d1), .d2(d2), .d3(d3),  
  33.                 .d4(d4), .d5(d5), .d6(d6), .d7(d7));  
  34. endmodule  
  35. //控制模組
  36. //控制模組產生計數使能訊號、鎖存使能訊號和計數器清零訊號
  37. module control(clk_1Hz, rst, count_en, latch_en, clear);  
  38.   input clk_1Hz;  
  39.   input rst;  
  40.   output count_en;  
  41.   output latch_en;  
  42.   output clear;  
  43.   reg[1:0] state; //狀態訊號,用於控制各種使能訊號
  44.   reg count_en;  
  45.   reg latch_en;  
  46.   reg clear;  
  47.   always @(posedge clk_1Hz or negedge rst)  
  48.   if(!rst)   //復位訊號有效
  49.     begin    //各種使能訊號清零
  50.       state <= 2'd0;  
  51.       count_en <= 1'b0;  
  52.       latch_en <=1'b0;  
  53.       clear <= 1'b0;  
  54.     end  
  55.      else//遇到基準訊號的下一個上升沿,狀態變化一次,每次變化後狀態持續1s
  56.     begin  
  57.       case(state)  
  58.             2'd0:   
  59.             begin //第一個上升沿到達,開始計數,計數1個基準訊號週期內待測訊號的上升沿個數,此個數即為待測訊號的頻率
  60.             count_en <= 1'b1;  //計數使能訊號有效
  61.             latch_en <=1'b0;  
  62.             clear <= 1'b0;  
  63.             state <= 2'd1;  
  64.           end  
  65.         2'd1:  
  66.           begin //第二個上升沿到達,計數完成,鎖存使能訊號有效,測得頻率鎖存至鎖存器中
  67.             count_en <= 1'b0;  
  68.             latch_en <=1'b1;  
  69.             clear <= 1'b0;  
  70.             state <= 2'd2;  
  71.           end  
  72.         2'd2:   
  73.           begin //第三個上升沿到達,清零使能訊號有效,計數器清零,為下一次計數做準備
  74.             count_en <= 1'b0;  
  75.             latch_en <=1'b0;  
  76.             clear <= 1'b1;  
  77.             state <= 2'd0; //狀態清零,進入下一次測量
  78.           end  
  79.         default:  
  80.           begin  
  81.             count_en <= 1'b0;  
  82.             latch_en <=1'b0;  
  83.             clear <= 1'b0;  
  84.             state <= 2'd0;  
  85.           end  
  86.       endcase  
  87.     end  
  88. endmodule  
  89. //計數模組
  90. //模10計數器,當計數使能時計數開始,當計數器到達4'b1001,即9時,輸出下一模式計數器的使能訊號並將計數器清零
  91. module counter_10(en_in, rst, clear, fin, en_out, q);  
  92.   input en_in; //輸入使能訊號
  93.   input rst;   //復位訊號
  94.   input clear; //清零訊號
  95.   input fin;   //待測訊號
  96.   output en_out; //輸出使能,用於控制下一個計數器的狀態,當輸出使能有效時,下一個模10計數器計數加1
  97.   output[3:0] q; //計數器的輸出,4位BCD碼輸出
  98.   reg en_out;  
  99.   reg[3:0] q;  
  100.   [email protected] (posedge fin or negedge rst) //輸入待測訊號的上升沿作為敏感訊號
  101.   if(!rst) //復位訊號有效,計數器輸出清零
  102.       begin  
  103.         en_out <= 1'b0;  
  104.         q <= 4'b0;  
  105.       end  
  106.     elseif(en_in) //進位輸入使能訊號有效
  107.       begin  
  108.         if(q == 4'b1001) //若q = 4'b1001的話,q清零,同時進位輸出使能有效,即en_out 賦值為1'b1  
  109.           begin  
  110.             q <= 4'b0;  
  111.             en_out <= 1'b1;  
  112.           end  
  113.              else//若q未達到4'b1001時,每到達待測訊號的一個上升沿,q加1,同時輸出進位清零
  114.           begin  
  115.             q <= q + 1'b1;  
  116.             en_out <=1'b0;  
  117.           end  
  118.       end  
  119.     elseif(clear) //若清零訊號有效,計數器清零,主要用於為下一次測量準備
  120.       begin  
  121.         q <= 4'b0;  
  122.         en_out <= 1'b0;  
  123.       end  
  124.     else
  125.     begin  
  126.     q <= q;  
  127.     en_out <=1'b0;  
  128.     end   
  129. endmodule  
  130. //鎖存器模組
  131. //當鎖存使能時,鎖存器將8個模10計數器的輸出值鎖存並輸出
  132. module latch(clk_1Hz, latch_en, rst, q0, q1, q2, q3, q4, q5, q6, q7,  
  133.             d0, d1, d2, d3, d4, d5, d6, d7);  
  134.   input clk_1Hz, latch_en, rst;  
  135.   input[3:0] q0, q1, q2, q3, q4, q5, q6, q7;  
  136.   output[3:0] d0, d1, d2, d3, d4, d5, d6, d7;  
  137.   reg[3:0] d0, d1, d2, d3, d4, d5, d6, d7;  
  138.   [email protected] (posedge clk_1Hz or negedge rst)  
  139.   if(!rst) //復位訊號有效時輸出清零
  140.     begin  
  141.       d0 <= 4'b0; d1 <= 4'b0; d2 <= 4'b0; d3 <= 4'b0; d4 <= 4'b0;  
  142.       d5 <= 4'b0; d6 <= 4'b0; d7 <= 4'b0;  
  143.     end  
  144.   elseif(latch_en) //鎖存訊號有效時,將計數器的輸出訊號鎖存至鎖存器
  145.     begin  
  146.       d0 <= q0; d1 <= q1; d2 <= q2; d3 <= q3; d4 <= q4;  
  147.       d5 <= q5; d6 <= q6; d7 <= q7;  
  148.     end  
  149.      else//上面兩種情況均未發生時,輸入不變