diff --git a/sys/hps_io.v b/sys/hps_io.v index eab005e..a4c9bd6 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -36,12 +36,15 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) // parameter STRLEN and the actual length of conf_str have to match input [(8*STRLEN)-1:0] conf_str, + // buttons up to 32 output reg [31:0] joystick_0, output reg [31:0] joystick_1, output reg [31:0] joystick_2, output reg [31:0] joystick_3, output reg [31:0] joystick_4, output reg [31:0] joystick_5, + + // analog -127..+127, Y: [15:8], X: [7:0] output reg [15:0] joystick_analog_0, output reg [15:0] joystick_analog_1, output reg [15:0] joystick_analog_2, @@ -49,6 +52,22 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) output reg [15:0] joystick_analog_4, output reg [15:0] joystick_analog_5, + // paddle 0..255 + output reg [7:0] paddle_0, + output reg [7:0] paddle_1, + output reg [7:0] paddle_2, + output reg [7:0] paddle_3, + output reg [7:0] paddle_4, + output reg [7:0] paddle_5, + + // spinner [7:0] -128..+127, [8] - toggle with every update + output reg [8:0] spinner_0, + output reg [8:0] spinner_1, + output reg [8:0] spinner_2, + output reg [8:0] spinner_3, + output reg [8:0] spinner_4, + output reg [8:0] spinner_5, + output [1:0] buttons, output forced_scandoubler, output direct_video, @@ -139,6 +158,8 @@ module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) inout [21:0] gamma_bus ); +localparam MAX_W = $clog2((512 > (STRLEN+1)) ? 512 : (STRLEN+1))-1; + localparam DW = (WIDE) ? 15 : 7; localparam AW = (WIDE) ? 7 : 8; localparam VD = VDNUM-1; @@ -212,12 +233,13 @@ 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; +reg [MAX_W:0] byte_cnt; always@(posedge clk_sys) begin reg [15:0] cmd; reg [2:0] b_wr; - reg [2:0] stick_idx; + reg [3:0] stick_idx; + reg [3:0] pdsp_idx; reg ps2skip = 0; reg [3:0] stflg = 0; reg [63:0] status_req; @@ -307,13 +329,13 @@ always@(posedge clk_sys) begin mouse_we <= 1; end if(&io_din[15:8]) ps2skip <= 1; - if(~&io_din[15:8] & ~ps2skip) begin - case(byte_cnt) + if(~&io_din[15:8] && ~ps2skip && !byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) 1: ps2_mouse[7:0] <= io_din[7:0]; 2: ps2_mouse[15:8] <= io_din[7:0]; 3: ps2_mouse[23:16] <= io_din[7:0]; endcase - case(byte_cnt) + case(byte_cnt[1:0]) 1: ps2_mouse_ext[7:0] <= {io_din[14], io_din[14:8]}; 2: ps2_mouse_ext[11:8] <= io_din[11:8]; 3: ps2_mouse_ext[15:12]<= io_din[11:8]; @@ -335,12 +357,14 @@ always@(posedge clk_sys) begin 'h14: if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; // reading sd card status - 'h16: case(byte_cnt) - 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 + 'h16: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 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 + end // send SD config IO -> FPGA // flag that download begins @@ -361,17 +385,33 @@ always@(posedge clk_sys) begin end // joystick analog - 'h1a: case(byte_cnt) - 1: stick_idx <= io_din[2:0]; // first byte is joystick index - 2: case(stick_idx) - 0: joystick_analog_0 <= io_din; - 1: joystick_analog_1 <= io_din; - 2: joystick_analog_2 <= io_din; - 3: joystick_analog_3 <= io_din; - 4: joystick_analog_4 <= io_din; - 5: joystick_analog_5 <= io_din; - endcase - endcase + 'h1a: if(!byte_cnt[MAX_W:2]) begin + case(byte_cnt[1:0]) + 1: {pdsp_idx,stick_idx} <= io_din[7:0]; // first byte is joystick index + 2: case(stick_idx) + 0: joystick_analog_0 <= io_din; + 1: joystick_analog_1 <= io_din; + 2: joystick_analog_2 <= io_din; + 3: joystick_analog_3 <= io_din; + 4: joystick_analog_4 <= io_din; + 5: joystick_analog_5 <= io_din; + 15: case(pdsp_idx) + 0: paddle_0 <= io_din[7:0]; + 1: paddle_1 <= io_din[7:0]; + 2: paddle_2 <= io_din[7:0]; + 3: paddle_3 <= io_din[7:0]; + 4: paddle_4 <= io_din[7:0]; + 5: paddle_5 <= io_din[7:0]; + 8: spinner_0 <= {~spinner_0[8],io_din[7:0]}; + 9: spinner_1 <= {~spinner_1[8],io_din[7:0]}; + 10: spinner_2 <= {~spinner_2[8],io_din[7:0]}; + 11: spinner_3 <= {~spinner_3[8],io_din[7:0]}; + 12: spinner_4 <= {~spinner_4[8],io_din[7:0]}; + 13: spinner_5 <= {~spinner_5[8],io_din[7:0]}; + endcase + endcase + endcase + end // notify image selection 'h1c: begin @@ -383,12 +423,14 @@ always@(posedge clk_sys) begin 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +: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 + 'h1e: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 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 + end // 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]}; @@ -410,7 +452,7 @@ always@(posedge clk_sys) begin 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: if(!byte_cnt[9:4]) io_dout <= vc_dout; + 'h23: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout; //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; @@ -419,13 +461,15 @@ always@(posedge clk_sys) begin 'h28: io_dout <= uart_mode; //status set - 'h29: case(byte_cnt) - 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 - + 'h29: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2: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 + end + //menu mask 'h2E: if(byte_cnt == 1) io_dout <= status_menumask; @@ -441,18 +485,22 @@ always@(posedge clk_sys) begin end //CD get - 'h34: case(byte_cnt) - 1: io_dout <= cd_in[15:0]; - 2: io_dout <= cd_in[31:16]; - 3: io_dout <= cd_in[47:32]; - endcase + 'h34: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 1: io_dout <= cd_in[15:0]; + 2: io_dout <= cd_in[31:16]; + 3: io_dout <= cd_in[47:32]; + endcase + end //CD set - 'h35: case(byte_cnt) - 1: cd_out[15:0] <= io_din; - 2: cd_out[31:16] <= io_din; - 3: cd_out[47:32] <= io_din; - endcase + 'h35: if(!byte_cnt[MAX_W:3]) begin + case(byte_cnt[2:0]) + 1: cd_out[15:0] <= io_din; + 2: cd_out[31:16] <= io_din; + 3: cd_out[47:32] <= io_din; + endcase + end endcase end end diff --git a/sys/osd.v b/sys/osd.v index eee77d8..a4fbdde 100644 --- a/sys/osd.v +++ b/sys/osd.v @@ -38,7 +38,7 @@ reg osd_enable; reg info = 0; reg [8:0] infoh; reg [8:0] infow; -reg [11:0] infox; +reg [21:0] infox; reg [21:0] infoy; reg [21:0] osd_h; reg [21:0] osd_t; @@ -123,31 +123,39 @@ end reg [2:0] osd_de; reg osd_pixel; reg [21:0] v_cnt; - -reg v_cnt_half, v_cnt_single, v_cnt_double, v_cnt_triple; - -reg [21:0] v_osd_start_h, v_osd_start_s, v_osd_start_d, v_osd_start_t, v_osd_start_q; +reg v_cnt_h, v_cnt_1, v_cnt_2, v_cnt_3, v_cnt_4; +reg [21:0] v_osd_start_h, v_osd_start_1, v_osd_start_2, v_osd_start_3, v_osd_start_4, v_osd_start_5; +reg [21:0] v_info_start_h, v_info_start_1, v_info_start_2, v_info_start_3, v_info_start_4, v_info_start_5; 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_half <= v_cnt < osd_t; - v_cnt_single <= v_cnt < 320; - v_cnt_double <= v_cnt < 640; - v_cnt_triple <= v_cnt < 960; + v_cnt_h <= v_cnt < osd_t; + v_cnt_1 <= v_cnt < 320; + v_cnt_2 <= v_cnt < 640; + v_cnt_3 <= v_cnt < 960; + v_cnt_4 <= v_cnt < 1280; - 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); + v_osd_start_h <= (v_cnt-(osd_h_hdr>>1))>>1; + v_osd_start_1 <= (v_cnt-osd_h_hdr)>>1; + v_osd_start_2 <= (v_cnt-(osd_h_hdr<<1))>>1; + v_osd_start_3 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<1)))>>1; + v_osd_start_4 <= (v_cnt-(osd_h_hdr<<2))>>1; + v_osd_start_5 <= (v_cnt-(osd_h_hdr + (osd_h_hdr<<2)))>>1; + + v_info_start_h <= rot[0] ? infox : infoy; + v_info_start_1 <= rot[0] ? infox : infoy; + v_info_start_2 <= rot[0] ? (infox<<1) : (infoy<<1); + v_info_start_3 <= rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1)); + v_info_start_4 <= rot[0] ? (infox << 2) : (infoy << 2); + v_info_start_5 <= rot[0] ? (infox + (infox << 2)) : (infoy + (infoy << 2)); end always @(posedge clk_video) begin reg deD; - reg [1:0] osd_div; - reg [1:0] multiscan; + reg [2:0] osd_div; + reg [2:0] multiscan; reg [7:0] osd_byte; reg [23:0] h_cnt; reg [21:0] dsp_width; @@ -199,26 +207,30 @@ always @(posedge clk_video) begin if(~osd_enable) osd_en <= 0; half <= 0; - if(v_cnt_half) begin + if(v_cnt_h) begin multiscan <= 0; - v_osd_start <= info ? (rot[0] ? infox : infoy) : v_osd_start_h; + v_osd_start <= info ? v_info_start_h : v_osd_start_h; half <= 1; end - else if(v_cnt_single | (rot[0] & v_cnt_double)) begin + else if(v_cnt_1 | (rot[0] & v_cnt_2)) begin multiscan <= 0; - v_osd_start <= info ? (rot[0] ? infox : infoy) : v_osd_start_s; + v_osd_start <= info ? v_info_start_1 : v_osd_start_1; end - else if(rot[0] ? v_cnt_triple : v_cnt_double) begin + else if(rot[0] ? v_cnt_3 : v_cnt_2) begin multiscan <= 1; - v_osd_start <= info ? (rot[0] ? (infox<<1) : (infoy<<1)) : v_osd_start_d; + v_osd_start <= info ? v_info_start_2 : v_osd_start_2; end - else if(v_cnt_triple | rot[0]) begin + else if(rot[0] ? v_cnt_4 : v_cnt_3) begin multiscan <= 2; - v_osd_start <= info ? (rot[0] ? (infox + (infox << 1)) : (infoy + (infoy << 1))) : v_osd_start_t; + v_osd_start <= info ? v_info_start_3 : v_osd_start_3; + end + else if(rot[0] | v_cnt_4) begin + multiscan <= 3; + v_osd_start <= info ? v_info_start_4 : v_osd_start_4; end else begin - multiscan <= 3; - v_osd_start <= info ? (rot[0] ? (infox<<2) : (infoy<<2)) : v_osd_start_q; + multiscan <= 4; + v_osd_start <= info ? v_info_start_5 : v_osd_start_5; end end end diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc index 74d9d97..67619ac 100644 --- a/sys/sys_top.sdc +++ b/sys/sys_top.sdc @@ -28,13 +28,16 @@ set_false_path -to {cfg[*]} set_false_path -from {cfg[*]} set_false_path -from {VSET[*]} set_false_path -to {wcalc[*] hcalc[*]} +set_false_path -to {width[*] height[*]} set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2 -set_multicycle_path -to {*_osd|osd_vcnt*} -hold 2 +set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1 set_false_path -to {*_osd|v_cnt*} set_false_path -to {*_osd|v_osd_start*} +set_false_path -to {*_osd|v_info_start*} set_false_path -to {*_osd|h_osd_start*} set_false_path -from {*_osd|v_osd_start*} +set_false_path -from {*_osd|v_info_start*} set_false_path -from {*_osd|h_osd_start*} set_false_path -from {*_osd|rot*} set_false_path -from {*_osd|dsp_width*} diff --git a/sys/sys_top.v b/sys/sys_top.v index 1c5c38b..e7e2cec 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -303,7 +303,7 @@ reg [8:0] coef_data; reg coef_wr = 0; wire [7:0] ARX, ARY; -reg [11:0] VSET = 0; +reg [11:0] VSET = 0, HSET = 0; reg [2:0] scaler_flt; reg lowlat = 0; reg cfg_dis = 0; @@ -387,6 +387,7 @@ always@(posedge clk_sys) begin if(cmd == 'h27) VSET <= io_din[11:0]; if(cmd == 'h2A) {coef_wr,coef_addr,coef_data} <= {1'b1,io_din}; if(cmd == 'h2B) scaler_flt <= io_din[2:0]; + if(cmd == 'h37) HSET <= io_din[11:0]; end end @@ -671,7 +672,12 @@ always @(posedge clk_vid) begin reg [2:0] state; reg [11:0] videow; reg [11:0] videoh; - + reg [11:0] height; + reg [11:0] width; + + height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT; + width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH; + state <= state + 1'd1; case(state) 0: if(FB_EN) begin @@ -682,21 +688,16 @@ always @(posedge clk_vid) begin state<= 0; end else if(ARX && ARY) begin - wcalc <= VSET ? (VSET*ARX)/ARY : (HEIGHT*ARX)/ARY; - hcalc <= (WIDTH*ARY)/ARX; + wcalc <= (height*ARX)/ARY; + hcalc <= (width*ARY)/ARX; end else begin - hmin <= 0; - hmax <= WIDTH - 1'd1; - vmin <= 0; - vmax <= HEIGHT - 1'd1; - wcalc<= WIDTH; - hcalc<= HEIGHT; - state<= 0; + wcalc <= width; + hcalc <= height; end 6: begin - videow <= (!VSET && (wcalc > WIDTH)) ? WIDTH : wcalc[11:0]; - videoh <= VSET ? VSET : (hcalc > HEIGHT) ? HEIGHT : hcalc[11:0]; + videow <= (wcalc > width) ? width : wcalc[11:0]; + videoh <= (hcalc > height) ? height : hcalc[11:0]; end 7: begin hmin <= ((WIDTH - videow)>>1); diff --git a/sys/video_mixer.sv b/sys/video_mixer.sv index 65f0fb4..8f204ee 100644 --- a/sys/video_mixer.sv +++ b/sys/video_mixer.sv @@ -185,41 +185,54 @@ end wire hde = scandoubler ? ~hb_sd : ~hb_g; wire vde = scandoubler ? ~vb_sd : ~vb_g; +reg [7:0] v_r,v_g,v_b; +reg v_vs,v_hs,v_de; always @(posedge clk_vid) begin reg old_hde; - case(scanlines & {scanline, scanline}) - 1: begin // reduce 25% = 1/2 + 1/4 - VGA_R <= {1'b0, r[7:1]} + {2'b00, r[7:2]}; - VGA_G <= {1'b0, g[7:1]} + {2'b00, g[7:2]}; - VGA_B <= {1'b0, b[7:1]} + {2'b00, b[7:2]}; - end + if(ce_pix_out) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + v_r <= {1'b0, r[7:1]} + {2'b00, r[7:2]}; + v_g <= {1'b0, g[7:1]} + {2'b00, g[7:2]}; + v_b <= {1'b0, b[7:1]} + {2'b00, b[7:2]}; + end - 2: begin // reduce 50% = 1/2 - VGA_R <= {1'b0, r[7:1]}; - VGA_G <= {1'b0, g[7:1]}; - VGA_B <= {1'b0, b[7:1]}; - end + 2: begin // reduce 50% = 1/2 + v_r <= {1'b0, r[7:1]}; + v_g <= {1'b0, g[7:1]}; + v_b <= {1'b0, b[7:1]}; + end - 3: begin // reduce 75% = 1/4 - VGA_R <= {2'b00, r[7:2]}; - VGA_G <= {2'b00, g[7:2]}; - VGA_B <= {2'b00, b[7:2]}; - end + 3: begin // reduce 75% = 1/4 + v_r <= {2'b00, r[7:2]}; + v_g <= {2'b00, g[7:2]}; + v_b <= {2'b00, b[7:2]}; + end - default: begin - VGA_R <= r; - VGA_G <= g; - VGA_B <= b; - end - endcase + default: begin + v_r <= r; + v_g <= g; + v_b <= b; + end + endcase - VGA_VS <= vs; - VGA_HS <= hs; + v_vs <= vs; + v_hs <= hs; - old_hde <= hde; - if(~old_hde && hde) VGA_DE <= vde; - if(old_hde && ~hde) VGA_DE <= 0; + old_hde <= hde; + if(~old_hde && hde) v_de <= vde; + if(old_hde && ~hde) v_de <= 0; + end +end + +always @(posedge clk_vid) if(ce_pix_out) begin + VGA_R <= v_r; + VGA_G <= v_g; + VGA_B <= v_b; + VGA_HS <= v_hs; + VGA_VS <= v_vs; + VGA_DE <= v_de; end endmodule