脉宽调制(PWM)和1位数模转换
2012-06-27

在FPGA的一个引脚连接一个扬声器,然后用来听MP3?当然可以。

这里我们采用的方法是:使用PC来解码MP3,然后将解码后的数据送到配置为1位DAC的FPGA。

音频输出

我们需要一个部件来连接FPGA的输出引脚(数字)和扬声器(模拟),以完成数模转换。最简单的办法是用一个电阻网络或者数模转换器件实现。

由于相当于声音信号的频域来说,FPGA是在是太快了,所以采用1位DAC是更好的选择。最简单的实验1位DAC的办法是:使用脉宽调制(PWM)

脉宽调制

脉宽调制在输出引脚上产生一系列脉冲输出。输出有这样的特性:输出信号幅度的平均值正比于输入调制器的数值的大小。想办法对输出进行滤波,就可以在输出端得到与数字输入对应的模拟信号。

脉宽调制器的输入可以是任意宽度,通常是8位或16位

其输出则是1位的(一个输出)

脉宽调制也广泛的应用于微控制器,详见应用笔记AN665.

累加器

生成脉宽调制信号的最简单的办法就是使用硬件累加器。一旦累加结果溢出,就输出1(高电平),否则输出0(低电平)。

这在FPGA中很容易实现。

Verilog 代码:

module PWM(clk, PWM_in, PWM_out);

input clk;

input [7:0] PWM_in;

output PWM_out;

reg [8:0] PWM_accumulator;

always @(posedge clk) PWM_accumulator <= PWM_accumulator[7:0] + PWM_in;

assign PWM_out = PWM_accumulator[8];

endmodule

VHDL 代码:

library IEEE;

use IEEE.STD_LOGIC_1164.all;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PWM is

port (

clk : in std_logic;

PWM_in : in std_logic_vector (7 downto 0) := "00000000";

PWM_out : out std_logic

);

end PWM;

architecture PWM_arch of PWM is

signalPWM_Accumulator : std_logic_vector(8 downto 0);

begin

process(clk, PWM_in)

begin

if rising_edge(clk) then

PWM_Accumulator<=("0" & PWM_Accumulator(7 downto 0)) + ("0" & PWM_in);

end if;

end process;

PWM_out <= PWM_Accumulator(8);

end PWM_arch;

输入数据越大,累加器越快溢出,从而使得输出1的频率越高,这正是我们希望的。

通常使用计数器和比较其来生成PWM信号,但是这样要消耗更多的逻辑资源,所以采用累加器的方法来的更加容易。

1位的DAC

为了得到模拟输出,我们连接一个低通网络到这个输出。如果产生的脉冲的频率足够高,就可以用一个简单的RC滤波器来实现。

播放MP3

第一步:解码mp3数据。解码后的数据成为“PCM”数据

为了简化设计,通过串口完成数据从PC到FPGA的传输,串口上的最大波特率为115200,大约11.5KByte每秒。所以mp3的采样率必须降到11K以下,并且采样精度为8位,这些对于PC机来说是很容易的。这里是使用的软件(带源程序)

好了现在该连接FPGA跟扬声器了,通常有三中方案,如下所示。

1.直接连接。应为扬声器基本上是根导线,我们通过控制通过它的电路来产生声音,为了不致损坏器件,通常要求扬声器的阻抗较大,如使用耳机等。

2.通过RC网络连接。同样要求扬声器有较大的输入阻抗,不至于影响RC滤波器。

3.通过RC网络和运放连接。得到最好音质的最佳方案。

最后我们修改HDL代码,使用从串口接收的数据。

module PWM(clk, RxD, PWM_out);

input clk, RxD;

output PWM_out;

wire RxD_data_ready;

wire [7:0] RxD_data;

async_receiver deserialer(.clk(clk), .RxD(RxD), .RxD_data_ready(RxD_data_ready), .RxD_data(RxD_data));

reg [7:0] RxD_data_reg;

always @(posedge clk) if(RxD_data_ready) RxD_data_reg <= RxD_data;

////////////////////////////////////////////////////////////////////////////

reg [8:0] PWM_accumulator;

always @(posedge clk) PWM_accumulator <= PWM_accumulator[7:0] + RxD_data_reg;

assign PWM_out = PWM_accumulator[8];

endmodule

好了,现在开始用FPGA来听mp3吧。

补充材料

数字音频是一个非常广泛的主题,下面是一些重要的补充材料

1.segma-delta调制简介

2.数字滤波器

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号