151 lines
3.9 KiB
Verilog
151 lines
3.9 KiB
Verilog
module i2s_audio
|
|
(
|
|
input bus_clk,
|
|
input quiesce,
|
|
input clk_100,
|
|
|
|
output reg audio_mclk,
|
|
output reg audio_dac,
|
|
input audio_adc,
|
|
input audio_bclk,
|
|
input audio_lrclk,
|
|
|
|
input user_w_audio_wren,
|
|
input [31:0] user_w_audio_data,
|
|
output user_w_audio_full,
|
|
input user_w_audio_open,
|
|
|
|
input user_r_audio_rden,
|
|
output [31:0] user_r_audio_data,
|
|
output user_r_audio_empty,
|
|
|
|
output user_r_audio_eof,
|
|
input user_r_audio_open
|
|
);
|
|
|
|
reg audio_adc_reg;
|
|
reg audio_bclk_reg;
|
|
reg audio_lrclk_reg;
|
|
reg audio_lrclk_reg_d;
|
|
|
|
reg [1:0] clk_div;
|
|
reg [15:0] play_shreg;
|
|
reg [1:0] bclk_d;
|
|
reg fifo_rd_en;
|
|
wire bclk_rising, bclk_falling;
|
|
wire [31:0] play_fifo_data;
|
|
|
|
reg [31:0] record_shreg;
|
|
reg [4:0] record_count;
|
|
reg write_when_done;
|
|
reg fifo_wr_en;
|
|
|
|
// synthesis attribute IOB of audio_mclk is TRUE
|
|
// synthesis attribute IOB of audio_dac is TRUE
|
|
// synthesis attribute IOB of audio_adc_reg is TRUE
|
|
// synthesis attribute IOB of audio_bclk_reg is TRUE
|
|
// synthesis attribute IOB of audio_lrclk_reg is TRUE
|
|
|
|
assign user_r_audio_eof = 0;
|
|
|
|
// Produce a 25 MHz clock for MCLK
|
|
|
|
always @(posedge clk_100)
|
|
begin
|
|
clk_div <= clk_div + 1;
|
|
audio_mclk <= clk_div[1];
|
|
end
|
|
|
|
assign bclk_rising = (bclk_d == 2'b01);
|
|
assign bclk_falling = (bclk_d == 2'b10);
|
|
|
|
// BCLK runs at 3.072 MHz, so the signals are sampled and handled
|
|
// synchronously, with an obvious delay, which is negligble compared
|
|
// with a BCLK clock cycle.
|
|
|
|
always @(posedge bus_clk)
|
|
begin
|
|
audio_adc_reg <= audio_adc;
|
|
audio_bclk_reg <= audio_bclk;
|
|
audio_lrclk_reg <= audio_lrclk;
|
|
|
|
bclk_d <= { bclk_d, audio_bclk_reg };
|
|
|
|
if (bclk_rising)
|
|
audio_lrclk_reg_d <= audio_lrclk_reg;
|
|
|
|
// Playback
|
|
|
|
fifo_rd_en <= 0; // Possibly overridden below
|
|
|
|
if (bclk_rising && !audio_lrclk_reg && audio_lrclk_reg_d)
|
|
play_shreg <= play_fifo_data[31:16]; // Left channel
|
|
else if (bclk_rising && audio_lrclk_reg && !audio_lrclk_reg_d)
|
|
begin
|
|
play_shreg <= play_fifo_data[15:0]; // Right channel
|
|
fifo_rd_en <= 1;
|
|
end
|
|
else if (bclk_falling)
|
|
begin
|
|
audio_dac <= play_shreg[15];
|
|
play_shreg <= { play_shreg, 1'b0 };
|
|
end
|
|
|
|
// Recording
|
|
|
|
fifo_wr_en <= 0; // Possibly overridden below
|
|
|
|
if (bclk_rising && (record_count != 0))
|
|
begin
|
|
record_shreg <= { record_shreg, audio_adc_reg };
|
|
record_count <= record_count - 1;
|
|
|
|
if (record_count == 1)
|
|
begin
|
|
fifo_wr_en <= write_when_done;
|
|
write_when_done <= 0;
|
|
end
|
|
end
|
|
|
|
if (bclk_rising && !audio_lrclk_reg && audio_lrclk_reg_d)
|
|
begin
|
|
record_count <= 16;
|
|
write_when_done <= 0;
|
|
end
|
|
else if (bclk_rising && audio_lrclk_reg && !audio_lrclk_reg_d)
|
|
begin
|
|
record_count <= 16;
|
|
write_when_done <= 1;
|
|
end
|
|
end
|
|
|
|
// Note that there is no check on the empty line. If the FIFO is empty,
|
|
// it will emit the same output all the time, so the audio output will be
|
|
// silent, which is fairly OK for an underrun.
|
|
|
|
fifo_32x512 playback_fifo
|
|
(
|
|
.clk(bus_clk),
|
|
.srst(!user_w_audio_open),
|
|
.din(user_w_audio_data), // Bus [31 : 0]
|
|
.wr_en(user_w_audio_wren),
|
|
.rd_en(fifo_rd_en),
|
|
.dout(play_fifo_data), // Bus [31 : 0]
|
|
.full(user_w_audio_full),
|
|
.empty());
|
|
|
|
// The full lines isn't checked. Not much to do on an overrun
|
|
|
|
fifo_32x512 record_fifo
|
|
(
|
|
.clk(bus_clk),
|
|
.srst(!user_r_audio_open),
|
|
.din(record_shreg), // Bus [31 : 0]
|
|
.wr_en(fifo_wr_en),
|
|
.rd_en(user_r_audio_rden),
|
|
.dout(user_r_audio_data), // Bus [31 : 0]
|
|
.full(),
|
|
.empty(user_r_audio_empty));
|
|
|
|
|
|
endmodule
|