经过前面的学习,相信大家已经掌握了软件的基本操作和设计的基本流程,接下来我们尝试设计一个比较有趣的东西,那就是一个音乐播放器,可以用来播放自己的爱曲。 在做FPGA设计之前,我们先来了解一下声音是怎么播放出来的,首先我们在本次设计中,用到的是一个无源蜂鸣器,如下图所示: 由于FPGA的驱动能力不够,我们添加了一个三极管来驱动这个无源蜂鸣器,而无源蜂鸣器的主要特点是内部不带振荡源,所以如果使用直流信号是无法使无源蜂鸣器鸣叫的,必须使用方波去驱动它。 现在我们明白了,只要往蜂鸣器发送一定频率的方波,就可以使得蜂鸣器发出声音,然后现在的问题是,我们究竟要往蜂鸣器发送什么频率的方波信号呢?具体的频率可以查看下图:
现在我们知道了如何让蜂鸣器响起,又知道发送什么频率可以让蜂鸣器响起什么的声音,所以我相信我们已经有能力让蜂鸣器响起我们需要的音乐了。 下面我们来FPGA来设计一个蜂鸣器的播放器,首先我们至芯板子上FPGA的晶振是50Mhz的,所以我们首先需要一个锁相环模块(PLL)来得到一个比较低的频率,然后在用这个比较低的频率来分出所需要的频率送往蜂鸣器,有了锁相环(PLL),有了锁相环,我们就需要有一个模块来保存我们的音乐,那就ROM模块,这个我们可以通过IP核来创建,有了PLL和ROM模块,我们还需要一样东西,那就是音乐的节拍控制器,就比如,我现在要发出一个低音1需要维持1秒钟,那怎么办呢,所以我们需要一个模块控制每0.25秒钟,ROM的地址才自动加一,若要发出一个低音1需要维持1秒钟,我们仅仅需要在ROM里面的连续4个地址数写上低音1即可,具体的设计架构图如下图所示: 由上图可知,整个FPGA设计里面一共有6个模块,其中PLL模块,是把50Mhz的时钟信号降到1Mhz,而ROM模块式存储音乐的数据,Time_counter模块是一个计数器模块,每当到0.25秒之后,Time_counter输出的Time_finsh信号会变一个时钟周期的高电平,发送个Addr_gen模块,让ROM输出下一个地址的数据,简单来说,就是实现0.25秒之后,把ROM的地址加一,读取下一个音乐数据。而decode解码模块,是把的数据解码然后发到Music_gen模块,产生特定的方波频率。而为了方便我们往ROM保存的数据时8’hAB,其中A暂时只有3个值,1,2,4分别表示低音,中音,高音,而B暂时有7个值,分别是1,2,3,4,5,6,7,比如,现在要产生一个低音1,仅仅需要在ROM里面写8’H11,需要产生一个高音5,则需要在ROM里面写8’H45依次类推。但是实际上,你要产生一个低音1,然后把ROM里面的8’H11发给Music_gen是不行的,因为在ROM里面的数据是为了方便我们编写音乐而定义成这样的格式,所以我们需要一个decode模块(解码模块)来把ROM的数据还原成Music_gen所需要的数据。 Time_counter的功能很简单,就不断的计数,当计数到249_999(1Mhz/4Hz=250_000-1 ,4Hz=0.25S)的时候数据选择器选择18’d0,让count归零,然后又继续累加,直到计数到249_999,不断这样循环。
下面是FPGA代码: Addr_gen模块的主要功能就是,每当Time_finsh变成高电平(每0.25s)的时候,ROM的地址信号线Addr自加一,FPGA代码如下: decode模块其实就是一个22的数据选择器,每一个音对应一个数据,接着我们看看decode的FPGA代码: 在Music_gen模块中,music_data的会寄存在data寄存器里面,当data=11’d0(停止节拍)的时候,计数器count归一,输出的方波信号beep归零,当data!=11’d0的时候,就判断当前计数器的值是否小于等于data的值,如果计数器的值小于等于data的值,计数器继续累加,输出的方波信号beep不变,当计数器的值大于等于data的值,计数器归一,输出的方波信号beep取反,通过改变data的值来改变输出的方波频率。
最后我们看看Music_gen的FPGA代码: 顶层设计就是把各个模块之间的线连接在一起。
顶层设计FPGA代码如下:
仿真代码如下: 仿真结果如下: 由仿真图可知,当ROM输出的q等于23的时候,代表着输出中音3,解码后的结果等于758,输出的方波周期等于1.518ms,等于658.76Hz约等于中音3的659.25Hz,当ROM输出的q等于00的时候,代表着输出停止节拍,解码后的结果等于0,输出一个低电平,当ROM输出的q等于24的时候,代表着输出中音4,解码后的结果等于716,输出的方波周期等于1.434ms,等于697.35Hz约等于中音4的698.46Hz,虽然存在一点误差,当并不影响音乐播放器的功能,若如果有同学想把精度提上去,可以把时钟1Mhz的时钟频率网上提高,时钟频率越高,分频精度越高,误差即可越小。下面送上一首歌曲欢乐颂的ROM数据:
|