mirror of
https://github.com/MiSTer-devel/ZX-Spectrum_MISTer.git
synced 2026-05-17 03:04:59 +00:00
Fix audio. 96k/48k audio over HDMI.
This commit is contained in:
@@ -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
|
||||
};
|
||||
|
||||
90
sys/i2s.v
90
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
|
||||
|
||||
84
sys/spdif.v
84
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),
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user