3

我正在尝试在 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

这是实现这一点的最佳方法吗?有没有更好的方法来做加法?

任何帮助是极大的赞赏!

也非常感谢有帮助的资源。

4

2 回答 2

2

面积和功率高效的 FIR/IIR 滤波器是某些人的圣杯。

使用生成语句,您已经实例化了 13 个乘法器。乘法器占用了相当多的区域。通常只实例化一个并对其进行时分复用 (TDM)。在这种情况下,提供比所需输出速率快 13 倍的时钟(滴答声)。

您的加法器链虽然看起来再次有效,但将非常大,并且可能导致时序问题,因为可能存在很长的波纹链。在多个周期内将其分解可能会导致较小的面积和功耗。

如果将样本的乘法与加法相结合,您将拥有更典型的 MAC 架构(乘法累加)。

我也会避免在参数中初始化常量,always @*因为参数的右侧没有更改,这可能不会触发敏感度列表。

对于这些我会使用localparams,或者如果沿着 TDM 路线走,我会创建一个查找表 (LUT)。

always @* begin
  case( program_counter )
    0 : coeff = 6375;
    1 : coeff = 1   ;
    ...
  endcase
end
于 2013-02-27T09:06:42.820 回答
1

假设您选择的滤波器响应是合理的(5.2dB 纹波!)

然后一种方法是通过使用规范符号数字表示 [http://en.wikipedia.org/wiki/Canonical_signed_digit] 来近似每个系数来权衡一些响应精度以减少芯片资源。这种强度减少[http://en.wikipedia.org/wiki/Strength_reduction](编译器术语)允许有效的转变,即使用路由和添加来代替昂贵的乘法。

然后由于系数的对称性,可以在应用系数之前对各个样本求和,这大大降低了所需的芯片资源。 [1]

但是在实现的系数中可能存在共同因素,对于芯片目标可能会得到一些优化,但对于固件可以做出重大改进。

[1] = DSP 技巧:构建简化 FIR 滤波器结构的奇怪方法 Richard G. Lyons

试试http://www.embedded.com/design/embedded/4008837/DSP-Tricks-An-odd-way-to-build-a-simplified-FIR-filter-structure

于 2013-03-02T10:57:29.780 回答