From d348294f660d3bc8d81e1769acfc49dfecbb39f2 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Fri, 7 Jul 2017 02:13:00 +0800 Subject: [PATCH] Fix audio. 96k/48k audio over HDMI. --- sys/hdmi_config.sv | 18 +++++----- sys/i2s.v | 90 ++++++++++++++++++++++++++++------------------ sys/spdif.v | 84 +++++++++++++++++-------------------------- sys/sys_top.v | 62 ++++++++++++++++++++++---------- sys/vga_out.sv | 36 ++----------------- 5 files changed, 145 insertions(+), 145 deletions(-) diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv index 18c6d38..dbc0dfd 100644 --- a/sys/hdmi_config.sv +++ b/sys/hdmi_config.sv @@ -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 }; diff --git a/sys/i2s.v b/sys/i2s.v index df8296c..4de12b5 100644 --- a/sys/i2s.v +++ b/sys/i2s.v @@ -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 diff --git a/sys/spdif.v b/sys/spdif.v index bda94d4..d4e711e 100644 --- a/sys/spdif.v +++ b/sys/spdif.v @@ -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), diff --git a/sys/sys_top.v b/sys/sys_top.v index 48339a1..b592f2d 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -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), diff --git a/sys/vga_out.sv b/sys/vga_out.sv index cfe8bae..e316000 100644 --- a/sys/vga_out.sv +++ b/sys/vga_out.sv @@ -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,