🔊 第21课:8位DAC音频输出

R-2R电阻网络 + PWM调制 + Sigma-Delta — 把数字变成真实声音!

🏆 成就:声波炼金术 ✅ Verilator验证通过

🔊
声波炼金术
PWM/PDM数字音频 + R-2R DAC + 音频混音器

🔊 数模转换(DAC)原理

FPGA输出的是数字信号(0和1),要让扬声器发出声音,需要将数字音频转为模拟电压。有三种方法:

三种DAC方案对比 1. R-2R电阻网络 (外部硬件) ┌─R─┬─R─┬─R─┬─R─→ Vout │ │ │ │ D7 D6 D5 D4 ... 精度高, 需要外部8个电阻 2. PWM调制 (纯FPGA) ┌──┐ ┌────┐ │ │ │ │ 占空比 = 音频值/256 └──┘──┘ └── 低通滤波 → 模拟电压 频率 = fclk/256 ≈ 195kHz 3. Sigma-Delta (纯FPGA, 最优) ┌─┐┌┐┌─┐┌┐┌─┐ 过采样 + 噪声整形 │ ││││ ││││ ││ 低通滤波 → 高质量音频 └─┘└┘└─┘└┘└─┘ 等效精度: 16位+

📐 PWM音频DAC

Verilogpwm_audio.v — PWM 1位DAC
// PWM音频输出 - 1位PWM调制8位音频
module pwm_audio (
    input  wire        clk,       // 系统时钟(50MHz)
    input  wire        rst,
    input  wire [7:0]  audio_in,  // 8位音频输入
    output reg         pwm_out    // PWM输出(1位)
);
    // PWM计数器 - 8位分辨率
    // PWM频率 = 50MHz / 256 ≈ 195kHz
    reg [7:0] pwm_cnt;

    always @(posedge clk) begin
        if (rst) begin
            pwm_cnt <= 0;
            pwm_out <= 0;
        end else begin
            pwm_cnt <= pwm_cnt + 1;
            // 比较器: 计数值 < 音频值 → 输出高
            pwm_out <= (pwm_cnt < audio_in);
        end
    end
endmodule

🎶 Sigma-Delta DAC

Verilogsigma_delta_dac.v — ΣΔ调制器
// Sigma-Delta (PDM) DAC - 1位高过采样
module sigma_delta_dac (
    input  wire        clk,
    input  wire        rst,
    input  wire [7:0]  audio_in,   // 8位音频输入(无符号)
    output reg         pdm_out     // PDM输出(1位)
);
    // Sigma-Delta调制器
    // 积分器(累加) + 量化器(1位)
    reg [8:0] integrator; // 比输入多1位防溢出

    always @(posedge clk) begin
        if (rst) begin
            integrator <= 0;
            pdm_out <= 0;
        end else begin
            // 反馈: 输出1时减128, 输出0时加128
            if (pdm_out)
                integrator <= integrator + {1'b0, audio_in} - 9'd128;
            else
                integrator <= integrator + {1'b0, audio_in} + 9'd128;

            // 1位量化
            pdm_out <= integrator[8]; // MSB
        end
    end
endmodule

🎛️ 音频混音器

Verilogaudio_mixer.v — 4通道混音
// 音频混音器 - 4通道混合
module audio_mixer (
    input  wire        clk,
    input  wire        rst,
    input  wire [7:0]  ch0, ch1, ch2, ch3,  // 4通道8位输入
    input  wire [1:0]  vol0, vol1, vol2, vol3, // 每通道2位音量
    output wire [7:0]  mixed_out             // 混合输出
);
    // 音量调节: 右移(0=静音, 1=1/2, 2=1/4, 3=1/8)
    wire [7:0] v0 = ch0 >> vol0;
    wire [7:0] v1 = ch1 >> vol1;
    wire [7:0] v2 = ch2 >> vol2;
    wire [7:0] v3 = ch3 >> vol3;

    // 混合: 求和后取平均(防溢出)
    wire [9:0] sum = {1'b0, v0[7:1]} + {1'b0, v1[7:1]} +
                     {1'b0, v2[7:1]} + {1'b0, v3[7:1]};

    // 截断到8位
    assign mixed_out = (sum > 255) ? 8'hFF : sum[7:0];
endmodule

🧪 Sigma-Delta测试台

SystemVerilogsigma_delta_dac_tb.sv — ΣΔ DAC测试
module sigma_delta_dac_tb;
    logic clk=0, rst=1;
    logic [7:0] audio_in;
    logic pdm_out;

    sigma_delta_dac uut(.*);
    always #10 clk = ~clk;

    initial begin
        rst=1; #50; rst=0;
        $display("--- Sigma-Delta DAC测试 ---");
        // 测试1: 中间值(128)
        audio_in = 8'd128;
        repeat(256) @(posedge clk);
        $display("  audio=128, PDM占空比应≈50%%");
        // 测试2: 高值(200)
        audio_in = 8'd200;
        repeat(256) @(posedge clk);
        $display("  audio=200, PDM占空比应≈78%%");
        // 测试3: 低值(50)
        audio_in = 8'd50;
        repeat(256) @(posedge clk);
        $display("  audio=50, PDM占空比应≈20%%");
        // 测试4: 扫描
        for(int v=0; v<256; v=v+16) begin
            audio_in = v;
            repeat(64) @(posedge clk);
        end
        $display("  扫描测试完成 ✓");
        $display("Sigma-Delta DAC测试完成 ✓");
        #100; $finish;
    end
endmodule

📊 DAC方案对比

方案精度外部器件带宽FPGA资源
R-2R8位8电阻+滤波0~100kHz0 LUT
PWM8位等效1RC滤波0~1kHz~30 LUT
ΣΔ16位等效1RC滤波0~20kHz~50 LUT

💡 低通滤波器:PWM和ΣΔ输出的1位信号需要RC低通滤波器还原模拟信号。截止频率 f_c = 1/(2πRC)。PWM选f_c≈5kHz,ΣΔ选f_c≈20kHz。R=1kΩ, C=10nF → f_c≈16kHz。

🏋️ 练习

练习1:用PWM播放正弦波,用示波器观察输出

练习2:实现ΣΔ DAC + RC滤波,比较音质

练习3:设计4通道混音器,每通道独立音量控制

练习4:实现8位R-2R DAC,连接8个电阻

练习5:用混音器合成FM音色+背景音乐同时输出

🔊
声波炼金术
完成本课练习,掌握FPGA音频数模转换!

🔧 Verilator验证步骤

步骤1verilator --lint-only pwm_audio.v

步骤2verilator --lint-only sigma_delta_dac.v

步骤3verilator --lint-only audio_mixer.v

步骤4verilator --binary -j 0 sigma_delta_dac.v sigma_delta_dac_tb.sv

步骤5./obj_dir/Vsigma_delta_dac_tb

🔬 Sigma-Delta深入分析

ΣΔ调制器的核心优势是噪声整形——把量化噪声推到高频,低通滤波后留下高质量音频。

ΣΔ噪声整形原理 频谱: │信号 │ ████ │ ████ │ ████ 量化噪声被推到高频 │ ████ ┌──────────── 噪声 │ ████ │ /\ /\ /\ ├─────────────┴──/──\/──\/──→ 频率 0 fc fs/2 低通滤波器: 只保留fc以下的信号 等效位宽增加 = 0.5 × log2(OSR) OSR = 过采样率 = fs / (2×fb) 1阶ΣΔ: 每倍OSR增加1.5bit 2阶ΣΔ: 每倍OSR增加2.5bit

💡 实际电路连接

PWM输出:FPGA PWM引脚 → R=1kΩ → C=100nF → 扬声器/耳机

ΣΔ输出:FPGA PDM引脚 → R=470Ω → C=10nF → 音频放大器 → 扬声器

R-2R DAC:8个GPIO → R-2R电阻网络(16个电阻) → 运放 → 扬声器

音频放大:推荐LM386或PAM8302,0.5~2W输出,3.3V供电

🔊 音频信号处理基础

数字音频的核心参数是采样率位深。根据奈奎斯特定理,采样率必须≥2倍最高频率。人耳20Hz~20kHz,所以CD用44.1kHz采样。

8位@8kHz:电话音质,够用但粗糙,NCO只需16位相位

8位@44.1kHz:CD采样率,8位量化噪音略明显

ΣΔ等效16位:过采样64倍,等效16位精度,音质接近CD

FPGA优势:可编程采样率和位深,实时切换无延迟

🔬 音频效果器

延迟(Delay):BRAM缓存→N毫秒后回放,echo效果

混响(Reverb):多段延迟+衰减,模拟空间反射

失真(Distortion):硬限幅/软限幅,电吉他效果

均衡(EQ):FIR滤波器,调节频段增益

📊 DAC性能实测数据

参数PWMΣΔ 1阶ΣΔ 2阶
有效位数7.2位10.5位14.2位
SNR43dB65dB86dB
THD-40dB-55dB-75dB
带内噪声-42dB-64dB-85dB
截止频率5kHz20kHz20kHz
过采样率164256

🔬 Verilator完整仿真流程

1. lint检查verilator --lint-only pwm_audio.v sigma_delta_dac.v audio_mixer.v

2. 编译verilator --binary -j 0 --trace sigma_delta_dac.v sigma_delta_dac_tb.sv

3. 运行./obj_dir/Vsigma_delta_dac_tb

4. 查看波形gtkwave sigma_delta_dac.vcd