/* Frequency Counter 簡易周波数カウンター Copyright(C) 2007 Tatsuyuki Sato ・1秒毎に〜99.99MHzまでの周波数をHz単位で測定します。 ・リファレンスクロックとして1Hzのクロック信号が必要です。 ・1Hzの桁の測定値は正確ではありません。 ・1秒間の単純加算評価のため、低い周波数は正確に測定できません。 ・出力形式はBCD7桁で7セグメントLED表示に適しています。 ・100MHzを超えると10MHzの位が10以上を示すようになります。 ・メインは2分周、5分周をカスケードした1/10クロックで動作します。  Spatran3では100MHz前後までは動作します。 */ /**************************************************************************** ****************************************************************************/ module freq_cnt ( // System Controll input I_Reset, input I_Clk1Hz, // Target Signal input I_ClkTarget, // Output output reg O_VALID, output reg [3:0] O_BCD1Hz, output reg [3:0] O_BCD10Hz, output reg [3:0] O_BCD100Hz, output reg [3:0] O_BCD1KHz, output reg [3:0] O_BCD10KHz, output reg [3:0] O_BCD100KHz, output reg [3:0] O_BCD1MHz, output reg [3:0] O_BCD10MHz ); /**************************************************************************** ****************************************************************************/ reg reset_r; reg clk_half; reg [1:0] trg_r1; reg [2:0] div10; reg [1:0] trg_r2; reg start_req; reg [1:0] trg_r3; reg is_sampling_r; reg [3:0] cnt_10; reg [3:0] cnt_100; reg [3:0] cnt_1k; reg [3:0] cnt_10k; reg [3:0] cnt_100k; reg [3:0] cnt_1m; reg [3:0] cnt_10m; /**************************************************************************** ****************************************************************************/ // fin/2 prescaler always @(posedge I_ClkTarget) begin // divider & counter clk_half <= ~clk_half || (trg_r1==2'b01); // trigger sampling trg_r1 <= {trg_r1[0],I_Clk1Hz}; // reset sampling if(I_Reset) reset_r <= 1'b1; else if(trg_r1==2'b10) // fall 1Hz reset_r <= 1'b0; if(reset_r) begin O_BCD1Hz[0] <= 1'b0; end if(trg_r1==2'b01) // raise 1Hz begin // sampling & hold O_BCD1Hz[0] <= clk_half; clk_half <= 1'b1; end end // fin/2/5 prescaler always @(negedge clk_half) begin // trigger sampling trg_r2 <= reset_r ? 2'b11 : {trg_r2[0],trg_r1[0]}; // reset clear if(reset_r) O_BCD1Hz[3:1] <= 3'b000; // sampling / hold if(trg_r2==2'b01) // raise 1Hz begin // SYNC start div10 <= 3'b100; // set -1 O_BCD1Hz[3:1] <= div10; end else begin div10 <= div10[2] ? 0 : div10+1; end end wire clk10 = div10[2]; wire carry_1 = 1'b1; wire carry_10 = (cnt_10 >=9) & carry_1; wire carry_100 = (cnt_100 >=9) & carry_10; wire carry_1k = (cnt_1k >=9) & carry_100; wire carry_10k = (cnt_10k >=9) & carry_1k; wire carry_100k = (cnt_100k>=9) & carry_10k; wire carry_1m = (cnt_1m >=9) & carry_100k; // fin/2/5 clock counter always @(negedge clk10) begin // trigger sampling trg_r3 <= reset_r ? 2'b11 : {trg_r3[0],trg_r1[0]}; if(reset_r) begin trg_r3 <= 2'b11; O_VALID <= 1'b0; O_BCD10Hz <= 4'h0; O_BCD100Hz <= 4'h0; O_BCD1KHz <= 4'h0; O_BCD10KHz <= 4'h0; O_BCD100KHz <= 4'h0; O_BCD1MHz <= 4'h0; O_BCD10MHz <= 4'h0; is_sampling_r <= 1'b0; cnt_10 <= 0; cnt_100 <= 0; cnt_1k <= 0; cnt_10k <= 0; cnt_100k <= 0; cnt_1m <= 0; cnt_10m <= 0; end else begin if(trg_r3==2'b01) begin // update sampling data O_VALID <= is_sampling_r; O_BCD10Hz <= cnt_10; O_BCD100Hz <= cnt_100; O_BCD1KHz <= cnt_1k; O_BCD10KHz <= cnt_10k; O_BCD100KHz <= cnt_100k; O_BCD1MHz <= cnt_1m; O_BCD10MHz <= cnt_10m; // start next sample is_sampling_r <= 1'b1; cnt_10 <= 0; cnt_100 <= 0; cnt_1k <= 0; cnt_10k <= 0; cnt_100k <= 0; cnt_1m <= 0; cnt_10m <= 0; end else begin // running cycle // countup if(carry_1) cnt_10 <= carry_10 ? 0 : cnt_10 + 1; if(carry_10) cnt_100 <= carry_100 ? 0 : cnt_100 + 1; if(carry_100) cnt_1k <= carry_1k ? 0 : cnt_1k + 1; if(carry_1k) cnt_10k <= carry_10k ? 0 : cnt_10k + 1; if(carry_10k) cnt_100k <= carry_100k ? 0 : cnt_100k + 1; if(carry_100k) cnt_1m <= carry_1m ? 0 : cnt_1m + 1; if(carry_1m) cnt_10m <= cnt_10m + 1; end end end endmodule