FPGA设计标准I2S协议音频编解码器

FPGA设计标准I2S协议音频编解码器

  • --I2S基本介绍
  • --I2S采样和处理过程
  • --I2S协议规范
  • --FPGA设计标准I2S音频编解码器

–I2S基本介绍

I2S(Inter-IC Sound)是飞利浦公司针对数字音频设备(如CD播放器、数码音效处理器、数字电视音响系统)之间的音频数据传输而制定的一种总线标准。它采用了独立的导线传输时钟与数据信号的设计,通过将数据和时钟信号分离,避免了因时差诱发的失真,为用户节省了购买抵抗音频抖动的专业设备的费用。

–I2S采样和处理过程

模拟信号–>音频codec芯片–>I2S数字信号(音频ADC转换过程)
I2S数字信号–>音频codec芯片–>模拟信号(音频DAC转换过程)
FPGA设计标准I2S协议音频编解码器_第1张图片备注:音频codec芯片需要进行相关寄存器配置才能工作。相关配置资料可以查看芯片手册。

–I2S协议规范

I2S有3个主要信号

  • 1.串行时钟SCLK,也叫位时钟(BCLK),即对应数字音频的每一位数据,SCLK都有1个脉冲。SCLK的频率=2×采样频率×采样位数。
  • 2.帧时钟LRCK,(也称WS),用于切换左右声道的数据。LRCK为“1”表示正在传输的是右声道的数据,为“0”则表示正在传输的是左声道的数据。LRCK的频率等于采样频率。
  • 3.串行数据SDATA,由于音频数据有正负之分,故而用二进制补码表示的音频数据。

有时为了使系统间能够更好地同步,还需要另外传输一个信号MCLK,称为主时钟,也叫系统时钟(Sys Clock),是采样频率的256倍或384倍。

随着技术的发展,在统一的 I2S接口下,出现了多种不同的数据格式。根据SDATA数据相对于LRCK和SCLK的位置不同,分为左对齐(较少使用)、I2S格式(即飞利浦规定的格式)和右对齐(也叫日本格式、普通格式)。
FPGA设计标准I2S协议音频编解码器_第2张图片FPGA设计标准I2S协议音频编解码器_第3张图片

–FPGA设计标准I2S音频编解码器

代码已经在Cyclone ® IV EP4CE6 Device硬件平台测试OK.
音频解码器代码如下,欢迎各位学友共同探讨

在这里插入代码片
 module i2s_decoder_slave#(
parameter DATA_WIDTH = 32
)
(
input sys_clk_i,
input audio_clk_i,
input rstn_i,
//
output reg [DATA_WIDTH-1:0] audio_data_o, //hi:left lw:right
output reg audio_den_o,
//
input i2s_din_i,
output reg i2s_mclk_o,
input i2s_lrclk_i,
input i2s_bclk_i
);
////////////////////////////////////////////////////////////////////////////////////////
//ʱ��ʱ 49.152M������ʱ��Ϊ fs=48khz��mclk=256fs=12.288M,bclk=mclk/4,ʱ��Ϊ mclk �� 4�����ʴ˴�Ϊ 16
localparam BCLK_PER_NUM = 16;
localparam LRCLK_BCLK_RATE = 64;
localparam I2S_EMPTY_WIDTH = LRCLK_BCLK_RATE/2 - DATA_WIDTH/2;
reg [1:0] mclk_cntr;
reg [3:0] i2s_din_dly;
reg [3:0] i2s_bclk_dly;
reg [4:0] bit_cntr;
reg [LRCLK_BCLK_RATE/2-1:0] rsr;
reg [7:0] i2s_lrclk_dly;
reg sample_en;
reg [DATA_WIDTH/2-1:0] audio_left_data;//left data
reg [DATA_WIDTH/2-1:0] audio_right_data;//right data
////////////////////////////////////////////////////////////////////////////////////////
always@(posedge audio_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
mclk_cntr <= 'b0;
else
mclk_cntr <= mclk_cntr + 2'b1;
end
always@(posedge audio_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
i2s_mclk_o <= 'b0;
else if (mclk_cntr[0])
i2s_mclk_o <= ~i2s_mclk_o;
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
i2s_bclk_dly <= 4'b0;
else
i2s_bclk_dly <= {i2s_bclk_dly[2:0],i2s_bclk_i};
end
wire i2s_bclk_rise = (i2s_bclk_dly[3:2]==2'b01);
wire i2s_bclk_fall = (i2s_bclk_dly[3:2]==2'b10);
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
bit_cntr <= 5'b0;
else if (^i2s_lrclk_dly[3:2])
bit_cntr <= 5'b0;
else if(i2s_bclk_fall)
bit_cntr <= bit_cntr + 1'b1;
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
i2s_lrclk_dly <= 8'b0;
else
i2s_lrclk_dly <= {i2s_lrclk_dly[6:0],i2s_lrclk_i};
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
sample_en <= 1'b0;
else if (^i2s_lrclk_dly[3:2])
sample_en <= 1'b0;
else if (i2s_bclk_fall)
sample_en <= 1'b1;
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
i2s_din_dly <= 4'b0;
else
i2s_din_dly <= {i2s_din_dly[2:0],i2s_din_i};
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
rsr <= 32'h0;
else if(sample_en && i2s_bclk_rise)
rsr <= { rsr[30:0],i2s_din_dly[3] };
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
begin
audio_left_data <= 'h0;
audio_right_data <= 'h0;
end
else if(^i2s_lrclk_dly[3:2])
begin
if(~i2s_lrclk_dly[3])
audio_left_data <= rsr[LRCLK_BCLK_RATE/2-2:I2S_EMPTY_WIDTH-1];
if(i2s_lrclk_dly[3])
audio_right_data <= rsr[LRCLK_BCLK_RATE/2-2:I2S_EMPTY_WIDTH-1];
end
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
audio_den_o <= 1'b0;
else if(i2s_lrclk_dly[5:4]==2'b10 )
audio_den_o <= 1'b1;
else
audio_den_o <= 1'b0;
end
always@(posedge sys_clk_i or negedge rstn_i)
begin
if(rstn_i == 1'b0)
audio_data_o <= 0;
else if(i2s_lrclk_dly[5:4]==2'b10)
audio_data_o <= {audio_left_data,audio_right_data};
end
//////////////////////////////////////////////////////////////////////////

你可能感兴趣的:(fpga音频设计)