周波数カウンタ(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で、赤がカウントしているタイミング(立ち上がり、立ち下がりのエッジ)。