前書き
機械学習も高スループットになってきました。FPGAはニューラルネット系で各レイヤーにパイプラインを組むことができるため高スループットを実現しています。そのようシステム向けに高スループットのローパスフィルタを設計しました。
フィルタ部
1000 Hz以降の信号電力を低減するフィルタを固定小数点Q30で作りました。何故無駄に大きいサイズで作ったかというと,フィルタパラメータに対する数値表現力を上げるに適当に大きくしておきました。入力はバイナリ,クロック100 MHzとしてレイテンシ20ns,出力レートは100MHzです。
ht_lpf.vhd
module ht_lpf(input wire clk, input wire in, output wire [31:0] out);
//Unsigned Q30 format
//Filter parameters
//cutoff:gpd=1000*2pi (1000 Hz),sampling time:Ts=10e-9 (100 MHz)
localparam [31:0] n1=32'h000083c4; //(Ts*gpd)/(2.0+Ts*gpd);
localparam [31:0] n2=32'h3FFEF899; //(2.0-Ts*gpd)/(Ts*gpd+2.0);
reg inz1=1'b0;
reg [33:0] mv=1'b0;
reg [63:0] ar=1'b0;
reg [31:0] res=1'b0;
always@(posedge clk)
begin
inz1<=in;
//res=n1*(in+inz1)+n2*resz1;
mv <= n1*{in&inz1,in^inz1}; //in+inz1
ar <= n2*res;
res <=mv[31:0]+ar[61:30];
end
assign out=res;
endmodule
動作確認
フィルタへの入力に白色雑音を入れます。白色雑音として,25次のM系列信号(擬似白色)を生成しました。
mseq.vhd
module mseq(input wire clk,output wire out);
// Irreducible polynomial: x^25+x^3+1
reg [24:0] seq=25'b0110100101101101100101101;
always@(posedge clk) seq<={seq[24]^seq[2],seq[24:1]};
assign out=seq[24];
endmodule
テストベンチは以下のように作成。
tb.vhd
module tb();
parameter cycle=10;
reg clk=1'b0;
always#(cycle/2) clk<=~clk;
wire z;
mseq mseq_u0(.clk(clk),.out(z));
wire [31:0] out;
ht_lpf ht_lpf_u0(.clk(clk),.in(z),.out(out));
integer fd;
initial
begin
fd=$fopen("output.dat","w");
repeat(1000000)
begin
$fdisplay(fd,"%b %d",z,out);
#cycle;
end
$fclose(fd);
$finish;
end
endmodule
この生成雑音に対するローパスフィルタの出力は以下のように。M系列がバイナリなので平均値は0.5に収束。

M系列信号とフィルタ出力のパワーは以下のようになりました。フィルタ出力は1000 Hzからパワーが減衰しました。低域のパワーがM系列より高いのは,固定少数点数を使用して表現力を落としたことに起因すると思います。