原創(chuàng)聲明:
本原創(chuàng)教程由芯驛電子科技(上海)有限公司(ALINX)創(chuàng)作,版權(quán)歸本公司所有,如需轉(zhuǎn)載,需授權(quán)并注明出處(http://www.alinx.com)。
適用于板卡型號(hào):
PGL22G/PGL12G
1. 實(shí)驗(yàn)簡(jiǎn)介
本實(shí)驗(yàn)的錄音和播放實(shí)驗(yàn)因?yàn)殚_(kāi)發(fā)板上沒(méi)有音頻部分的電路,需要外接一個(gè)芯驛電子的AUDIO音頻模塊AN831。
AN831
音頻模塊上有三個(gè)音頻連接器,其中粉色的接口為麥克風(fēng)輸入;綠色的接口為耳機(jī)輸出;藍(lán)色的接口為音頻輸入, 用于連接DVD等音頻輸出口。本實(shí)驗(yàn)將實(shí)現(xiàn)音頻模塊和FPGA之間的數(shù)據(jù)通信, 通過(guò)音頻模塊把麥克風(fēng)輸入的語(yǔ)音數(shù)據(jù)存儲(chǔ)到SDRAM存儲(chǔ)器里, 再把音頻數(shù)據(jù)發(fā)送給音頻模塊,從耳機(jī)接口進(jìn)行語(yǔ)音的播放,從而實(shí)現(xiàn)錄音和播放的功能。
2. 實(shí)驗(yàn)原理
2.1 硬件介紹
開(kāi)發(fā)板通過(guò)40PIN的擴(kuò)展口和AN831音頻模塊連接,AN831音頻模塊使用WOLFSON公司的WM8731芯片實(shí)現(xiàn)聲音信號(hào)的A/D和D/A轉(zhuǎn)換功能。以下為AN831音頻模塊的硬件電路:
2.2 WM8731配置和時(shí)序
這里簡(jiǎn)單介紹一下音頻模塊AN831用到的音頻編/解碼芯片WM8731。該芯片在本設(shè)計(jì)中主要完成聲音信號(hào)在采集和回放過(guò)程中的A/D和D/A轉(zhuǎn)換功能。該芯片的ADC和DAC的采樣頻率為8KHz到96KHz可調(diào),可轉(zhuǎn)換的數(shù)據(jù)長(zhǎng)度為16-32位可調(diào)。WM8731的內(nèi)部有11個(gè)寄存器。該芯片的初始化以及工作時(shí)的工作狀態(tài)和功能都是通過(guò)以I2C總線方式對(duì)其內(nèi)部的這11個(gè)寄存器進(jìn)行相應(yīng)的配置來(lái)實(shí)現(xiàn)的。本設(shè)計(jì)中WM8731工作于主模式,采樣頻率設(shè)為48KHZ,轉(zhuǎn)換的數(shù)據(jù)位長(zhǎng)度為16位。WM8731的數(shù)字音頻接口有5根引腳,分別為:BCLK(數(shù)字音頻位時(shí)鐘)、DACDAT(DAC數(shù)字音頻數(shù)據(jù)輸入)、DACLRC(DAC采樣左/右聲道信號(hào))、ADCDAT(ADC數(shù)字音頻信號(hào)輸出)、ADCLRC(ADC采樣左/右聲道信號(hào))。在本設(shè)計(jì)中FPGA為從設(shè)備,WM8731為主設(shè)備。ADCDAT、DACDAT、ADCLRC和DACLRC與位時(shí)鐘BCLK同步,在每個(gè)BCLK的下降沿進(jìn)行一次數(shù)據(jù)傳輸。BCLK、DACDAT、DACLRC、ADCLRC為WM8731的輸入信號(hào)。ADCDAT為WM8731的輸出信號(hào)。
在本系統(tǒng)中FPAG和WM8731的控制和數(shù)據(jù)通信將用到I2C和數(shù)字音頻總線接口。FPGA通過(guò)I2C接口配置WM8731的寄存器,通過(guò)I2S總線接口來(lái)進(jìn)行音頻數(shù)據(jù)的通信。關(guān)于I2C接口,其他實(shí)驗(yàn)中已經(jīng)有講解,下面我們主要來(lái)了解數(shù)字音頻接口。
數(shù)字音頻接口可提供4種模式:
Left justified模式I2S模式Right justified模式DSP/PCM 模式(MODE A)DSP/PCM 模式(MODE B)
本實(shí)驗(yàn)選擇Right justified模式。
3. 程序設(shè)計(jì)
本實(shí)驗(yàn)的功能是程序檢測(cè)按鍵KEY2是否按下,如果檢測(cè)到KEY2按下了,開(kāi)始錄音,錄音的最長(zhǎng)時(shí)間為20秒;錄音結(jié)束后,開(kāi)始播放剛才錄下的音頻。本程序設(shè)計(jì)包含四大部分:SDRAM的讀寫(xiě)控制程序,音頻錄音和播放,按鍵檢測(cè)和系統(tǒng)控制。
lut_wm8731模塊將寄存器配置地址和配置信息通過(guò)查找表的形式通過(guò)I2C總線寫(xiě)入音頻模塊中,具體的請(qǐng)參考例程代碼和wm9731的芯片數(shù)據(jù)手冊(cè)。
audio_rx接收模塊,接收從麥克風(fēng)輸入的語(yǔ)音信號(hào),完成左右聲道的音頻接收,將串行數(shù)據(jù)轉(zhuǎn)換成并行數(shù)據(jù)。通過(guò)“Right justified”模式的時(shí)序圖可以看到接收語(yǔ)音信號(hào)時(shí)在LRC信號(hào)為高電平,且BCLK信號(hào)的上升沿時(shí)左聲道接收數(shù)據(jù)并完成串行信號(hào)轉(zhuǎn)換成并行信號(hào)的過(guò)程。在LRC信號(hào)為低電平,且BCLK 信號(hào)的上升沿時(shí)右聲道接收數(shù)據(jù)并完成串行信號(hào)轉(zhuǎn)換成并行信號(hào)的過(guò)程。
信號(hào)名稱 | 方向 | 說(shuō)明 |
clk | in | 時(shí)鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
sck_bclk | in | 數(shù)字音頻接口bit時(shí)鐘 |
ws_lrc | in | ADC采樣時(shí)鐘 |
sdata | in | 音頻數(shù)字接口串行數(shù)據(jù)輸入 |
left_data | out | 左聲道數(shù)據(jù) |
right_data | out | 右聲道數(shù)據(jù) |
data_valid | out | 音頻數(shù)據(jù)有效 |
audio_rx音頻接收模塊端口
audio_tx是音頻發(fā)送模塊,完成左右聲道音頻數(shù)據(jù)的串行化。同樣通過(guò)時(shí)序圖可以看到,語(yǔ)音信號(hào)完成模數(shù),數(shù)模轉(zhuǎn)換從SDRAM輸出后進(jìn)入發(fā)送模塊,在LRC信號(hào)上升沿,且即將跳變?yōu)楦唠娖綍r(shí)接收左聲道數(shù)據(jù),BCLK信號(hào)下降沿時(shí)完成緩存將并行信號(hào)轉(zhuǎn)換為串行信號(hào)的過(guò)程;在LRC信號(hào)上升沿且即將跳變?yōu)榈碗娖綍r(shí)接收右聲道數(shù)據(jù),在BCLK信號(hào)下降沿時(shí)完成緩存將并行信號(hào)轉(zhuǎn)換為串行信號(hào)的過(guò)程。
信號(hào)名稱 | 方向 | 說(shuō)明 |
clk | in | 時(shí)鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
sck_bclk | in | 數(shù)字音頻接口bit時(shí)鐘 |
ws_lrc | in | ADC采樣時(shí)鐘 |
sdata | out | 音頻數(shù)字接口串行數(shù)據(jù)輸入 |
left_data | in | 左聲道數(shù)據(jù) |
right_data | in | 右聲道數(shù)據(jù) |
read_data_en | out | 音頻數(shù)據(jù)讀取,提前一個(gè)采樣周期讀取 |
audio_tx音頻發(fā)送模塊端口
在模塊‘frame_read_write’中使用到了FIFO 的IP core,通過(guò)兩個(gè)FIFO分別作為DDR3控制器的讀寫(xiě)接口,避免復(fù)雜的DDR3時(shí)序。因?yàn)闀r(shí)鐘速率的不同,所使用的是異步FIFO。以write_buf寫(xiě)入模塊的FIFO為例在vivado中FIFO IP core設(shè)置如下:
-
打開(kāi)Tools菜單下的“IP Compiler”, 在彈出的界面下進(jìn)行如下設(shè)置,設(shè)置完成后點(diǎn)擊”Customize”:
-
在彈出的界面下進(jìn)行如下設(shè)置,設(shè)置完成后點(diǎn)擊保存后Generate即可生成IP:
-
接著在模塊中直接例化FIFO 的端口名就可以使用FIFO了,在read_buf中也是同樣的操作步驟。具體的參數(shù)設(shè)置和端口例化的信號(hào)連接參考例程。
frame_fifo_write模塊完成FIFO數(shù)據(jù)到外部存儲(chǔ)器的寫(xiě)入,如果FIFO接口是異步FIFO,可以完成寫(xiě)數(shù)據(jù)的跨時(shí)鐘域轉(zhuǎn)換。狀態(tài)機(jī)轉(zhuǎn)換圖如下,收到寫(xiě)數(shù)據(jù)請(qǐng)求后進(jìn)入應(yīng)答狀態(tài)“S_ACK”,如果寫(xiě)請(qǐng)求撤銷,則進(jìn)入檢測(cè)FIFO空間大小狀態(tài)“S_CHECK_FIFO”,檢查FIFO內(nèi)數(shù)據(jù)是否夠一次突發(fā)寫(xiě),如果有足夠多的數(shù)據(jù),進(jìn)入突發(fā)寫(xiě)存儲(chǔ)器狀態(tài)“S_WRITE_BURST”,突發(fā)寫(xiě)完成后進(jìn)入“S_WRITE_BURST_END”狀態(tài)。
frame_fifo_write模塊狀態(tài)機(jī)
信號(hào)名稱 | 方向 | 說(shuō)明 |
mem_clk | in | 外部存儲(chǔ)器用戶時(shí)鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
wr_burst_req | out | 對(duì)接存儲(chǔ)器控制器,寫(xiě)請(qǐng)求 |
wr_burst_len | out | 對(duì)接存儲(chǔ)器控制器,寫(xiě)請(qǐng)求長(zhǎng)度 |
wr_burst_addr | out | 對(duì)接存儲(chǔ)器控制器,寫(xiě)請(qǐng)求基地址 |
wr_burst_data_req | in | 對(duì)接存儲(chǔ)器控制器,寫(xiě)請(qǐng)求數(shù)據(jù)索取,提前一個(gè)時(shí)鐘周期發(fā)出,用于連接FIFO的讀數(shù)據(jù) |
wr_burst_finish | in | 對(duì)接存儲(chǔ)器控制器,寫(xiě)請(qǐng)求完整 |
write_req | in | 一幀(大量數(shù)據(jù))寫(xiě)開(kāi)始,收到應(yīng)答后必須撤銷請(qǐng)求,新的請(qǐng)求會(huì)中斷正在進(jìn)行的請(qǐng)求 |
write_req_ack | out | 一幀(大量數(shù)據(jù))寫(xiě)應(yīng)答 |
write_finish | out | 一幀(大量數(shù)據(jù))完成 |
write_addr_0 | in | 一幀(大量數(shù)據(jù))寫(xiě)基地址0 |
write_addr_1 | in | 一幀(大量數(shù)據(jù))寫(xiě)基地址1 |
write_addr_2 | in | 一幀(大量數(shù)據(jù))寫(xiě)基地址2 |
write_addr_3 | in | 一幀(大量數(shù)據(jù))寫(xiě)基地址3 |
write_addr_index | in | 一幀(大量數(shù)據(jù))寫(xiě)基地址選擇,0:write_addr_01:write_addr_12:write_addr_23:write_addr_3 |
write_len | in | 一幀(大量數(shù)據(jù))寫(xiě)長(zhǎng)度 |
fifo_aclr | out | 在收到寫(xiě)請(qǐng)求后,模塊會(huì)清空FIFO |
rdusedw | in | FIFO讀端的數(shù)據(jù)使用量 |
frame_fifo_write模塊端口
frame_fifo_read讀模塊完成從外部存儲(chǔ)器讀取數(shù)據(jù),然后寫(xiě)到FIFO,如果使用異步FIFO可以完成數(shù)據(jù)從存儲(chǔ)器時(shí)鐘域到其他時(shí)鐘域的轉(zhuǎn)換。狀態(tài)機(jī)轉(zhuǎn)換圖如下圖所示,收到讀請(qǐng)求以后進(jìn)入應(yīng)答狀態(tài)“S_ACK”,等待讀請(qǐng)求撤銷后應(yīng)答,進(jìn)入FIFO深度檢測(cè)狀態(tài)“S_CHECK_FIFO”,如果FIFO空間足夠一次突發(fā)讀,進(jìn)入突發(fā)讀狀態(tài)“S_READ_BURST”,突發(fā)讀結(jié)束后進(jìn)入“S_READ_BURST_END”。
frame_fifo_read模塊狀態(tài)機(jī)
信號(hào)名稱 | 方向 | 說(shuō)明 |
mem_clk | in | 外部存儲(chǔ)器用戶時(shí)鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
rd_burst_req | out | 對(duì)接存儲(chǔ)器控制器,讀請(qǐng)求 |
rd_burst_len | out | 對(duì)接存儲(chǔ)器控制器,讀請(qǐng)求長(zhǎng)度 |
rd_burst_addr | out | 對(duì)接存儲(chǔ)器控制器,讀請(qǐng)求基地址 |
rd_burst_data_valid | in | 對(duì)接存儲(chǔ)器控制器,讀請(qǐng)求數(shù)據(jù)有效 |
rd_burst_finish | in | 對(duì)接存儲(chǔ)器控制器,讀請(qǐng)求完全 |
read_req | in | 一幀數(shù)據(jù)讀開(kāi)始 |
read_req_ack | out | 一幀數(shù)據(jù)讀應(yīng)答 |
read_finish | out | 一幀數(shù)據(jù)讀完成 |
read_addr_0 | in | 一幀數(shù)據(jù)讀基地址0 |
read_addr_1 | in | 一幀數(shù)據(jù)讀基地址1 |
read_addr_2 | in | 一幀數(shù)據(jù)讀基地址2 |
read_addr_3 | in | 一幀數(shù)據(jù)讀基地址3 |
read_addr_index | in | 一幀數(shù)據(jù)讀基地址選擇0:read_addr_01:read_addr_12:read_addr_23:read_addr_3 |
read_len | in | 幀數(shù)據(jù)讀長(zhǎng)度 |
fifo_aclr | out | 外部FIFO異步復(fù)位 |
wrusedw | in | FIFO寫(xiě)端使用空間大小 |
frame_fifo_read模塊端口
audio_key模塊主要完成錄音播放的按鍵控制,狀態(tài)轉(zhuǎn)換如下,當(dāng)按鍵按下后進(jìn)入錄音狀態(tài),當(dāng)按鍵松開(kāi)時(shí)進(jìn)入播放狀態(tài)。
audio_key模塊狀態(tài)轉(zhuǎn)換圖
信號(hào)名稱 | 方向 | 說(shuō)明 |
clk | in | 時(shí)鐘輸入 |
rst | in | 異步復(fù)位輸入,高復(fù)位 |
key | in | 按鍵輸入 |
record | out | 錄音狀態(tài)指示 |
play | out | 播放狀態(tài)指示 |
write_req | out | 寫(xiě)數(shù)據(jù)開(kāi)始 |
write_req_ack | in | 寫(xiě)數(shù)據(jù)應(yīng)答 |
read_req | out | 讀數(shù)據(jù)開(kāi)始 |
read_req_ack | in | 讀數(shù)據(jù)應(yīng)答 |
frame_read_write模塊完成音頻幀數(shù)據(jù)讀寫(xiě)的封裝,這里使用了異步FIFO來(lái)解決跨時(shí)鐘問(wèn)題,例如FIFO 輸入寬度和輸出寬度的不同來(lái)完成數(shù)據(jù)位寬的轉(zhuǎn)換。
4. 實(shí)驗(yàn)現(xiàn)象
開(kāi)發(fā)板首先將音頻模塊插入擴(kuò)展口,同時(shí)插入麥克風(fēng)和耳機(jī),然后下載實(shí)驗(yàn)程序,按下KEY2不放,進(jìn)行錄音,松開(kāi)按鍵后可通過(guò)耳機(jī)回放錄音。
-
FPGA
+關(guān)注
關(guān)注
1630文章
21769瀏覽量
604648 -
電路
+關(guān)注
關(guān)注
172文章
5950瀏覽量
172588 -
音頻
+關(guān)注
關(guān)注
29文章
2891瀏覽量
81708 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
5093瀏覽量
97802 -
紫光同創(chuàng)
+關(guān)注
關(guān)注
5文章
88瀏覽量
27530
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論