精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用FPGA播放音頻文件

OpenFPGA ? 來源:OpenFPGA ? 2024-01-17 09:26 ? 次閱讀

9b3d3e8c-b4d0-11ee-8b88-92fbcf53809c.png

讓我們看一下I2S規范,并嘗試用FPGA播放音頻文件。

開篇第一步

Inter-IC Sound Interface(簡稱I2S)是由飛利浦公司開發,用于通過不同IC之間的串行接口(例如從處理器DAC)傳輸數字音頻數據。該接口使用以下信號進行數據傳輸:

SCK (串行時鐘)——用于數據傳輸的時鐘。

SD (串行數據)- 每個數據字的各個位通過該線傳輸。

WS (字選擇)- 定義傳輸數據字的長度。它用于標記右或左音頻通道。

僅音頻數據通過 I2S 傳輸。附加數據(例如各個總線用戶的配置)通過其他接口傳輸。數據傳輸總是在兩個總線之間沿一個方向進行,其中一路總線必須充當主機并負責生成時鐘信號。在由多個發送器和接收器組成的復雜系統中,時鐘信號由外部總線主控器生成,并且相應的發送器生成數據。

9b4c1128-b4d0-11ee-8b88-92fbcf53809c.png

所有數據均以二進制補碼和 MSB 優先的方式傳輸。如果接收方和發送方的字寬存在正差(即一方的字寬小于另一方的字寬),則剩余位填充0。根據規范,數據可以同步于正時鐘沿或負時鐘沿,從而數據總是在負時鐘沿讀入。

WS信號選擇活動通道,并將低或高相位內的所有數據分配給相應的通道:

WS = 0 – 通道 1(左)

WS = 1 – 通道 2(右)

?WS信號必須在下一個數據字的 MSB 之前的一個時鐘周期發生變化,以便接收器可以將數據讀入正確的通道。WS信號的時鐘頻率通常對應于音頻信號的采樣頻率。

9b593894-b4d0-11ee-8b88-92fbcf53809c.png

在這篇文章中,展示如何設計一個簡單的 I2S 發射器,并使用 CS4344 立體聲 D/A 轉換器通過揚聲器輸出恒定的聲音。

要輸出的聲音將存儲在 FPGA 的block memory中,并由發送器讀出,并將數據發送到 D/A 轉換器。整個項目分為三個部分,將逐步討論:

集成系統時鐘和I2S模塊的Top設計

集成ROM和I2S發送器的I2S模塊

I2S發送器

I2S發送器

設計的最底層應該是 I2S 發送器,其任務是通過 I2S 接口發送各個數據字。

9b739d56-b4d0-11ee-8b88-92fbcf53809c.png

該框圖產生了以下發送器:

entityI2S_Transmitteris
Generic(WIDTH:INTEGER:=16
);
Port(Clock:inSTD_LOGIC;
nReset:inSTD_LOGIC;
Ready:outSTD_LOGIC;
Tx:inSTD_LOGIC_VECTOR(((2*WIDTH)-1)downto0);
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC
);
endI2S_Transmitter;

數據字的大小通過WIDTH參數定義。

三級狀態機控制發送器,描述如下:

architectureI2S_Transmitter_ArchofI2S_Transmitteris

typeState_tis(State_Reset,State_LoadWord,State_TransmitWord);

signalCurrentState:State_t:=State_Reset;

signalTx_Int:STD_LOGIC_VECTOR(((2*WIDTH)-1)downto0):=(others=>'0');
signalReady_Int:STD_LOGIC:='0';
signalLRCLK_Int:STD_LOGIC:='1';
signalSD_Int:STD_LOGIC:='0';
signalEnable:STD_LOGIC:='0';

begin

process
variableBitCounter:INTEGER:=0;
begin
waituntilfalling_edge(Clock);

caseCurrentStateis
whenState_Reset=>
Ready_Int<=?'0';
????????????????LRCLK_Int?<=?'1';
????????????????Enable?<=?'1';
????????????????SD_Int?<=?'0';
????????????????Tx_Int?<=?(others?=>'0');
CurrentState<=?State_LoadWord;
????????????when?State_LoadWord?=>
BitCounter:=0;
Tx_Int<=?Tx;
????????????????LRCLK_Int?<=?'0';
????????????????CurrentState?<=?State_TransmitWord;
????????????when?State_TransmitWord?=>
BitCounter:=BitCounter+1;
if(BitCounter>(WIDTH-1))then
LRCLK_Int<=?'1';
????????????????end?if;
????????????????if(BitCounter?

復位期間,輸出信號被置位,SCLK時鐘被停用。復位后,機器從State_Reset狀態變為State_TransmitWord狀態。在此狀態下,機器Tx_Int通過 I2S 接口傳輸緩沖區的內容。

一旦開始傳輸最后一個數據位,Ready就設置為表示傳輸結束并準備好接受新數據。然后機器更改為 stateState_LoadWord狀態,其中發送緩沖區填充有新的數據字并開始新的傳輸。

I2S模塊

I2S 模塊使用 I2S 發送器將數據從 ROM 傳輸到 D/A 轉換器。

9b7cc9c6-b4d0-11ee-8b88-92fbcf53809c.png

具有以下代碼:

entityI2Sis
Generic(RATIO:INTEGER:=8;
WIDTH:INTEGER:=16
);
Port(MCLK:inSTD_LOGIC;
nReset:inSTD_LOGIC;
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC
);
endI2S;

參數RATIO 定義了SCLK與MCLK WIDTH的比率以及每個通道的數據字的寬度。

除了 I2S 發送器之外,該模塊還使用 ROM,該 ROM 可以通過block memory生成器創建并填充數據。兩者都可以使用 Vivado 的 IP 來完成。

9b875b48-b4d0-11ee-8b88-92fbcf53809c.png

最后,通過其他選項使用正弦信號 coe 文件(參見附件)對 ROM 進行初始化。

I2S 模塊使用狀態機從 ROM 讀取數據并將其傳輸到 I2S 發送器。

architectureI2S_ArchofI2Sis

typeState_tis(State_Reset,State_WaitForReady,State_IncreaseAddress,State_WaitForStart);

signalCurrentState:State_t:=State_Reset;

signalTx:STD_LOGIC_VECTOR(((2*WIDTH)-1)downto0):=(others=>'0');
signalROM_Data:STD_LOGIC_VECTOR((WIDTH-1)downto0):=(others=>'0');
signalROM_Address:STD_LOGIC_VECTOR(6downto0):=(others=>'0');

signalReady:STD_LOGIC;
signalSCLK_Int:STD_LOGIC:='0';

componentI2S_Transmitteris
Generic(WIDTH:INTEGER:=16
);
Port(Clock:inSTD_LOGIC;
nReset:inSTD_LOGIC;
Ready:outSTD_LOGIC;
Tx:inSTD_LOGIC_VECTOR(((2*WIDTH)-1)downto0);
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC
);
endcomponent;

componentSineROMis
Port(Address:inSTD_LOGIC_VECTOR(6downto0);
Clock:inSTD_LOGIC;
DataOut:outSTD_LOGIC_VECTOR(15downto0)
);
endcomponentSineROM;

begin

Transmitter:I2S_Transmittergenericmap(WIDTH=>WIDTH
)
portmap(Clock=>SCLK_Int,
nReset=>nReset,
Ready=>Ready,
Tx=>Tx,
LRCLK=>LRCLK,
SCLK=>SCLK,
SD=>SD
);

ROM:SineROMportmap(Clock=>MCLK,
Address=>ROM_Address,
DataOut=>ROM_Data
);

process
variableCounter:INTEGER:=0;
begin
waituntilrising_edge(MCLK);
if(Counter
WordCounter:=0;
CurrentState<=?State_WaitForReady;
????????????when?State_WaitForReady?=>
if(Ready='1')then
CurrentState<=?State_WaitForStart;
????????????????else
????????????????????CurrentState?<=?State_WaitForReady;
????????????????end?if;
????????????when?State_WaitForStart?=>
ROM_Address<=?STD_LOGIC_VECTOR(to_unsigned(WordCounter,?ROM_Address'length));
????????????????Tx?<=?x"0000"?&?ROM_Data;
????????????????if(Ready?=?'0')?then
????????????????????CurrentState?<=?State_IncreaseAddress;
????????????????else
????????????????????CurrentState?<=?State_WaitForStart;
????????????????end?if;
????????????when?State_IncreaseAddress?=>
if(WordCounter

第一個過程用于從MCLK生成發送器所需的時鐘信號SCLK 。

process
variableCounter:INTEGER:=0;
begin
waituntilrising_edge(MCLK);
if(Counter

第二個進程負責狀態機的處理。離開State_Reset狀態后,機器在該State_WaitForReady狀態下等待,直到發送器發出就緒信號Ready 。??

一旦發送器準備就緒,機器就會更改State_WaitForStart狀態。在此狀態下,從 ROM 讀取當前數據字并將其傳輸到發送器。

PS:此處顯示的 ROM 僅包含一個通道的信息。第二個通道的數據需進行擴展。

一旦發送器清除就緒信號并開始發送數據,狀態機就會更改為State_IncreaseAddress狀態。該狀態下ROM地址加1,然后切換回State_WaitForReady狀態

top模塊

最后一個組件是頂層設計,包括 I2S 模塊和時鐘PLL。

本示例使用以下參數來控制 CS4344:

MCLK:12.288MHz

SCLK:1.536 MHz

LRCLK:48kHz

比率:8

寬度:16

時鐘PLL生成 12.288 MHz 時鐘,并與之前代碼中完成的 I2S 模塊一起實例化。

9b96a652-b4d0-11ee-8b88-92fbcf53809c.png

entityTopis
Generic(RATIO:INTEGER:=8;
WIDTH:INTEGER:=16
);
Port(Clock:inSTD_LOGIC;
nReset:inSTD_LOGIC;
MCLK:outSTD_LOGIC;
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC;
LED:outSTD_LOGIC_VECTOR(3downto0)
);
endTop;

architectureTop_ArchofTopis

signalnSystemReset:STD_LOGIC:='0';
signalMCLK_DCM:STD_LOGIC:='0';
signalLocked:STD_LOGIC:='0';

componentI2Sis
Generic(RATIO:INTEGER:=8;
WIDTH:INTEGER:=16
);
Port(MCLK:inSTD_LOGIC;
nReset:inSTD_LOGIC;
LRCLK:outSTD_LOGIC;
SCLK:outSTD_LOGIC;
SD:outSTD_LOGIC
);
endcomponent;

componentAudioClockis
Port(ClockIn:inSTD_LOGIC;
Locked:outSTD_LOGIC;
MCLK:outSTD_LOGIC;
nReset:inSTD_LOGIC
);
endcomponent;

begin

InputClock:AudioClockportmap(ClockIn=>Clock,
nReset=>nReset,
MCLK=>MCLK_DCM,
Locked=>Locked
);

I2S_Module:I2Sgenericmap(RATIO=>RATIO,
WIDTH=>WIDTH
)
portmap(MCLK=>MCLK_DCM,
nReset=>nSystemReset,
LRCLK=>LRCLK,
SCLK=>SCLK,
SD=>SD
);

nSystemReset<=?nReset?and?Locked;
????LED(0)?<=?nReset;
????LED(1)?<=?Locked;
????LED(2)?<=?nSystemReset;
????MCLK?<=?MCLK_DCM;

end?Top_Arch;

最后就可以進行測試。理想情況下,D/A 轉換器輸出 480 Hz 正弦信號。因為來自 ROM 的信號模式的長度為 100 個樣本,采樣頻率為 48 kHz。可以用示波器檢查總線和信號:

9ba75fd8-b4d0-11ee-8b88-92fbcf53809c.png

此外,還可以檢查音頻信號(示波器的 FFT 功能是實現此目的的最佳工具)。

9bb38236-b4d0-11ee-8b88-92fbcf53809c.png

附件-Coe

memory_initialization_radix=16;
memory_initialization_vector=
0000,
0809,
100A,
17FB,
1FD4,
278D,
2F1E,
367F,
3DA9,
4495,
4B3B,
5196,
579E,
5D4E,
629F,
678D,
6C12,
7029,
73D0,
7701,
79BB,
7BF9,
7DBA,
7EFC,
7FBE,
7FFF,
7FBE,
7EFC,
7DBA,
7BF9,
79BB,
7701,
73D0,
7029,
6C12,
678D,
629F,
5D4E,
579E,
5196,
4B3B,
4495,
3DA9,
367F,
2F1E,
278D,
1FD4,
17FB,
100A,
0809,
0000,
F7F7,
EFF6,
E805,
E02C,
D873,
D0E2,
C981,
C257,
BB6B,
B4C5,
AE6A,
A862,
A2B2,
9D61,
9873,
93EE,
8FD7,
8C30,
88FF,
8645,
8407,
8246,
8104,
8042,
8001,
8042,
8104,
8246,
8407,
8645,
88FF,
8C30,
8FD7,
93EE,
9873,
9D61,
A2B2,
A862,
AE6A,
B4C5,
BB6B,
C257,
C981,
D0E2,
D873,
E02C,
E805,
EFF6,
F7F7,

下一篇文章,將向 I2S 發送器添加 AXI-Stream 接口,并將其與 ZYNQ 的處理系統連接,播放 SD 卡中的音頻文件。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    18927

    瀏覽量

    227254
  • FPGA
    +關注

    關注

    1620

    文章

    21510

    瀏覽量

    598994
  • 接口
    +關注

    關注

    33

    文章

    8257

    瀏覽量

    149976
  • 音頻
    +關注

    關注

    29

    文章

    2766

    瀏覽量

    80790

原文標題:使用 FPGA 播放音頻(一)

文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    請問如何使用PSoC4播放音頻文件

    如何使用 PSoC4 播放音頻文件
    發表于 07-02 07:19

    音頻文件(WAV)特技播放的原理及實現

    本帖最后由 eehome 于 2013-1-5 10:08 編輯 音頻文件播放是開發多媒體軟件中的一個重要內容,但有時需要對它進行特技播放,如快速播放,慢速
    發表于 03-12 00:42

    LabVIEW 播放音頻文件-

    LabVIEW 播放音頻文件-
    發表于 01-20 17:30

    labview 數組轉換成數組波形并寫入音頻文件重新播放

    我先對一個音頻文件進行處理 將左右聲道的波形分別進行量化編碼調制解調解碼了 請問 各位大神解碼后 如果我想把一個數組轉換回數組波形 并寫入一個音頻文件 重新播放 怎么實現?
    發表于 05-12 20:30

    FPGA+VS1003+flash方案,播放音頻文件耳機沒有任何聲音

    大家好,公司項目采用的是FPGA+VS1003+flash方案,flash用于保存音頻文件。目前播放遇到問題了,描述如下:首先我確認了以下幾點:1.首先是硬件方面,目前已經完成了寄存器配置的測試
    發表于 01-16 23:10

    5509A播放音頻文件感覺全是雜音

    我將音頻文件放到SD卡中,用DSP5509A將其讀取出來,并發送給AIC23,但是播放出來的音樂感覺全是雜音,請問是對AIC23的配置不對嗎?我放在SD卡中的文件是MP3文件,比特率是
    發表于 02-12 11:41

    Matlab處理音頻文件

    文章目錄Matlab處理音頻文件DAC播放DAC配置Tim配置開始應用層數據流向Matlab處理音頻文件Audio_filename = 'Audio.wav';% 獲取原音頻數據[A
    發表于 08-17 06:36

    如何用STM32F103xx單片機通過外部I2S音頻編解碼器來播放音頻文件

    如何用高密度STM32F103xx單片機通過外部 I2S音頻編解碼器來播放音頻文件,本手冊僅適用于STM32F103系列,可以實現音頻播放功能
    發表于 12-01 07:42

    103xx通過外部I2S音頻解碼器播放音頻文件

    103xx通過外部I2S音頻解碼器播放音頻文件
    發表于 01-12 18:26 ?54次下載

    基于ESP32構建的音頻播放

    在這里,我們將使用LM386 和一個帶有 ESP32 的揚聲器來播放音樂文件音頻輸出可能不大,但此應用程序顯示了 ESP32 板播放音頻文件的能力。
    發表于 08-08 15:37 ?2.2w次閱讀
    基于ESP32構建的<b class='flag-5'>音頻</b><b class='flag-5'>播放</b>器

    AN4309_將STM32L1xx微控制器與外部I2S音頻編解碼器連接起來播放音頻文件

    AN4309_將STM32L1xx微控制器與外部I2S音頻編解碼器連接起來播放音頻文件
    發表于 11-21 08:11 ?0次下載
    AN4309_將STM32L1xx微控制器與外部I2S<b class='flag-5'>音頻</b>編解碼器連接起來<b class='flag-5'>播放音頻文件</b>

    AN2739 如何用高密度STM32F103xx單片機來播放音頻文件

    AN2739 如何用高密度STM32F103xx單片機來播放音頻文件
    發表于 11-24 08:30 ?4次下載
    AN2739 如何用高密度STM32F103xx單片機來<b class='flag-5'>播放音頻文件</b>

    在Arduino中播放音頻

    電子發燒友網站提供《在Arduino中播放音頻.zip》資料免費下載
    發表于 06-25 15:16 ?0次下載
    在Arduino中<b class='flag-5'>播放音頻</b>

    使用STM32L1xx微控制器與外部I2S音頻編解碼器播放音頻文件

    電子發燒友網站提供《使用STM32L1xx微控制器與外部I2S音頻編解碼器播放音頻文件.pdf》資料免費下載
    發表于 09-21 11:30 ?2次下載
    使用STM32L1xx微控制器與外部I2S<b class='flag-5'>音頻</b>編解碼器<b class='flag-5'>播放音頻文件</b>

    如何使用音頻接口播放音頻文件

    ZDP1440是一款基于開源GUI引擎的圖像顯示專用驅動芯片,內部集成16MB顯示內存、2D圖形加速器、音頻解碼器等豐富多媒體功能,本文將介紹如何使用音頻接口播放音頻文件
    的頭像 發表于 08-06 16:12 ?305次閱讀
    如何使用<b class='flag-5'>音頻</b>接口<b class='flag-5'>播放音頻文件</b>