周波数カウンタ(ADC入力)

I2Sをシリアル→パラレル変換したものから音声波形の周波数をカウントしてみます。

パラレル変換した値は2の補数表現となっているので、msbはサインビットとなります。

これが0→1になったときカウントすれば、ゼロクロス点を検出できるので、1秒間にこれが何回あったかカウントすれば、カウント値が周波数(Hz)となります。

レシプロカウンターにして周期Tから周波数fを求められるようにすると非常に低い周波数を測るときに便利なのですが

そのためには f=1/Tの計算を実装する必要がありやや難しいので、そっちの方法は別の機会にすることにします。

コード解説

clk50mhzには50MHzのクロックを入力します。1秒間measurement_signalの立ち上がりエッジを検出して、count変数を

+1づつします。1秒経過すると、countの内容をfrequencyに入れて出力します

frequency_meter.v

module frequency_meter(input clk50mhz, input reset_n, input measurement_signal, output reg[31:0]frequency);

reg [31:0] count, number;

reg previous_measurement_signal;

always @ (negedge reset_n or posedge clk50mhz)

begin

if (reset_n == 0) begin

count = 0;

previous_measurement_signal = measurement_signal;

number = 0;

frequency = 0;

end

else if (count >= 50000000)

begin

count = 0;

frequency = number;

number = 0;

end

else begin

count = count + 1;

if (previous_measurement_signal != measurement_signal) begin

if (measurement_signal) begin

number = number + 1;

end

end

previous_measurement_signal = measurement_signal;

end

end

endmodule

動作検証

実際の入力波形(黄)、ロジック(緑)はI2SのMSBです。

茶色がI2SMSBで、赤がカウントしているタイミング(立ち上がり、立ち下がりのエッジ)。

アクセスカウンター
アクセスカウンター