i2s

发布时间 2023-11-11 17:25:23作者: moerjie

I2S简单介绍及接收端代码实现

简介

I2S(Inter-IC Sound)是一种数字音频传输协议,通常用于在数字音频设备之间传输音频数据。它是一种同步的串行数据传输协议,用于将音频信号从一个设备传输到另一个设备,例如从麦克风到音频编解码器、音频接口到音频处理器等。

接口定义

  • SCLK:对应数字音频的每一位数据,$f_{SCLK}=2采样频率采样位宽$。
  • LRCLK:用于同步左右声道的采样数据,低电平为左声道,高电平为右声道。
  • SDATA:使用二补码表示的音频数据。
  • MCLK:高速率主时钟

接口时序

pi16tD1.jpg

可以看到LRCLK跳变后的第一个SCLK周期没有数据写入。

代码实现

  1. 定义模块接口和内部寄存器,并通过异或LRCLK检测边沿信号

pi16bbq.png

  1. 对LRCLK延迟一拍采集,并产生计数信号

pi1c9M9.png

  1. 将串行数据写入寄存器中,输出并行数据和接收完成信号

pi1cBd0.png

完整代码

module i2s_receive #(
    parameter WL = 6'd32  //采样位宽
) (

    input rst,
    input sclk,
    input lrclk,
    input sdata_in,

    output reg        rx_done,
    output reg [31:0] data_out
);

  reg         lrclk_d0;
  reg  [ 5:0] rx_cnt;
  reg  [31:0] data_out_t;

  wire        lrc_edge;  // 边沿信号检测

  assign lrc_edge = lrclk ^ lrclk_d0;  // LRC信号的边沿检测



  always @(posedge sclk or negedge rst) begin
    if (!rst) begin
      lrclk_d0 <= 1'b0;
    end else lrclk_d0 <= lrclk;
  end

  always @(posedge sclk or negedge rst) begin
    if (!rst) begin
      rx_cnt <= 6'd0;
    end else if (lrc_edge == 1'b1) rx_cnt <= 6'd0;
    else if (rx_cnt < 6'd35) rx_cnt <= rx_cnt + 1'b1;
  end

  always @(posedge sclk or posedge rst) begin
    if (rst) begin
      data_out_t <= 32'b0;
    end 
    else if (rx_cnt < WL) begin
      data_out_t[WL-1'd1-rx_cnt] <= sdata_in;
    end

  end

  always @(posedge sclk or negedge rst) begin
    if (!rst) begin
      rx_done  <= 1'b0;
      data_out <= 32'b0;
    end else if (rx_cnt == 6'd31) begin
      rx_done  <= 1'b1;
      data_out <= data_out_t;
    end else rx_done <= 1'b0;
  end
endmodule