📄 freedev_aic23_自生成bclk读写.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 + -