2017-10-22 01:22:56 +00:00
|
|
|
|
|
|
|
module i2s
|
|
|
|
#(
|
|
|
|
parameter CLK_RATE = 50000000,
|
|
|
|
parameter AUDIO_DW = 16,
|
|
|
|
parameter AUDIO_RATE = 96000
|
|
|
|
)
|
|
|
|
(
|
|
|
|
input reset,
|
|
|
|
input clk_sys,
|
|
|
|
input half_rate,
|
|
|
|
|
|
|
|
output reg sclk,
|
|
|
|
output reg lrclk,
|
|
|
|
output reg sdata,
|
|
|
|
|
|
|
|
input [AUDIO_DW-1:0] left_chan,
|
|
|
|
input [AUDIO_DW-1:0] right_chan
|
|
|
|
);
|
|
|
|
|
|
|
|
localparam WHOLE_CYCLES = (CLK_RATE) / (AUDIO_RATE*AUDIO_DW*4);
|
|
|
|
localparam ERROR_BASE = 10000;
|
|
|
|
localparam [63:0] ERRORS_PER_BIT = ((CLK_RATE * ERROR_BASE) / (AUDIO_RATE*AUDIO_DW*4)) - (WHOLE_CYCLES * ERROR_BASE);
|
|
|
|
|
2018-03-05 17:40:43 +00:00
|
|
|
reg lpf_ce;
|
|
|
|
wire [AUDIO_DW-1:0] al, ar;
|
|
|
|
|
|
|
|
lpf_i2s lpf_l
|
|
|
|
(
|
|
|
|
.CLK(clk_sys),
|
|
|
|
.CE(lpf_ce),
|
|
|
|
.IDATA(left_chan),
|
|
|
|
.ODATA(al)
|
|
|
|
);
|
|
|
|
|
|
|
|
lpf_i2s lpf_r
|
|
|
|
(
|
|
|
|
.CLK(clk_sys),
|
|
|
|
.CE(lpf_ce),
|
|
|
|
|
|
|
|
.IDATA(right_chan),
|
|
|
|
.ODATA(ar)
|
|
|
|
);
|
|
|
|
|
2017-10-22 01:22:56 +00:00
|
|
|
always @(posedge clk_sys) begin
|
2018-03-05 17:40:43 +00:00
|
|
|
reg [31:0] count_q;
|
|
|
|
reg [31:0] error_q;
|
|
|
|
reg [7:0] bit_cnt;
|
|
|
|
reg skip = 0;
|
2017-10-22 01:22:56 +00:00
|
|
|
|
|
|
|
reg [AUDIO_DW-1:0] left;
|
|
|
|
reg [AUDIO_DW-1:0] right;
|
|
|
|
|
|
|
|
reg msclk;
|
|
|
|
reg ce;
|
2018-03-05 17:40:43 +00:00
|
|
|
|
|
|
|
lpf_ce <= 0;
|
2017-10-22 01:22:56 +00:00
|
|
|
|
|
|
|
if (reset) begin
|
|
|
|
count_q <= 0;
|
|
|
|
error_q <= 0;
|
|
|
|
ce <= 0;
|
|
|
|
bit_cnt <= 1;
|
|
|
|
lrclk <= 1;
|
|
|
|
sclk <= 1;
|
|
|
|
msclk <= 1;
|
|
|
|
end
|
|
|
|
else
|
|
|
|
begin
|
|
|
|
if(count_q == WHOLE_CYCLES-1) begin
|
|
|
|
if (error_q < (ERROR_BASE - ERRORS_PER_BIT)) begin
|
|
|
|
error_q <= error_q + ERRORS_PER_BIT[31:0];
|
|
|
|
count_q <= 0;
|
|
|
|
end else begin
|
|
|
|
error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE;
|
|
|
|
count_q <= count_q + 1;
|
|
|
|
end
|
|
|
|
end else if(count_q == WHOLE_CYCLES) begin
|
|
|
|
count_q <= 0;
|
|
|
|
end else begin
|
|
|
|
count_q <= count_q + 1;
|
|
|
|
end
|
|
|
|
|
|
|
|
sclk <= msclk;
|
|
|
|
if(!count_q) begin
|
|
|
|
ce <= ~ce;
|
|
|
|
if(~half_rate || ce) begin
|
|
|
|
msclk <= ~msclk;
|
|
|
|
if(msclk) begin
|
2018-03-05 17:40:43 +00:00
|
|
|
skip <= ~skip;
|
|
|
|
if(skip) lpf_ce <= 1;
|
2017-10-22 01:22:56 +00:00
|
|
|
if(bit_cnt >= AUDIO_DW) begin
|
|
|
|
bit_cnt <= 1;
|
|
|
|
lrclk <= ~lrclk;
|
|
|
|
if(lrclk) begin
|
2018-03-05 17:40:43 +00:00
|
|
|
left <= al;
|
|
|
|
right <= ar;
|
2017-10-22 01:22:56 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else begin
|
|
|
|
bit_cnt <= bit_cnt + 1'd1;
|
|
|
|
end
|
|
|
|
sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|
2018-03-05 17:40:43 +00:00
|
|
|
|
|
|
|
module lpf_i2s
|
|
|
|
(
|
|
|
|
input CLK,
|
|
|
|
input CE,
|
|
|
|
input [15:0] IDATA,
|
|
|
|
output reg [15:0] ODATA
|
|
|
|
);
|
|
|
|
|
|
|
|
reg [511:0] acc;
|
|
|
|
reg [20:0] sum;
|
|
|
|
|
|
|
|
always @(*) begin
|
|
|
|
integer i;
|
|
|
|
sum = 0;
|
|
|
|
for (i = 0; i < 32; i = i+1) sum = sum + {{5{acc[(i*16)+15]}}, acc[i*16 +:16]};
|
|
|
|
end
|
|
|
|
|
|
|
|
always @(posedge CLK) begin
|
|
|
|
if(CE) begin
|
|
|
|
acc <= {acc[495:0], IDATA};
|
|
|
|
ODATA <= sum[20:5];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
endmodule
|