ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 数据接收 ` `I2S(Inter—IC Sound)总线,是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,该总线专门用于音频设备之间的音频数据传输。I2S总线有三条数据信号线: ` `(1)BCLK:串行时钟,也叫位时钟,对应数字音频的每一位数据。 ` `(2)WS:字段(声道)选择,用于选择左右声道。为“0”表示正在传输的是左声道的数据, 为“1”表示正在传输的是右声道的数据。 ` `(3)SD:串行数据,用二进制补码来表示音频数据(数据传输从高位到低位)。 ` `BLK=2*采样频率*采样位数 ` `采样频率即WS的频率,采样位数即在WS的左右声道内采样的数据位数。 ` `常见的I2S音频传输有48K,44.1Khz和32Khz三种采样率。传输的音频数据位宽常见的有16,20和24三种。I2S传输的数据是声音的模拟信号经过AD采样数字化后的数据,所以数据位宽越宽,数据的采样精度就越高。下图是I2S传输的波形图,I2S在BCLK的下降沿发送数据(发送),在上升沿进行数据采样(接收)。每次是先发送最高位,最后发送最低位。MSB在WS变化的下一个时钟周期有效。因此,最高位拥有固定的位置,而最低位的位置则是依赖于数据的有效位数。也就使得接收端与发送端的有效位数可以不同。如果接收端能处理的有效位数少于发送端,可以放弃数据帧中多余的低位数据;如果接收端能处理的有效位数多于发送端,可以自行补足剩余的位(常补足为零)。 ` `I2S发送数据:发送是在每个时钟周期的下降沿发送数据,这样在WS沿变化开始后的第二个下降沿发送数据的最高位。接着在每个下降沿依次发送数据,直到发送完最低位。 I2S接收数据:在每个时钟周期的上升沿接收数据,在WS沿变化开始后的第二个上升沿接收数据的最高位。接着在每个位时钟上升沿依次接收数据,直到接收完最低位。 ![](https://img.kancloud.cn/7b/7d/7b7dc3a800e56eea69def2c481cc51e4_1091x193.png) verilog实现I2S数据接收,下面是一个24位宽的I2S音频数据接收模块。 ``` reg finish_flag;//完成一次数据转换标志 reg [5:0]R_cnt; reg [5:0]L_cnt; reg [31:0]ak5394_data_int; always@(negedge finish_flag) begin if(!rst_n)begin AD_DATA1_reg <= 24'd0; AD_DATA2_reg <= 24'd0; ak5394_data_int <= 32'd0; end else begin AD_DATA1_reg <= data1; AD_DATA2_reg <= data2; ak5394_data_int <= ddr_data1_int; end end always@(posedge SCLK) begin if(!rst_n)begin data1 <= 24'd0; data2 <= 24'd0; R_cnt <= 6'd0; L_cnt <= 6'd0; finish_flag <= 1'b0; end else begin //finish_flag <= 1'b0; if(LRCK == 1'b0)begin R_cnt <= 6'd0; if(L_cnt < 6'd25)begin L_cnt <= L_cnt + 1'b1; data1 <= {data1[22:0],SDATA}; end end else begin L_cnt <= 6'd0; if(R_cnt< 6'd25)begin R_cnt <= R_cnt + 1'b1; data2 <= {data2[22:0],SDATA}; end end if(R_cnt == 6'd24)begin finish_flag <= 1'b1; end else finish_flag <= 1'b0; end end ``` ## 数据扩展 ` `对于数据为24位的数据,为了方便处理,通常会将数据扩展为32位的int型数据。I2S的数据是补码格式,因此这就是补码扩展。 ` `如果8位二进制补码的最高位(符号位)为0,那么扩展后的16位补码直接在最高位前面添加8个0即可; ` `如果8位二进制补码的最高位(符号位)为1,那么扩展后的16位补码直接在最高位前面添加8个1即可; 举例如下: ` `-13 ` `8位原码:1000 1101 ` `8位补码:1111 0011 ` `16位原码:1000 0000 0000 1101 ` `16位补码:1111 1111 1111 0011 ` `根据前面的知识,由于-13的最高位为1,所以直接在最高位前面添加8个1即可变为16位补码,即1111 1111 1111 0011(与前面由原码求补码的结果一致)。 ` `13 ` `8位原码:0000 1101 ` `8位补码:0000 1101 ` `16位原码:0000 0000 0000 1101 ` `16位补码:0000 0000 0000 1101 ` `根据前面的知识,由于13的最高位为0,所以直接在最高位前面添加8个0即可变为16位补码,即0000 0000 0000 1101(与前面由原码求补码的结果一致)。