IIS FPGA CORE



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

Class A-Like Topology

- "New Class A" bias module (see Technics folklore - synchro bias) - "Super-A" bias module (see JVC folklore) - "No...