diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/ReadMe.txt b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/ReadMe.txt index ee68fd00..4ff7a9b7 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/ReadMe.txt +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/ReadMe.txt @@ -15,13 +15,13 @@ --------------------------------------------------------------------------------- -- -- --- Keyboard inputs : +-- Keyboard and Joystick controls : -- --- ESC : Coin + Start --- SPACE : Fire --- CTRL,UP : Jump --- LEFT,RIGHT : Increase/Decrease the speed +-- ESC or Button C : Coin +-- 1, 2 or Button Start : Start +-- SPACE or Button A : Fire +-- ALT, UP or Button B : Jump +-- LEFT,RIGHT : Increase/Decrease the speed -- --- Joystick support. --- ---------------------------------------------------------------------------------- \ No newline at end of file +-- +--------------------------------------------------------------------------------- diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf index 70e61ae1..7e86a389 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/mpatrol.qsf @@ -234,7 +234,7 @@ set_global_assignment -name VERILOG_FILE src/keyboard.v set_global_assignment -name VERILOG_FILE src/scandoubler.v set_global_assignment -name SYSTEMVERILOG_FILE src/rgb2ypbpr.sv set_global_assignment -name VERILOG_FILE src/osd.v -set_global_assignment -name VERILOG_FILE src/mist_io.v +set_global_assignment -name VERILOG_FILE src/user_io.v set_global_assignment -name VHDL_FILE src/sprite_array.vhd set_global_assignment -name VHDL_FILE src/Clock.vhd set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/input_mapper.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/input_mapper.vhd index bd898ba2..a4d45fc1 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/input_mapper.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/input_mapper.vhd @@ -34,7 +34,7 @@ architecture SYN of inputmapper is begin - process (clk, rst_n) + process (clk, rst_n, dips) variable jamma_v : from_MAPPED_INPUTS_t(0 to NUM_INPUTS-1); variable keybd_v : from_MAPPED_INPUTS_t(0 to NUM_INPUTS-1); begin @@ -76,9 +76,9 @@ begin inputs(0).d <= jamma_v(0).d and not keybd_v(0).d; inputs(1).d <= jamma_v(1).d and not keybd_v(1).d; inputs(2).d <= jamma_v(2).d and not keybd_v(2).d; - inputs(3).d <= "11111111"; -- 1C/1C, 10/30/50K, 3 lives + inputs(3).d <= dips(7 downto 0); --"11111111"; -- 1C/1C, 10/30/50K, 3 lives - inputs(4).d <= "11111100"; + inputs(4).d <= dips(15 downto 8);--"11111100"; -- activate service which is only checked on startup -- inputs(4).d <= "01111100"; inputs(NUM_INPUTS-1).d <= keybd_v(NUM_INPUTS-1).d; diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mist_io.v b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mist_io.v deleted file mode 100644 index 2a935b22..00000000 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mist_io.v +++ /dev/null @@ -1,503 +0,0 @@ -// -// mist_io.v -// -// mist_io for the MiST board -// http://code.google.com/p/mist-board/ -// -// Copyright (c) 2014 Till Harbaum -// -// 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. -// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK -// (Sorgelig) -// -// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. -// clk_ps2 = clk_sys/(PS2DIV*2) -// - -module mist_io #(parameter PS2DIV=100) -( - - // parameter STRLEN and the actual length of conf_str have to match -// input [(8*STRLEN)-1:0] conf_str, - - // Global clock. It should be around 100MHz (higher is better). - input clk_sys, - - // Global SPI clock from ARM. 24MHz - input SPI_SCK, - - input CONF_DATA0, - input SPI_SS2, - output SPI_DO, - input SPI_DI, - - output reg [7:0] joystick_0, - output reg [7:0] joystick_1, - output reg [15:0] joystick_analog_0, - output reg [15:0] joystick_analog_1, - output [1:0] buttons, - output [1:0] switches, - output scan_disable, - output ypbpr, - - output reg [31:0] status, - - // SD config - input sd_conf, - input sd_sdhc, - output img_mounted, // signaling that new image has been mounted - output reg [31:0] img_size, // size of image in bytes - - // SD block level access - input [31:0] sd_lba, - input sd_rd, - input sd_wr, - output reg sd_ack, - output reg sd_ack_conf, - - // SD byte level access. Signals for 2-PORT altsyncram. - output reg [8:0] sd_buff_addr, - output reg [7:0] sd_buff_dout, - input [7:0] sd_buff_din, - output reg sd_buff_wr, - - // ps2 keyboard emulation - output ps2_kbd_clk, - output reg ps2_kbd_data, - output ps2_mouse_clk, - output reg ps2_mouse_data, - input ps2_caps_led, - - // 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 ioctl_wr, - output reg [24:0] ioctl_addr, - output reg [7:0] ioctl_dout -); - -`include "src\build_id.v" - -localparam conf_str = { - "Moon Patr.;;", - "O34,Scandoubler Fx,None,CRT 25%,CRT 50%,CRT 75%;", - "T5,Reset;", - "V,v1.11.",`BUILD_DATE -}; - -localparam STRLEN = ($size(conf_str)>>3); - - -reg [7:0] b_data; -reg [6:0] sbuf; -reg [7:0] cmd; -reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... -reg [9:0] byte_cnt; // counts bytes -reg [7:0] but_sw; -reg [2:0] stick_idx; - -reg mount_strobe = 0; -assign img_mounted = mount_strobe; - -assign buttons = but_sw[1:0]; -assign switches = but_sw[3:2]; -assign scan_disable = but_sw[4]; -assign ypbpr = but_sw[5]; - -wire [7:0] spi_dout = { sbuf, SPI_DI}; - -// this variant of user_io is for 8 bit cores (type == a4) only -wire [7:0] core_type = 8'ha4; - -// command byte read by the io controller -wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; - -reg spi_do; -assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; - -wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; - -// drive MISO only when transmitting core id -always@(negedge SPI_SCK) begin - if(!CONF_DATA0) begin - // first byte returned is always core type, further bytes are - // command dependent - if(byte_cnt == 0) begin - spi_do <= core_type[~bit_cnt]; - - end else begin - case(cmd) - // reading config string - 8'h14: begin - // returning a byte from string - if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; - else spi_do <= 0; - end - - // reading sd card status - 8'h16: begin - if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; - else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; - else spi_do <= 0; - end - - // reading sd card write data - 8'h18: - spi_do <= b_data[~bit_cnt]; - - // reading keyboard LED status - 8'h1f: - spi_do <= kbd_led[~bit_cnt]; - - default: - spi_do <= 0; - endcase - end - end -end - -reg b_wr2,b_wr3; -always @(negedge clk_sys) begin - b_wr3 <= b_wr2; - sd_buff_wr <= b_wr3; -end - -// SPI receiver -always@(posedge SPI_SCK or posedge CONF_DATA0) begin - - if(CONF_DATA0) begin - b_wr2 <= 0; - bit_cnt <= 0; - byte_cnt <= 0; - sd_ack <= 0; - sd_ack_conf <= 0; - end else begin - b_wr2 <= 0; - - sbuf <= spi_dout[6:0]; - bit_cnt <= bit_cnt + 1'd1; - if(bit_cnt == 5) begin - if (byte_cnt == 0) sd_buff_addr <= 0; - if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; - if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; - end - - // finished reading command byte - if(bit_cnt == 7) begin - if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; - if(byte_cnt == 0) begin - cmd <= spi_dout; - - if(spi_dout == 8'h19) begin - sd_ack_conf <= 1; - sd_buff_addr <= 0; - end - if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin - sd_ack <= 1; - sd_buff_addr <= 0; - end - if(spi_dout == 8'h18) b_data <= sd_buff_din; - - mount_strobe <= 0; - - end else begin - - case(cmd) - // buttons and switches - 8'h01: but_sw <= spi_dout; - 8'h02: joystick_0 <= spi_dout; - 8'h03: joystick_1 <= spi_dout; - - // store incoming ps2 mouse bytes - 8'h04: begin - ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; - ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; - end - - // store incoming ps2 keyboard bytes - 8'h05: begin - ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; - ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; - end - - 8'h15: status[7:0] <= spi_dout; - - // 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) - 8'h19, - // send sector IO -> FPGA - // flag that download begins - 8'h17: begin - sd_buff_dout <= spi_dout; - b_wr2 <= 1; - end - - 8'h18: b_data <= sd_buff_din; - - // joystick analog - 8'h1a: begin - // first byte is joystick index - if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; - else if(byte_cnt == 2) begin - // second byte is x axis - if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; - else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; - end else if(byte_cnt == 3) begin - // third byte is y axis - if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; - else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; - end - end - - // notify image selection - 8'h1c: mount_strobe <= 1; - - // send image info - 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; - - // status, 32bit version - 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; - default: ; - endcase - end - end - end -end - - -/////////////////////////////// PS2 /////////////////////////////// -// 8 byte fifos to store ps2 bytes -localparam PS2_FIFO_BITS = 3; - -reg clk_ps2; -always @(negedge clk_sys) begin - integer cnt; - cnt <= cnt + 1'd1; - if(cnt == PS2DIV) begin - clk_ps2 <= ~clk_ps2; - cnt <= 0; - end -end - -// keyboard -reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin - ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits - ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down - if(ps2_kbd_tx_byte[0]) - ps2_kbd_parity <= !ps2_kbd_parity; - end - - // transmission of parity - if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; - - // transmission of stop bit - if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 - - // advance state machine - if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; - else ps2_kbd_tx_state <= 0; - end - end -end - -// mouse -reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin - ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits - ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down - if(ps2_mouse_tx_byte[0]) - ps2_mouse_parity <= !ps2_mouse_parity; - end - - // transmission of parity - if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; - - // transmission of stop bit - if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 - - // advance state machine - if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; - else ps2_mouse_tx_state <= 0; - end - end -end - - -/////////////////////////////// DOWNLOADING /////////////////////////////// - -reg [7:0] data_w; -reg [24:0] addr_w; -reg rclk = 0; - -localparam UIO_FILE_TX = 8'h53; -localparam UIO_FILE_TX_DAT = 8'h54; -localparam UIO_FILE_INDEX = 8'h55; - -// data_io has its own SPI interface to the io controller -always@(posedge SPI_SCK, posedge SPI_SS2) begin - reg [6:0] sbuf; - reg [7:0] cmd; - reg [4:0] cnt; - reg [24:0] addr; - - if(SPI_SS2) cnt <= 0; - else begin - rclk <= 0; - - // don't shift in last bit. It is evaluated directly - // when writing to ram - if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; - - // increase target address after write - if(rclk) addr <= addr + 1'd1; - - // count 0-7 8-15 8-15 ... - if(cnt < 15) cnt <= cnt + 1'd1; - else cnt <= 8; - - // finished command byte - if(cnt == 7) cmd <= {sbuf, SPI_DI}; - - // prepare/end transmission - if((cmd == UIO_FILE_TX) && (cnt == 15)) begin - // prepare - if(SPI_DI) begin - addr <= 0; - ioctl_download <= 1; - end else begin - addr_w <= addr; - ioctl_download <= 0; - end - end - - // command 0x54: UIO_FILE_TX - if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin - addr_w <= addr; - data_w <= {sbuf, SPI_DI}; - rclk <= 1; - end - - // expose file (menu) index - if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; - end -end - -assign ioctl_wr = |ioctl_wrd; -reg [1:0] ioctl_wrd; - -always@(negedge clk_sys) begin - reg rclkD, rclkD2; - - rclkD <= rclk; - rclkD2 <= rclkD; - ioctl_wrd<= {ioctl_wrd[0],1'b0}; - - if(rclkD & ~rclkD2) begin - ioctl_dout <= data_w; - ioctl_addr <= addr_w; - ioctl_wrd <= 2'b11; - end -end - -endmodule diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mpatrol.vhd b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mpatrol.vhd index f287f060..9dc6e7c0 100644 --- a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mpatrol.vhd +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/mpatrol.vhd @@ -48,6 +48,7 @@ architecture SYN of mpatrol is signal status : std_logic_vector(31 downto 0); signal joystick1 : std_logic_vector(7 downto 0); signal joystick2 : std_logic_vector(7 downto 0); + signal joystick : std_logic_vector(7 downto 0); signal kbd_joy : std_logic_vector(9 downto 0); signal switches : std_logic_vector(1 downto 0); signal buttons : std_logic_vector(1 downto 0); @@ -77,6 +78,32 @@ architecture SYN of mpatrol is signal vga_pb_o : std_logic_vector(5 downto 0); signal vga_pr_o : std_logic_vector(5 downto 0); + constant CONF_STR : string := + "MPATROL;;"& + "O12,Scandoubler Fx,None,CRT 25%,CRT 50%,CRT 75%;"& + "O34,Patrol cars,5,3,2,1;"& + "O56,New car at,10/30/50K,20/40/60K,10K,Never;"& + "O7,Demo mode,Off,On;"& + "O8,Sector selection,Off,On;"& + "O9,Test mode,Off,On;"& + "T0,Reset;"; +-- "V,v1.11.",`BUILD_DATE + + -- convert string to std_logic_vector to be given to user_io + function to_slv(s: string) return std_logic_vector is + constant ss: string(1 to s'length) := s; + variable rval: std_logic_vector(1 to 8 * s'length); + variable p: integer; + variable c: integer; + begin + for i in ss'range loop + p := 8 * i; + c := character'pos(ss(i)); + rval(p - 7 to p) := std_logic_vector(to_unsigned(c,8)); + end loop; + return rval; + end function; + component keyboard port ( clk :in STD_LOGIC; @@ -86,23 +113,24 @@ component keyboard joystick :out STD_LOGIC_VECTOR(9 downto 0)); end component; -component mist_io - port ( - clk_sys :in STD_LOGIC; - SPI_SCK :in STD_LOGIC; - CONF_DATA0 :in STD_LOGIC; - SPI_DI :in STD_LOGIC; - SPI_DO :out STD_LOGIC; - SPI_SS2 :in STD_LOGIC; - switches :out STD_LOGIC_VECTOR(1 downto 0); - buttons :out STD_LOGIC_VECTOR(1 downto 0); - scan_disable :out STD_LOGIC; - ypbpr :out STD_LOGIC; - joystick_1 :out STD_LOGIC_VECTOR(7 downto 0); - joystick_0 :out STD_LOGIC_VECTOR(7 downto 0); - status :out STD_LOGIC_VECTOR(31 downto 0); - ps2_kbd_clk :out STD_LOGIC; - ps2_kbd_data :out STD_LOGIC); +component user_io + generic ( STRLEN : integer := 0 ); + port ( + clk_sys : in STD_LOGIC; + conf_str : in std_logic_vector(8*STRLEN-1 downto 0); + SPI_CLK : in STD_LOGIC; + SPI_SS_IO : in STD_LOGIC; + SPI_MOSI : in STD_LOGIC; + SPI_MISO : out STD_LOGIC; + switches : out STD_LOGIC_VECTOR(1 downto 0); + buttons : out STD_LOGIC_VECTOR(1 downto 0); + scandoubler_disable : out STD_LOGIC; + ypbpr : out STD_LOGIC; + joystick_1 : out STD_LOGIC_VECTOR(7 downto 0); + joystick_0 : out STD_LOGIC_VECTOR(7 downto 0); + status : out STD_LOGIC_VECTOR(31 downto 0); + ps2_kbd_clk : out STD_LOGIC; + ps2_kbd_data : out STD_LOGIC); end component; component scandoubler @@ -188,7 +216,7 @@ Clock_inst : entity work.Clock end if; end process; - clkrst_i.arst <= init or status(5) or buttons(1); + clkrst_i.arst <= init or status(0) or buttons(1); clkrst_i.arst_n <= not clkrst_i.arst; GEN_RESETS : for i in 0 to 3 generate @@ -206,23 +234,24 @@ Clock_inst : entity work.Clock end generate GEN_RESETS; -mist_io_inst : mist_io - port map ( - clk_sys => clk_sys, - SPI_SCK => SPI_SCK, - CONF_DATA0 => CONF_DATA0, - SPI_DI => SPI_DI, - SPI_DO => SPI_DO, - SPI_SS2 => SPI_SS2, - switches => switches, - buttons => buttons, - scan_disable => scandoubler_disable, - ypbpr => ypbpr, - joystick_1 => joystick2, - joystick_0 => joystick1, - status => status, - ps2_kbd_clk => ps2_kbd_clk, - ps2_kbd_data => ps2_kbd_data +user_io_inst : user_io + generic map (STRLEN => CONF_STR'length) + port map ( + clk_sys => clk_sys, + conf_str => to_slv(CONF_STR), + SPI_CLK => SPI_SCK, + SPI_SS_IO => CONF_DATA0, + SPI_MOSI => SPI_DI, + SPI_MISO => SPI_DO, + switches => switches, + buttons => buttons, + scandoubler_disable => scandoubler_disable, + ypbpr => ypbpr, + joystick_1 => joystick2, + joystick_0 => joystick1, + status => status, + ps2_kbd_clk => ps2_kbd_clk, + ps2_kbd_data => ps2_kbd_data ); u_keyboard : keyboard @@ -234,23 +263,26 @@ u_keyboard : keyboard joystick => kbd_joy ); - inputs_i.jamma_n.coin(1) <= joystick1(7) or joystick2(7) or kbd_joy(3);--ESC - inputs_i.jamma_n.p(1).start <= kbd_joy(1) or kbd_joy(2);--KB 1+2 - inputs_i.jamma_n.p(1).up <= not (joystick1(3) or joystick2(3) or kbd_joy(4)); - inputs_i.jamma_n.p(1).down <= not (joystick1(2) or joystick2(2) or kbd_joy(5)); - inputs_i.jamma_n.p(1).left <= not (joystick1(1) or joystick2(1) or kbd_joy(6)); - inputs_i.jamma_n.p(1).right <= not (joystick1(0) or joystick2(0) or kbd_joy(7)); - inputs_i.jamma_n.p(1).button(1) <= not (joystick1(4) or joystick2(4) or kbd_joy(0));--Fire - inputs_i.jamma_n.p(1).button(2) <= not (joystick1(5) or joystick2(5) or kbd_joy(8) or joystick1(3) or joystick2(3) or kbd_joy(4));--Jump + joystick <= joystick1 or joystick2; + + inputs_i.jamma_n.coin(1) <= not (joystick(6) or kbd_joy(3));--ESC + inputs_i.jamma_n.p(1).start <= not (kbd_joy(1) or joystick1(7));--KB 1 + inputs_i.jamma_n.p(1).up <= not (joystick(3) or kbd_joy(4)); + inputs_i.jamma_n.p(1).down <= not (joystick(2) or kbd_joy(5)); + inputs_i.jamma_n.p(1).left <= not (joystick(1) or kbd_joy(6)); + inputs_i.jamma_n.p(1).right <= not (joystick(0) or kbd_joy(7)); + inputs_i.jamma_n.p(1).button(1) <= not (joystick(4) or kbd_joy(0));--Fire + inputs_i.jamma_n.p(1).button(2) <= not (joystick(5) or kbd_joy(8) or joystick(3) or kbd_joy(4));--Jump inputs_i.jamma_n.p(1).button(3) <= '1'; inputs_i.jamma_n.p(1).button(4) <= '1'; inputs_i.jamma_n.p(1).button(5) <= '1'; - inputs_i.jamma_n.p(2).up <= not (joystick1(3) or joystick2(3) or kbd_joy(4)); - inputs_i.jamma_n.p(2).down <= not (joystick1(2) or joystick2(2) or kbd_joy(5)); - inputs_i.jamma_n.p(2).left <= not (joystick1(1) or joystick2(1) or kbd_joy(6)); - inputs_i.jamma_n.p(2).right <= not (joystick1(0) or joystick2(0) or kbd_joy(7)); - inputs_i.jamma_n.p(2).button(1) <= not (joystick1(4) or joystick2(4) or kbd_joy(0));--Fire - inputs_i.jamma_n.p(2).button(2) <= not (joystick1(5) or joystick2(5) or kbd_joy(8) or joystick1(3) or joystick2(3) or kbd_joy(4)); --Jump + inputs_i.jamma_n.p(2).start <= not (kbd_joy(2) or joystick2(7));--KB 2 + inputs_i.jamma_n.p(2).up <= not (joystick(3) or kbd_joy(4)); + inputs_i.jamma_n.p(2).down <= not (joystick(2) or kbd_joy(5)); + inputs_i.jamma_n.p(2).left <= not (joystick(1) or kbd_joy(6)); + inputs_i.jamma_n.p(2).right <= not (joystick(0) or kbd_joy(7)); + inputs_i.jamma_n.p(2).button(1) <= not (joystick(4) or kbd_joy(0));--Fire + inputs_i.jamma_n.p(2).button(2) <= not (joystick(5) or kbd_joy(8) or joystick(3) or kbd_joy(4)); --Jump inputs_i.jamma_n.p(2).button(3) <= '1'; inputs_i.jamma_n.p(2).button(4) <= '1'; inputs_i.jamma_n.p(2).button(5) <= '1'; @@ -283,6 +315,14 @@ dac : entity work.dac AUDIO_R <= audio; AUDIO_L <= audio; +switches_i(15) <= not status(9); -- Test mode +switches_i(14) <= not status(7); +switches_i(13) <= not status(8); -- Sector select +switches_i(12 downto 8) <= "11101"; +switches_i( 7 downto 4) <= "1111"; +switches_i( 1 downto 0) <= not status(4 downto 3); -- Patrol cars +switches_i( 3 downto 2) <= not status(6 downto 5); -- New car + pace_inst : entity work.pace port map ( clkrst_i => clkrst_i, @@ -298,7 +338,7 @@ pace_inst : entity work.pace scandoubler_inst: scandoubler port map ( clk_sys => clk_vid, - scanlines => status(4 downto 3), + scanlines => status(2 downto 1), hs_in => video_o.hsync, vs_in => video_o.vsync, diff --git a/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/user_io.v b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/user_io.v new file mode 100644 index 00000000..5b03cd17 --- /dev/null +++ b/Arcade_MiST/IremM52 Hardware/MoonPatrol_MIST/src/user_io.v @@ -0,0 +1,550 @@ +// +// user_io.v +// +// user_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// 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 . +// + +// parameter STRLEN and the actual length of conf_str have to match + +module user_io #(parameter STRLEN=0, parameter PS2DIV=100) ( + input [(8*STRLEN)-1:0] conf_str, + + input clk_sys, // clock for system-related messages (kbd, joy, etc...) + input clk_sd, // clock for SD-card related messages + + input SPI_CLK, + input SPI_SS_IO, + output reg SPI_MISO, + input SPI_MOSI, + + 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 [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + output reg [31:0] status, + + // connection to sd card emulation + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + input sd_conf, + input sd_sdhc, + output reg [7:0] sd_dout, // valid on rising edge of sd_dout_strobe + output reg sd_dout_strobe, + input [7:0] sd_din, + output reg sd_din_strobe, + output reg [8:0] sd_buff_addr, + + output reg img_mounted, //rising edge if a new image is mounted + output reg [31:0] img_size, // size of image in bytes + + // ps2 keyboard/mouse emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + + // mouse data + output reg [8:0] mouse_x, + output reg [8:0] mouse_y, + output reg [7:0] mouse_flags, // YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn + output reg mouse_strobe, // mouse data is valid on mouse_strobe + + // serial com port + input [7:0] serial_data, + input serial_strobe +); + +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +wire spi_sck = SPI_CLK; + +// ---------------- PS2 --------------------- +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg ps2_clk; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + ps2_clk <= ~ps2_clk; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo [(2**PS2_FIFO_BITS)-1:0]; +reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr; +reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr; + +// ps2 transmitter state machine +reg [3:0] ps2_kbd_tx_state; +reg [7:0] ps2_kbd_tx_byte; +reg ps2_kbd_parity; + +assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0); + +// ps2 transmitter +// Takes a byte from the FIFO and sends it in a ps2 compliant serial format. +reg ps2_kbd_r_inc; +always@(posedge clk_sys) begin + reg ps2_clkD; + + ps2_clkD <= ps2_clk; + if (~ps2_clkD & ps2_clk) begin + ps2_kbd_r_inc <= 1'b0; + + if(ps2_kbd_r_inc) + ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1; + + // transmitter is idle? + if(ps2_kbd_tx_state == 0) begin + // data in fifo present? + if(ps2_kbd_wptr != ps2_kbd_rptr) begin + // load tx register from fifo + ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr]; + ps2_kbd_r_inc <= 1'b1; + + // reset parity + ps2_kbd_parity <= 1'b1; + + // start transmitter + ps2_kbd_tx_state <= 4'd1; + + // put start bit on data line + ps2_kbd_data <= 1'b0; // start bit is 0 + end + end else begin + + // transmission of 8 data bits + if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) + ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) + ps2_kbd_data <= 1'b1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) + ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1; + else + ps2_kbd_tx_state <= 4'd0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo [(2**PS2_FIFO_BITS)-1:0]; +reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr; +reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr; + +// ps2 transmitter state machine +reg [3:0] ps2_mouse_tx_state; +reg [7:0] ps2_mouse_tx_byte; +reg ps2_mouse_parity; + +assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0); + +// ps2 transmitter +// Takes a byte from the FIFO and sends it in a ps2 compliant serial format. +reg ps2_mouse_r_inc; +always@(posedge clk_sys) begin + reg ps2_clkD; + + ps2_clkD <= ps2_clk; + if (~ps2_clkD & ps2_clk) begin + ps2_mouse_r_inc <= 1'b0; + + if(ps2_mouse_r_inc) + ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1; + + // transmitter is idle? + if(ps2_mouse_tx_state == 0) begin + // data in fifo present? + if(ps2_mouse_wptr != ps2_mouse_rptr) begin + // load tx register from fifo + ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr]; + ps2_mouse_r_inc <= 1'b1; + + // reset parity + ps2_mouse_parity <= 1'b1; + + // start transmitter + ps2_mouse_tx_state <= 4'd1; + + // put start bit on data line + ps2_mouse_data <= 1'b0; // start bit is 0 + end + end else begin + + // transmission of 8 data bits + if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) + ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) + ps2_mouse_data <= 1'b1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) + ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1; + else + ps2_mouse_tx_state <= 4'd0; + end + end +end + +// fifo to receive serial data from core to be forwarded to io controller + +// 16 byte fifo to store serial bytes +localparam SERIAL_OUT_FIFO_BITS = 6; +reg [7:0] serial_out_fifo [(2**SERIAL_OUT_FIFO_BITS)-1:0]; +reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_wptr; +reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_rptr; + +wire serial_out_data_available = serial_out_wptr != serial_out_rptr; +wire [7:0] serial_out_byte = serial_out_fifo[serial_out_rptr] /* synthesis keep */; +wire [7:0] serial_out_status = { 7'b1000000, serial_out_data_available}; + +// status[0] is reset signal from io controller and is thus used to flush +// the fifo +always @(posedge serial_strobe or posedge status[0]) begin + if(status[0] == 1) begin + serial_out_wptr <= 0; + end else begin + serial_out_fifo[serial_out_wptr] <= serial_data; + serial_out_wptr <= serial_out_wptr + 1'd1; + end +end + +always@(negedge spi_sck or posedge status[0]) begin + if(status[0] == 1) begin + serial_out_rptr <= 0; + end else begin + if((byte_cnt != 0) && (cmd == 8'h1b)) begin + // read last bit -> advance read pointer + if((bit_cnt == 7) && !byte_cnt[0] && serial_out_data_available) + serial_out_rptr <= serial_out_rptr + 1'd1; + end + end +end + + +// SPI bit and byte counters +always@(posedge spi_sck or posedge SPI_SS_IO) begin + if(SPI_SS_IO == 1) begin + bit_cnt <= 0; + byte_cnt <= 0; + end else begin + if((bit_cnt == 7)&&(~&byte_cnt)) + byte_cnt <= byte_cnt + 8'd1; + + bit_cnt <= bit_cnt + 1'd1; + end +end + +// SPI transmitter FPGA -> IO +reg [7:0] spi_byte_out; + +always@(negedge spi_sck or posedge SPI_SS_IO) begin + if(SPI_SS_IO == 1) begin + SPI_MISO <= 1'bZ; + end else begin + SPI_MISO <= spi_byte_out[~bit_cnt]; + end +end + +always@(posedge spi_sck or posedge SPI_SS_IO) begin + reg [31:0] sd_lba_r; + + if(SPI_SS_IO == 1) begin + spi_byte_out <= core_type; + end else begin + // read the command byte to choose the response + if(bit_cnt == 7) begin + if(!byte_cnt) cmd <= {sbuf, SPI_MOSI}; + + spi_byte_out <= 0; + case({(!byte_cnt) ? {sbuf, SPI_MOSI} : cmd}) + // reading config string + 8'h14: if(byte_cnt < STRLEN) spi_byte_out <= conf_str[(STRLEN - byte_cnt - 1)<<3 +:8]; + + // reading sd card status + 8'h16: if(byte_cnt == 0) begin + spi_byte_out <= sd_cmd; + sd_lba_r <= sd_lba; + end + else if(byte_cnt < 5) spi_byte_out <= sd_lba_r[(4-byte_cnt)<<3 +:8]; + + // reading sd card write data + 8'h18: spi_byte_out <= sd_din; + 8'h1b: + // send alternating flag byte and data + if(byte_cnt[0]) spi_byte_out <= serial_out_status; + else spi_byte_out <= serial_out_byte; + endcase + end + end +end + +// SPI receiver IO -> FPGA + +reg spi_receiver_strobe_r = 0; +reg spi_transfer_end_r = 1; +reg [7:0] spi_byte_in; + +// Read at spi_sck clock domain, assemble bytes for transferring to clk_sys +always@(posedge spi_sck or posedge SPI_SS_IO) begin + + if(SPI_SS_IO == 1) begin + spi_transfer_end_r <= 1; + end else begin + spi_transfer_end_r <= 0; + + if(bit_cnt != 7) + sbuf[6:0] <= { sbuf[5:0], SPI_MOSI }; + + // finished reading a byte, prepare to transfer to clk_sys + if(bit_cnt == 7) begin + spi_byte_in <= { sbuf, SPI_MOSI}; + spi_receiver_strobe_r <= ~spi_receiver_strobe_r; + end + end +end + +// Process bytes from SPI at the clk_sys domain +always @(posedge clk_sys) begin + + reg spi_receiver_strobe; + reg spi_transfer_end; + reg spi_receiver_strobeD; + reg spi_transfer_endD; + reg [7:0] acmd; + reg [7:0] abyte_cnt; // counts bytes + + reg [7:0] mouse_flags_r; + reg [7:0] mouse_x_r; + + //synchronize between SPI and sys clock domains + spi_receiver_strobeD <= spi_receiver_strobe_r; + spi_receiver_strobe <= spi_receiver_strobeD; + spi_transfer_endD <= spi_transfer_end_r; + spi_transfer_end <= spi_transfer_endD; + + mouse_strobe <= 0; + + if (~spi_transfer_endD & spi_transfer_end) begin + abyte_cnt <= 8'd0; + end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin + + if(~&abyte_cnt) + abyte_cnt <= abyte_cnt + 8'd1; + + if(abyte_cnt == 0) begin + acmd <= spi_byte_in; + end else begin + case(acmd) + // buttons and switches + 8'h01: but_sw <= spi_byte_in; + 8'h60: if (abyte_cnt < 5) joystick_0[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + 8'h61: if (abyte_cnt < 5) joystick_1[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + 8'h62: if (abyte_cnt < 5) joystick_2[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + 8'h63: if (abyte_cnt < 5) joystick_3[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + 8'h64: if (abyte_cnt < 5) joystick_4[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + 8'h04: begin + // store incoming ps2 mouse bytes + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_byte_in; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + if (abyte_cnt == 1) mouse_flags_r <= spi_byte_in; + else if (abyte_cnt == 2) mouse_x_r <= spi_byte_in; + else if (abyte_cnt == 3) begin + // flags: YOvfl, XOvfl, dy8, dx8, 1, mbtn, rbtn, lbtn + mouse_flags <= mouse_flags_r; + mouse_x <= { mouse_flags_r[4], mouse_x_r }; + mouse_y <= { mouse_flags_r[5], spi_byte_in }; + mouse_strobe <= 1; + end + end + 8'h05: begin + // store incoming ps2 keyboard bytes + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_byte_in; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(abyte_cnt == 1) + stick_idx <= spi_byte_in[2:0]; + else if(abyte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) + joystick_analog_0[15:8] <= spi_byte_in; + else if(stick_idx == 1) + joystick_analog_1[15:8] <= spi_byte_in; + end else if(abyte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) + joystick_analog_0[7:0] <= spi_byte_in; + else if(stick_idx == 1) + joystick_analog_1[7:0] <= spi_byte_in; + end + end + + 8'h15: status <= spi_byte_in; + + // status, 32bit version + 8'h1e: if(abyte_cnt<5) status[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + + endcase + end + end +end + +// Process SD-card related bytes from SPI at the clk_sd domain +always @(posedge clk_sd) begin + + reg spi_receiver_strobe; + reg spi_transfer_end; + reg spi_receiver_strobeD; + reg spi_transfer_endD; + reg sd_wrD; + reg [7:0] acmd; + reg [7:0] abyte_cnt; // counts bytes + + //synchronize between SPI and sd clock domains + spi_receiver_strobeD <= spi_receiver_strobe_r; + spi_receiver_strobe <= spi_receiver_strobeD; + spi_transfer_endD <= spi_transfer_end_r; + spi_transfer_end <= spi_transfer_endD; + + if(sd_dout_strobe) begin + sd_dout_strobe<= 0; + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + end + + sd_din_strobe<= 0; + sd_wrD <= sd_wr; + // fetch the first byte immediately after the write command seen + if (~sd_wrD & sd_wr) begin + sd_buff_addr <= 0; + sd_din_strobe <= 1; + end + + img_mounted <= 0; + + if (~spi_transfer_endD & spi_transfer_end) begin + abyte_cnt <= 8'd0; + sd_ack <= 1'b0; + sd_ack_conf <= 1'b0; + sd_dout_strobe <= 1'b0; + sd_din_strobe <= 1'b0; + sd_buff_addr <= 0; + end else if (spi_receiver_strobeD ^ spi_receiver_strobe) begin + + if(~&abyte_cnt) + abyte_cnt <= abyte_cnt + 8'd1; + + if(abyte_cnt == 0) begin + acmd <= spi_byte_in; + + if(spi_byte_in == 8'h18) begin + sd_din_strobe <= 1'b1; + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + end + + if((spi_byte_in == 8'h17) || (spi_byte_in == 8'h18)) + sd_ack <= 1'b1; + + end else begin + case(acmd) + + // send sector IO -> FPGA + 8'h17: begin + // flag that download begins + sd_dout_strobe <= 1'b1; + sd_dout <= spi_byte_in; + end + + // send sector FPGA -> IO + 8'h18: begin + sd_din_strobe <= 1'b1; + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + end + + // send SD config IO -> FPGA + 8'h19: begin + // flag that download begins + sd_dout_strobe <= 1'b1; + sd_ack_conf <= 1'b1; + sd_dout <= spi_byte_in; + end + + 8'h1c: img_mounted <= 1; + + // send image info + 8'h1d: if(abyte_cnt<5) img_size[(abyte_cnt-1)<<3 +:8] <= spi_byte_in; + endcase + end + end +end + +endmodule