From 0490b2fa2c005d2c2b36172beebb51b6920df955 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sun, 9 Sep 2018 11:59:45 +0800 Subject: [PATCH] Support dual-way (OSD/HotKey) settings (CPU speed for now). --- sys/hps_io.v | 114 +++++++++++++++++++++++++++----------------------- zxspectrum.sv | 81 +++++++++++++++++++++++------------ 2 files changed, 116 insertions(+), 79 deletions(-) diff --git a/sys/hps_io.v b/sys/hps_io.v index a7f8962..51eaf26 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -47,7 +47,9 @@ module hps_io #(parameter STRLEN=0, PS2DIV=2000, WIDE=0, VDNUM=1, PS2WE=0) output forced_scandoubler, output reg [31:0] status, - + input [31:0] status_in, + input status_set, + //toggle to force notify of video mode change input new_vmode, @@ -61,7 +63,7 @@ module hps_io #(parameter STRLEN=0, PS2DIV=2000, WIDE=0, VDNUM=1, PS2WE=0) input [VD:0] sd_rd, // only single sd_rd can be active at any given time input [VD:0] sd_wr, // only single sd_wr can be active at any given time output reg sd_ack, - + // do not use in new projects. // CID and CSD are fake except CSD image size field. input sd_conf, @@ -88,6 +90,9 @@ module hps_io #(parameter STRLEN=0, PS2DIV=2000, WIDE=0, VDNUM=1, PS2WE=0) // Seconds since 1970-01-01 00:00:00 output reg [32:0] TIMESTAMP, + // UART flags + input [15:0] uart_mode, + // ps2 keyboard emulation output ps2_kbd_clk_out, output ps2_kbd_data_out, @@ -106,7 +111,7 @@ module hps_io #(parameter STRLEN=0, PS2DIV=2000, WIDE=0, VDNUM=1, PS2WE=0) // [8] - extended, [9] - pressed, [10] - toggles with every press/release output reg [10:0] ps2_key = 0, - + // [24] - toggles with every event output reg [24:0] ps2_mouse = 0 ); @@ -135,7 +140,7 @@ assign forced_scandoubler = cfg[4]; //cfg[5] - ypbpr handled in sys_top // command byte read by the io controller -wire [15:0] sd_cmd = +wire [15:0] sd_cmd = { 2'b00, (VDNUM>=4) ? sd_wr[3] : 1'b0, @@ -145,7 +150,7 @@ wire [15:0] sd_cmd = (VDNUM>=4) ? sd_rd[3] : 1'b0, (VDNUM>=3) ? sd_rd[2] : 1'b0, (VDNUM>=2) ? sd_rd[1] : 1'b0, - + 4'h5, sd_conf, 1'b1, sd_wr[0], sd_rd[0] @@ -261,13 +266,20 @@ always@(posedge clk_sys) begin reg [2:0] b_wr; reg [2:0] stick_idx; reg ps2skip = 0; + reg [3:0] stflg = 0; + reg [31:0] status_req; + + if(status_set) begin + stflg <= stflg + 1'd1; + status_req <= status_in; + end sd_buff_wr <= b_wr[0]; if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; b_wr <= (b_wr<<1); {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; - + if(~io_enable) begin if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24]; if(cmd == 5 && !ps2skip) begin @@ -297,6 +309,7 @@ always@(posedge clk_sys) begin 'h19: sd_ack_conf <= 1; 'h17, 'h18: sd_ack <= 1; + 'h29: io_dout <= {4'hA, stflg}; endcase sd_buff_addr <= 0; @@ -306,11 +319,11 @@ always@(posedge clk_sys) begin case(cmd) // buttons and switches - 'h01: cfg <= io_din[7:0]; + 'h01: cfg <= io_din[7:0]; 'h02: joystick_0 <= io_din; 'h03: joystick_1 <= io_din; - // store incoming ps2 mouse bytes + // store incoming ps2 mouse bytes 'h04: begin mouse_data <= io_din[7:0]; mouse_we <= 1; @@ -324,7 +337,7 @@ always@(posedge clk_sys) begin end end - // store incoming ps2 keyboard bytes + // store incoming ps2 keyboard bytes 'h05: begin if(&io_din[15:8]) ps2skip <= 1; if(~&io_din[15:8] & ~ps2skip) ps2_key_raw[31:0] <= {ps2_key_raw[23:0], io_din[7:0]}; @@ -332,20 +345,15 @@ always@(posedge clk_sys) begin kbd_we <= 1; end - // reading config string - 'h14: begin - // returning a byte from string - if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; - end + // reading config string, returning a byte from string + 'h14: if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; // reading sd card status - 'h16: begin - case(byte_cnt) + 'h16: case(byte_cnt) 1: io_dout <= sd_cmd; 2: io_dout <= sd_lba[15:0]; 3: io_dout <= sd_lba[31:16]; endcase - end // send SD config IO -> FPGA // flag that download begins @@ -366,14 +374,11 @@ always@(posedge clk_sys) begin end // joystick analog - 'h1a: begin - // first byte is joystick index - if(byte_cnt == 1) stick_idx <= io_din[2:0]; - if(byte_cnt == 2) begin - if(stick_idx == 0) joystick_analog_0 <= io_din; - if(stick_idx == 1) joystick_analog_1 <= io_din; - end - end + 'h1a: case(byte_cnt) + 1: stick_idx <= io_din[2:0]; // first byte is joystick index + 2: if(stick_idx == 0) joystick_analog_0 <= io_din; + else if(stick_idx == 1) joystick_analog_1 <= io_din; + endcase // notify image selection 'h1c: begin @@ -392,41 +397,46 @@ always@(posedge clk_sys) begin '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]}; // reading ps2 keyboard/mouse control - 'h21: begin - if(byte_cnt == 1) begin + 'h21: if(byte_cnt == 1) begin io_dout <= kbd_data_host; kbd_rd <= 1; end - + else if(byte_cnt == 2) begin io_dout <= mouse_data_host; mouse_rd <= 1; end - end //RTC 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; //Video res. - 'h23: begin - case(byte_cnt) - 1: io_dout <= 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 - end + 'h23: case(byte_cnt) + 1: io_dout <= 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 //RTC 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //UART flags + 'h28: io_dout <= uart_mode; + + //status set + 'h29: case(byte_cnt) + 1: io_dout <= status_req[15:0]; + 2: io_dout <= status_req[31:16]; + endcase endcase end end @@ -460,7 +470,7 @@ ps2_device keyboard .ps2_clk(clk_ps2), .ps2_clk_out(ps2_kbd_clk_out), .ps2_dat_out(ps2_kbd_data_out), - + .ps2_clk_in(ps2_kbd_clk_in || !PS2WE), .ps2_dat_in(ps2_kbd_data_in || !PS2WE), @@ -538,7 +548,7 @@ always@(posedge clk_sys) begin begin if(io_din[7:0]) begin addr <= 0; - ioctl_download <= 1; + ioctl_download <= 1; end else begin ioctl_addr <= addr; ioctl_download <= 0; @@ -577,7 +587,7 @@ module ps2_device #(parameter PS2_FIFO_BITS=5) input ps2_clk_in, input ps2_dat_in, - + output [8:0] rdata, input rd ); @@ -632,7 +642,7 @@ always@(posedge clk_sys) begin rx_state <= rx_state + 1'b1; rx_cnt <= 0; end - + 2: begin if(rx_cnt <= 7) data <= {d1, data[7:1]}; else rx_state <= rx_state + 1'b1; @@ -643,7 +653,7 @@ always@(posedge clk_sys) begin rx_state <= rx_state + 1'b1; ps2_dat_out <= 0; end - + 4: begin ps2_dat_out <= 1; has_data <= 1; @@ -678,7 +688,7 @@ always@(posedge clk_sys) begin if((tx_state >= 1)&&(tx_state < 9)) begin ps2_dat_out <= tx_byte[0]; // data bits tx_byte[6:0] <= tx_byte[7:1]; // shift down - if(tx_byte[0]) + if(tx_byte[0]) parity <= !parity; end diff --git a/zxspectrum.sv b/zxspectrum.sv index 9845228..37f9ab0 100644 --- a/zxspectrum.sv +++ b/zxspectrum.sv @@ -128,6 +128,7 @@ localparam CONF_STR1 = { "O23,Stereo mix,none,25%,50%,100%;", "-;", "OHJ,Joystick,Kempston,Sinclair I,Sinclair II,Sinclair I+II,Cursor;", + "OMO,CPU Speed,Original,7MHz,14MHz,28MHz,56MHz;", "OD,Port #FF,Timex,SAA1099;", "OE,ULA+,Enabled,Disabled;", "OAC,Memory,Spectrum 128K/+2,Pentagon 1024K,Profi 1024K,Spectrum 48K,Spectrum +2A/+3;" @@ -194,24 +195,38 @@ always @(negedge clk_sys) begin ce_cpu_tn <= !((counter & turbo) ^ turbo ^ turbo[4:1]); end -reg [4:0] turbo = 5'b11111, turbo_key = 5'b11111; + +wire [4:0] turbo_req; +always_comb begin + casex({tape_active & ~status[6], status[24:22]}) + 'b1XXX: turbo_req = 5'b00001; + 'b0001: turbo_req = 5'b01111; + 'b0010: turbo_req = 5'b00111; + 'b0011: turbo_req = 5'b00011; + 'b0100: turbo_req = 5'b00001; + default: turbo_req = 5'b11111; + endcase +end + +reg [2:0] speed_req; always @(posedge clk_sys) begin reg [9:4] old_Fn; old_Fn <= Fn[9:4]; if(reset) pause <= 0; + status_set <= 0; if(!mod) begin - if(~old_Fn[4] & Fn[4]) turbo_key <= 5'b11111; - if(~old_Fn[5] & Fn[5]) turbo_key <= 5'b01111; - if(~old_Fn[6] & Fn[6]) turbo_key <= 5'b00111; - if(~old_Fn[7] & Fn[7]) turbo_key <= 5'b00011; - if(~old_Fn[8] & Fn[8]) turbo_key <= 5'b00001; + if(~old_Fn[4] & Fn[4]) {status_set,speed_req} <= 4'b1_000; + if(~old_Fn[5] & Fn[5]) {status_set,speed_req} <= 4'b1_001; + if(~old_Fn[6] & Fn[6]) {status_set,speed_req} <= 4'b1_010; + if(~old_Fn[7] & Fn[7]) {status_set,speed_req} <= 4'b1_011; + if(~old_Fn[8] & Fn[8]) {status_set,speed_req} <= 4'b1_100; if(~old_Fn[9] & Fn[9]) pause <= ~pause; end end -wire [4:0] turbo_req = (tape_active & ~status[6]) ? 5'b00001 : turbo_key; +reg [4:0] turbo = 5'b11111; always @(posedge clk_sys) begin reg [1:0] timeout; @@ -272,33 +287,45 @@ wire [7:0] ioctl_dout; wire ioctl_download; wire [7:0] ioctl_index; +reg status_set; +reg [31:0] status_out; + hps_io #(.STRLEN(($size(CONF_STR1)>>3)+($size(CONF_STR2)>>3)+5+1)) hps_io ( - .*, + .clk_sys(clk_sys), + .HPS_BUS(HPS_BUS), + .conf_str({CONF_STR1, need_apply ? "R" : "+", CONF_STR2, plus3_fdd_ready ? CONF_PLUS3 : plusd_en ? CONF_PLUSD : CONF_BDI}), - .sd_conf(0), - .ioctl_wait(0), - .sd_ack_conf(), .ps2_key(ps2_key), - .ps2_kbd_led_use(0), - .ps2_kbd_led_status(0), .ps2_mouse(ps2_mouse), - // unused - .ioctl_file_ext(), - .joystick_analog_0(), - .joystick_analog_1(), - .RTC(), - .TIMESTAMP(), - .ps2_kbd_clk_out(), - .ps2_kbd_data_out(), - .ps2_mouse_clk_out(), - .ps2_mouse_data_out(), - .ps2_kbd_clk_in(1), - .ps2_kbd_data_in(1), - .ps2_mouse_clk_in(1), - .ps2_mouse_data_in(1) + .joystick_0(joystick_0), + .joystick_1(joystick_1), + .buttons(buttons), + .forced_scandoubler(forced_scandoubler), + .status(status), + .status_set(status_set), + .status_in({status[31:25],speed_req,status[21:0]}), + + .sd_lba(sd_lba), + .sd_rd(sd_rd), + .sd_wr(sd_wr), + .sd_ack(sd_ack), + .sd_buff_addr(sd_buff_addr), + .sd_buff_dout(sd_buff_dout), + .sd_buff_din(sd_buff_din), + .sd_buff_wr(sd_buff_wr), + .img_mounted(img_mounted), + .img_size(img_size), + .img_readonly(img_readonly), + + .ioctl_wr(ioctl_wr), + .ioctl_addr(ioctl_addr), + .ioctl_dout(ioctl_dout), + .ioctl_download(ioctl_download), + .ioctl_index(ioctl_index), + .ioctl_wait(0) ); reg [2:0] cur_mode = 0;