module i2s #(parameter SAMPLE_WIDTH = 16)(
input CLK,
input BCLK, // Bit clock from codec
input LRCLK, // LR clock from codec
input ADCDA, // ADC digitized data from the codec
input [SAMPLE_WIDTH-1:0] LEFT_IN, // left channel vector output to DAC
input [SAMPLE_WIDTH-1:0] RIGHT_IN, // right channel output to the DAC
output reg [SAMPLE_WIDTH-1:0] LEFT_OUT, // deserialized ADC data, left
output reg [SAMPLE_WIDTH-1:0] RIGHT_OUT, // deserialized ADC data, right
output reg DATAREADY, // strobe - data updated
output BCLK_S, // synchronized BCLK signal
output LRCLK_S, // synchronized LRCLK signal
output DACDA); // data output to DAC of codec
// ==============================================================
// synchronization of clone domains and edge selection
// ==============================================================
reg [2:0] bclk_trg; always @(posedge CLK) bclk_trg <= { bclk_trg[1:0], BCLK };
assign BCLK_S = bclk_trg[1]; // synchronized BCLK
wire BCLK_PE = ~bclk_trg[2] & BCLK_S; // allocated BCLK leading edge
wire BCLK_NE = bclk_trg[2] & ~BCLK_S; // dedicated BCLK trailing edge
reg [2:0] lrclk_trg; always @(posedge CLK) lrclk_trg <= { lrclk_trg[1:0], LRCLK };
assign LRCLK_S = lrclk_trg[1]; // synchronized LRCLK
wire LRCLK_PRV = lrclk_trg[2]; // previous LRCLK value
wire LRCLK_CH = LRCLK_PRV ^ LRCLK_S; // any change of LRCLK
reg [1:0] adcda_trg; always @(posedge CLK) adcda_trg <= { adcda_trg[0], ADCDA };
wire ADCDA_S = adcda_trg[1]; // synchronized DAT
// ==============================================================
// I2S input data shift register
// ==============================================================
wire [31:0] shift_w = { shift[30:0], ADCDA_S };
reg [31:0] shift; always @(posedge CLK) if (BCLK_PE) shift <= shift_w;
// vectors for input data (for DAC)
reg [SAMPLE_WIDTH-1:0] lb;
reg [SAMPLE_WIDTH-1:0] rb;
reg [4:0] bit_cnt; // pointer of the current bit
reg actualLR;
// bitstream output to DAC
wire [4:0] bit_ptr = (~bit_cnt - (32-SAMPLE_WIDTH));
assign DACDA = (bit_cnt < SAMPLE_WIDTH) ? actualLR ? lb[bit_ptr] : rb[bit_ptr] : 1'b0;
// pointer calculation, data latching for DAC output
always @(posedge CLK)
begin
if (LRCLK_CH)
begin
bit_cnt <= 5'd31;
actualLR <= ~LRCLK_S;
end
else
if (BCLK_NE)
begin
actualLR <= LRCLK_S;
bit_cnt <= bit_cnt + 1'b1;
if (bit_cnt == 5'd31)
begin
lb <= LEFT_IN;
rb <= RIGHT_IN;
end
end
end
// capture ADC data
always @(posedge CLK)
begin
if (LRCLK_CH)
begin
if (LRCLK_PRV)
begin
RIGHT_OUT <= shift_w[31:32-SAMPLE_WIDTH];
DATAREADY <= 1'b1;
end
else
LEFT_OUT <= shift_w[31:32-SAMPLE_WIDTH];
end
else
DATAREADY <= 1'b0;
end
endmodule
No comments:
Post a Comment