我正在尝试在Verilog中实现FIR滤波器。我在MATLAB中预先确定了系数。但我不确定寄存器是否会使用此代码正确传播。
module fir_filter(
input clock,
input reset,
input wire[15:0] input_sample,
output reg[15:0] output_sample);
parameter N = 13;
reg signed[15:0] coeffs[12:0];
reg [15:0] holderBefore[12:0];
wire [15:0] toAdd[12:0];
always @(*)
begin
coeffs[0]=6375;
coeffs[1]=1;
coeffs[2]=-3656;
coeffs[3]=3;
coeffs[4]=4171;
coeffs[5]=4;
coeffs[6]=28404;
coeffs[7]=4;
coeffs[8]=4171;
coeffs[9]=3;
coeffs[10]=-3656;
coeffs[11]=1;
coeffs[12]=6375;
end
genvar i;
generate
for (i=0; i<N; i=i+1)
begin: mult
multiplier mult1(
.dataa(coeffs[i]),
.datab(holderBefore[i]),
.result(toAdd[i]));
end
endgenerate
always @(posedge clock or posedge reset)
begin
if(reset)
begin
holderBefore[12] <= 0;
holderBefore[11] <= 0;
holderBefore[10] <= 0;
holderBefore[9] <= 0;
holderBefore[8] <= 0;
holderBefore[7] <= 0;
holderBefore[6] <= 0;
holderBefore[5] <= 0;
holderBefore[4] <= 0;
holderBefore[3] <= 0;
holderBefore[2] <= 0;
holderBefore[1] <= 0;
holderBefore[0] <= 0;
output_sample <= 0;
end
else
begin
holderBefore[12] <= holderBefore[11];
holderBefore[11] <= holderBefore[10];
holderBefore[10] <= holderBefore[9];
holderBefore[9] <= holderBefore[8];
holderBefore[8] <= holderBefore[7];
holderBefore[7] <= holderBefore[6];
holderBefore[6] <= holderBefore[5];
holderBefore[5] <= holderBefore[4];
holderBefore[4] <= holderBefore[3];
holderBefore[3] <= holderBefore[2];
holderBefore[2] <= holderBefore[1];
holderBefore[1] <= holderBefore[0];
holderBefore[0] <= input_sample;
output_sample <= (input_sample + toAdd[0] + toAdd[1] +
toAdd[2] + toAdd[3] + toAdd[4] + toAdd[5] +
toAdd[6] + toAdd[7] + toAdd[8] + toAdd[9] +
toAdd[10] + toAdd[11] + toAdd[12]);
end
end
endmodule
这是实现此目的的最佳方式吗?是否有更好的方法来添加?
非常感谢任何帮助!
也非常感谢有用的资源。
答案 0 :(得分:2)
面积和功率效率高的FIR / IIR滤波器对某些人来说是个圣杯。
使用生成语句,您已实例化了13个乘数。乘数占据了相当多的面积。通常只实例化一个时间多路复用(TDM)。在这种情况下,提供比所需输出速率快13倍的时钟(滴答)。
您的加法器链虽然再次看起来有效,但是会非常大并且可能导致时序问题,因为可能存在很长的纹波链。在多个周期内将其分解可能会导致面积和功率降低。
如果将样本的乘法与加法相结合,您将拥有更典型的MAC架构(乘法累加)。
我也会避免在always @*
中初始化常量,因为参数的右侧没有变化,这可能不会触发灵敏度列表。
对于这些我会使用localparams
,或者如果沿着TDM路线走,我会创建一个查找表(LUT)。
always @* begin
case( program_counter )
0 : coeff = 6375;
1 : coeff = 1 ;
...
endcase
end
答案 1 :(得分:1)
假设您选择滤波器响应是合理的(5.2dB纹波!)
然后,一种方法是通过使用Canonical签名数字表示[http://en.wikipedia.org/wiki/Canonical_signed_digit]来估算每个系数,从而权衡一些响应精度以减少芯片资源。强度降低[http://en.wikipedia.org/wiki/Strength_reduction](编译器术语)允许有效的转换,即使用路由和添加而不是昂贵的乘法。
然后由于系数的对称性,可以在应用系数之前对各个样本求和,这显着降低了所需的芯片资源。[1]
但是,实现的系数中可能存在共同因素,对于芯片目标可能会得到一些优化但是对于固件可以进行重大改进。
[1] = DSP技巧:构建简化FIR滤波器结构的奇怪方法Richard G. Lyons