FPGA設計標準I2S協議音訊編解碼器
阿新 • • 發佈:2018-12-20
FPGA設計標準I2S協議音訊編解碼器
–I2S基本介紹
I2S(Inter-IC Sound)是飛利浦公司針對數字音訊裝置(如CD播放器、數碼音效處理器、數字電視音響系統)之間的音訊資料傳輸而制定的一種匯流排標準。它採用了獨立的導線傳輸時鐘與資料訊號的設計,通過將資料和時鐘訊號分離,避免了因時差誘發的失真,為使用者節省了購買抵抗音訊抖動的專業裝置的費用。
–I2S取樣和處理過程
模擬訊號–>音訊codec晶片–>I2S數字訊號(音訊ADC轉換過程)
I2S數字訊號–>音訊codec晶片–>模擬訊號(音訊DAC轉換過程)
–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音訊編解碼器
程式碼已經在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
////////////////////////////////////////////////////////////////////////////////////////
[email protected](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
[email protected](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
[email protected](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);
[email protected](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
[email protected](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
[email protected](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
[email protected](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
[email protected](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
[email protected](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
[email protected](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
[email protected](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
//////////////////////////////////////////////////////////////////////////