FPGA 20个例程篇:18.SD卡存放音频WAV播放(下)

第七章 实战项目提升,完善简历

18.SD卡存放音频WAV播放(下)

      进一步地我们再结合图1的示意图来分析wav_play模块的时序逻辑设计,大家可以清楚地看到WM8731在Right justified和主从时钟模式下,是先发左声道后发右声道数据的,这里需要强调4点也是之前困扰笔者很久的问题:     

      1. WAV格式的音频数据采用了16Bit双声道编码格式,相当于一个基本音频数据单元是32Bit,这也就是为什么要把SD卡扇区中读到的4个字节数据拼接到一起后存入FIFO中,主要是为了方便wav_play模块的数据拆分;

       2. 在这个例程中我们选取的是Right justified、主时钟、默认32bit模式,注意到手册里明确写道在主时钟模式下,DACLRC/ADCLRC是输出64个BCLK时钟周期即32个BCLK高电平,32个BCLK低电平;

        3. 在Right justified、默认32bit模式下,前32个BCLK对应DACLRC/ADCLRC的高电平,这时应该在后16个BCLK中输入左声道16位的数据,后32个BCLK对应对应DACLRC/ADCLRC的低电平,这时应该在后16个BCLK中输入右声道16位的数据,而对应的左右声道的前16个BCLK可以做补零操作,且DACDAT/ADCDAT的数据应该在BCLK时钟下降沿更新;

      4. 注意到WAV下16 Bit双声道编码格式为:左声道数据低字节、左声道数据高字节、

      右声道数据低字节、右声道数据高字节,而WM8731在Right justified、默认32bit模式下的编码格式为:左声道数据高字节、左声道数据低字节、右声道数据高字节、右声道数据低字节,所以需要在程序里把上游wav_query模块从FIFO中读到的32位数据进行数据拼接,重新组成左声道和右声道的数据。

图1 WM8731在Right justified和主从时钟模式下的说明

      如表1所示是wav_play模块信号列表,在这个模块里我们先把上游wav_query模块从FIFO中读到的32位数据进行数据拆分处理,再拼接成32位的左声道数据和32位的右声道数据,最后按照Right justified、主时钟、默认32bit模式,在BCLK和ADCLRC的作用下把数据一位位地送到DACDAT上。

      显然本模块的CLK对应50Mhz时钟比BCLK快很多,可以捕获到BCLK的时钟下降沿和ADCLRC的时钟上升沿,在这里wav_data和wav_data_vld分别对应上游模块的数据信号和数据指示信号,而wav_playrdy作为读准备信号例化到上游wav_query模块,激发FIFO的读使能信号,如图2所示是WAV音频播放模块的代码设计。

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

wav_bclk

I

1

wav_adclrc

I

1

wav_data

I

32

wav_data_vld

I

1

wav_playrdy

O

1

wav_dacdata

O

1

表1 wav_play模块信号列表

图2 WAV音频播放模块的代码设计

      如表2和表3所示分别是config_wm8731和i2c_wm8731模块的信号列表,显然我们需要去初始化WM8731后,芯片才能按照我们的想法工作,其中config_wm8731模块存储了10个寄存器地址和参数值,i2c_wm8731模块则实现了整个IIC配置的时序逻辑,依次配置10个寄存器,完成IIC初始化后,通过i2c_config_done信号指示初始完成,如图3和4所示分别是2个模块的代码设计。

信号列表

信号名

I/O

位宽

lut_index

I

4

lut_data

O

24

lut_size

O

4

表2 config_wm8731模块信号列表

信号列表

信号名

I/O

位宽

clk

I

1

rst_n

I

1

i2c_config_size

I

4

i2c_config_data

I

24

i2c_sda

I/O

1

i2c_scl

O

1

i2c_config_index

O

4

i2c_config_done

O

1

表3 i2c_wm8731模块信号列表

图3 WM8731初始化寄存器值模块的代码设计

图4 WM8731初始化寄存器设置模块的代码设计

      如图5所示是SD卡存放音频WAV播放顶层模块的代码设计,大家需要把各个模块的相关信号例化到一起,在这个例程中首先我们在SD卡中事先存储好了很多首WAV格式的歌曲,然后按下按键KEY1,FPGA会按照SD卡的扇区依次遍历各个扇区直到找到WAV文件头格式的歌曲,把WAV格式的音频数据按照WM8731配置的Right justified、主时钟、默认32bit模式播放歌曲,接着当播放完一首歌曲后,再按下按键KEY1,FPGA会再去查找SD卡扇区的下一首WAV文件头格式的歌曲,找到后继续播放下一首。

     为了便于调试观察,这里笔者也把各个模块的关键信号添加到ILA IP核中,同时通过LED0点亮代表SD卡和WM8731均初始化完毕,通过LED1闪烁代表当前正在播放SD卡中的音频数据,插上SD卡后即可观察到板载的LED0点亮,按下按键KEY1很快板载的LED1会不断地闪烁,同时把耳机座子插到豌豆开发板的绿色耳机接口处,即可播放出动听美妙的战歌Counting Stars。

图5 SD卡存放音频WAV播放顶层模块的代码设计

SD卡音乐WM8731播放

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
FPGA 读写SD卡音乐播放例程Verilog逻辑源码Quartus工程文件+文档说明,,FPGA型号Cyclone4E系列中的EP4CE6F17C8,Quartus版本17.1。 实验简介 在其他实验中我们已经完成了 SD读写音频模块的录音播放,本实验通过搜索 SD 卡中 WAV 音乐文件,然后送到音频模块播放,完成一个简单音乐播放器的功能。 2 实验原理 本实验一个关键是在没有文件系统的情况下,搜索 SD 卡每个扇区的内容,匹配出 WAV 文件, 这里有一个假设:假设每一个文件都是从一个扇区第一个字节开始而且文件是连续存储的,经过 大量实验,发现 FAT32 文件格式中的文件确实如此。 2.1 WAV 文件格式 大部分的文件都有文件头,WAV 也丌例外,我们通过分析 SD 卡一个扇区的前几个字节,判 断这个文件是否为 WAV 文件。 WAV 文件作为多媒体中使用的声波文件格式之一,它是以 RIFF 格式为标准的。RIFF 是英文 Resource Interchange File Format 的缩,每个 WAV 文件的头四个字节便是“RIFF”,所以本实验 就简单的以每个扇区的前 4 个字节是否为“RIFF”判断该文件是否为 WAV 文件,紧接着 4 个字节 表示文件的大小,这样我们就可以确定要读取的数据量。WAV 文件头大小是 88 字节,在播放时 要把前 88 个字节的文件头去掉。 module top( input clk, input rst_n, input key1, input wm8731_bclk, //audio bit clock input wm8731_daclrc, //DAC sample rate left right clock output wm8731_dacdat, //DAC audio data output input wm8731_adclrc, //ADC sample rate left right clock input wm8731_adcdat, //ADC audio data input inout wm8731_scl, //I2C clock inout wm8731_sda, //I2C data output sd_ncs, //SD card chip select (SPI mode) output sd_dclk, //SD card clock output sd_mosi, //SD card controller data output input sd_miso, //SD card controller data input output [5:0] seg_sel, output [7:0] seg_data ); wire[9:0] lut_index; wire[31:0] lut_data; wire[3:0] state_code; wire[6:0] seg_data_0; //I2C master controller i2c_config i2c_config_m0( .rst (~rst_n ), .clk (clk ),
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值