FPGA音频编解码驱动及I2C写入代码

FPGA音频编解码驱动及I2C写入代码

 

使用音频编解码芯片为WM8731,其通过I2CWM8731进行寄存器写入,将需要写入的数据放入例化的ROM块中,通过状态机控制数据的写入;通过对50M24M的时钟分频提供WM8731的主时钟和位写入时钟,数据没有进行处理,仅仅是数据的采集,后期数据可以进行FFT等数字信号处理操作。代码最后边有一个波形的仿真图,代码里有一点需要修改,在仿真图里可以看出来。共勉

 

代码如下:

module memory(                                      //I2C数据通信协议

            clk,               //系统输入50M时钟

clk24,             //系统输入24M时钟

rst_n,             //系统复位

            sclk,              //I2C时钟线

            sdin,              //I2C数据线

mclk,              //wm8731的主时钟

bclk,              //发送数据的bit时钟

dadat,             //DA接受的数据

addat,             //AD发送的数据

dalrc,             //DA的声道选择

adlrc,              //AD的声道选择

data,

I2Caddress

           ); 

 

input clk,rst_n,clk24;

output sclk,sdin;

output mclk,bclk,dalrc,adlrc,dadat;           //使用WM8731作为slave模式

input addat;

output [8:0] data;

output [6:0] I2Caddress;

 

reg sclk,sdin;

reg bclk,dalrc,adlrc,dadat;

wire mclk;

 

 

rom rom_inst (                     //ROM的例化程序

.address (I2Caddress ),

.clock ( clk ),

.q ( data)

);

 

memorypll memorypll_inst (                           //例化的Pll

.areset ( rst_n ),

.inclk0 ( clk ),

.c0 ( mclk ),

.locked ( locked_sig )

);

 

 

//assign data = q;

//assign I2Caddress = address;

reg flag;                 //应答信号

reg [6:0] I2Caddre;            //I2C的访问地址

reg [6:0] I2Caddress;       //      //内存的地址

wire [8:0] data;                //内存的数据

reg [5:0] state;               //状态描述

reg [31:0] dadataddress;        //DA存放数据内存

reg [31:0] addataddress;        //AD存放数据内存

 

 

 

 

parameter IDLE  = 6'd0;        //复位初始化状态

parameter START = 6'd1;        //开始状态

parameter I2CADDR0 = 6'd2;     //I2C的地址数据

parameter I2CADDR1 = 6'd3;

parameter I2CADDR2 = 6'd4;

parameter I2CADDR3 = 6'd5;

parameter I2CADDR4 = 6'd6;

parameter I2CADDR5 = 6'd7;

parameter I2CADDR6 = 6'd8;

parameter REWE  = 6'd9;        //对于从机的读写选择

parameter I2Caddress0 = 6'd10;    //内存的地址

parameter I2Caddress1 = 6'd11;

parameter I2Caddress2 = 6'd12;

parameter I2Caddress3 = 6'd13;

parameter I2Caddress4 = 6'd14;

parameter I2Caddress5 = 6'd15;

parameter I2Caddress6 = 6'd16;

parameter DATA0 = 6'd17;       //内存的数据       

parameter DATA1 = 6'd18;

parameter DATA2 = 6'd19;

parameter DATA3 = 6'd20;

parameter DATA4 = 6'd21;

parameter DATA5 = 6'd22;

parameter DATA6 = 6'd23;

parameter DATA7 = 6'd24;

parameter DATA8 = 6'd25;

parameter STOP  = 6'd26;       //关闭状态

parameter ACK0 = 6'd27;        //应答状态

parameter ACK1 = 6'd28;

parameter ACK2 = 6'd29;

parameter READY = 6'd30;

parameter PRESTOP = 6'd31;

 

 

parameter N = 625;

reg [9:0] count;              //计数

always @(posedge clk or negedge rst_n)     //I2C时钟的调配,输入时钟50M,输出时钟40k,对其1250分频

begin

     if(!rst_n)

    begin

   count <= 10'd0;

sclk  <= 1'b0;

 end

  else if( count==N )

    begin

   sclk  <= ~sclk;

count <= 10'd0;

 end

  

  else count <= count + 1'b1;    

  

end

     

      

 

 

//

//

//

always @(sclk )     //对于状态机的描述

begin

      if(!rst_n)

  begin

   state <= IDLE;

flag  <= 0;

I2Caddress <= 7'd0;

  end

else

  begin

        case(state)                        //对于29种状态的描述

  

IDLE : if(sclk == 1)                 //起始状态

               begin 

  sdin <= 1;

  flag  <= 0;

  state <= READY;   

end

 else state <= IDLE;

 

READY : if(sclk == 1)                //准备状态

          begin

         sdin <= 0;

flag  <= 0;

         state <= START;

       end

     else state <= READY;

  

START : if(sclk == 0)                //起始状态

           begin

    sdin <= 0;

 flag  <= 0;

 state <= I2CADDR0;

  end

else state <= START;

I2CADDR0 : if(sclk == 0)              //I2C地址

             begin

   sdin <= 0;

flag  <= 0;

state <= I2CADDR1;

 end

  else state <= I2CADDR0;

  

 

I2CADDR1 : if(sclk == 0)           

             begin

   sdin <= 1;

flag  <= 0;

state <= I2CADDR2;

 end

  else state <= I2CADDR1;

 

I2CADDR2 : if(sclk == 0)             

             begin

   sdin <= 1;

flag  <= 0;

state <= I2CADDR3;

 end

  else state <= I2CADDR2;

  

I2CADDR3 : if(sclk == 0)             

             begin

   sdin <= 0;

flag  <= 0;

state <= I2CADDR4;

 end

  else state <= I2CADDR3;

  

I2CADDR4 : if(sclk == 0)              

             begin

   sdin <= 1;

flag  <= 0;

state <= I2CADDR5;

 end

  else state <= I2CADDR4;

  

I2CADDR5 : if(sclk == 0)             

             begin

   sdin <= 0;

flag  <= 0;

state <= I2CADDR6;

 end

  else state <= I2CADDR5;

  

I2CADDR6 : if(sclk == 0)              

             begin

   sdin <= 0;

flag  <= 0;

state <= REWE;

 end

  else state <= I2CADDR6;

  

REWE : if(sclk == 0)                 //读写状态

          begin

   sdin <= 0;

flag  <= 0;

state <= ACK0;

 end

  else state <= REWE;

  

ACK0 : if(sclk == 0)                  //应答状态

         begin

  flag  <= 0;

  sdin <= I2Caddress[6];

  state <= I2Caddress0;

end

 else state <= ACK0;

 

I2Caddress0 : if(sclk == 0)              //数据地址状态

             begin

   flag  <= 0;

   sdin <= I2Caddress[5];

   state <= I2Caddress1;

 end

  else state <= I2Caddress0;

  

I2Caddress1 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= I2Caddress[4];

   state <= I2Caddress2;

 end

  else state <= I2Caddress1;

    

I2Caddress2 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= I2Caddress[3];

   state <= I2Caddress3;

 end

  else state <= I2Caddress2;

    

I2Caddress3 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= I2Caddress[2];

   state <= I2Caddress4;

 end

  else state <= I2Caddress3;

           

I2Caddress4 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= I2Caddress[1];

   state <= I2Caddress5;

 end

  else state <= I2Caddress4;

  

I2Caddress5 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= I2Caddress[0];

   state <= I2Caddress6;

 end

  else state <= I2Caddress5;

  

I2Caddress6 : if(sclk == 0)              

             begin

   flag  <= 0;

   sdin <= data[8];

   state <= ACK1;

 end

  else state <= I2Caddress6;

  

     DATA0 : if(sclk == 0)                     //应答状态

           begin

    flag  <= 0;

    sdin <= 0;

 state <= ACK1;

  end

            else state <= DATA0;

  ACK1 : if(sclk == 0)                    //数据状态

            begin

  flag  <= 0;

  sdin <= data[7];

  state <= DATA1;

end

 else state <= ACK1;

  DATA1 : if(sclk == 0)                   

            begin

  flag  <= 0;

  sdin <= data[6];

  state <= DATA2;

end

 else state <= DATA1;

  DATA2 : if(sclk == 0)                 

            begin

  flag  <= 0;

  sdin <= data[5];

  state <= DATA3;

end

 else state <= DATA2;

  DATA3 : if(sclk == 0)                   

            begin

  flag  <= 0;

  sdin <= data[4];

  state <= DATA4;

end

 else state <= DATA3;

  DATA4 : if(sclk == 0)                  

            begin

  flag  <= 0;

  sdin <= data[3];

  state <= DATA5;

end

 else state <= DATA4;

  DATA5 : if(sclk == 0)                    

            begin

  flag  <= 0;

  sdin <= data[2];

  state <= DATA6;

end

 else state <= DATA5;

  DATA6 : if(sclk == 0)                    

            begin

  flag  <= 0;

  sdin <= data[1];

  state <= DATA7;

end

 else state <= DATA6;

  DATA7 : if(sclk == 0)                   

            begin

  flag  <= 0;

  sdin <= data[0];

  state <= DATA8;

end

 else state <= DATA7;

  DATA8 : if(sclk == 0)                    

            begin

  flag  <= 0;

  sdin <= 0;

  state <= ACK2;

end

 else state <= DATA8;

     

  ACK2 : if(sclk == 1)                 //应答状态

           begin

    flag  <= 0;

    sdin <= 0;

 state <= PRESTOP;

  end

else state <= ACK2;

  PRESTOP : if(sclk == 1)              //结束前状态

              begin

    flag  <= 1;

    sdin <= 1;

 state <= STOP;

  end

else state <= PRESTOP;

  STOP : if(sclk == 0)

           begin

    flag  <= 0;

    sdin <= 0;

 state <= IDLE;

 I2Caddress <= I2Caddress + 1;

  end

else state <= STOP;

  default :  begin 

               state <= IDLE;

               flag  <= 0;

 end

       endcase

       end  

end  

 

 

//

//

// 

 

reg [9:0] count2;

always @(posedge clk24 or negedge rst_n)              //24Mhz的时钟分为48Khz

begin

     if(!rst_n)

    begin

   count2 <= 10'd0;

bclk  <= 1'b0;

 end

  else if( count2==500 )

    begin

   bclk  <= ~bclk;

count2 <= 10'd0;

 end

 else count2 <= count2 + 1'b1;  

end 

 

 

 

 

 

 

 

 

 

 

 

 

//

 

//

 //

reg [5:0] count3;

always @(posedge bclk or negedge rst_n )               //DA进行赋值

begin

    if(!rst_n)

   begin

  dadat <= 1'b0;

  count3 <= 6'd32;

 dalrc <= 1'b0;

end

 else if(count3 > 0)

   begin

     dadat <= dadataddress[count3];

  count3 <= count3 - 1'b1;

end

    else if(count3 < 1)

   begin

     count3 <= 6'd32;

  dalrc  <= ~dalrc;

      end   

end

 

 

//

//

//

reg[5:0] count4; 

always @(posedge bclk or negedge rst_n )               //AD的数据读取

begin

  if(!rst_n)

    begin

   addataddress <= 32'd0;

count4 <= 6'd32;

adlrc <= 1'b0;

 end 

  else if(count4 > 1'b0)

   begin

     addataddress[count4] <= addat;

  count4 <= count4 - 1'b1;

end

  else if(count4 < 1'b1)

   begin

     count4 <= 6'd32;

  //addataddress <= 32'd0;

  adlrc  <= ~adlrc;

      end   

end

 

 

 

 

 

 

 

 

//

//

always @( adlrc)                  //在一组数据完成后,AD的数据给DA

begin

    dadataddress <= addataddress; 

end

 

 

endmodule

 

 

 

 

 

 

你可能感兴趣的:(FPGA,音频,编译码,fpga,Verilog,状态机,I2C,WM8731)