原创声明:
本原创教程由芯驿电子科技(上海)有限公司(ALINX)创作,版权归本公司所有,如需转载,需授权并注明出处(http://www.alinx.com)。
适用于板卡型号:
PGL22G/PGL12G
1. 实验简介
本实验的录音和播放实验因为开发板上没有音频部分的电路,需要外接一个芯驿电子的AUDIO音频模块AN831。
AN831
音频模块上有三个音频连接器,其中粉色的接口为麦克风输入;绿色的接口为耳机输出;蓝色的接口为音频输入, 用于连接DVD等音频输出口。本实验将实现音频模块和FPGA之间的数据通信, 通过音频模块把麦克风输入的语音数据存储到SDRAM存储器里, 再把音频数据发送给音频模块,从耳机接口进行语音的播放,从而实现录音和播放的功能。
2. 实验原理
2.1 硬件介绍
开发板通过40PIN的扩展口和AN831音频模块连接,AN831音频模块使用WOLFSON公司的WM8731芯片实现声音信号的A/D和D/A转换功能。以下为AN831音频模块的硬件电路:
2.2 WM8731配置和时序
这里简单介绍一下音频模块AN831用到的音频编/解码芯片WM8731。该芯片在本设计中主要完成声音信号在采集和回放过程中的A/D和D/A转换功能。该芯片的ADC和DAC的采样频率为8KHz到96KHz可调,可转换的数据长度为16-32位可调。WM8731的内部有11个寄存器。该芯片的初始化以及工作时的工作状态和功能都是通过以I2C总线方式对其内部的这11个寄存器进行相应的配置来实现的。本设计中WM8731工作于主模式,采样频率设为48KHZ,转换的数据位长度为16位。WM8731的数字音频接口有5根引脚,分别为:BCLK(数字音频位时钟)、DACDAT(DAC数字音频数据输入)、DACLRC(DAC采样左/右声道信号)、ADCDAT(ADC数字音频信号输出)、ADCLRC(ADC采样左/右声道信号)。在本设计中FPGA为从设备,WM8731为主设备。ADCDAT、DACDAT、ADCLRC和DACLRC与位时钟BCLK同步,在每个BCLK的下降沿进行一次数据传输。BCLK、DACDAT、DACLRC、ADCLRC为WM8731的输入信号。ADCDAT为WM8731的输出信号。
在本系统中FPAG和WM8731的控制和数据通信将用到I2C和数字音频总线接口。FPGA通过I2C接口配置WM8731的寄存器,通过I2S总线接口来进行音频数据的通信。关于I2C接口,其他实验中已经有讲解,下面我们主要来了解数字音频接口。
数字音频接口可提供4种模式:
- Right justified
- Left justified
- I2S
- DSP mode
Left justified模式
I2S模式
Right justified模式
DSP/PCM 模式(MODE A)
DSP/PCM 模式(MODE B)
本实验选择Right justified模式。
3. 程序设计
本实验的功能是程序检测按键KEY2是否按下,如果检测到KEY2按下了,开始录音,录音的最长时间为20秒;录音结束后,开始播放刚才录下的音频。本程序设计包含四大部分:SDRAM的读写控制程序,音频录音和播放,按键检测和系统控制。
lut_wm8731模块将寄存器配置地址和配置信息通过查找表的形式通过I2C总线写入音频模块中,具体的请参考例程代码和wm9731的芯片数据手册。
audio_rx接收模块,接收从麦克风输入的语音信号,完成左右声道的音频接收,将串行数据转换成并行数据。通过“Right justified”模式的时序图可以看到接收语音信号时在LRC信号为高电平,且BCLK信号的上升沿时左声道接收数据并完成串行信号转换成并行信号的过程。在LRC信号为低电平,且BCLK 信号的上升沿时右声道接收数据并完成串行信号转换成并行信号的过程。
信号名称 | 方向 | 说明 |
clk | in | 时钟输入 |
rst | in | 异步复位输入,高复位 |
sck_bclk | in | 数字音频接口bit时钟 |
ws_lrc | in | ADC采样时钟 |
sdata | in | 音频数字接口串行数据输入 |
left_data | out | 左声道数据 |
right_data | out | 右声道数据 |
data_valid | out | 音频数据有效 |
audio_rx音频接收模块端口
audio_tx是音频发送模块,完成左右声道音频数据的串行化。同样通过时序图可以看到,语音信号完成模数,数模转换从SDRAM输出后进入发送模块,在LRC信号上升沿,且即将跳变为高电平时接收左声道数据,BCLK信号下降沿时完成缓存将并行信号转换为串行信号的过程;在LRC信号上升沿且即将跳变为低电平时接收右声道数据,在BCLK信号下降沿时完成缓存将并行信号转换为串行信号的过程。
信号名称 | 方向 | 说明 |
clk | in | 时钟输入 |
rst | in | 异步复位输入,高复位 |
sck_bclk | in | 数字音频接口bit时钟 |
ws_lrc | in | ADC采样时钟 |
sdata | out | 音频数字接口串行数据输入 |
left_data | in | 左声道数据 |
right_data | in | 右声道数据 |
read_data_en | out | 音频数据读取,提前一个采样周期读取 |
audio_tx音频发送模块端口
在模块‘frame_read_write’中使用到了FIFO 的IP core,通过两个FIFO分别作为DDR3控制器的读写接口,避免复杂的DDR3时序。因为时钟速率的不同,所使用的是异步FIFO。以write_buf写入模块的FIFO为例在vivado中FIFO IP core设置如下:
- 打开Tools菜单下的“IP Compiler”, 在弹出的界面下进行如下设置,设置完成后点击”Customize”:
- 在弹出的界面下进行如下设置,设置完成后点击保存后Generate即可生成IP:
- 接着在模块中直接例化FIFO 的端口名就可以使用FIFO了,在read_buf中也是同样的操作步骤。具体的参数设置和端口例化的信号连接参考例程。
frame_fifo_write模块完成FIFO数据到外部存储器的写入,如果FIFO接口是异步FIFO,可以完成写数据的跨时钟域转换。状态机转换图如下,收到写数据请求后进入应答状态“S_ACK”,如果写请求撤销,则进入检测FIFO空间大小状态“S_CHECK_FIFO”,检查FIFO内数据是否够一次突发写,如果有足够多的数据,进入突发写存储器状态“S_WRITE_BURST”,突发写完成后进入“S_WRITE_BURST_END”状态。
frame_fifo_write模块状态机
信号名称 | 方向 | 说明 |
mem_clk | in | 外部存储器用户时钟输入 |
rst | in | 异步复位输入,高复位 |
wr_burst_req | out | 对接存储器控制器,写请求 |
wr_burst_len | out | 对接存储器控制器,写请求长度 |
wr_burst_addr | out | 对接存储器控制器,写请求基地址 |
wr_burst_data_req | in | 对接存储器控制器,写请求数据索取,提前一个时钟周期发出,用于连接FIFO的读数据 |
wr_burst_finish | in | 对接存储器控制器,写请求完整 |
write_req | in | 一帧(大量数据)写开始,收到应答后必须撤销请求,新的请求会中断正在进行的请求 |
write_req_ack | out | 一帧(大量数据)写应答 |
write_finish | out | 一帧(大量数据)完成 |
write_addr_0 | in | 一帧(大量数据)写基地址0 |
write_addr_1 | in | 一帧(大量数据)写基地址1 |
write_addr_2 | in | 一帧(大量数据)写基地址2 |
write_addr_3 | in | 一帧(大量数据)写基地址3 |
write_addr_index | in | 一帧(大量数据)写基地址选择,0:write_addr_01:write_addr_12:write_addr_23:write_addr_3 |
write_len | in | 一帧(大量数据)写长度 |
fifo_aclr | out | 在收到写请求后,模块会清空FIFO |
rdusedw | in | FIFO读端的数据使用量 |
frame_fifo_write模块端口
frame_fifo_read读模块完成从外部存储器读取数据,然后写到FIFO,如果使用异步FIFO可以完成数据从存储器时钟域到其他时钟域的转换。状态机转换图如下图所示,收到读请求以后进入应答状态“S_ACK”,等待读请求撤销后应答,进入FIFO深度检测状态“S_CHECK_FIFO”,如果FIFO空间足够一次突发读,进入突发读状态“S_READ_BURST”,突发读结束后进入“S_READ_BURST_END”。
frame_fifo_read模块状态机
信号名称 | 方向 | 说明 |
mem_clk | in | 外部存储器用户时钟输入 |
rst | in | 异步复位输入,高复位 |
rd_burst_req | out | 对接存储器控制器,读请求 |
rd_burst_len | out | 对接存储器控制器,读请求长度 |
rd_burst_addr | out | 对接存储器控制器,读请求基地址 |
rd_burst_data_valid | in | 对接存储器控制器,读请求数据有效 |
rd_burst_finish | in | 对接存储器控制器,读请求完全 |
read_req | in | 一帧数据读开始 |
read_req_ack | out | 一帧数据读应答 |
read_finish | out | 一帧数据读完成 |
read_addr_0 | in | 一帧数据读基地址0 |
read_addr_1 | in | 一帧数据读基地址1 |
read_addr_2 | in | 一帧数据读基地址2 |
read_addr_3 | in | 一帧数据读基地址3 |
read_addr_index | in | 一帧数据读基地址选择0:read_addr_01:read_addr_12:read_addr_23:read_addr_3 |
read_len | in | 帧数据读长度 |
fifo_aclr | out | 外部FIFO异步复位 |
wrusedw | in | FIFO写端使用空间大小 |
frame_fifo_read模块端口
audio_key模块主要完成录音播放的按键控制,状态转换如下,当按键按下后进入录音状态,当按键松开时进入播放状态。
audio_key模块状态转换图
信号名称 | 方向 | 说明 |
clk | in | 时钟输入 |
rst | in | 异步复位输入,高复位 |
key | in | 按键输入 |
record | out | 录音状态指示 |
play | out | 播放状态指示 |
write_req | out | 写数据开始 |
write_req_ack | in | 写数据应答 |
read_req | out | 读数据开始 |
read_req_ack | in | 读数据应答 |
frame_read_write模块完成音频帧数据读写的封装,这里使用了异步FIFO来解决跨时钟问题,例如FIFO 输入宽度和输出宽度的不同来完成数据位宽的转换。
4. 实验现象
开发板首先将音频模块插入扩展口,同时插入麦克风和耳机,然后下载实验程序,按下KEY2不放,进行录音,松开按键后可通过耳机回放录音。
转载:https://blog.csdn.net/m0_53439615/article/details/113862583