Fix audio. 96k/48k audio over HDMI.

This commit is contained in:
sorgelig
2017-07-07 02:13:00 +08:00
parent acf04a0eed
commit d348294f66
5 changed files with 145 additions and 145 deletions

View File

@@ -17,6 +17,8 @@ module hdmi_config
// 1 - 16:9
input iAR,
input audio_48k,
// I2C Side
output I2C_SCL,
inout I2C_SDA
@@ -47,7 +49,7 @@ always@(posedge iCLK or negedge iRST_N) begin
reg [1:0] mSetup_ST = 0;
if(!iRST_N) begin
LUT_INDEX <= 8'd0;
LUT_INDEX <= 0;
mSetup_ST <= 0;
mI2C_GO <= 0;
end else begin
@@ -237,7 +239,7 @@ wire [15:0] init_data[58] =
{8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified.
{8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits.
{8'h15, 8'b0010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
{8'h15, ~audio_48k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
// Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs.
// {8'h15, 8'b0010_0001}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
@@ -246,14 +248,14 @@ wire [15:0] init_data[58] =
// {8'h15, 8'b0010_0011}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
// Input ID [3:0] b0011 (3) = 16, 20, 24 bit YCbCr 4:2:2 (2x Pixel Clock, with Separate Syncs).
// Audio Clock Config: 74.25/12 = 148500/12375 = 6187.5
// Audio Clock Config
16'h0100, //
16'h0230, // Set N Value 12375
16'h0357, //
audio_48k ? 16'h0218 : 16'h0230, // Set N Value 12288/6144
16'h0300, //
16'h0702, //
16'h0844, // Set CTS Value 148500
16'h0914, //
16'h0701, //
16'h0822, // Set CTS Value 74250
16'h090A, //
16'hFFFF // END
};

View File

@@ -1,60 +1,82 @@
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 signed_sample,
input [AUDIO_DW-1:0] left_chan,
input [AUDIO_DW-1:0] right_chan
);
localparam AUDIO_DW = 16;
reg bit_en;
always @(negedge clk_sys) begin
reg [5:0] div;
div <= div + 1'd1;
if(div == 23) div <= 0;
bit_en <= !div;
end
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);
always @(posedge clk_sys) begin
reg [AUDIO_DW-1:0] bit_cnt;
reg [31:0] count_q;
reg [31:0] error_q;
reg [7:0] bit_cnt;
reg [AUDIO_DW-1:0] left;
reg [AUDIO_DW-1:0] right;
reg msclk;
sclk <= msclk;
reg msclk;
reg ce;
if(reset) begin
bit_cnt <= 1;
lrclk <= 1;
sclk <= 1;
msclk <= 1;
if (reset) begin
count_q <= 0;
error_q <= 0;
ce <= 0;
bit_cnt <= 1;
lrclk <= 1;
sclk <= 1;
msclk <= 1;
end
else begin
if(bit_en) begin
msclk <= ~msclk;
if(msclk) begin
if(bit_cnt >= AUDIO_DW) begin
bit_cnt <= 1;
lrclk <= ~lrclk;
if(lrclk) begin
left <= left_chan;
right <= right_chan;
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
if(bit_cnt >= AUDIO_DW) begin
bit_cnt <= 1;
lrclk <= ~lrclk;
if(lrclk) begin
left <= left_chan;
right <= right_chan;
end
end
else begin
bit_cnt <= bit_cnt + 1'd1;
end
sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt];
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

View File

@@ -51,6 +51,7 @@ module spdif
(
input clk_i,
input rst_i,
input half_rate,
// Output
output spdif_o,
@@ -61,65 +62,44 @@ module spdif
output sample_req_o
);
//-----------------------------------------------------------------
// External clock source
//-----------------------------------------------------------------
wire bit_clock_w;
reg [31:0] count_q;
reg [31:0] error_q;
reg bit_clk_q;
// Clock pulse generator
always @ (posedge rst_i or posedge clk_i)
begin
if (rst_i)
begin
count_q <= 32'd0;
error_q <= 32'd0;
bit_clk_q <= 1'b1;
end
else
begin
case (count_q)
0 :
begin
bit_clk_q <= 1'b1;
count_q <= count_q + 32'd1;
end
always @ (posedge rst_i or posedge clk_i) begin
reg [31:0] count_q;
reg [31:0] error_q;
reg ce;
WHOLE_CYCLES-1:
begin
if (error_q < (ERROR_BASE - ERRORS_PER_BIT))
begin
error_q <= error_q + ERRORS_PER_BIT[31:0];
count_q <= 32'd0;
end
else
begin
error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE;
count_q <= count_q + 32'd1;
end
bit_clk_q <= 1'b0;
if (rst_i) begin
count_q <= 0;
error_q <= 0;
bit_clk_q <= 1;
ce <= 0;
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
WHOLE_CYCLES:
begin
count_q <= 32'd0;
bit_clk_q <= 1'b0;
end
default:
begin
count_q <= count_q + 32'd1;
bit_clk_q <= 1'b0;
end
endcase
end
bit_clk_q <= 0;
if(!count_q) begin
ce <= ~ce;
if(~half_rate || ce) bit_clk_q <= 1;
end
end
end
assign bit_clock_w = bit_clk_q;
//-----------------------------------------------------------------
// Core SPDIF
//-----------------------------------------------------------------
@@ -132,7 +112,7 @@ u_core
.clk_i(clk_i),
.rst_i(rst_i),
.bit_out_en_i(bit_clock_w),
.bit_out_en_i(bit_clk_q),
.spdif_o(spdif_o),

View File

@@ -170,6 +170,39 @@ cyclonev_hps_interface_mpu_general_purpose h2f_gp
);
reg [15:0] cfg;
reg cfg_ready = 0;
wire audio_48k = cfg[6];
wire ypbpr_en = cfg[5];
wire csync = cfg[3];
`ifndef LITE
wire vga_scaler= cfg[2];
`endif
always@(posedge clk_sys) begin
reg [7:0] cmd;
reg has_cmd;
reg old_strobe;
old_strobe <= io_strobe;
if(~io_uio) has_cmd <= 0;
else
if(~old_strobe & io_strobe) begin
if(!has_cmd) begin
has_cmd <= 1;
cmd <= io_din[7:0];
end
else
if(cmd == 1) begin
cfg <= io_din;
cfg_ready <= 1;
end
end
end
/////////////////////////// RESET ///////////////////////////////////
reg reset_req = 0;
@@ -427,10 +460,11 @@ pll_hdmi pll_hdmi
hdmi_config hdmi_config
(
.iCLK(FPGA_CLK1_50),
.iRST_N(~reset),
.iRST_N(cfg_ready),
.I2C_SCL(HDMI_I2C_SCL),
.I2C_SDA(HDMI_I2C_SDA),
.audio_48k(audio_48k),
.iRES(4), // 720p
.iAR(1) // Aspect Ratio
);
@@ -453,8 +487,9 @@ osd hdmi_osd
assign HDMI_MCLK = 0;
i2s i2s
(
.reset(reset),
.clk_sys(HDMI_TX_CLK),
.reset(~cfg_ready),
.clk_sys(FPGA_CLK1_50),
.half_rate(audio_48k),
.sclk(HDMI_SCLK),
.lrclk(HDMI_LRCLK),
@@ -484,38 +519,27 @@ osd vga_osd
);
wire [23:0] vga_o;
wire csync;
vga_out vga_out
(
.clk_sys(clk_sys),
.io_uio(io_uio),
.io_strobe(io_strobe),
.io_din(io_din),
.ypbpr_full(1),
.ypbpr_en(ypbpr_en),
.dout(vga_o),
`ifdef LITE
.din(vga_q),
`else
.din(vga_scaler ? HDMI_TX_D : vga_q),
.scaler(vga_scaler),
.din(vga_scaler ? HDMI_TX_D : vga_q)
`endif
.csync(csync)
);
`ifdef LITE
wire vs1 = vs;
wire hs1 = hs;
`else
wire vga_scaler;
wire vs1 = vga_scaler ? HDMI_TX_VS : vs;
wire hs1 = vga_scaler ? HDMI_TX_HS : hs;
`endif
assign VGA_VS = VGA_EN ? 1'bZ : csync ? 1'b1 : ~vs1;
assign VGA_HS = VGA_EN ? 1'bZ : csync ? ~(vs1 ^ hs1) : ~hs1;
assign VGA_R = VGA_EN ? 6'bZZZZZZ : vga_o[23:18];
@@ -527,7 +551,7 @@ assign VGA_B = VGA_EN ? 6'bZZZZZZ : vga_o[7:2];
sigma_delta_dac #(15) dac_l
(
.CLK(FPGA_CLK2_50),
.CLK(FPGA_CLK3_50),
.RESET(reset),
.DACin({audio_l[15] ^ audio_s, audio_l[14:0]}),
.DACout(AUDIO_L)
@@ -535,7 +559,7 @@ sigma_delta_dac #(15) dac_l
sigma_delta_dac #(15) dac_r
(
.CLK(FPGA_CLK2_50),
.CLK(FPGA_CLK3_50),
.RESET(reset),
.DACin({audio_r[15] ^ audio_s, audio_r[14:0]}),
.DACout(AUDIO_R)
@@ -546,6 +570,8 @@ spdif toslink
.clk_i(FPGA_CLK3_50),
.rst_i(reset),
.half_rate(0),
.audio_l(audio_l >> !audio_s),
.audio_r(audio_r >> !audio_s),

View File

@@ -1,43 +1,13 @@
module vga_out
(
input clk_sys,
input io_uio,
input io_strobe,
input [7:0] io_din,
input ypbpr_full,
input ypbpr_en,
input [23:0] din,
output [23:0] dout,
output scaler,
output csync
output [23:0] dout
);
reg [7:0] cfg;
wire ypbpr_en = cfg[5];
assign csync = cfg[3];
assign scaler = cfg[2];
always@(posedge clk_sys) begin
reg [7:0] cmd;
reg has_cmd;
reg old_strobe;
old_strobe <= io_strobe;
if(~io_uio) has_cmd <= 0;
else if(~old_strobe & io_strobe) begin
if(!has_cmd) begin
has_cmd <= 1;
cmd <= io_din;
end else begin
if(cmd == 1) cfg <= io_din;
end
end
end
wire [5:0] yuv_full[225] = '{
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,