差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
book_excise_audio_if [2021/08/23 16:47]
zili
book_excise_audio_if [2021/08/23 16:57] (当前版本)
zili
行 25: 行 25:
  
 {{ :​图17-1.png |图17-1 UDA1341TS与FPGA连接方式}} {{ :​图17-1.png |图17-1 UDA1341TS与FPGA连接方式}}
 +<WRAP centeralign>​
 +**图17-1 UDA1341TS与FPGA连接方式**
 +</​WRAP>​
 +
 +#### 2.2 音频芯片UDA1341TS的基本工作流程
 +图 17 2为UDA1341TS的系统框图,在此仅介绍本实验中音频信号的流向。在本实验中从音频接口输入的信号从2和4引脚输入到UDA1341TS内部,注意的是因为音频是分左右声道的,所以需要2和4两个引脚,然后通过一个可供选择的6dB放大器输入到UDA1341TS内部的ADC1输入端。AD变换后的数字音频通过DIGITAL MIXER(数字混频器)和DECIMATION FILTER(数字滤波器)通过AUDIO_DO(也即是18引脚),连接到FPGA。
 +
 +FPGA通过AUDIO_DI(也即是19引脚)将上面输入的数字音频环回给UDA1341TS,该数字音频信号通过DSP FEATURES(数字信号处理)、INTERPOLOATION FILTER和NOISE SHAPER,最后到达UDA1341TS的DAC的输入端,完成最后的数字音频向模拟音频的转换,可以通过耳机听到该模拟音频。这中间数字信号处理模块可以完成很多特效功能,如去加重、低音增强等,可以通过设置UDA1341TS内部的DATA0寄存器来达到这些声音特效。
 +
 +{{ :​图17-2.png |图17-2 UDA1341TS系统框图}}
 +<WRAP centeralign>​
 +**图17-2 UDA1341TS系统框图**
 +</​WRAP>​
 +
 +#### 2.3 UDA1341TS的控制接口时序
 +FPGA和UDA1341TS之间的控制接口是L3接口, L3接口的时序如图 17 3所示。
 +{{ :​图17-3.png |图17-3 L3控制接口时序}}
 +<WRAP centeralign>​
 +**图17-3 L3控制接口时序**
 +</​WRAP>​
 +
 +L3接口的时序和I2C类似,也是先发送地址,然后发送要写入该地址的数据。L3通信协议多了一个L3MODE信号指示信号线,当L3MODE为低电平时,发送的为地址信号,当L3MODE为高时发送的是数据信号。
 +
 +UDA1341TS有direct addressing registers和extended addressing registers两种地址之分,direct addressing registers只需要一个8位主地址信号,而extended addressing registers不仅需要一个主地址信号,还需要一个子地址信号。
 +
 +direct addressing registers:
 +
 +在读写direct addressing registers时,只需要首先发送direct addressing registers的地址,然后即可发送要写入该寄存器的数据。该地址为8位,该8位地址信号的高6位为固定数值:000101,而通过低2位来选择具体需要设置的寄存器。UDA1341TS的寄存器有3个:DATA0、DATA1和STATUS。而direct addressing registers模式只针对寄存器STATUS。
 +
 +extended addressing registers:
 +
 +在控制extended addressing registers时,首先需要发送direct addressing registers的地址,然后发送extended addressing registers的地址,最后才是发送数据。该模式主要针对DATA0寄存器。
 +
 +具体操作就是在发送8位信号00010100后,还需要发送8位信号:11000xxx,其中3个x表示扩展子地址,最后在发送8位信号:111xxxxx,其中5个x表示需要向该扩展位写入的数据。具体操作如图 17 4所示。
 +
 +在发送direct addressing registers时,需要将L3MODE信号线拉低,而在发送子地址和发送数据时需要将L3MODE信号线拉高。
 +{{ :​图17-4.jpg |图17-4 extended addressing registers所需要的子地址及数据}}
 +<WRAP centeralign>​
 +**图17-4 extended addressing registers所需要的子地址及数据**
 +</​WRAP>​
 +
 +本实验中为了程序简单起见,将direct addressing registers和extended addressing registers两种地址模式归一化处理,对于direct addressing registers模式通过发送两次相同数据,使其工作方式和extended addressing registers相同。
  
-      
 \\ \\
 \\ \\
 ### 3. 程序设计 ### 3. 程序设计
 +#### 3.1 总体架构
 +整个程序基本由3个模块(图 17-5)组成:
 +1. Sound是顶层模块,将各子模块实例化并连接各模块。
 +2. L3_AUD_Control模块依次将24位宽的控制字传递给L3_Control模块。
 +3. L3_Control模块将L3_AUD_Control送来的24位宽的控制字转为L3接口时序对UDA1341TS进行配置。
 +4. Counter模块产生音频芯片所需要的AUDIO_WSEL和AUDIO_BCK。
 +5. PLL模块产生音频芯片需要的AUDIO_SYSCLK。
 +{{ :​图17-5.png |图17-5 L3控制接口时序}}
 +<WRAP centeralign>​
 +**图17-5 L3控制接口时序**
 +</​WRAP>​
  
 +#### 3.2 sound模块(sound.v)
 +sound模块是顶层模块,负责连接各子模块。在整个设计中最重要的就是各个时钟之间关系,也就是AUDIO_WSEL、AUDIO_BCLK和 AUDIO_SYSCLK之间的对应关系。
  
 +在介绍该三个时钟信号之间关系之前需要介绍一下声音采样频率fs的概念。在此fs选择为44.1kHz,44.1kHz的采样频率是很多音频标准中使用的采样频率,其源于著名的“乃奎斯特采样定理”。“乃奎斯特采样定理”指出,在模拟信号数字化过程中,如果保证取样频率大于模拟讯号最高频率的2倍,就能100%精确地再还原出原始的模拟信号。音频的最高频率为20kHz,所以取样率至少应该大于40kHz,为了留一点安全系数,再考虑到工程上的习惯,很多标准最终选择了44.1kHz这个值。
  
 +UDA1341TS的Datasheet中提到UDA1341TS的系统时钟AUDIO_SYSCLK可以可以通过设置STATUS寄存器的SC位选择是256fs、384fs,还是512fs。本实验中选择256fs,由于声音的采样频率为44.1Khz,所以UDA1341TS的系统时钟AUDIO_SYSCLK为11289.6Khz。该时钟是用FPGA内部的PLL(audio_pll模块)完成。
 +
 +对于时钟AUDIO_BCLK,其对应的主要是AD后的数字音频的比特率。如果采样频率为fs,而采样量化比特为16bit,同时因为分为左右声道,也就是一个采用量化点需要32比特,所以AUDIO_BCLK应该为32fs,那么AUDIO_BCLK可以通过对UDA1341TS的系统时钟AUDIO_SYSCLK进行32分频得到。
 +
 +对于AUDIO_WSEL信号,其用于I2S的左右声道选择,每一个采样点分为左右声道,也就是每个采样点为一个时钟周期,对应的AUDIO_WSEL的频率为fs,可以通过对AUDIO_SYSCLK进行256分频得到。严格意义上,采用触发器搭建的时钟有很大的抖动,但是对于低频信号影响不大。
 +
 +程序如下所示:
 +<code verilog> ​
 +
 +//​PLL产生时钟AUDIO_SYSCLK
 +audio_pll audio_pll_inst (.inclk0 ( CLOCK_50 ),.c0 ( AUDIO_SYSCLK ));
 +//​AUDIO_BCLK:AUDIO_SYSCLK 的8分频
 +assign AUDIO_BCLK = counter[2];
 +//​AUDIO_WSEL:AUDIO_SYSCLK的256分频
 +assign AUDIO_WSEL = counter[7];
 +reg [7:0] counter;
 +always@(posedge AUDIO_SYSCLK or negedge Reset) begin
 + if(!Reset) begin
 + counter <​= 0;​
 + end
 + else begin
 + counter <= counter + 1;
 + end
 +end
 +
 +</​code>​
 +
 +#### 3.3 L3_AUD_Control模块(L3_AUD_Control.v)
 +L3_AUD_Control模块依次将24位宽的控制字传递给L3_Control模块。L3接口中的L3CLOCK的频率无特殊的要求,未要求和UDA1341TS的系统时钟AUDIO_SYSCLK成为分频或者同步关系,是完全独立的时钟。
 +
 +L3_AUD_Control模块接口为:
 +<code verilog> ​
 +
 +  iReset_n, ​ //​异步复位
 +     ​iClk, ​     // AUDIO_SYSCLK时钟的256分频所得
 +     ​oL3_mode, ​ //​地址还是数据选择信号
 +     ​oL3_clk, ​   //​L3时钟信号
 +     ​oL3_data ​   //​L3数据信号
 +其核心程序为:
 +parameter L3_size = 9;
 +always@(posedge iClk or negedge iReset_n)
 +begin
 + if(!iReset_n)
 + begin
 + L3_index <= 0;//​当前发送24位宽的控制字的序号
 + start <= 1; //​控制L3_Control模块开始发送一个24位宽的数据
 + end
 + else
 + begin
 + if(mEnd == 1'b1) //​mEnd为L3_Control模块返回的24位宽数据通过
 + //​串行L3模块发送完成指示信号,收到该指示信号后,
 + //​L3_index加一,发送下一个24位宽的控制字
 + begin
 + if(L3_index<​=L3_size)
 + begin
 + L3_index <= L3_index + 1;
 + start <= 1;
 + end
 + else
 + begin
 + L3_index <= L3_index;
 + start <= 0;
 + end
 + end
 + end
 +endalways@(L3_index) begin
 + case(L3_index)
 + 0:iData = {8'​b00100001,​8'​b00100001,​6'​b000101,​2'​b10};//​设置status寄存器使
 +//​UDA1341TS得工作时钟为:256fs
 + 1:iData = {8'​b11100011,​8'​b11100011,​6'​b000101,​2'​b10};//​设置status寄存器使
 +//​UDA1341TS的ADC:​on ​ DAC:on
 + 2:iData = {8'​b00000000,​8'​b00000000,​6'​b000101,​2'​b00};//​通过设置data0寄存器
 +//​设置音量寄存器:Volume control
 + 3:iData = {8'​b10_100000,​8'​b10_100000,​6'​b000101,​2'​b00};//​输入信号选择信号
 + 4:iData = {8'​b111_00000,​8'​b11000_000,​6'​b000101,​2'​b00};//​DATAGITAL MIXER处:
 +//Channel 1输入的增益
 + 5:iData = {8'​b111_00000,​8'​b11000_001,​6'​b000101,​2'​b00};//​DATAGITAL MIXER处:
 +//Channel 2输入的增益
 +
 + 6:iData = {8'​b111_00001,​8'​b11000_010,​6'​b000101,​2'​b00};//​选择输入信号input ​
 +//channel 1:​on;input channel 2:off
 + 7:iData = {8'​b111_10010,​8'​b11000_100,​6'​b000101,​2'​b00};//​设置data0使输入端的
 +//AGC开启
 + 8:iData = {8'​b111_00001,​8'​b11000_101,​6'​b000101,​2'​b00};//​data0 channel 1 gain
 + 9:iData = {8'​b111_00000,​8'​b11000_110,​6'​b000101,​2'​b00};//​设置输出自动增益开启
 + default:​iData = 24'h0;
 + endcase
 +end
 +
 +</​code>​
 +
 +L3_Control模块将L3_AUD_Control模块传递过来的24位宽的数据发送完成后,将返回一个mEnd,则L3_AUD_Control模块根据该信号使L3_index加一,以发送下一个24位宽数据,直至将待设置数据发送完。
 +
 +#### 3.4 L3 _Control模块(L3 _Control.v)
 +L3_Control模块将L3_AUD_Control传递过来的24位宽的数据严格按照图 17 3所示的时序对UDA1341TS进行配置。其接口为:
 +<code verilog> ​
 +
 + ​iReset_n,​ //​异步复位
 +    iClk,    //​AUDIO_SYSCLK时钟的256分频所得 ​     ​
 +iData, ​ //​L3_AUD_Control传递过来的24位宽的数据
 +iStart, ​   // L3_AUD_Control传递过来的24位宽的数据开始传输信号
 +oEnd,    // L3 _Control传递给L3_AUD_Control的24位宽的数据传输完毕信号
 +oL3_mode, //​地址还是数据选择信号
 +oL3_clk, //​L3时钟信号
 +oL3_data //​L3数据信号
 + 程序如下:
 +reg [5:0] counter;
 +always@(posedge iClk or negedge iReset_n) begin
 +    if(!iReset_n)
 +    begin
 +        counter<​=0; ​ //​计数器counter作为状态机控制L3接口的时序,一次操作大概需要53个L3接口周期。
 +    end
 +    else begin
 +       ​if(counter<​53) ​ begin
 +           ​ counter <= counter + 1;
 +          end
 +       ​ else begin
 +            counter <= 0;           
 +       ​ end ​             ​
 +    end
 +end
 +
 +//按照图 17 3所示时序产生相应的L3接口时序
 +always@(posedge iClk or negedge iReset_n ) begin
 + if( !iReset_n ) begin
 + oEnd <= 0;
 + oL3_data <= 1;
 + oL3_clk <= 1;
 + end
 + else begin
 + oEnd <= 0;
 + if( iStart ) begin 
 + case(counter)
 + //​counter从0~19送出地址。
 + 0:begin oL3_clk<​=1;​ oL3_mode<​=1;​ end
 + 1:begin oL3_clk<​=1;​ oL3_mode<​=0;​ end
 + 2:begin oL3_clk<​=0;​ oL3_data <= iData[0]; ​ end
 + 3:begin oL3_clk<​=1; ​ end
 + 4:begin oL3_clk<​=0; ​ oL3_data <= iData[1]; end
 + 5:begin oL3_clk<​=1; ​ end
 + 6:begin oL3_clk<​=0; ​ oL3_data <= iData[2]; end
 + 7:begin oL3_clk<​=1; ​ end
 + 8:begin oL3_clk<​=0; ​ oL3_data <= iData[3]; end
 + 9:begin oL3_clk<​=1; ​ end
 + 10:​begin oL3_clk<​=0;​ oL3_data <= iData[4]; end
 + 11:​begin oL3_clk<​=1;​ end
 + 12:​begin oL3_clk<​=0;​ oL3_data <= iData[5]; end
 + 13:​begin oL3_clk<​=1;​ end
 + 14:​begin oL3_clk<​=0;​ oL3_data <= iData[6]; end
 + 15:​begin oL3_clk<​=1;​ end
 + 16:​begin oL3_clk<​=0;​ oL3_data <= iData[7]; end
 + 17:​begin oL3_clk<​=1;​ end
 +
 + 18:​begin oL3_clk<​=1;​ oL3_mode<​=1;​ end
 + 19:​begin oL3_clk<​=1;​ end
 + //​counter从20到37送出数据或者子地址。
 + 20:​begin oL3_clk<​=0;​ oL3_data <= iData[8]; ​ end
 + 21:​begin oL3_clk<​=1;​ end
 + 22:​begin oL3_clk<​=0;​ oL3_data <= iData[9]; ​ end
 + 23:​begin oL3_clk<​=1; ​ end
 + 24:​begin oL3_clk<​=0; ​ oL3_data <= iData[10]; end
 + 25:​begin oL3_clk<​=1; ​ end
 + 26:​begin oL3_clk<​=0; ​ oL3_data <= iData[11]; end
 + 27:​begin oL3_clk<​=1; ​ end
 + 28:​begin oL3_clk<​=0; ​ oL3_data <= iData[12]; end
 + 29:​begin oL3_clk<​=1; ​ end
 + 30:​begin oL3_clk<​=0; ​ oL3_data <= iData[13];​end
 + 31:​begin oL3_clk<​=1; ​ end
 + 32:​begin oL3_clk<​=0; ​ oL3_data <= iData[14];​end
 + 33:​begin oL3_clk<​=1; ​ end
 + 34:​begin oL3_clk<​=0; ​ oL3_data <= iData[15];​end
 +
 + 35:​begin oL3_clk<​=1; ​ end
 + 36:​begin oL3_clk<​=1; ​ oL3_mode<​=0;​ end
 + 37:​begin oL3_clk<​=1; ​ oL3_mode<​=1;​ end
 +
 + ////​counter从28到53送出数据。
 + 38:​begin oL3_clk<​=0;​ oL3_data <= iData[16];​end
 + 39:​begin oL3_clk<​=1;​ end
 + 40:​begin oL3_clk<​=0;​ oL3_data <= iData[17];​end
 + 41:​begin oL3_clk<​=1; ​ end
 + 42:​begin oL3_clk<​=0; ​ oL3_data <= iData[18];​end
 + 43:​begin oL3_clk<​=1; ​ end
 + 44:​begin oL3_clk<​=0; ​ oL3_data <= iData[19];​end
 + 45:​begin oL3_clk<​=1; ​ end
 + 46:​begin oL3_clk<​=0;​ oL3_data <= iData[20]; end
 + 47:​begin oL3_clk<​=1; ​ end
 + 48:​begin oL3_clk<​=0;​ oL3_data <= iData[21]; end
 + 49:​begin oL3_clk<​=1; ​ end
 + 50:​begin oL3_clk<​=0; ​ oL3_data <= iData[22];​end
 + 51:​begin oL3_clk<​=1; ​ end
 + 52:​begin oL3_clk<​=0; ​ oL3_data <= iData[23];​end
 +//​通知L3_AUD_Control模块发送下一个24位宽数据
 + 53:​begin oL3_clk<​=1; ​ oEnd <= 1; oL3_data <= 1; end
 + default:​begin oL3_clk<​=1;​ oL3_mode<​=1;​ oL3_data <= 1; end        ​
 + endcase
 + end
 + end
 +end
 +
 +</​code>​
  
 \\ \\
 \\ \\
-### 4. 仿真结果+### 4. 运行结果 
 +通过signaltap看到程序的内部时序如图 17-6所示。 
 +{{ :​图17-6.jpg |图17-6 L3运行结果}} 
 +<WRAP centeralign>​ 
 +**图17-6 L3运行结果** 
 +</​WRAP>​
  
 +可以看出,L3_MODE拉低的第一个周期内,接口发送的数据为:{6'​b000101,​2'​b00},而在连续两个的L3_MODE拉高的周期内发送的的数据分别为:8'​b111_00000,​8'​b11000_000。注意两点,第一,程序L3接口是数据低位先发送,第二,数据上升沿有效。从运行结果可以看出L3_MODE、L3_CLK和L3_DATA完全符合图3所示标准。
 +{{ :​图17-7.png |图17-7 I2S运行结果}}
 +<WRAP centeralign>​
 +**图17-7 I2S运行结果**
 +</​WRAP>​
  
 +图17-7所示为I2S音频时序,其中WSEL为左右声道选择信号,符合i2s数字音频接口标准定义。
  
 \\ \\
行 44: 行 311:
 ### 5. 演示程序文件说明 ### 5. 演示程序文件说明
  
- +|文件名|功能| 
- +|sound.v|顶层模块。| 
 +|L3_AUD_Contro.v|依次将24位宽的控制字传递给L3_Control模块。| 
 +|L3 _Contro.v|产生L3接口时序。|
  
 \\ \\
 \\ \\
 ### 6. 演示程序使用 ### 6. 演示程序使用
 +演示设备:核心板、扩展板、音频播放设备、音箱或耳机。
 +
 +演示方法:将音频播放设备的音频输出连接到开发板的J4接口上,同时将音箱或耳机线连到开发板上的音频输出接口J5上。把程序下载到开发板上之后,通过耳机就可以听到音频播放设备播放的音频。