diff --git a/MacPlus.sdc b/MacPlus.sdc new file mode 100644 index 0000000..6372c8e --- /dev/null +++ b/MacPlus.sdc @@ -0,0 +1,5 @@ +derive_pll_clocks +derive_clock_uncertainty + +set_multicycle_path -from {emu|m68k|*} -setup 2 +set_multicycle_path -from {emu|m68k|*} -hold 1 diff --git a/files.qip b/files.qip index 86dcef8..0467d09 100644 --- a/files.qip +++ b/files.qip @@ -1,16 +1,17 @@ -set_global_assignment -name QIP_FILE src/tg68k/TG68K.qip -set_global_assignment -name SYSTEMVERILOG_FILE src/sdram.sv -set_global_assignment -name VERILOG_FILE src/scsi.v -set_global_assignment -name VERILOG_FILE src/ncr5380.v -set_global_assignment -name VERILOG_FILE src/floppy_track_encoder.v -set_global_assignment -name VERILOG_FILE src/floppy.v -set_global_assignment -name SYSTEMVERILOG_FILE src/ps2_kbd.sv -set_global_assignment -name VERILOG_FILE src/ps2_mouse.v -set_global_assignment -name VERILOG_FILE src/scc.v -set_global_assignment -name VERILOG_FILE src/iwm.v -set_global_assignment -name VERILOG_FILE src/via.v -set_global_assignment -name VERILOG_FILE src/addrDecoder.v -set_global_assignment -name VERILOG_FILE src/addrController_top.v -set_global_assignment -name VERILOG_FILE src/dataController_top.v -set_global_assignment -name VERILOG_FILE src/video.v +set_global_assignment -name QIP_FILE rtl/tg68k/TG68K.qip +set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VERILOG_FILE rtl/scsi.v +set_global_assignment -name VERILOG_FILE rtl/ncr5380.v +set_global_assignment -name VERILOG_FILE rtl/floppy_track_encoder.v +set_global_assignment -name VERILOG_FILE rtl/floppy.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/ps2_kbd.sv +set_global_assignment -name VERILOG_FILE rtl/ps2_mouse.v +set_global_assignment -name VERILOG_FILE rtl/scc.v +set_global_assignment -name VERILOG_FILE rtl/iwm.v +set_global_assignment -name VERILOG_FILE rtl/via.v +set_global_assignment -name VERILOG_FILE rtl/addrDecoder.v +set_global_assignment -name VERILOG_FILE rtl/addrController_top.v +set_global_assignment -name VERILOG_FILE rtl/dataController_top.v +set_global_assignment -name VERILOG_FILE rtl/video.v +set_global_assignment -name SDC_FILE MacPlus.sdc set_global_assignment -name SYSTEMVERILOG_FILE MacPlus.sv diff --git a/src/addrController_top.v b/rtl/addrController_top.v similarity index 100% rename from src/addrController_top.v rename to rtl/addrController_top.v diff --git a/src/addrDecoder.v b/rtl/addrDecoder.v similarity index 100% rename from src/addrDecoder.v rename to rtl/addrDecoder.v diff --git a/src/dataController_top.v b/rtl/dataController_top.v similarity index 100% rename from src/dataController_top.v rename to rtl/dataController_top.v diff --git a/src/floppy.v b/rtl/floppy.v similarity index 100% rename from src/floppy.v rename to rtl/floppy.v diff --git a/src/floppy_track_encoder.v b/rtl/floppy_track_encoder.v similarity index 100% rename from src/floppy_track_encoder.v rename to rtl/floppy_track_encoder.v diff --git a/src/iwm.v b/rtl/iwm.v similarity index 100% rename from src/iwm.v rename to rtl/iwm.v diff --git a/src/ncr5380.v b/rtl/ncr5380.v similarity index 100% rename from src/ncr5380.v rename to rtl/ncr5380.v diff --git a/sys/pll.qip b/rtl/pll.qip similarity index 100% rename from sys/pll.qip rename to rtl/pll.qip diff --git a/sys/pll.v b/rtl/pll.v similarity index 100% rename from sys/pll.v rename to rtl/pll.v diff --git a/sys/pll/pll_0002.qip b/rtl/pll/pll_0002.qip similarity index 100% rename from sys/pll/pll_0002.qip rename to rtl/pll/pll_0002.qip diff --git a/sys/pll/pll_0002.v b/rtl/pll/pll_0002.v similarity index 100% rename from sys/pll/pll_0002.v rename to rtl/pll/pll_0002.v diff --git a/src/ps2_kbd.sv b/rtl/ps2_kbd.sv similarity index 100% rename from src/ps2_kbd.sv rename to rtl/ps2_kbd.sv diff --git a/src/ps2_mouse.v b/rtl/ps2_mouse.v similarity index 100% rename from src/ps2_mouse.v rename to rtl/ps2_mouse.v diff --git a/src/scc.v b/rtl/scc.v similarity index 100% rename from src/scc.v rename to rtl/scc.v diff --git a/src/scsi.v b/rtl/scsi.v similarity index 100% rename from src/scsi.v rename to rtl/scsi.v diff --git a/src/sdram.sv b/rtl/sdram.sv similarity index 100% rename from src/sdram.sv rename to rtl/sdram.sv diff --git a/src/tg68k/TG68K.qip b/rtl/tg68k/TG68K.qip similarity index 100% rename from src/tg68k/TG68K.qip rename to rtl/tg68k/TG68K.qip diff --git a/src/tg68k/TG68K_ALU.vhd b/rtl/tg68k/TG68K_ALU.vhd similarity index 100% rename from src/tg68k/TG68K_ALU.vhd rename to rtl/tg68k/TG68K_ALU.vhd diff --git a/src/tg68k/TG68K_Pack.vhd b/rtl/tg68k/TG68K_Pack.vhd similarity index 100% rename from src/tg68k/TG68K_Pack.vhd rename to rtl/tg68k/TG68K_Pack.vhd diff --git a/src/tg68k/TG68KdotC_Kernel.vhd b/rtl/tg68k/TG68KdotC_Kernel.vhd similarity index 100% rename from src/tg68k/TG68KdotC_Kernel.vhd rename to rtl/tg68k/TG68KdotC_Kernel.vhd diff --git a/src/via.v b/rtl/via.v similarity index 100% rename from src/via.v rename to rtl/via.v diff --git a/src/video.v b/rtl/video.v similarity index 100% rename from src/video.v rename to rtl/video.v diff --git a/sys/hps_io.v b/sys/hps_io.v index eab005e..1f37785 100644 --- a/sys/hps_io.v +++ b/sys/hps_io.v @@ -1,964 +1,896 @@ -// -// hps_io.v -// -// Copyright (c) 2014 Till Harbaum -// Copyright (c) 2017-2019 Alexey Melnikov -// -// This source file is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This source file is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -/////////////////////////////////////////////////////////////////////// - -// -// Use buffer to access SD card. It's time-critical part. -// -// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. -// clk_ps2 = CLK_SYS/(PS2DIV*2) -// - -// WIDE=1 for 16 bit file I/O -// VDNUM 1-4 -module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) -( - input clk_sys, - inout [45:0] HPS_BUS, - - // parameter STRLEN and the actual length of conf_str have to match - input [(8*STRLEN)-1:0] conf_str, - - 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, - output reg [15:0] joystick_analog_0, - output reg [15:0] joystick_analog_1, - output reg [15:0] joystick_analog_2, - output reg [15:0] joystick_analog_3, - output reg [15:0] joystick_analog_4, - output reg [15:0] joystick_analog_5, - - output [1:0] buttons, - output forced_scandoubler, +// +// hps_io.v +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2017-2020 Alexey Melnikov +// +// This source file is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This source file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +/////////////////////////////////////////////////////////////////////// +// altera message_off 10665 + +// +// Use buffer to access SD card. It's time-critical part. +// +// WIDE=1 for 16 bit file I/O +// VDNUM 1-4 +module hps_io #(parameter STRLEN=0, PS2DIV=0, WIDE=0, VDNUM=1, PS2WE=0) +( + input clk_sys, + inout [45:0] HPS_BUS, + + // 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, + output reg [15:0] joystick_analog_3, + 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, - - output reg [63:0] status, - input [63:0] status_in, - input status_set, - input [15:0] status_menumask, - - input info_req, - input [7:0] info, - - //toggle to force notify of video mode change - input new_vmode, - - // SD config - output reg [VD:0] img_mounted, // signaling that new image has been mounted - output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted - output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted - - // SD block level access - input [31:0] sd_lba, - 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, - output reg sd_ack_conf, - - // SD byte level access. Signals for 2-PORT altsyncram. - output reg [AW:0] sd_buff_addr, - 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 [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, - - // [15]: 0 - unset, 1 - set. [1:0]: 0 - none, 1 - 32MB, 2 - 64MB, 3 - 128MB - // [14]: debug mode: [8]: 1 - phase up, 0 - phase down. [7:0]: amount of shift. + + output reg [63:0] status, + input [63:0] status_in, + input status_set, + input [15:0] status_menumask, + + input info_req, + input [7:0] info, + + //toggle to force notify of video mode change + input new_vmode, + + // SD config + output reg [VD:0] img_mounted, // signaling that new image has been mounted + output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted + output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted + + // SD block level access + input [31:0] sd_lba, + 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, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [AW:0] sd_buff_addr, + 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 [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, + + // [15]: 0 - unset, 1 - set. [1:0]: 0 - none, 1 - 32MB, 2 - 64MB, 3 - 128MB + // [14]: debug mode: [8]: 1 - phase up, 0 - phase down. [7:0]: amount of shift. output reg [15:0] sdram_sz, - - // RTC MSM6242B layout - output reg [64:0] RTC, - - // Seconds since 1970-01-01 00:00:00 - output reg [32:0] TIMESTAMP, - - // UART flags - input [15:0] uart_mode, - - // CD interface - input [48:0] cd_in, - output reg [48:0] cd_out, - - // ps2 keyboard emulation - output ps2_kbd_clk_out, - output ps2_kbd_data_out, - input ps2_kbd_clk_in, - input ps2_kbd_data_in, - - input [2:0] ps2_kbd_led_status, - input [2:0] ps2_kbd_led_use, - - output ps2_mouse_clk_out, - output ps2_mouse_data_out, - input ps2_mouse_clk_in, - input ps2_mouse_data_in, - - // ps2 alternative interface. - - // [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, - output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements - - inout [21:0] gamma_bus -); - -localparam DW = (WIDE) ? 15 : 7; -localparam AW = (WIDE) ? 7 : 8; -localparam VD = VDNUM-1; - -wire io_wait = ioctl_wait; -wire io_enable= |HPS_BUS[35:34]; + + // RTC MSM6242B layout + output reg [64:0] RTC, + + // 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, + input ps2_kbd_clk_in, + input ps2_kbd_data_in, + + input [2:0] ps2_kbd_led_status, + input [2:0] ps2_kbd_led_use, + + output ps2_mouse_clk_out, + output ps2_mouse_data_out, + input ps2_mouse_clk_in, + input ps2_mouse_data_in, + + // ps2 alternative interface. + + // [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, + output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements + + inout [21:0] gamma_bus, + + // for core-specific extensions + inout [35:0] EXT_BUS +); + +assign EXT_BUS[31:16] = HPS_BUS[31:16]; +assign EXT_BUS[35:33] = HPS_BUS[35:33]; + +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; + wire io_strobe= HPS_BUS[33]; -wire io_wide = (WIDE) ? 1'b1 : 1'b0; -wire [15:0] io_din = HPS_BUS[31:16]; -reg [15:0] io_dout; - -assign HPS_BUS[37] = io_wait; -assign HPS_BUS[36] = clk_sys; -assign HPS_BUS[32] = io_wide; -assign HPS_BUS[15:0] = io_dout; - +wire io_enable= HPS_BUS[34]; +wire fp_enable= HPS_BUS[35]; +wire io_wide = (WIDE) ? 1'b1 : 1'b0; +wire [15:0] io_din = HPS_BUS[31:16]; +reg [15:0] io_dout; + +assign HPS_BUS[37] = ioctl_wait; +assign HPS_BUS[36] = clk_sys; +assign HPS_BUS[32] = io_wide; +assign HPS_BUS[15:0] = EXT_BUS[32] ? EXT_BUS[15:0] : io_dout; + reg [15:0] cfg; -assign buttons = cfg[1:0]; -//cfg[2] - vga_scaler handled in sys_top -//cfg[3] - csync handled in sys_top -assign forced_scandoubler = cfg[4]; -//cfg[5] - ypbpr handled in sys_top +assign buttons = cfg[1:0]; +//cfg[2] - vga_scaler handled in sys_top +//cfg[3] - csync handled in sys_top +assign forced_scandoubler = cfg[4]; +//cfg[5] - ypbpr handled in sys_top assign direct_video = cfg[10]; - -// command byte read by the io controller -wire [15:0] sd_cmd = -{ - 2'b00, - (VDNUM>=4) ? sd_wr[3] : 1'b0, - (VDNUM>=3) ? sd_wr[2] : 1'b0, - (VDNUM>=2) ? sd_wr[1] : 1'b0, - - (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] -}; - -///////////////////////////////////////////////////////// - -wire [15:0] vc_dout; -video_calc video_calc -( - .clk_100(HPS_BUS[43]), - .clk_vid(HPS_BUS[42]), - .clk_sys(clk_sys), - .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) -); - -///////////////////////////////////////////////////////// - -assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value}; + +// command byte read by the io controller +wire [15:0] sd_cmd = +{ + 2'b00, + (VDNUM>=4) ? sd_wr[3] : 1'b0, + (VDNUM>=3) ? sd_wr[2] : 1'b0, + (VDNUM>=2) ? sd_wr[1] : 1'b0, + + (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] +}; + +///////////////////////////////////////////////////////// + +wire [15:0] vc_dout; +video_calc video_calc +( + .clk_100(HPS_BUS[43]), + .clk_vid(HPS_BUS[42]), + .clk_sys(clk_sys), + .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) +); + +///////////////////////////////////////////////////////// + +assign gamma_bus[20:0] = {clk_sys, gamma_en, gamma_wr, gamma_wr_addr, gamma_value}; reg gamma_en; reg gamma_wr; reg [9:0] gamma_wr_addr; reg [7:0] gamma_value; - -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 [2:0] b_wr; - reg [2:0] stick_idx; - reg ps2skip = 0; - reg [3:0] stflg = 0; - reg [63:0] status_req; - reg old_status_set = 0; - reg [7:0] cd_req = 0; - reg old_cd = 0; - reg old_info = 0; - reg [7:0] info_n = 0; - - old_status_set <= status_set; - if(~old_status_set & status_set) begin - stflg <= stflg + 1'd1; - status_req <= status_in; - end - - old_info <= info_req; - if(~old_info & info_req) info_n <= info; - - old_cd <= cd_in[48]; - if(old_cd ^ cd_in[48]) cd_req <= cd_req + 1'd1; - - 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); - - if(PS2DIV) {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; - - gamma_wr <= 0; - - if(~io_enable) begin - if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24]; - if(cmd == 5 && !ps2skip) begin - ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]}; - if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed - if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released - if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed - end - if(cmd == 'h22) RTC[64] <= ~RTC[64]; - if(cmd == 'h24) TIMESTAMP[32] <= ~TIMESTAMP[32]; - if(cmd == 'h35) cd_out[48] <= ~cd_out[48]; - cmd <= 0; - byte_cnt <= 0; - sd_ack <= 0; - sd_ack_conf <= 0; - io_dout <= 0; - ps2skip <= 0; - end else begin - if(io_strobe) begin - - io_dout <= 0; - if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; - - if(byte_cnt == 0) begin - cmd <= io_din; - - case(io_din) - 'h19: sd_ack_conf <= 1; - 'h17, - 'h18: sd_ack <= 1; - 'h29: io_dout <= {4'hA, stflg}; - 'h2B: io_dout <= 1; - 'h2F: io_dout <= 1; - 'h32: io_dout <= gamma_bus[21]; - 'h34: io_dout <= cd_req; - 'h36: begin io_dout <= info_n; info_n <= 0; end - endcase - - sd_buff_addr <= 0; - img_mounted <= 0; - if(io_din == 5) ps2_key_raw <= 0; - end else begin - - case(cmd) - // buttons and switches - 'h01: cfg <= io_din; - 'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din; - 'h03: if(byte_cnt==1) joystick_1[15:0] <= io_din; else joystick_1[31:16] <= io_din; - 'h10: if(byte_cnt==1) joystick_2[15:0] <= io_din; else joystick_2[31:16] <= io_din; - 'h11: if(byte_cnt==1) joystick_3[15:0] <= io_din; else joystick_3[31:16] <= io_din; - 'h12: if(byte_cnt==1) joystick_4[15:0] <= io_din; else joystick_4[31:16] <= io_din; - 'h13: if(byte_cnt==1) joystick_5[15:0] <= io_din; else joystick_5[31:16] <= io_din; - - // store incoming ps2 mouse bytes - 'h04: begin - if(PS2DIV) begin - mouse_data <= io_din[7:0]; - mouse_we <= 1; - end - if(&io_din[15:8]) ps2skip <= 1; - if(~&io_din[15:8] & ~ps2skip) begin - case(byte_cnt) - 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) - 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]; - endcase - end - end - - // 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]}; - if(PS2DIV) begin - kbd_data <= io_din[7:0]; - kbd_we <= 1; - end - 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: 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 - - // send SD config IO -> FPGA - // flag that download begins - // sd card knows data is config if sd_dout_strobe is asserted - // with sd_ack still being inactive (low) - 'h19, - // send sector IO -> FPGA - // flag that download begins - 'h17: begin - sd_buff_dout <= io_din[DW:0]; - b_wr <= 1; - end - - // reading sd card write data - 'h18: begin - if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; - io_dout <= sd_buff_din; - 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 - - // notify image selection - 'h1c: begin - img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; - img_readonly <= io_din[7]; - end - - // send image info - '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 - - // 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]}; - - // reading ps2 keyboard/mouse control - 'h21: if(PS2DIV) begin - 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: if(!byte_cnt[9:4]) io_dout <= vc_dout; - - //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: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 - 'h2E: if(byte_cnt == 1) io_dout <= status_menumask; - - //sdram size set - 'h31: if(byte_cnt == 1) sdram_sz <= io_din; - - // Gamma - 'h32: gamma_en <= io_din[0]; - 'h33: begin - gamma_wr_addr <= {(byte_cnt[1:0]-1'b1),io_din[15:8]}; - {gamma_wr, gamma_value} <= {1'b1,io_din[7:0]}; - if (byte_cnt[1:0] == 3) byte_cnt <= 1; - 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 - - //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 - endcase - end - end - end -end - - -/////////////////////////////// PS2 /////////////////////////////// -generate - if(PS2DIV) begin - reg clk_ps2; - always @(posedge clk_sys) begin - integer cnt; - cnt <= cnt + 1'd1; - if(cnt == PS2DIV) begin - clk_ps2 <= ~clk_ps2; - cnt <= 0; - end - end - - reg [7:0] kbd_data; - reg kbd_we; - wire [8:0] kbd_data_host; - reg kbd_rd; - - ps2_device keyboard - ( - .clk_sys(clk_sys), - - .wdata(kbd_data), - .we(kbd_we), - - .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), - - .rdata(kbd_data_host), - .rd(kbd_rd) - ); - - reg [7:0] mouse_data; - reg mouse_we; - wire [8:0] mouse_data_host; - reg mouse_rd; - - ps2_device mouse - ( - .clk_sys(clk_sys), - - .wdata(mouse_data), - .we(mouse_we), - - .ps2_clk(clk_ps2), - .ps2_clk_out(ps2_mouse_clk_out), - .ps2_dat_out(ps2_mouse_data_out), - - .ps2_clk_in(ps2_mouse_clk_in || !PS2WE), - .ps2_dat_in(ps2_mouse_data_in || !PS2WE), - - .rdata(mouse_data_host), - .rd(mouse_rd) - ); - end - else begin - assign ps2_kbd_clk_out = 0; - assign ps2_kbd_data_out = 0; - assign ps2_mouse_clk_out = 0; - assign ps2_mouse_data_out = 0; - end -endgenerate - -/////////////////////////////// DOWNLOADING /////////////////////////////// - -localparam UIO_FILE_TX = 8'h53; -localparam UIO_FILE_TX_DAT = 8'h54; -localparam UIO_FILE_INDEX = 8'h55; -localparam UIO_FILE_INFO = 8'h56; - -always@(posedge clk_sys) begin - reg [15:0] cmd; - reg [2:0] cnt; - reg has_cmd; - reg [26:0] addr; - reg wr; - - ioctl_wr <= wr; - wr <= 0; - - if(~io_enable) has_cmd <= 0; - else begin - if(io_strobe) begin - - if(!has_cmd) begin - cmd <= io_din; - has_cmd <= 1; - cnt <= 0; - end else begin - - case(cmd) - UIO_FILE_INFO: - if(~cnt[1]) begin - case(cnt) - 0: ioctl_file_ext[31:16] <= io_din; - 1: ioctl_file_ext[15:00] <= io_din; - endcase - cnt <= cnt + 1'd1; - end - - UIO_FILE_INDEX: - begin - ioctl_index <= io_din[7:0]; - end - - UIO_FILE_TX: - begin - if(io_din[7:0]) begin - addr <= 0; - ioctl_download <= 1; - end else begin - ioctl_addr <= addr; - ioctl_download <= 0; - end - end - - UIO_FILE_TX_DAT: - begin - ioctl_addr <= addr; - ioctl_dout <= io_din[DW:0]; - wr <= 1; - addr <= addr + (WIDE ? 2'd2 : 2'd1); - end - endcase - end - end - end -end - -endmodule - -////////////////////////////////////////////////////////////////////////////////// - - -module ps2_device #(parameter PS2_FIFO_BITS=5) -( - input clk_sys, - - input [7:0] wdata, - input we, - - input ps2_clk, - output reg ps2_clk_out, - output reg ps2_dat_out, - output reg tx_empty, - - input ps2_clk_in, - input ps2_dat_in, - - output [8:0] rdata, - input rd -); - - -(* ramstyle = "logic" *) reg [7:0] fifo[1<= 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]) - parity <= !parity; - end - - // transmission of parity - if(tx_state == 9) ps2_dat_out <= parity; - - // transmission of stop bit - if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1 - - // advance state machine - if(tx_state < 11) tx_state <= tx_state + 1'd1; - else tx_state <= 0; - end - end - end - - if(~old_clk & ps2_clk) ps2_clk_out <= 1; - if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2)); - -end - -endmodule - - -///////////////// calc video parameters ////////////////// -module video_calc -( - input clk_100, - input clk_vid, - input clk_sys, - - 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 @(posedge clk_sys) 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. -// -// Copyright (c) 2019 Alexey Melnikov -// - -module phase_shift #(parameter M32MB=0, M64MB=0, M128MB=0) -( - input reset, - - input clk, - input pll_locked, - - output reg phase_en, - output reg updn, - input phase_done, - - input [15:0] sdram_sz, - output reg ready -); - -localparam ph32 = ($signed(M32MB ) >= 0) ? M32MB : (0 - M32MB); -localparam ph64 = ($signed(M64MB ) >= 0) ? M64MB : (0 - M64MB); -localparam ph128 = ($signed(M128MB) >= 0) ? M128MB : (0 - M128MB); - -localparam up32 = ($signed(M32MB ) >= 0) ? 1'b1 : 1'b0; -localparam up64 = ($signed(M64MB ) >= 0) ? 1'b1 : 1'b0; -localparam up128 = ($signed(M128MB) >= 0) ? 1'b1 : 1'b0; - -always @(posedge clk, posedge reset) begin - reg [2:0] state = 0; - reg [7:0] cnt; - reg [8:0] ph; - - if(reset) begin - state <= 0; - ready <= 0; - end - else begin - case(state) - 0: begin - ready <= 0; - if(pll_locked) state <= state + 1'd1; - end - 1: if(sdram_sz[15]) begin - cnt <= 0; - if(sdram_sz[14]) ph <= sdram_sz[8:0]; - else begin - case(sdram_sz[1:0]) - 0: ph <= 0; - 1: ph <= {up32[0],ph32[7:0]}; - 2: ph <= {up64[0],ph64[7:0]}; - 3: ph <= {up128[0],ph128[7:0]}; - endcase - end - state <= state + 1'd1; - end - 2: if(ph[7:0]) begin - ph[7:0] <= ph[7:0] - 1'd1; - updn <= ph[8]; - state <= state + 1'd1; - end - else begin - state <= 6; - end - 3: begin - phase_en <= 1; - state <= state + 1'd1; - end - 4: if(~phase_done) begin - phase_en <= 0; - state <= state + 1'd1; - end - 5: if(phase_done) begin - cnt <= cnt + 1'd1; - if(cnt == ph[7:0]) state <= state + 1'd1; - else state <= 3; - end - 6: begin - ready <= 1; - if(!sdram_sz[15]) state <= 0; - end - endcase - end -end - -endmodule + +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 [MAX_W:0] byte_cnt; + +always@(posedge clk_sys) begin + reg [15:0] cmd; + reg [2:0] b_wr; + reg [3:0] stick_idx; + reg [3:0] pdsp_idx; + reg ps2skip = 0; + reg [3:0] stflg = 0; + reg [63:0] status_req; + reg old_status_set = 0; + reg old_info = 0; + reg [7:0] info_n = 0; + + old_status_set <= status_set; + if(~old_status_set & status_set) begin + stflg <= stflg + 1'd1; + status_req <= status_in; + end + + old_info <= info_req; + if(~old_info & info_req) info_n <= info; + + 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); + + if(PS2DIV) {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; + + gamma_wr <= 0; + + if(~io_enable) begin + if(cmd == 4 && !ps2skip) ps2_mouse[24] <= ~ps2_mouse[24]; + if(cmd == 5 && !ps2skip) begin + ps2_key <= {~ps2_key[10], pressed, extended, ps2_key_raw[7:0]}; + if(ps2_key_raw == 'hE012E07C) ps2_key[9:0] <= 'h37C; // prnscr pressed + if(ps2_key_raw == 'h7CE0F012) ps2_key[9:0] <= 'h17C; // prnscr released + if(ps2_key_raw == 'hF014F077) ps2_key[9:0] <= 'h377; // pause pressed + end + if(cmd == 'h22) RTC[64] <= ~RTC[64]; + if(cmd == 'h24) TIMESTAMP[32] <= ~TIMESTAMP[32]; + cmd <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + io_dout <= 0; + ps2skip <= 0; + end + else if(io_strobe) begin + + io_dout <= 0; + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + if(byte_cnt == 0) begin + cmd <= io_din; + + case(io_din) + 'h19: sd_ack_conf <= 1; + 'h17, + 'h18: sd_ack <= 1; + 'h29: io_dout <= {4'hA, stflg}; + 'h2B: io_dout <= 1; + 'h2F: io_dout <= 1; + 'h32: io_dout <= gamma_bus[21]; + 'h36: begin io_dout <= info_n; info_n <= 0; end + endcase + + sd_buff_addr <= 0; + img_mounted <= 0; + if(io_din == 5) ps2_key_raw <= 0; + end else begin + + case(cmd) + // buttons and switches + 'h01: cfg <= io_din; + 'h02: if(byte_cnt==1) joystick_0[15:0] <= io_din; else joystick_0[31:16] <= io_din; + 'h03: if(byte_cnt==1) joystick_1[15:0] <= io_din; else joystick_1[31:16] <= io_din; + 'h10: if(byte_cnt==1) joystick_2[15:0] <= io_din; else joystick_2[31:16] <= io_din; + 'h11: if(byte_cnt==1) joystick_3[15:0] <= io_din; else joystick_3[31:16] <= io_din; + 'h12: if(byte_cnt==1) joystick_4[15:0] <= io_din; else joystick_4[31:16] <= io_din; + 'h13: if(byte_cnt==1) joystick_5[15:0] <= io_din; else joystick_5[31:16] <= io_din; + + // store incoming ps2 mouse bytes + 'h04: begin + if(PS2DIV) begin + mouse_data <= io_din[7:0]; + mouse_we <= 1; + end + if(&io_din[15:8]) ps2skip <= 1; + 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[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]; + endcase + end + end + + // 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]}; + if(PS2DIV) begin + kbd_data <= io_din[7:0]; + kbd_we <= 1; + end + 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: 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 + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 'h19, + // send sector IO -> FPGA + // flag that download begins + 'h17: begin + sd_buff_dout <= io_din[DW:0]; + b_wr <= 1; + end + + // reading sd card write data + 'h18: begin + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + io_dout <= sd_buff_din; + end + + // joystick analog + '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 + img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; + img_readonly <= io_din[7]; + end + + // send image info + 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; + + // status, 64bit version + '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]}; + + // reading ps2 keyboard/mouse control + 'h21: if(PS2DIV) begin + 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: if(!byte_cnt[MAX_W:4]) io_dout <= vc_dout; + + //RTC + 'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //UART flags + 'h28: io_dout <= uart_mode; + + //status set + '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; + + //sdram size set + 'h31: if(byte_cnt == 1) sdram_sz <= io_din; + + // Gamma + 'h32: gamma_en <= io_din[0]; + 'h33: begin + gamma_wr_addr <= {(byte_cnt[1:0]-1'b1),io_din[15:8]}; + {gamma_wr, gamma_value} <= {1'b1,io_din[7:0]}; + if (byte_cnt[1:0] == 3) byte_cnt <= 1; + end + endcase + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +generate + if(PS2DIV) begin + reg clk_ps2; + always @(posedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end + end + + reg [7:0] kbd_data; + reg kbd_we; + wire [8:0] kbd_data_host; + reg kbd_rd; + + ps2_device keyboard + ( + .clk_sys(clk_sys), + + .wdata(kbd_data), + .we(kbd_we), + + .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), + + .rdata(kbd_data_host), + .rd(kbd_rd) + ); + + reg [7:0] mouse_data; + reg mouse_we; + wire [8:0] mouse_data_host; + reg mouse_rd; + + ps2_device mouse + ( + .clk_sys(clk_sys), + + .wdata(mouse_data), + .we(mouse_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_mouse_clk_out), + .ps2_dat_out(ps2_mouse_data_out), + + .ps2_clk_in(ps2_mouse_clk_in || !PS2WE), + .ps2_dat_in(ps2_mouse_data_in || !PS2WE), + + .rdata(mouse_data_host), + .rd(mouse_rd) + ); + end + else begin + assign ps2_kbd_clk_out = 0; + assign ps2_kbd_data_out = 0; + assign ps2_mouse_clk_out = 0; + assign ps2_mouse_data_out = 0; + end +endgenerate + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; +localparam UIO_FILE_INFO = 8'h56; + +always@(posedge clk_sys) begin + reg [15:0] cmd; + reg [2:0] cnt; + reg has_cmd; + reg [26:0] addr; + reg wr; + + ioctl_wr <= wr; + wr <= 0; + + if(~fp_enable) has_cmd <= 0; + else begin + if(io_strobe) begin + + if(!has_cmd) begin + cmd <= io_din; + has_cmd <= 1; + cnt <= 0; + end else begin + + case(cmd) + UIO_FILE_INFO: + if(~cnt[1]) begin + case(cnt) + 0: ioctl_file_ext[31:16] <= io_din; + 1: ioctl_file_ext[15:00] <= io_din; + endcase + cnt <= cnt + 1'd1; + end + + UIO_FILE_INDEX: + begin + ioctl_index <= io_din[7:0]; + end + + UIO_FILE_TX: + begin + if(io_din[7:0]) begin + addr <= 0; + ioctl_download <= 1; + end else begin + ioctl_addr <= addr; + ioctl_download <= 0; + end + end + + UIO_FILE_TX_DAT: + begin + ioctl_addr <= addr; + ioctl_dout <= io_din[DW:0]; + wr <= 1; + addr <= addr + (WIDE ? 2'd2 : 2'd1); + end + endcase + end + end + end +end + +endmodule + +////////////////////////////////////////////////////////////////////////////////// + + +module ps2_device #(parameter PS2_FIFO_BITS=5) +( + input clk_sys, + + input [7:0] wdata, + input we, + + input ps2_clk, + output reg ps2_clk_out, + output reg ps2_dat_out, + output reg tx_empty, + + input ps2_clk_in, + input ps2_dat_in, + + output [8:0] rdata, + input rd +); + + +(* ramstyle = "logic" *) reg [7:0] fifo[1<= 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]) + parity <= !parity; + end + + // transmission of parity + if(tx_state == 9) ps2_dat_out <= parity; + + // transmission of stop bit + if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1 + + // advance state machine + if(tx_state < 11) tx_state <= tx_state + 1'd1; + else tx_state <= 0; + end + end + end + + if(~old_clk & ps2_clk) ps2_clk_out <= 1; + if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2)); + +end + +endmodule + + +///////////////// calc video parameters ////////////////// +module video_calc +( + input clk_100, + input clk_vid, + input clk_sys, + + 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 @(posedge clk_sys) 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 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/pll.13.qip b/sys/pll.13.qip index a5cd7dc..a6a1dca 100644 --- a/sys/pll.13.qip +++ b/sys/pll.13.qip @@ -4,9 +4,13 @@ set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] set_global_assignment -name SYNTHESIS_ONLY_QIP ON -set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] -set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"] -set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002_q13.qip"] +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll.v +set_global_assignment -library "pll" -name VERILOG_FILE rtl/pll/pll_0002.v + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "13.1" diff --git a/sys/pll/pll_0002_q13.qip b/sys/pll/pll_0002_q13.qip deleted file mode 100644 index 9f8ded1..0000000 --- a/sys/pll/pll_0002_q13.qip +++ /dev/null @@ -1,4 +0,0 @@ -set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_hdmi.13.qip b/sys/pll_hdmi.13.qip index 705d514..76def89 100644 --- a/sys/pll_hdmi.13.qip +++ b/sys/pll_hdmi.13.qip @@ -6,7 +6,11 @@ set_global_assignment -name SYNTHESIS_ONLY_QIP ON set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] -set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002_q13.qip"] + +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "13.1" diff --git a/sys/pll_hdmi/pll_hdmi_0002_q13.qip b/sys/pll_hdmi/pll_hdmi_0002_q13.qip deleted file mode 100644 index fb8053d..0000000 --- a/sys/pll_hdmi/pll_hdmi_0002_q13.qip +++ /dev/null @@ -1,4 +0,0 @@ -set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" -set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_q17.qip b/sys/pll_q17.qip index 9c69934..5bc92e0 100644 --- a/sys/pll_q17.qip +++ b/sys/pll_q17.qip @@ -1,3 +1,3 @@ -set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll.qip ] +set_global_assignment -name QIP_FILE rtl/pll.qip set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_hdmi.qip ] set_global_assignment -name QIP_FILE [file join $::quartus(qip_path) pll_cfg.qip ] 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..c8ef6f7 100644 --- a/sys/sys_top.v +++ b/sys/sys_top.v @@ -235,7 +235,6 @@ wire io_clk = gp_outr[17]; wire io_ss0 = gp_outr[18]; wire io_ss1 = gp_outr[19]; wire io_ss2 = gp_outr[20]; -//wire io_sdd = gp_outr[21]; // used only in ST core wire io_osd_hdmi = io_ss1 & ~io_ss0; wire io_fpga = ~io_ss1 & io_ss0; @@ -303,13 +302,16 @@ 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 FREESCALE = 0; reg [2:0] scaler_flt; reg lowlat = 0; reg cfg_dis = 0; reg vs_wait = 0; +reg [11:0] vs_line = 0; +reg scaler_out = 0; always@(posedge clk_sys) begin reg [7:0] cmd; reg has_cmd; @@ -336,6 +338,7 @@ always@(posedge clk_sys) begin if(cmd == 1) begin cfg <= io_din; cfg_set <= 1; + scaler_out <= 1; end if(cmd == 'h20) begin cfg_set <= 0; @@ -384,12 +387,14 @@ always@(posedge clk_sys) begin end if(cmd == 'h25) {led_overtake, led_state} <= io_din; if(cmd == 'h26) vol_att <= io_din[4:0]; - if(cmd == 'h27) VSET <= io_din[11:0]; + 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) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]}; + if(cmd == 'h38) vs_line <= io_din[11:0]; end end - + vs_d0 <= HDMI_TX_VS; if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0; @@ -434,7 +439,7 @@ cyclonev_hps_interface_peripheral_spi_master spi .ss_in_n(1) ); -wire [63:0] f2h_irq = {HDMI_TX_VS}; +wire [63:0] f2h_irq = {video_sync,HDMI_TX_VS}; cyclonev_hps_interface_interrupts interrupts ( .irq(f2h_irq) @@ -599,7 +604,7 @@ ascal .vimax (0), .o_clk (clk_hdmi), - .o_ce (1), + .o_ce (scaler_out), .o_r (hdmi_data[23:16]), .o_g (hdmi_data[15:8]), .o_b (hdmi_data[7:0]), @@ -671,7 +676,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 @@ -681,22 +691,17 @@ always @(posedge clk_vid) begin vmax <= FB_VMAX; state<= 0; end - else if(ARX && ARY) begin - wcalc <= VSET ? (VSET*ARX)/ARY : (HEIGHT*ARX)/ARY; - hcalc <= (WIDTH*ARY)/ARX; + else if(ARX && ARY && !FREESCALE) begin + 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); @@ -1047,6 +1052,31 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd); assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : vga_o[7:2]; `endif +reg video_sync = 0; +always @(posedge clk_vid) begin + reg [11:0] line_cnt = 0; + reg [11:0] sync_line = 0; + reg [1:0] hs_cnt = 0; + reg old_hs; + + old_hs <= hs_fix; + if(~old_hs & hs_fix) begin + + video_sync <= (sync_line == line_cnt); + + line_cnt <= line_cnt + 1'd1; + if(~hs_cnt[1]) begin + hs_cnt <= hs_cnt + 1'd1; + if(hs_cnt[0]) begin + sync_line <= (line_cnt - vs_line); + line_cnt <= 0; + end + end + end + + if(de_emu) hs_cnt <= 0; +end + ///////////////////////// Audio output //////////////////////////////// assign SDCD_SPDIF =(SW[3] & ~spdif) ? 1'b0 : 1'bZ; 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