阶段二:FIR滤波器

🔀 第12课:多相FIR

多相分解FIR——高效多采样率滤波的核心

1. 多相分解原理

多相分解将N抽头FIR分解为M个子滤波器,每个处理不同相位分量:

H(z) = Σ(m=0 to M-1) z⁻ᵐ · Eₘ(zᴹ),Eₘ(zᴹ)=Σh[m+lM]·z⁻ˡ

2. 多相分解的三大应用

🎯 核心应用

Noble恒等式:↓M·H(z) ≡ H(zᴹ)·↓M,H(z)·↑L ≡ ↑L·H(zᴸ)

3. Verilog实现:多相FIR滤波器

//=============================================
// dsp_fir_polyphase.v
// M路多相FIR滤波器
//=============================================
module dsp_fir_polyphase #(
    parameter DATA_WIDTH = 16,
    parameter COEFF_WIDTH = 16,
    parameter PHASES = 4,
    parameter TAP_PER_PHASE = 8,
    parameter OUT_WIDTH = 32
)(
    input  wire                          clk,
    input  wire                          rst_n,
    input  wire                          data_valid,
    input  wire signed [DATA_WIDTH-1:0]  data_in,
    input  wire signed [COEFF_WIDTH-1:0] coeffs [0:PHASES-1][0:TAP_PER_PHASE-1],
    output reg  signed [OUT_WIDTH-1:0]   data_out,
    output reg                           out_valid
);
    reg [$clog2(PHASES)-1:0] phase_cnt;
    reg signed [DATA_WIDTH-1:0] phase_delay [0:PHASES-1][0:TAP_PER_PHASE-1];
    integer p,k;
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin phase_cnt<=0; data_out<=0; out_valid<=1'b0;
            for (p=0;p<PHASES;p=p+1) for (k=0;k<TAP_PER_PHASE;k=k+1) phase_delay[p][k]<=0;
        end else if (data_valid) begin
            phase_delay[phase_cnt][0] <= data_in;
            for (k=1;k<TAP_PER_PHASE;k=k+1) phase_delay[phase_cnt][k]<=phase_delay[phase_cnt][k-1];
            data_out <= 0;
            for (p=0;p<PHASES;p=p+1) data_out <= data_out+phase_mac(p);
            out_valid <= 1'b1; phase_cnt <= phase_cnt+1'b1;
        end else out_valid <= 1'b0;
    end
    function signed [OUT_WIDTH-1:0] phase_mac;
        input integer phase;
        reg signed [OUT_WIDTH-1:0] acc;
        reg signed [DATA_WIDTH+COEFF_WIDTH-1:0] prod;
        integer j;
        begin acc=0;
            for (j=0;j<TAP_PER_PHASE;j=j+1) begin
                prod=phase_delay[phase][j]*coeffs[phase][j]; acc=acc+prod;
            end
            phase_mac=acc;
        end
    endfunction
endmodule

4. 多相抽取滤波器

//=============================================
// dsp_decimator_polyphase.v
// 多相抽取滤波器:先分相后滤波
// 计算量降为1/M
//=============================================
module dsp_decimator_polyphase #(
    parameter DATA_WIDTH = 16,
    parameter COEFF_WIDTH = 16,
    parameter DECIM_FACTOR = 4,
    parameter TAP_TOTAL = 32,
    parameter OUT_WIDTH = 32
)(
    input  wire                          clk,
    input  wire                          rst_n,
    input  wire                          data_valid,
    input  wire signed [DATA_WIDTH-1:0]  data_in,
    output reg  signed [OUT_WIDTH-1:0]   data_out,
    output reg                           out_valid
);
    localparam TAP_PER_PHASE = TAP_TOTAL/DECIM_FACTOR;
    reg signed [COEFF_WIDTH-1:0] phase_coeffs [0:DECIM_FACTOR-1][0:TAP_PER_PHASE-1];
    reg signed [DATA_WIDTH-1:0] phase_buf [0:DECIM_FACTOR-1][0:TAP_PER_PHASE-1];
    reg [$clog2(DECIM_FACTOR)-1:0] phase_cnt;
    integer p,k;
    initial begin
        for (p=0;p<DECIM_FACTOR;p=p+1) for (k=0;k<TAP_PER_PHASE;k=k+1)
            phase_coeffs[p][k] = 16'sd1024;
    end
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin phase_cnt<=0; data_out<=0; out_valid<=0;
            for (p=0;p<DECIM_FACTOR;p=p+1) for (k=0;k<TAP_PER_PHASE;k=k+1) phase_buf[p][k]<=0;
        end else if (data_valid) begin
            phase_buf[phase_cnt][0] <= data_in;
            for (k=1;k<TAP_PER_PHASE;k=k+1) phase_buf[phase_cnt][k]<=phase_buf[phase_cnt][k-1];
            if (phase_cnt==DECIM_FACTOR-1) begin
                data_out <= 0;
                for (p=0;p<DECIM_FACTOR;p=p+1) begin
                    for (k=0;k<TAP_PER_PHASE;k=k+1)
                        data_out <= data_out+phase_buf[p][k]*phase_coeffs[p][k];
                end
                out_valid <= 1;
            end else out_valid <= 0;
            phase_cnt <= phase_cnt+1'b1;
        end
    end
endmodule

5. 多相内插与滤波器组

🔄 多相内插结构

  1. 输入信号同时送入L个子滤波器
  2. 每个子滤波器独立计算
  3. 输出按相位顺序交织
  4. 等效于内插后在L倍速率下滤波

📡 多相DFT滤波器组

6. 练习

📝 练习1:多相分解

将16抽头FIR h[n]={1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4}分解为4相,写出E₀-E₃。

📝 练习2:计算量对比

32抽头FIR,4倍抽取。比较直接法和多相法的每输出乘法次数。

📝 练习3:Noble恒等式

证明↓M·H(z)=H(zᴹ)·↓M,并解释其工程意义。

📝 练习4:多相内插

修改dsp_decimator_polyphase.v为内插版本。

🏆 成就解锁:多相分解大师

✅ 理解了多相分解的数学原理

✅ 掌握了Noble恒等式及其应用

✅ 实现了多相FIR和抽取滤波器

✅ 理解了多相内插与滤波器组

✅ 掌握了多相分解如何减少计算量

7. 多相内插滤波器详解

多相分解同样适用于内插(升采样),结构恰好是抽取的"镜像":

内插恒等式:H(z)·↑L ≡ ↑L·{E₀(z), E₁(z)·z⁻¹, ..., E_{L-1}(z)·z^{-(L-1)}}

多相内插步骤:(1)输入信号同时送入L个子滤波器;(2)每个子滤波器独立计算;(3)输出按相位顺序交织:E₀→E₁→...→E_{L-1}→E₀→...;(4)等效于内插后在L倍速率下滤波,但计算量仅为1/L。

8. 多相DFT滤波器组

多相分解与DFT结合构成滤波器组,用于子带编码和频分复用:

y_m[n] = Σ(k=0 to M-1) x[k]·e^{-j2πkm/M}·E_m(z)

📡 多相DFT滤波器组架构

9. 多级多相抽取

对于大比率抽取(如M=64),单级实现阶数过高。采用多级结构:M=M₁×M₂×...,每级做小比率抽取,总计算量显著降低。例如64=4×4×4,三级4倍抽取,每级阶数大幅减少。

📊 单级vs多级抽取对比

方案总乘法/输出存储需求设计复杂度
单级64倍640×2=12801280字简单
3级4×4×430×2+22×2+18×2=140140字中等

7. 多相内插滤波器详解

多相分解同样适用于内插(升采样),结构恰好是抽取的"镜像":

内插恒等式:H(z)·↑L ≡ ↑L·{E₀(z), E₁(z)·z⁻¹, ..., E_{L-1}(z)·z^{-(L-1)}}

多相内插步骤:(1)输入信号同时送入L个子滤波器;(2)每个子滤波器独立计算;(3)输出按相位顺序交织;(4)等效于内插后在L倍速率下滤波,但计算量仅为1/L。

8. 多相DFT滤波器组

多相分解与DFT结合构成滤波器组:

y_m[n] = Σ(k=0 to M-1) x[k]·e^{-j2πkm/M}·E_m(z)

📡 多相DFT滤波器组架构

9. 多级多相抽取

对于大比率抽取(如M=64),单级实现阶数过高。采用多级结构:M=M₁×M₂×...,每级做小比率抽取。

📊 单级vs多级对比

方案总乘法/输出存储复杂度
单级64倍12801280字简单
3级4×4×4140140字中等

10. 多相FIR的FPGA实现技巧

🔧 多相FIR的FPGA优化

11. 多相FIR设计实例

📌 4倍抽取多相FIR设计

设计规格:fs=48kHz,输出12kHz,通带0-4kHz,过渡4-6kHz,阻带>50dB

12. 多相滤波器的进阶主题

多相滤波器的几个进阶设计主题:

📚 进阶主题

13. 多相FIR与其他技术的结合

🔗 技术融合

11. 补充:多相FIR的进阶主题

多相FIR在进阶应用中还有以下重要主题值得深入研究:

📚 进阶研究方向

12. 与前后课程的关联

本课内容在整个DSP课程体系中处于承上启下的位置:

🔗 课程关联图

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单

13. 设计经验总结

在实际工程中,多相FIR的设计经验总结如下:(1)始终从系统级需求出发,不要过早陷入实现细节;(2)先用浮点仿真验证算法正确性,再转为定点;(3)系数量化后必须重新验证频率响应;(4)硬件实现前用C/MATLAB模型作为参考;(5)综合后检查时序和资源是否符合预期;(6)板级验证时用已知的测试信号对比参考输出。每一步验证都是必要的,跳过任何一步都可能导致最终的调试时间成倍增加。

📌 关键设计检查清单