diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv index 8cbad8b..ada954f 100644 --- a/sys/hdmi_config.sv +++ b/sys/hdmi_config.sv @@ -2,12 +2,14 @@ module hdmi_config ( // Host Side - input iCLK, - input iRST_N, + input iCLK, + input iRST_N, input dvi_mode, input audio_96k, - input hdmi_limited, + input limited, + input ypbpr, + output reg done, // I2C Side @@ -105,34 +107,32 @@ wire [15:0] init_data[82] = {8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 - {8'h18, hdmi_limited, // CSC enable [7]. 0 - Off. 1 - On. - 7'h0D}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. - {8'h19, 8'hBC}, // Taken from table in ADV7513 Programming Guide. - {8'h1A, 8'h00}, // CSC Channel A. - {8'h1B, 8'h00}, - {8'h1C, 8'h00}, - {8'h1D, 8'h00}, - {8'h1E, 8'h01}, + {8'h18, ypbpr ? 8'h88 : limited ? 8'h8D : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited. + {8'h19, ypbpr ? 8'h2E : 8'hBC}, // Taken from table in ADV7513 Programming Guide. + {8'h1A, ypbpr ? 8'h18 : 8'h00}, // CSC Channel A. + {8'h1B, ypbpr ? 8'h93 : 8'h00}, + {8'h1C, ypbpr ? 8'h1F : 8'h00}, + {8'h1D, ypbpr ? 8'h3F : 8'h00}, + {8'h1E, ypbpr ? 8'h08 : 8'h01}, {8'h1F, 8'h00}, - - {8'h20, 8'h00}, // CSC Channel B. - {8'h21, 8'h00}, - {8'h22, 8'h0D}, - {8'h23, 8'hBC}, - {8'h24, 8'h00}, - {8'h25, 8'h00}, - {8'h26, 8'h01}, + + {8'h20, ypbpr ? 8'h03 : 8'h00}, // CSC Channel B. + {8'h21, ypbpr ? 8'h67 : 8'h00}, + {8'h22, ypbpr ? 8'h0B : 8'h0D}, + {8'h23, ypbpr ? 8'h71 : 8'hBC}, + {8'h24, ypbpr ? 8'h01 : 8'h00}, + {8'h25, ypbpr ? 8'h28 : 8'h00}, + {8'h26, ypbpr ? 8'h00 : 8'h01}, {8'h27, 8'h00}, - - {8'h28, 8'h00}, // CSC Channel C. - {8'h29, 8'h00}, - {8'h2A, 8'h00}, - {8'h2B, 8'h00}, - {8'h2C, 8'h0D}, - {8'h2D, 8'hBC}, - {8'h2E, 8'h01}, + + {8'h28, ypbpr ? 8'h1E : 8'h00}, // CSC Channel C. + {8'h29, ypbpr ? 8'h21 : 8'h00}, + {8'h2A, ypbpr ? 8'h19 : 8'h00}, + {8'h2B, ypbpr ? 8'hB2 : 8'h00}, + {8'h2C, ypbpr ? 8'h08 : 8'h0D}, + {8'h2D, ypbpr ? 8'h2D : 8'hBC}, + {8'h2E, ypbpr ? 8'h08 : 8'h01}, {8'h2F, 8'h00}, - {8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx. @@ -152,7 +152,7 @@ wire [15:0] init_data[82] = {8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59). 3'b000, // [6:4] Color space (ignored for RGB) - hdmi_limited ? 2'b01 : 2'b10, // [3:2] RGB Quantization range + (ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range 2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both. 16'h7301, diff --git a/sys/hps_io.v b/sys/hps_io.v index 013ac75..cc75f12 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -83,12 +83,13 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output reg [DW:0] sd_buff_dout, input [DW:0] sd_buff_din, output reg sd_buff_wr, + input [15:0] sd_req_type, // ARM -> FPGA download output reg ioctl_download = 0, // signal indicating an active download output reg [7:0] ioctl_index, // menu index used to upload the file output reg ioctl_wr, - output reg [24:0] ioctl_addr, // in WIDE mode address will be incremented by 2 + output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2 output reg [DW:0] ioctl_dout, output reg [31:0] ioctl_file_ext, input ioctl_wait, @@ -199,7 +200,7 @@ always @(posedge clk_vid) begin if(old_vs & ~vs) begin vid_int <= {vid_int[0],f1}; - if(~f1) begin + if(~f1) begin if(hcnt && vcnt) begin old_vmode <= new_vmode; @@ -390,6 +391,7 @@ always@(posedge clk_sys) begin 1: io_dout <= sd_cmd; 2: io_dout <= sd_lba[15:0]; 3: io_dout <= sd_lba[31:16]; + 4: io_dout <= sd_req_type; endcase // send SD config IO -> FPGA @@ -571,7 +573,7 @@ always@(posedge clk_sys) begin reg [15:0] cmd; reg [2:0] cnt; reg has_cmd; - reg [24:0] addr; + reg [26:0] addr; reg wr; ioctl_wr <= wr; diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index c253d88..922169c 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -3,7 +3,7 @@ create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] -create_clock -period 10.0 [get_pins -compatibility_mode spi|sclk_out] -name spi_sck +create_clock -period 10.0ns [get_pins -compatibility_mode spi|sclk_out] -name spi_sck derive_pll_clocks @@ -20,8 +20,8 @@ set_clock_groups -asynchronous \ -group [get_clocks { *|h2f_user0_clk}] \ -group [get_clocks { FPGA_CLK1_50 FPGA_CLK2_50 FPGA_CLK3_50}] -set_output_delay -max -clock HDMI_CLK 2.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] -set_output_delay -min -clock HDMI_CLK -1.5ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] +set_output_delay -max -clock HDMI_CLK 3.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] +set_output_delay -min -clock HDMI_CLK 2.0ns [get_ports {HDMI_TX_D[*] HDMI_TX_DE HDMI_TX_HS HDMI_TX_VS}] set_false_path -from {*} -to [get_registers {wcalc[*] hcalc[*]}] @@ -36,3 +36,4 @@ set_false_path -from * -to [get_ports {VGA_*}] set_false_path -from * -to [get_ports {AUDIO_SPDIF}] set_false_path -from * -to [get_ports {AUDIO_L}] set_false_path -from * -to [get_ports {AUDIO_R}] +set_false_path -from * -to [get_keepers {cfg[*]}] diff --git a/sys/sys_top.v b/sys/sys_top.v index 5d0a8bb..493bf34 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -257,12 +257,13 @@ reg cfg_set = 0; wire hdmi_limited = cfg[8]; wire dvi_mode = cfg[7]; wire audio_96k = cfg[6]; +wire direct_video = cfg[10]; +wire csync = cfg[3]; +wire ypbpr_en = cfg[5]; +wire io_osd_vga= io_ss1 & ~io_ss2; `ifndef DUAL_SDRAM wire sog = cfg[9]; - wire ypbpr_en = cfg[5]; - wire csync = cfg[3]; wire vga_scaler= cfg[2]; - wire io_osd_vga= io_ss1 & ~io_ss2; `endif reg cfg_custom_t = 0; @@ -431,7 +432,7 @@ always @(posedge FPGA_CLK2_50) begin end wire clk_100m; -wire clk_hdmi = ~HDMI_TX_CLK; // Internal HDMI clock, inverted in relation to external clock +wire clk_hdmi = hdmi_tx_clk; wire clk_audio = FPGA_CLK3_50; wire clk_pal = FPGA_CLK3_50; @@ -496,6 +497,7 @@ wire [127:0] vbuf_writedata; wire [15:0] vbuf_byteenable; wire vbuf_write; +wire hdmi_vs, hdmi_hs; ascal #( .RAMBASE(32'h20000000), @@ -528,8 +530,8 @@ ascal .o_r (hdmi_data[23:16]), .o_g (hdmi_data[15:8]), .o_b (hdmi_data[7:0]), - .o_hs (HDMI_TX_HS), - .o_vs (HDMI_TX_VS), + .o_hs (hdmi_hs), + .o_vs (hdmi_vs), .o_de (hdmi_de), .o_lltune (lltune), .htotal (WIDTH + HFP + HBP + HS), @@ -687,13 +689,14 @@ fbpal fbpal ///////////////////////// HDMI output ///////////////////////////////// +wire hdmi_tx_clk; pll_hdmi pll_hdmi ( .refclk(FPGA_CLK1_50), .rst(reset_req), .reconfig_to_pll(reconfig_to_pll), .reconfig_from_pll(reconfig_from_pll), - .outclk_0(HDMI_TX_CLK) + .outclk_0(hdmi_tx_clk) ); //1920x1080@60 PCLK=148.5MHz CEA @@ -772,7 +775,8 @@ hdmi_config hdmi_config .dvi_mode(dvi_mode), .audio_96k(audio_96k), - .hdmi_limited(hdmi_limited) + .limited(hdmi_limited), + .ypbpr(ypbpr_en & direct_video) ); wire [23:0] hdmi_data; @@ -790,6 +794,8 @@ scanlines #(1) HDMI_scanlines .vs(HDMI_TX_VS) ); +wire [23:0] hdmi_tx_d; +wire hdmi_tx_de; osd hdmi_osd ( .clk_sys(clk_sys), @@ -800,56 +806,102 @@ osd hdmi_osd .clk_video(clk_hdmi), .din(hdmi_data_sl), - .dout(HDMI_TX_D), + .dout(hdmi_tx_d), .de_in(hdmi_de), - .de_out(HDMI_TX_DE), + .de_out(hdmi_tx_de), .osd_status(osd_status) ); +reg [23:0] dv_d; +reg dv_hs, dv_vs, dv_de; +always @(negedge clk_vid) begin + reg [23:0] dv_d1, dv_d2; + reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2; + reg [12:0] vsz, vcnt; + reg old_hs, old_vs; + reg vde; + reg [3:0] hss; + + if(ce_pix) begin + hss <= (hss << 1) | hs; + + old_hs <= hs; + if(~old_hs && hs) begin + old_vs <= vs; + if(~&vcnt) vcnt <= vcnt + 1'd1; + if(~old_vs & vs & ~f1) vsz <= vcnt; + if(old_vs & ~vs) vcnt <= 0; + + if(vcnt == 1) vde <= 1; + if(vcnt == vsz - 3) vde <= 0; + end + + dv_de1 <= !{hss,hs} && vde; + dv_hs1 <= csync ? (vs ^ hs) : hs; + dv_vs1 <= vs; + end + + dv_d1 <= vga_q; + dv_d2 <= dv_d1; + dv_de2 <= dv_de1; + dv_hs2 <= dv_hs1; + dv_vs2 <= dv_vs1; + + dv_d <= dv_d2; + dv_de <= dv_de2; + dv_hs <= dv_hs2; + dv_vs <= dv_vs2; +end + +assign HDMI_TX_CLK = direct_video ? clk_vid : hdmi_tx_clk; +assign HDMI_TX_HS = direct_video ? dv_hs : hdmi_hs ; +assign HDMI_TX_VS = direct_video ? dv_vs : hdmi_vs ; +assign HDMI_TX_D = direct_video ? dv_d : hdmi_tx_d ; +assign HDMI_TX_DE = direct_video ? dv_de : hdmi_tx_de ; + ///////////////////////// VGA output ////////////////////////////////// +wire [23:0] vga_data_sl; + +scanlines #(0) VGA_scanlines +( + .clk(clk_vid), + + .scanlines(scanlines), + .din(de ? {r_out, g_out, b_out} : 24'd0), + .dout(vga_data_sl), + .hs(hs), + .vs(vs) +); + +wire [23:0] vga_q; +osd vga_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd_vga), + .io_strobe(io_strobe), + .io_din(io_din), + + .clk_video(clk_vid), + .din(vga_data_sl), + .dout(vga_q), + .de_in(de) +); + `ifndef DUAL_SDRAM - wire [23:0] vga_data_sl; - - scanlines #(0) VGA_scanlines - ( - .clk(clk_vid), - - .scanlines(scanlines), - .din(de ? {r_out, g_out, b_out} : 24'd0), - .dout(vga_data_sl), - .hs(hs1), - .vs(vs1) - ); - - osd vga_osd - ( - .clk_sys(clk_sys), - - .io_osd(io_osd_vga), - .io_strobe(io_strobe), - .io_din(io_din), - - .clk_video(clk_vid), - .din(vga_data_sl), - .dout(vga_q), - .de_in(de) - ); - - wire [23:0] vga_q; wire [23:0] vga_o; - vga_out vga_out ( - .ypbpr_full(1), + .ypbpr_full(0), .ypbpr_en(ypbpr_en), .dout(vga_o), - .din(vga_scaler ? {24{HDMI_TX_DE}} & HDMI_TX_D : vga_q) + .din(vga_scaler ? {24{hdmi_tx_de}} & hdmi_tx_d : vga_q) ); - wire vs1 = vga_scaler ? HDMI_TX_VS : vs; - wire hs1 = vga_scaler ? HDMI_TX_HS : hs; + wire vs1 = vga_scaler ? hdmi_vs : vs; + wire hs1 = vga_scaler ? hdmi_hs : hs; assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : csync ? 1'b1 : ~vs1; assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : csync ? ~(vs1 ^ hs1) : ~hs1; diff --git a/video.sv b/video.sv index fb0f14a..d7c4cb8 100644 --- a/video.sv +++ b/video.sv @@ -111,17 +111,17 @@ always @(posedge clk_sys) begin sync <= 0; if(!mZX) begin if(hc == 312) HBlank <= 1; - if(hc == 338) {HSync,sync} <= 3; + if(hc == 338) sync <= 1; if(hc == 370) HSync <= 0; if(hc == 420) HBlank <= 0; end else if(m128) begin if(hc == 312) HBlank <= 1; - if(hc == 340) {HSync,sync} <= 3; //ULA 6C + if(hc == 340) sync <= 1; //ULA 6C if(hc == 372) HSync <= 0; //ULA 6C if(hc == 424) HBlank <= 0; end else begin if(hc == 300) HBlank <= 1; - if(hc == 336) {HSync,sync} <= 3; //ULA 5C + if(hc == 336) sync <= 1; //ULA 5C if(hc == 368) HSync <= 0; //ULA 5C if(hc == 428) HBlank <= 0; end @@ -129,6 +129,7 @@ always @(posedge clk_sys) begin if(wide) HBlank <= !(hc < 312 || hc >= ((mZX && m128) ? 455-33 : 447-33)); if(sync) begin + HSync <= 1; if(mZX) begin if(vc == 236) VBlank <= 1; if(vc == 240) VSync <= 1;