FPGA播放声音和音乐
2012-06-02
标签: FPGA

这里我们将让我们的FPGA播放声音和音乐。我们从产生一个单频音开始。然后,逐步让它实现一些更加有趣的功能,例如播放警笛和曲子。

这个工程中用到的硬件器件包括:一块Pluto板、一个扬声器(speaker)以及一个1千欧姆的电阻(resistor)。

关于此硬件系统的一个更加正式的表示方法如下图所示:

振荡器(oscillator)产生一个固定频率输入到FPGA,FPGA将此频率分频后驱动一个I/O口。这个I/O口通过一个1千欧姆的电阻连接到一个扬声器。通过改变这个I/O口的输出频率,就可以使扬声器发出各种声音。

HDL(硬件描述语言)设计

这里将分三部分来描述它:

  • 第一部分 - 简单的哔哔声
  • 第二部分 - 警笛声
  • 第三部分 - 曲调

简单的哔哔声

FPGA 可以很容易就实现二进制的计数。让我们从一个16位的计数器开始。首先从25MHz的时钟开始,对于这个时钟信号,我们可以简单的应用计数器来实现“分频”。一个16位的计数器从0计到65535(一共65536个不同的值)。计数器的最高位将以25000000/65536=381Hz的频率翻转。

对应的Verilog HDL语言如下所示:

代码

  • module music(clk, speaker);
  • input clk;
  • output speaker;
  • // 16位的2进制计数器
  • reg [15:0] counter;
  • always @(posedge clk) counter <= counter+1;
  • // 使用计数器的最高有效位驱动扬声器
  • assign speaker = counter[15];
  • endmodule

计数器的最低有效位(counter[0])以12.5MHz的频率翻转,类似的counter[1]以6.125MHz的频率翻转,以此类推。我们使用最高有效位(counter[15])来驱动扬声器。这样就可以给扬声器输出一个很好的381Hz的方波。

"A" 调 (440Hz)

好了,与其产生一个随机的频率,为何不试试得到一个440Hz的频率。这个频率就是“A”调的频率。这样一来,我们需要将25MHz的信号56818分频,下面是对应的Verilog HDL代码。

代码

  • module music(clk, speaker);
  • input clk;
  • output speaker;
  • reg [15:0] counter;
  • always @(posedge clk) if(counter==56817) counter <= 0; else counter <= counter+1;
  • assign speaker = counter[15];
  • endmodule

问题来了,输出信号的频率虽然是希望的440Hz,但是其占空比不再是50%。因为低电平从0一直维持到32767(期间counter[15]等于0),而高电平则从32768维持到56817。这样输出信号中,高电平的占空比仅为42%。

最简单的得到50%占空比的办法是添加一个状态,使输出信号先28409分频(56818的一半),然后再2分频。以下是修改后的Verilog HDL代码。

代码

  • module music(clk, speaker);
  • input clk;
  • output speaker;
  • reg [14:0] counter;
  • always @(posedge clk) if(counter==28408) counter <= 0; else counter <= counter+1;
  • reg speaker;
  • always @(posedge clk) if(counter==28408) speaker <= ~speaker;
  • endmodule

添加一个参数

下面的代码跟上面的代码效果完全一样,一个名为“clkdivider”的参数被添加到代码中,而计数器则变为向下技术(这个只是个人爱好问题).

代码

  • module music(clk, speaker);
  • input clk;
  • output speaker;
  • parameter clkdivider = 25000000/440/2;
  • reg [14:0] counter;
  • always @(posedge clk) if(counter==0) counter <= clkdivider-1; else counter <= counter-1;
  • reg speaker;
  • always @(posedge clk) if(counter==0) speaker <= ~speaker;
  • endmodule

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