阶段一:信号基础

📊 第02课:离散信号与系统

离散时间信号的基本表示与系统特性分析

1. 离散时间信号的表示

离散时间信号是一组有序的数值序列,用 x[n] 表示,其中 n 为整数索引。与连续信号 x(t) 不同,x[n] 仅在离散时间点上有定义。

1.1 常见离散信号

信号名称数学定义应用场景
单位脉冲 δ[n]δ[n] = 1 (n=0), 0 (n≠0)系统冲激响应、卷积基
单位阶跃 u[n]u[n] = 1 (n≥0), 0 (n<0)因果性判定、能量计算
实指数序列x[n] = a^n · u[n]系统响应、衰减建模
复指数序列x[n] = e^(jωn)频率分析基础
正弦序列x[n] = A·sin(ωn + φ)信号合成、测试信号
单位脉冲的筛选性质:x[n] = Σ x[k]·δ[n-k](任意信号可分解为脉冲的加权和)

1.2 信号的分类

2. 离散时间系统

离散时间系统是将输入序列 x[n] 映射为输出序列 y[n] 的变换:T{x[n]} = y[n]

2.1 系统基本性质

🔍 线性系统

满足叠加原理:T{a·x₁[n] + b·x₂[n]} = a·T{x₁[n]} + b·T{x₂[n]}

这意味着:可以先分别求响应再叠加,简化了复杂输入的分析。

🔍 时不变系统

若 y[n] = T{x[n]},则 y[n-n₀] = T{x[n-n₀]}

系统特性不随时间改变——延迟输入等价于延迟输出。

🔍 因果系统

y[n] 仅取决于 n 时刻及之前的输入,不依赖"未来"输入。

实时系统必须是因果的;离线处理可放宽。

🔍 稳定系统(BIBO稳定)

有界输入产生有界输出:|x[n]| ≤ M_x ⟹ |y[n]| ≤ M_y

LTI系统稳定的充要条件:Σ|h[n]| < ∞(冲激响应绝对可和)

3. 卷积运算

LTI系统的输出由输入与冲激响应的卷积给出:

y[n] = x[n] * h[n] = Σ x[k]·h[n-k](k从-∞到+∞)

3.1 卷积的性质

3.2 卷积计算方法

工程中常用四种方法计算卷积:

  1. 直接法:按定义逐点计算,O(N·M)复杂度
  2. 列表法:适合手工计算短序列
  3. 重叠相加法:长序列分段卷积
  4. FFT法:频域乘法,O(N·logN)复杂度

4. Verilog实现:线性卷积器

下面实现一个高效的硬件卷积器,使用移位寄存器实现延迟线结构:

//=============================================
// dsp_convolver.v
// 线性卷积器(FIR结构)
// y[n] = Σ h[k] * x[n-k], k=0..TAP-1
//=============================================
module dsp_convolver #(
    parameter DATA_WIDTH = 16,      // 数据位宽
    parameter COEFF_WIDTH = 16,     // 系数位宽
    parameter TAP = 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:TAP-1],
    output reg  signed [OUT_WIDTH-1:0]   data_out,
    output reg                           out_valid
);

    // 延迟线(移位寄存器)
    reg signed [DATA_WIDTH-1:0] delay_line [0:TAP-1];

    integer i;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i < TAP; i = i + 1)
                delay_line[i] <= {DATA_WIDTH{1'b0}};
            data_out <= {OUT_WIDTH{1'b0}};
            out_valid <= 1'b0;
        end else begin
            out_valid <= 1'b0;
            if (data_valid) begin
                // 移位:最新数据进入delay_line[0]
                delay_line[0] <= data_in;
                for (i = 1; i < TAP; i = i + 1)
                    delay_line[i] <= delay_line[i-1];

                // 乘加运算
                data_out <= compute_conv();
                out_valid <= 1'b1;
            end
        end
    end

    // 卷积计算函数
    function signed [OUT_WIDTH-1:0] compute_conv;
        reg signed [OUT_WIDTH-1:0] acc;
        reg signed [DATA_WIDTH+COEFF_WIDTH-1:0] product;
        integer k;
        begin
            acc = {OUT_WIDTH{1'b0}};
            for (k = 0; k < TAP; k = k + 1) begin
                product = delay_line[k] * coeffs[k];
                acc = acc + product;
            end
            compute_conv = acc;
        end
    endfunction

endmodule

5. Verilog实现:差分方程处理器

离散LTI系统可用差分方程描述:y[n] = Σbₖx[n-k] - Σaₖy[n-k]

//=============================================
// dsp_difference_eq.v
// 通用差分方程处理器
// y[n] = b0*x[n] + b1*x[n-1] + ... - a1*y[n-1] - ...
//=============================================
module dsp_difference_eq #(
    parameter DATA_WIDTH = 16,
    parameter COEFF_WIDTH = 16,
    parameter NUM_B = 4,            // 前馈系数个数
    parameter NUM_A = 3,            // 反馈系数个数(不含a0=1)
    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]  b_coeffs [0:NUM_B-1],  // 前馈系数
    input  wire signed [COEFF_WIDTH-1:0]  a_coeffs [0:NUM_A-1],  // 反馈系数
    output reg  signed [OUT_WIDTH-1:0]    data_out,
    output reg                            out_valid
);

    // 输入延迟线
    reg signed [DATA_WIDTH-1:0] x_delay [0:NUM_B-1];
    // 输出延迟线
    reg signed [OUT_WIDTH-1:0]  y_delay [0:NUM_A-1];

    integer i;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (i = 0; i < NUM_B; i = i + 1) x_delay[i] <= 0;
            for (i = 0; i < NUM_A; i = i + 1) y_delay[i] <= 0;
            data_out <= 0;
            out_valid <= 1'b0;
        end else if (data_valid) begin
            // 更新输入延迟线
            x_delay[0] <= data_in;
            for (i = 1; i < NUM_B; i = i + 1)
                x_delay[i] <= x_delay[i-1];

            // 计算前馈部分:Σ b[k] * x[n-k]
            data_out <= calc_output();
            out_valid <= 1'b1;

            // 更新输出延迟线
            y_delay[0] <= data_out;
            for (i = 1; i < NUM_A; i = i + 1)
                y_delay[i] <= y_delay[i-1];
        end else begin
            out_valid <= 1'b0;
        end
    end

    function signed [OUT_WIDTH-1:0] calc_output;
        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 < NUM_B; j = j + 1) begin
                prod = x_delay[j] * b_coeffs[j];
                acc = acc + prod;
            end
            // 反馈求和(减去)
            for (j = 0; j < NUM_A; j = j + 1) begin
                prod = y_delay[j] * a_coeffs[j];
                acc = acc - prod;
            end
            calc_output = acc;
        end
    endfunction

endmodule

6. Verilog实现:信号能量与功率检测

//=============================================
// dsp_energy_detector.v
// 信号能量/功率实时检测器
//=============================================
module dsp_energy_detector #(
    parameter DATA_WIDTH = 16,
    parameter ACCUM_WIDTH = 40,
    parameter WINDOW_SIZE = 256        // 滑动窗口长度
)(
    input  wire                           clk,
    input  wire                           rst_n,
    input  wire                           data_valid,
    input  wire signed [DATA_WIDTH-1:0]   data_in,
    output reg  [ACCUM_WIDTH-1:0]         energy_out,     // 窗口内总能量
    output reg  [ACCUM_WIDTH-1:0]         power_out,      // 平均功率
    output reg                            detect_out,     // 信号检测输出
    input  wire [ACCUM_WIDTH-1:0]         threshold       // 检测门限
);

    // 平方运算(能量 = |x|²)
    wire [2*DATA_WIDTH-1:0] squared = data_in * data_in;

    // 循环缓冲区存储平方值
    reg [2*DATA_WIDTH-1:0] window_buf [0:WINDOW_SIZE-1];
    reg [$clog2(WINDOW_SIZE)-1:0] wr_ptr;

    // 累加器
    reg [ACCUM_WIDTH-1:0] energy_acc;

    integer i;

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            wr_ptr <= 0;
            energy_acc <= 0;
            energy_out <= 0;
            power_out <= 0;
            detect_out <= 1'b0;
            for (i = 0; i < WINDOW_SIZE; i = i + 1)
                window_buf[i] <= 0;
        end else if (data_valid) begin
            // 滑动窗口:减去最旧值,加上最新值
            energy_acc <= energy_acc - window_buf[wr_ptr] + squared;
            window_buf[wr_ptr] <= squared;

            wr_ptr <= wr_ptr + 1'b1;
            energy_out <= energy_acc;
            power_out <= energy_acc / WINDOW_SIZE;

            // 信号检测
            detect_out <= (energy_acc > threshold);
        end
    end

endmodule

7. 系统稳定性判定实例

📌 稳定性判定方法

对于LTI系统,BIBO稳定 ⟺ 冲激响应绝对可和:Σ|h[n]| < ∞

对于因果系统,等价于系统函数H(z)的极点全部在单位圆内。

系统冲激响应h[n]Σ|h[n]|稳定性
y[n] = x[n] + x[n-1]{1,1}2✅ 稳定
y[n] = 2·y[n-1] + x[n]2^n·u[n]❌ 不稳定
y[n] = 0.5·y[n-1] + x[n]0.5^n·u[n]2✅ 稳定
y[n] = x[n] - x[n-1]{1,-1}2✅ 稳定

8. 练习

📝 练习1:卷积计算

手动计算以下卷积:x[n] = {1, 2, 3},h[n] = {1, -1, 1},求 y[n] = x[n] * h[n]

📝 练习2:系统性质判定

判断以下系统是否为线性、时不变、因果、稳定:

  1. y[n] = x[n]²
  2. y[n] = x[n] + x[n+1]
  3. y[n] = n·x[n]
  4. y[n] = Σ(k=0 to n) x[k]

📝 练习3:修改卷积器

将 dsp_convolver.v 修改为流水线结构,使得每个时钟周期都能接收新数据,吞吐率提升为原来的TAP倍。

📝 练习4:周期判定

判断离散正弦信号 x[n] = sin(2π·3/8·n) 是否为周期信号,若为周期信号求其基本周期。

🏆 成就解锁:信号分析师

✅ 掌握了离散信号的基本类型与性质

✅ 理解了LTI系统的四大性质(线性/时不变/因果/稳定)

✅ 实现了硬件卷积器(移位寄存器结构)

✅ 实现了差分方程处理器

✅ 掌握了信号能量/功率检测方法

11. 补充:离散信号与系统的进阶主题

离散信号与系统在进阶应用中还有以下重要主题值得深入研究:

📚 进阶研究方向

12. 与前后课程的关联

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

🔗 课程关联图

13. 设计经验总结

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

📌 关键设计检查清单

13. 设计经验总结

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

📌 关键设计检查清单

13. 设计经验总结

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

📌 关键设计检查清单

13. 设计经验总结

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

📌 关键设计检查清单

13. 设计经验总结

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

📌 关键设计检查清单