⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freedev_aic23_自生成bclk读写.v

📁 在开发FPGA上比较有用
💻 V
字号:
//---------------------------------------------------------
//杭州自由电子科技TLV320AIC23音频模块
//电话:0571-85084089
//网址:www.freefpga.com
//邮件:jhljs@hotmail.com
//开发日期:20060501
//简要说明:
//          1、向上连接Avalone总线,设置为Slave设备,支持旁路
//             模式、中断DMA传输模式
//          2、向下连接TLV320AIC23数字音频接口DSP模式数据
//             格式。
//          3、两个时钟域之间用FIFO连接。
//---------------------------------------------------------

module freedev_aic23(clk,rst_n,irq,cs_n,rd_n,wr_n,addr,rdata,wdata,
                    lrcin,din,lrcout,dout,bclk);
input clk;		// master clk
input rst_n;	// reset
output irq;		// interrupt request
reg irq;

input cs_n;		// chip select
input rd_n;		// read signal
input wr_n;		// write signal
input [2:0]addr;// address
output [31:0]rdata;	// out data
input  [31:0]wdata;	// in  data

input  lrcin;    // aic master mode,from AIC23 to fpga
output din;      // to DAC
input  lrcout;   // aic master mode,from AIC23 TO fpga
input  dout;     // from ADC
input  bclk;     // bclk from AIC23

	//================================= clk时钟域:avalone slave 接口部分  ==============================

	// 寄存器定义
	reg [31:0] mode_reg;	// modele register          address 000
	reg [31:0] command_reg; // command register         address 001
	reg [31:0] state_reg;   // state register           address 010
	reg [31:0] lr_data;     // left right audio data    address 011
	reg [31:0] out_data;    // out data

	// 总线读信号
	wire wacc = ~cs_n & ~wr_n;

	// 总线写信号
	wire racc = ~cs_n & ~rd_n;

	// 写寄存器
	always @(posedge clk or negedge rst_n)
	if (!rst_n)
	begin
		mode_reg    <= #1 32'h0;
		command_reg <= #1 32'h0;
		state_reg   <= #1 32'h0;
		lr_data   <= #1 32'h0;
	end
	else
	    if ( wacc )
		begin
	      case ( addr ) // synopsis parallel_case
			3'b000 : mode_reg    <= #1 wdata;
			3'b001 : command_reg <= #1 wdata;
			3'b010 : state_reg   <= #1 wdata;
			3'b011 : lr_data   <= #1 wdata;		         
			default: ;
	      endcase
		end
		
	// 读寄存器和中断信号生成
	assign rdata = (addr==3'b111)?infifo_rdata:out_data;
	
	always @(posedge clk)
	begin
	if( racc && addr != 3'b111)
	  case (addr) // synopsis parallel_case
	    3'b000: out_data <= #1 mode_reg;
	    3'b001: out_data <= #1 command_reg;
	    3'b010: out_data <= #1 {infifo_rdusedw[7:0],infifo_wrusedw,outfifo_rdusedw[7:0],outfifo_wrusedw[7:0]};
	    3'b011: out_data <= #1 {27'h0,infifo_rdempty,infifo_wrfull,outfifo_rdempty,outfifo_wrfull};	// full_empty state register  	
	    3'b100: out_data <= #1 lr_data;
	    3'b101: out_data <= #1 32'h0;	// reserved
	    3'b110: out_data <= #1 32'h0;	// reserved
	    3'b111: irq <= #1 1'b0;   		// clear irq
	  endcase
	else if(racc && addr ==3'b111)		// 中断信号清除
		irq<=1'b0;
	else 
		irq<=infifo_rdusedw[7];			// 读缓冲取半慢生成中断
	end
		
	//========================================== FIFO ============================================
	//输入FIFO定义
	wire [31:0]infifo_rdata;
	reg  [31:0]infifo_wdata;
	
	reg [7:0]infifo_rdusedw;
	reg [7:0]infifo_wrusedw;
	wire infifo_rdempty;
	wire infifo_wrfull;
	
	wire infifo_rd= (addr==3'b111) ? ~(rd_n | cs_n):0;
	reg  infifo_wr;
	wire infifo_rdhalf_full=infifo_rdusedw[7];
	wire infifo_wrhalf_full=infifo_wrusedw[7];
	
	//输出FIFO定义
	wire  [31:0]outfifo_rdata;
	wire  [31:0]outfifo_wdata;
	
	reg [7:0]outfifo_rdusedw;
	reg [7:0]outfifo_wrusedw;
	wire outfifo_rdempty;
	wire outfifo_wrfull;
	
	reg outfifo_rd;
	wire outfifo_wr= (addr==3'b111) ? ~(wr_n | cs_n):0;
	wire outfifo_rdhalf_full=outfifo_rdusedw[7];
	wire outfifo_wrhalf_full=outfifo_wrusedw[7];
	
	//输入FIFO
	fd_fifo in_fifo(
	.data(infifo_wdata),
	.rdclk(clk),
	.rdreq(infifo_rd),
	.wrclk(bclk),
	.wrreq(infifo_wr),
	.q(infifo_rdata),
	.rdempty(infifo_rdempty),
	.rdusedw(infifo_rdusedw),
	.wrfull(infifo_wrfull),
	.wrusedw(infifo_wrusedw)
	);
	
	//输出FIFO
	fd_fifo out_fifo(
	.data(wdata),
	.rdclk(bclk),
	.rdreq(outfifo_rd),
	.wrclk(clk),
	.wrreq(outfifo_wr),
	.q(outfifo_rdata),
	.rdempty(outfifo_rdempty),
	.rdusedw(outfifo_rdusedw),
	.wrfull(outfifo_wrfull),
	.wrusedw(outfifo_wrusedw)
	);

	//跨时钟域异步控制信号
	wire bypass_mode = mode_reg[1:0]==2'b00 ? 1:0 ;			//复位默认是数字旁路
	wire dma_mode = mode_reg[1:0]==2'b01 ? 1:0;				// DMA传输模式
	
	
	//===============================  bclk时钟域: TLV320AIC23数字音频接口 =====================
	
	reg s_lrcin,d_lrcin;    //lrcin同步和延时
	reg s_lrcout,d_lrcout;  //lrcout同步和延时
   
	always @(posedge bclk)
	begin
		d_lrcin <= s_lrcin;
		s_lrcin <= lrcin;
		d_lrcout <= s_lrcout;
		s_lrcout <= lrcout;
	end
   
	wire in_flag,out_flag;   //AIC23 DSP MODE

	assign in_flag = ~d_lrcout & s_lrcout;
	assign out_flag= ~d_lrcin  & s_lrcin;

	reg    [31:0]recv;       // recv data from aic23 adc
	reg    [31:0]recved;     // recved data
	reg    [4:0]recv_count;  // recv counter
	reg    [1:0]recv_state;  // recv state
  
	// state machine
	parameter RECEIVE  = 2'b00;
	parameter SEND = 2'b00;
	parameter WRITE_FIFO = 2'b01;
	parameter READ_FIFO = 2'b01;
	parameter STOP  = 2'b10;
	parameter IDLE  = 2'b11;
	
	reg [31:0]test_count;

	//数字音频接口DSP方式数据ADC数据读入处理块
	always @(posedge bclk)
	if(~rst_n)
	begin
		recv_state <= #1 IDLE;
		infifo_wr <= #1 1'b0;
		test_count <= #1 32'h0;
	end else
	begin
		if(lrcin)
			begin
				recved <= #1 recv;
				recv <= #1 32'h0;
				recv_count <= #1 5'h0;
				recv_state <= #1 RECEIVE;      
			end
		else 
		case (recv_state)
			RECEIVE:
				begin
					recv <= #1 {recv[30:0],dout};
					recv_count <= recv_count + 5'h1;
					if( recv_count == 5'b11111)
					begin
						if(dma_mode)
						begin
							infifo_wdata <= #1 {recv[30:0],dout};
							//test_count <= #1 test_count + 32'h1;
							//infifo_wdata <= #1 test_count;
							infifo_wr <=#1 1'b1;
							recv_state <= #1 WRITE_FIFO;
						end
						else
							recv_state <= #1 IDLE;
					end    
				end
			WRITE_FIFO:
				begin
					recv_state <=#1 STOP;
				end
			STOP:
				begin
					infifo_wr <= #1 1'b0;
					recv_state <= #1 IDLE;
				end
			
		endcase
	end 
   
	//数字音频接口DSP模式旁路处理块
	reg    [31:0]send;       // send data to dac
	reg    [31:0]sended;     // sended data
	reg    [4:0]send_count;  // send counter
	reg    [1:0]send_state;  // send state 
	reg    bypass_out;
	
	always @(negedge bclk)
	if(~rst_n)
	begin
		send_state <= IDLE;
	end else 
	begin  
		if(out_flag)
		begin
			bypass_out <= #1 recved[31]; 
			send <= #1 {recved[30:0],1'b0};
			send_count <= #1 5'h1;  
			send_state <= #1 SEND; 
		end
		else 
		case (send_state)
			SEND:
				begin
					bypass_out <= #1 send[31];
					send <= #1 {send[30:0],1'b0};
					send_count <= send_count + 5'h1;
					if( send_count == 5'b11111)
					begin
						send_state <= #1 IDLE;
					end    
				end
		endcase
	end
	
	//数字音频接口DSP模式 DMA传输
	reg    [31:0]dmasend;       // send data to dac
	reg    [31:0]dmasended;     // sended data
	reg    [4:0]dmasend_count;  // send counter
	reg    [1:0]dmasend_state;  // send state 
	reg    dma_out;
	always @(negedge bclk)
	if(~rst_n)
	begin
		dmasend_state <= IDLE;
	end else 
	begin  
		if(out_flag && dma_mode)
		begin
			//dma_out <= #1 outfifo_rdata[31]; 
			//dmasend <= #1 {outfifo_rdata[30:0],1'b0 };
			dma_out <= #1 1'b1; 
			dmasend <= #1 32'h55555555;
			dmasend_count <= #1 5'h1;  
			dmasend_state <= #1 SEND; 
			outfifo_rd <= #1 1'b0;
		end
		else 
			case (dmasend_state)
				SEND:
					begin
						dma_out <= #1 dmasend[31];
						dmasend <= #1 {dmasend[30:0],1'b0};
						dmasend_count <= dmasend_count + 5'h1;
						if( dmasend_count == 5'b11111)
						begin
							outfifo_rd <= #1 1'b1;
							dmasend_state <= #1 READ_FIFO;
						end    
					end
				READ_FIFO:
					begin
						dmasend_state <= #1 STOP;
					end
				STOP:
					begin
						dmasend_state <= #1 IDLE;
						outfifo_rd <= #1 1'b0;
					end
			endcase
	end
	
	//输出选择
	assign din = dma_mode?dma_out:(bypass_mode ? bypass_out:0);
     
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -