From 1cb48641cb8bad751bbf0d6dc3be48dcbaad4fac Mon Sep 17 00:00:00 2001 From: sorgelig Date: Mon, 14 Oct 2019 03:49:12 +0800 Subject: [PATCH] Update sys. --- NeoGeo.qsf | 2 +- sys/hps_io.v | 296 +++++++++++++++++++++++++++--------------------- sys/osd.v | 99 ++++++++++------ sys/sys_top.sdc | 11 ++ 4 files changed, 244 insertions(+), 164 deletions(-) diff --git a/NeoGeo.qsf b/NeoGeo.qsf index ed8e142..56d2347 100644 --- a/NeoGeo.qsf +++ b/NeoGeo.qsf @@ -13,7 +13,7 @@ set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top -set_global_assignment -name LAST_QUARTUS_VERSION "17.1.0 Lite Edition" +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.2 Standard Edition" set_global_assignment -name GENERATE_RBF_FILE ON set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files diff --git a/sys/hps_io.v b/sys/hps_io.v index d4d87cb..86b8a00 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -52,8 +52,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output [1:0] buttons, output forced_scandoubler, - output reg [31:0] status, - input [31:0] status_in, + output reg [63:0] status, + input [63:0] status_in, input status_set, input [15:0] status_menumask, @@ -169,113 +169,24 @@ wire [15:0] sd_cmd = sd_rd[0] }; -///////////////// calc video parameters ////////////////// +///////////////////////////////////////////////////////// -wire clk_100 = HPS_BUS[43]; -wire clk_vid = HPS_BUS[42]; -wire ce_pix = HPS_BUS[41]; -wire de = HPS_BUS[40]; -wire hs = HPS_BUS[39]; -wire vs = HPS_BUS[38]; -wire vs_hdmi = HPS_BUS[44]; -wire f1 = HPS_BUS[45]; - -reg [31:0] vid_hcnt = 0; -reg [31:0] vid_vcnt = 0; -reg [7:0] vid_nres = 0; -reg [1:0] vid_int = 0; -integer hcnt; - -always @(posedge clk_vid) begin - integer vcnt; - reg old_vs= 0, old_de = 0, old_vmode = 0; - reg [3:0] resto = 0; - reg calch = 0; - - if(ce_pix) begin - old_vs <= vs; - old_de <= de; - - if(~vs & ~old_de & de) vcnt <= vcnt + 1; - if(calch & de) hcnt <= hcnt + 1; - if(old_de & ~de) calch <= 0; - - if(old_vs & ~vs) begin - vid_int <= {vid_int[0],f1}; - if(~f1) begin - if(hcnt && vcnt) begin - old_vmode <= new_vmode; - - //report new resolution after timeout - if(resto) resto <= resto + 1'd1; - if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) resto <= 1; - if(&resto) vid_nres <= vid_nres + 1'd1; - vid_hcnt <= hcnt; - vid_vcnt <= vcnt; - end - vcnt <= 0; - hcnt <= 0; - calch <= 1; - end - end - end -end - -reg [31:0] vid_htime = 0; -reg [31:0] vid_vtime = 0; -reg [31:0] vid_pix = 0; - -always @(posedge clk_100) begin - integer vtime, htime, hcnt; - reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2; - reg calch = 0; - - old_vs <= vs; - old_hs <= hs; - - old_vs2 <= old_vs; - old_hs2 <= old_hs; - - vtime <= vtime + 1'd1; - htime <= htime + 1'd1; - - if(~old_vs2 & old_vs) begin - vid_pix <= hcnt; - vid_vtime <= vtime; - vtime <= 0; - hcnt <= 0; - end - - if(old_vs2 & ~old_vs) calch <= 1; - - if(~old_hs2 & old_hs) begin - vid_htime <= htime; - htime <= 0; - end - - old_de <= de; - old_de2 <= old_de; - - if(calch & old_de) hcnt <= hcnt + 1; - if(old_de2 & ~old_de) calch <= 0; -end - -reg [31:0] vid_vtime_hdmi; -always @(posedge clk_100) begin - integer vtime; - reg old_vs, old_vs2; - - old_vs <= vs_hdmi; - old_vs2 <= old_vs; - - vtime <= vtime + 1'd1; - - if(~old_vs2 & old_vs) begin - vid_vtime_hdmi <= vtime; - vtime <= 0; - end -end +wire [15:0] vc_dout; +video_calc video_calc +( + .clk_100(HPS_BUS[43]), + .clk_vid(HPS_BUS[42]), + .ce_pix(HPS_BUS[41]), + .de(HPS_BUS[40]), + .hs(HPS_BUS[39]), + .vs(HPS_BUS[38]), + .vs_hdmi(HPS_BUS[44]), + .f1(HPS_BUS[45]), + .new_vmode(new_vmode), + .par_num(byte_cnt[3:0]), + .dout(vc_dout) +); ///////////////////////////////////////////////////////// @@ -283,14 +194,15 @@ reg [31:0] ps2_key_raw = 0; wire pressed = (ps2_key_raw[15:8] != 8'hf0); wire extended = (~pressed ? (ps2_key_raw[23:16] == 8'he0) : (ps2_key_raw[15:8] == 8'he0)); +reg [9:0] byte_cnt; + always@(posedge clk_sys) begin reg [15:0] cmd; - reg [9:0] byte_cnt; // counts bytes reg [2:0] b_wr; reg [2:0] stick_idx; reg ps2skip = 0; reg [3:0] stflg = 0; - reg [31:0] status_req; + reg [63:0] status_req; reg old_status_set = 0; old_status_set <= status_set; @@ -436,9 +348,13 @@ always@(posedge clk_sys) begin // send image info 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; - // status, 32bit version - 'h1e: if(byte_cnt==1) status[15:0] <= io_din; - else if(byte_cnt==2) status[31:16] <= io_din; + // status, 64bit version + 'h1e: case(byte_cnt) + 1: status[15:00] <= io_din; + 2: status[31:16] <= io_din; + 3: status[47:32] <= io_din; + 4: status[63:48] <= io_din; + endcase // reading keyboard LED status 'h1f: io_dout <= {|PS2WE, 2'b01, ps2_kbd_led_status[2], ps2_kbd_led_use[2], ps2_kbd_led_status[1], ps2_kbd_led_use[1], ps2_kbd_led_status[0], ps2_kbd_led_use[0]}; @@ -460,21 +376,7 @@ always@(posedge clk_sys) begin 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: case(byte_cnt) - 1: io_dout <= {|vid_int, vid_nres}; - 2: io_dout <= vid_hcnt[15:0]; - 3: io_dout <= vid_hcnt[31:16]; - 4: io_dout <= vid_vcnt[15:0]; - 5: io_dout <= vid_vcnt[31:16]; - 6: io_dout <= vid_htime[15:0]; - 7: io_dout <= vid_htime[31:16]; - 8: io_dout <= vid_vtime[15:0]; - 9: io_dout <= vid_vtime[31:16]; - 10: io_dout <= vid_pix[15:0]; - 11: io_dout <= vid_pix[31:16]; - 12: io_dout <= vid_vtime_hdmi[15:0]; - 13: io_dout <= vid_vtime_hdmi[31:16]; - endcase + 'h23: if(!byte_cnt[9:4]) io_dout <= vc_dout; //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; @@ -484,8 +386,10 @@ always@(posedge clk_sys) begin //status set 'h29: case(byte_cnt) - 1: io_dout <= status_req[15:0]; + 1: io_dout <= status_req[15:00]; 2: io_dout <= status_req[31:16]; + 3: io_dout <= status_req[47:32]; + 4: io_dout <= status_req[63:48]; endcase //menu mask @@ -777,6 +681,142 @@ end endmodule + +///////////////// calc video parameters ////////////////// +module video_calc +( + input clk_100, + input clk_vid, + input ce_pix, + input de, + input hs, + input vs, + input vs_hdmi, + input f1, + input new_vmode, + + input [3:0] par_num, + output reg [15:0] dout +); + +always @(*) begin + case(par_num) + 1: dout = {|vid_int, vid_nres}; + 2: dout = vid_hcnt[15:0]; + 3: dout = vid_hcnt[31:16]; + 4: dout = vid_vcnt[15:0]; + 5: dout = vid_vcnt[31:16]; + 6: dout = vid_htime[15:0]; + 7: dout = vid_htime[31:16]; + 8: dout = vid_vtime[15:0]; + 9: dout = vid_vtime[31:16]; + 10: dout = vid_pix[15:0]; + 11: dout = vid_pix[31:16]; + 12: dout = vid_vtime_hdmi[15:0]; + 13: dout = vid_vtime_hdmi[31:16]; + default dout = 0; + endcase +end + +reg [31:0] vid_hcnt = 0; +reg [31:0] vid_vcnt = 0; +reg [7:0] vid_nres = 0; +reg [1:0] vid_int = 0; + +always @(posedge clk_vid) begin + integer hcnt; + integer vcnt; + reg old_vs= 0, old_de = 0, old_vmode = 0; + reg [3:0] resto = 0; + reg calch = 0; + + if(ce_pix) begin + old_vs <= vs; + old_de <= de; + + if(~vs & ~old_de & de) vcnt <= vcnt + 1; + if(calch & de) hcnt <= hcnt + 1; + if(old_de & ~de) calch <= 0; + + if(old_vs & ~vs) begin + vid_int <= {vid_int[0],f1}; + if(~f1) begin + if(hcnt && vcnt) begin + old_vmode <= new_vmode; + + //report new resolution after timeout + if(resto) resto <= resto + 1'd1; + if(vid_hcnt != hcnt || vid_vcnt != vcnt || old_vmode != new_vmode) resto <= 1; + if(&resto) vid_nres <= vid_nres + 1'd1; + vid_hcnt <= hcnt; + vid_vcnt <= vcnt; + end + vcnt <= 0; + hcnt <= 0; + calch <= 1; + end + end + end +end + +reg [31:0] vid_htime = 0; +reg [31:0] vid_vtime = 0; +reg [31:0] vid_pix = 0; + +always @(posedge clk_100) begin + integer vtime, htime, hcnt; + reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2; + reg calch = 0; + + old_vs <= vs; + old_hs <= hs; + + old_vs2 <= old_vs; + old_hs2 <= old_hs; + + vtime <= vtime + 1'd1; + htime <= htime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_pix <= hcnt; + vid_vtime <= vtime; + vtime <= 0; + hcnt <= 0; + end + + if(old_vs2 & ~old_vs) calch <= 1; + + if(~old_hs2 & old_hs) begin + vid_htime <= htime; + htime <= 0; + end + + old_de <= de; + old_de2 <= old_de; + + if(calch & old_de) hcnt <= hcnt + 1; + if(old_de2 & ~old_de) calch <= 0; +end + +reg [31:0] vid_vtime_hdmi; +always @(posedge clk_100) begin + integer vtime; + reg old_vs, old_vs2; + + old_vs <= vs_hdmi; + old_vs2 <= old_vs; + + vtime <= vtime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_vtime_hdmi <= vtime; + vtime <= 0; + end +end + +endmodule + + // // Phase shift helper module for better 64MB/128MB modules support. // diff --git a/sys/osd.v b/sys/osd.v index b564a26..f0a9dfe 100644 --- a/sys/osd.v +++ b/sys/osd.v @@ -22,14 +22,12 @@ module osd ); parameter OSD_COLOR = 3'd4; -parameter OSD_X_OFFSET = 12'd0; -parameter OSD_Y_OFFSET = 12'd0; localparam OSD_WIDTH = 12'd256; localparam OSD_HEIGHT = 12'd64; `ifdef OSD_HEADER -localparam OSD_HDR = 12'd32; +localparam OSD_HDR = 12'd24; `else localparam OSD_HDR = 12'd0; `endif @@ -42,7 +40,11 @@ reg [8:0] infoh; reg [8:0] infow; reg [11:0] infox; reg [21:0] infoy; -reg [21:0] hrheight; +reg [21:0] osd_h; +reg [21:0] osd_t; +reg [21:0] osd_w; + +reg [1:0] rot = 0; always@(posedge clk_sys) begin reg [12:0] bcnt; @@ -51,7 +53,9 @@ always@(posedge clk_sys) begin reg old_strobe; reg highres = 0; - hrheight <= info ? infoh : ((OSD_HEIGHT<> 9) > 1) ? (((cnt+1'b1) >> 9) - 1) : 0; + pixsz <= (((cnt+1'b1) >> (9-rot[0])) > 1) ? (((cnt+1'b1) >> (9-rot[0])) - 1'd1) : 22'd0; pixcnt <= 0; end end @@ -119,19 +124,24 @@ reg [2:0] osd_de; reg osd_pixel; reg [21:0] v_cnt; -reg v_cnt_below320, v_cnt_below640, v_cnt_below960; +reg v_cnt_half, v_cnt_single, v_cnt_double, v_cnt_triple; -reg [21:0] v_osd_start_320, v_osd_start_640, v_osd_start_960, v_osd_start_other; +reg [21:0] v_osd_start_h, v_osd_start_s, v_osd_start_d, v_osd_start_t, v_osd_start_q; + +wire [21:0] osd_h_hdr = (info || rot) ? osd_h : (osd_h + OSD_HDR); // pipeline the comparisons a bit always @(posedge clk_video) if(ce_pix) begin - v_cnt_below320 <= v_cnt < 320; - v_cnt_below640 <= v_cnt < 640; - v_cnt_below960 <= v_cnt < 960; - v_osd_start_320 <= ((v_cnt-hrheight)>>1) + OSD_Y_OFFSET; - v_osd_start_640 <= ((v_cnt-(hrheight<<1))>>1) + OSD_Y_OFFSET; - v_osd_start_960 <= ((v_cnt-(hrheight + (hrheight<<1)))>>1) + OSD_Y_OFFSET; - v_osd_start_other <= ((v_cnt-(hrheight<<2))>>1) + OSD_Y_OFFSET; + v_cnt_half <= v_cnt < osd_t; + v_cnt_single <= v_cnt < 320; + v_cnt_double <= v_cnt < 640; + v_cnt_triple <= v_cnt < 960; + + v_osd_start_h <= ((v_cnt-(osd_h_hdr>>1))>>1); + v_osd_start_s <= ((v_cnt-osd_h_hdr)>>1); + v_osd_start_d <= ((v_cnt-(osd_h_hdr<<1))>>1); + v_osd_start_t <= ((v_cnt-(osd_h_hdr + (osd_h_hdr<<1)))>>1); + v_osd_start_q <= ((v_cnt-(osd_h_hdr<<2))>>1); end always @(posedge clk_video) begin @@ -145,22 +155,31 @@ always @(posedge clk_video) begin reg [21:0] h_osd_start; reg [21:0] v_osd_start; reg [21:0] osd_hcnt; + reg [21:0] osd_hcnt2; reg osd_de1,osd_de2; reg [1:0] osd_en; reg f1; + reg half; if(ce_pix) begin deD <= de_in; if(~&h_cnt) h_cnt <= h_cnt + 1'd1; - if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1; + if(~&osd_hcnt) osd_hcnt <= osd_hcnt + 1'd1; + if(~&osd_hcnt2) osd_hcnt2 <= osd_hcnt2 + 1'd1; + if (h_cnt == h_osd_start) begin - osd_de[0] <= osd_en[1] && hrheight && (info ? (osd_vcnt < hrheight) : - (!osd_vcnt[11:7] || (osd_vcnt[11] && osd_vcnt[7] && (osd_vcnt[6:0] >= 4) && (osd_vcnt[6:0] < 19)))); + osd_de[0] <= osd_en[1] && osd_h && ( + osd_vcnt[11] ? (osd_vcnt[7] && (osd_vcnt[6:0] >= 4) && (osd_vcnt[6:0] < 19)) : + (info && (rot == 3)) ? !osd_vcnt[21:8] : + (osd_vcnt < osd_h) + ); osd_hcnt <= 0; + osd_hcnt2 <= 0; + if(info && rot == 1) osd_hcnt2 <= 22'd128-infoh; end - if (osd_hcnt+1 == (info ? infow : OSD_WIDTH)) osd_de[0] <= 0; + if (osd_hcnt+1 == osd_w) osd_de[0] <= 0; // falling edge of de if(!de_in && deD) dsp_width <= h_cnt[21:0]; @@ -169,7 +188,7 @@ always @(posedge clk_video) begin if(de_in && !deD) begin h_cnt <= 0; v_cnt <= v_cnt + 1'd1; - h_osd_start <= info ? infox : (((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET - 2'd2); + h_osd_start <= info ? (rot[0] ? infoy : infox) : (((dsp_width - osd_w)>>1) - 2'd2); if(h_cnt > {dsp_width, 2'b00}) begin v_cnt <= 1; @@ -179,21 +198,27 @@ always @(posedge clk_video) begin osd_en <= (osd_en << 1) | osd_enable; if(~osd_enable) osd_en <= 0; - if(v_cnt_below320) begin + half <= 0; + if(v_cnt_half) begin multiscan <= 0; - v_osd_start <= info ? infoy : v_osd_start_320; + v_osd_start <= info ? (rot[0] ? infox : infoy) : v_osd_start_h; + half <= 1; end - else if(v_cnt_below640) begin + else if(v_cnt_single | (rot[0] & v_cnt_double)) begin + multiscan <= 0; + v_osd_start <= info ? (rot[0] ? infox : infoy) : v_osd_start_s; + end + else if(rot[0] ? v_cnt_triple : v_cnt_double) begin multiscan <= 1; - v_osd_start <= info ? (infoy<<1) : v_osd_start_640; + v_osd_start <= info ? (rot[0] ? (infox<<1) : (infoy<<1)) : v_osd_start_d; end - else if(v_cnt_below960) begin + else if(v_cnt_triple | rot[0]) begin multiscan <= 2; - v_osd_start <= info ? (infoy + (infoy << 1)) : v_osd_start_960; + v_osd_start <= info ? (rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1))) : v_osd_start_t; end else begin multiscan <= 3; - v_osd_start <= info ? (infoy<<2) : v_osd_start_other; + v_osd_start <= info ? (rot[0] ? (infox<<2) : (infoy<<2)) : v_osd_start_q; end end end @@ -201,14 +226,18 @@ always @(posedge clk_video) begin osd_div <= osd_div + 1'd1; if(osd_div == multiscan) begin osd_div <= 0; - if(~osd_vcnt[10]) osd_vcnt <= osd_vcnt + 1'd1; + if(~osd_vcnt[10]) osd_vcnt <= osd_vcnt + 1'd1 + half; if(osd_vcnt == 'b100010011111 && ~info) osd_vcnt <= 0; end - if(v_osd_start == v_cnt) {osd_div, osd_vcnt} <= OSD_HDR ? {~info, 3'b000, ~info, 7'b0000000} : 22'd0; + if(v_osd_start == v_cnt) begin + {osd_div,osd_vcnt} <= 0; + if(info && rot == 3) osd_vcnt <= 22'd256-infow; + else if(OSD_HDR && !rot) osd_vcnt <= {~info, 3'b000, ~info, 7'b0000000}; + end end - osd_byte <= osd_buffer[{osd_vcnt[7:3], osd_hcnt[7:0]}]; - osd_pixel <= osd_byte[osd_vcnt[2:0]]; + osd_byte <= osd_buffer[rot[0] ? ({osd_hcnt2[6:3], osd_vcnt[7:0]} ^ { {4{~rot[1]}}, {8{rot[1]}} }) : {osd_vcnt[7:3], osd_hcnt[7:0]}]; + osd_pixel <= osd_byte[rot[0] ? ((osd_hcnt2[2:0]-1'd1) ^ {3{~rot[1]}}) : osd_vcnt[2:0]]; osd_de[2:1] <= osd_de[1:0]; end end diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 90d943d..7763fc8 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -35,3 +35,14 @@ set_false_path -to [get_ports {AUDIO_R}] set_false_path -to {cfg[*]} set_false_path -from {cfg[*]} set_false_path -to {wcalc[*] hcalc[*]} + +set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 +set_multicycle_path -to {*_osd|osd_vcnt*} -hold 2 +set_false_path -to {*_osd|v_cnt*} +set_false_path -to {*_osd|v_osd_start*} +set_false_path -to {*_osd|h_osd_start*} +set_false_path -from {*_osd|v_osd_start*} +set_false_path -from {*_osd|h_osd_start*} +set_false_path -from {*_osd|rot*} +set_false_path -from {*_osd|dsp_width*} +set_false_path -to {*_osd|half}