OpenCores
URL https://opencores.org/ocsvn/aic1106_avalon_ip/aic1106_avalon_ip/trunk

Subversion Repositories aic1106_avalon_ip

[/] [aic1106_avalon_ip/] [trunk/] [AIC1106_PCM.v] - Rev 2

Compare with Previous | Blame | View Log

module AIC1106_PCM(
        // Avalon clock 
        csi_avalon_clk,
        csi_reset, 
 
        // Avalon stream audio clock 2.048 MHz
        csi_audio_clk,
 
         // Control/status reg Avalon slave
		avs_creg_address,
		avs_creg_chipselect,
		avs_creg_write,
		avs_creg_read,
		avs_creg_writedata,
		avs_creg_readdata,         
 
         // Avalon stream sink
        asi_data,
        asi_valid,
        asi_ready,
 
         // Avalon stream source
        aso_data,
        aso_valid,
 
			// TLV320AIC1106 signal
        coe_mclk,
        coe_pcmsyn,
        coe_pcmi,
        coe_pcmo,
        coe_reset_n,
        coe_mute,
        coe_linsel   // always 0 (linear mode)
         );
 
input                   csi_avalon_clk;
input                   csi_reset;          
 
input                   csi_audio_clk;
 
output   [ 31:0]        avs_creg_readdata;
input    [  1:0]        avs_creg_address;
input                   avs_creg_chipselect;
input                   avs_creg_read;
input                   avs_creg_write;
input    [ 31:0]        avs_creg_writedata;          
 
input    [ 31:0]        asi_data;
input                   asi_valid;
output                  asi_ready;
 
output                  aso_valid;
output   [31:0]         aso_data;
 
output                  coe_mclk;
output                  coe_pcmsyn;
output                  coe_pcmi;
input                   coe_pcmo;
output                  coe_reset_n;
output                  coe_mute;
output   wire           coe_linsel = 1'b0;  // linear mode
 
reg                     enable_r;
reg                     loopback_r;
reg                     reset_req_r;
reg                     pcmsyn_r;
reg                     mute_r;
reg                     underflow_r;
reg      [31:0]         tx_latch_r;
reg      [31:0]         rx_latch_r;
reg      [15:0]         tx_shft_r;
reg      [15:0]         rx_shft_r;
reg      [2:0]          volume_r;
reg                     asi_ready_r;
reg                     aso_valid_r;
reg						reset_r;
reg      [8:0]          main_cnt;
 
wire                    asi_ready = asi_ready_r;
 
wire                    aso_valid = aso_valid_r;
assign                  aso_data[31:0] = rx_latch_r[31:0];
 
wire                    coe_mclk = csi_audio_clk & enable_r;
wire                    coe_pcmsyn = pcmsyn_r & enable_r;
wire                    coe_pcmi = tx_shft_r[15] & enable_r;
wire                    coe_mute = mute_r;
wire                    coe_reset_n = reset_r;//~(reset_req_r | csi_reset); 
 
wire                    rx_shft_in = (loopback_r)?(coe_pcmi):(coe_pcmo);
 
assign                  avs_creg_readdata = (avs_creg_address[1:0] == 2'h0)?(state):(0);
wire     [31:0]         state = {25'b0, underflow_r, coe_mute, ~coe_reset_n, 1'b0, volume_r[2:0]}; 
wire                    creg_reg_sel_w      = avs_creg_write & avs_creg_chipselect & (avs_creg_address[1:0] == 2'h0); 
 
// NIOS control interface
always @(posedge csi_avalon_clk or posedge csi_reset)
begin
  if (csi_reset)
  begin
     reset_req_r <= 0;
     mute_r <= 0;
     volume_r[2:0] <= 1;  // 0 db gain
     loopback_r <= 0;
	 enable_r <= 0;
  end   
  else if (creg_reg_sel_w)
  begin
     volume_r[2:0] <= avs_creg_writedata[2:0]; 
     mute_r        <= avs_creg_writedata[3];
	 enable_r      <= avs_creg_writedata[4];
     loopback_r    <= avs_creg_writedata[5];
     reset_req_r   <= avs_creg_writedata[6];
  end   
end 
 
// PCM state decoder
wire     fs_avalon_rdy_on   = (main_cnt == 9'd0);
wire     fs_avalon_rdy_off  = (main_cnt == 9'd1);
wire     fs_txlatch         = (main_cnt == 9'd2);
wire     fs_pcmsyn1_on      = (main_cnt == 9'd3);
wire     fs_pcmsyn1_off     = (main_cnt == 9'd4);
wire     fs_shift1          = ((main_cnt > 9'd4) && (main_cnt <= 9'd20));
wire     fs_rxlatch1        = (main_cnt == 9'd21);//21
wire     fs_pcmsyn2_on      = (main_cnt == 9'd259);
wire     fs_pcmsyn2_off     = (main_cnt == 9'd260);
wire     fs_shift2          = ((main_cnt > 9'd260) && (main_cnt <= 9'd276));
wire     fs_rxlatch2        = (main_cnt == 9'd277);//277
wire     fs_rxvalid_off     = (main_cnt == 9'd278);
 
 
// PCM receive shift register; clocked by negedge
always @(negedge csi_audio_clk or posedge reset_req_r)
begin
   if (reset_req_r)
   begin
      rx_shft_r <= 0;
   end
   else begin
      if (fs_shift1 || fs_shift2)
      begin
         rx_shft_r[15:0] <= {rx_shft_r[14:0], rx_shft_in};
      end
   end
end
 
// PCM receive path and AVALON stream source logic
always @(posedge csi_audio_clk or posedge reset_req_r)
begin
   if (reset_req_r)
   begin
      rx_latch_r <= 0;
      aso_valid_r <= 0;
   end
   else begin
      if (fs_rxlatch1)
      begin
         rx_latch_r[15:0] <= rx_shft_r[15:0];
      end
      else if (fs_rxlatch2)
      begin
         rx_latch_r[31:16] <= rx_shft_r[15:0];
         aso_valid_r <= 1;
      end
      else if (fs_rxvalid_off)
      begin
         aso_valid_r <= 0;
      end
   end
end   
 
// PCM transmit path and AVALON stream sink logic
always @(posedge csi_audio_clk or posedge reset_req_r)
begin
   if (reset_req_r)
   begin
      main_cnt <= 0;
      underflow_r <= 0;
      asi_ready_r <= 0;
      pcmsyn_r <= 0;
   end
   else begin
      main_cnt <= main_cnt + 1'b1;
      if (fs_avalon_rdy_on)
      begin
         asi_ready_r <= 1;
      end 
      else if (fs_avalon_rdy_off)
      begin
         asi_ready_r <= 0;
      end
      else if (fs_txlatch)
      begin
         if (asi_valid)
         begin
            tx_latch_r[31:0] <= asi_data[31:0];
         end   
         else begin
            underflow_r <= 1;
            tx_latch_r[31:0] <= 0;
         end   
      end
      else if (fs_pcmsyn1_on)
      begin
         pcmsyn_r <= 1;
         tx_shft_r[15:0] <= {tx_latch_r[12:0], volume_r[2:0]}; //!!
      end
      else if (fs_pcmsyn1_off)
      begin
         pcmsyn_r <= 0;
      end
      else if (fs_shift1)
      begin
         tx_shft_r[15:0] <= {tx_shft_r[14:0], 1'b0};
      end
      else if (fs_pcmsyn2_on)
      begin
         pcmsyn_r <= 1;
         tx_shft_r[15:0] <= {tx_latch_r[28:16], volume_r[2:0]};   //!!
      end
      else if (fs_pcmsyn2_off)
      begin
         pcmsyn_r <= 0;
      end
      else if (fs_shift2)
      begin
         tx_shft_r[15:0] <= {tx_shft_r[14:0], 1'b0};
      end
   end   
end
 
// resync reset to csi_audio_clk
always @(posedge csi_audio_clk)
begin
	reset_r <= ~(reset_req_r | csi_reset);
end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.