diff --git a/Arcade-LadyBug.sv b/Arcade-LadyBug.sv index 294952c..a9a09f9 100644 --- a/Arcade-LadyBug.sv +++ b/Arcade-LadyBug.sv @@ -193,61 +193,39 @@ assign FB_FORCE_BLANK = '0; wire [1:0] ar = status[20:19]; -assign VIDEO_ARX = (!ar) ? ((status[2] ) ? 8'd4 : 8'd3) : (ar - 1'd1); -assign VIDEO_ARY = (!ar) ? ((status[2] ) ? 8'd3 : 8'd4) : 12'd0; +assign VIDEO_ARX = (!ar) ? ((status[2] | landscape) ? 8'd4 : 8'd3) : (ar - 1'd1); +assign VIDEO_ARY = (!ar) ? ((status[2] | landscape) ? 8'd3 : 8'd4) : 12'd0; `include "build_id.v" localparam CONF_STR = { "A.LADYBG;;", "H0OJK,Aspect ratio,Original,Full Screen,[ARC1],[ARC2];", - "H0O2,Orientation,Vert,Horz;", + "H1H0O2,Orientation,Vert,Horz;", "O35,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%,CRT 75%;", "-;", - "O89,Difficulty,Easy,Medium,Hard,Hardest;", - "OB,Lives,3,5;", - "OC,Cabinet,Upright,Cocktail;", - "O6,Pause when OSD is open,On,Off;", + "P1,Pause options;", + "P1OP,Pause when OSD is open,On,Off;", + "P1OQ,Dim video after 10s,On,Off;", + "-;", + "DIP;", "-;", "R0,Reset;", - "J1,Start 1P,Start 2P,Coin,Pause;", - "jn,Start,Select,R,L;", + "J1,Fire,Bomb,Start 1P,Start 2P,Coin,Pause;", + "jn,A,B,Start,Select,R,L;", "V,v",`BUILD_DATE }; -/* - -- Lives ------------------------------------------------------------------ - -- 0 = 5 Lives - -- 1 = 3 Lives - '0' & - -- Free Play -------------------------------------------------------------- - -- 0 = Free Play - -- 1 = No Free Play - '1' & - -- Cabinet ---------------------------------------------------------------- - -- 0 = Upright - -- 1 = Cocktail - '0' & - -- Screen Freeze ---------------------------------------------------------- - -- 0 = Freeze - -- 1 = No Freeze - '1' & - -- Rack Test (Cheat) ------------------------------------------------------ - -- 0 = On - -- 1 = Off - '1' & - -- High Score Initials ---------------------------------------------------- - -- 0 = 3-Letter Initials - -- 1 = 10-Letter Initials - '1' & - -- Difficulty ------------------------------------------------------------- - -- 11 = Easy - -- 10 = Medium - -- 01 = Hard - -- 00 = Hardest - "10"; -*/ -wire [7:0] m_dip = {~status[11],1'b1,status[12],1'b1,1'b1,1'b1,~status[9:8]}; +// Read DIPs from MRA +reg [7:0] m_dip[8]; // Active-LOW +always @(posedge clk_sys) if(ioctl_wr && (ioctl_index==254) && !ioctl_addr[24:3]) m_dip[ioctl_addr[2:0]] <= ioctl_dout; + +// Read game index from MRA +localparam mod_ladybug = 0; +localparam mod_snapjack = 1; +localparam mod_cosmicavenger = 2; +reg [7:0] mod = 0; +always @(posedge clk_sys) if (ioctl_wr & (ioctl_index==1)) mod <= ioctl_dout; //////////////////// CLOCKS /////////////////// @@ -278,9 +256,7 @@ wire [24:0] ioctl_addr; wire [7:0] ioctl_dout; wire [7:0] ioctl_din; -wire [15:0] joystick_0,joystick_1; -wire [15:0] joy1 = joystick_0; -wire [15:0] joy2 = joystick_1; +wire [15:0] joy1,joy2; wire [21:0] gamma_bus; @@ -294,7 +270,7 @@ hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io .buttons(buttons), .status(status), - .status_menumask(direct_video), + .status_menumask({landscape,direct_video}), .forced_scandoubler(forced_scandoubler), .gamma_bus(gamma_bus), .direct_video(direct_video), @@ -307,86 +283,84 @@ hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io .ioctl_din(ioctl_din), .ioctl_index(ioctl_index), - .joystick_0(joystick_0), - .joystick_1(joystick_1) + .joystick_0(joy1), + .joystick_1(joy2) ); -wire no_rotate = status[2] | direct_video ; +wire m_up = joy1[3]; +wire m_down = joy1[2]; +wire m_left = joy1[1]; +wire m_right = joy1[0]; +wire m_fire = joy1[4]; +wire m_bomb = joy1[5]; +wire m_up_2 = joy2[3]; +wire m_down_2 = joy2[2]; +wire m_left_2 = joy2[1]; +wire m_right_2 = joy2[0]; +wire m_fire_2 = joy2[5]; +wire m_bomb_2 = joy2[6]; +wire m_start1 = joy1[6] | joy2[6]; +wire m_start2 = joy1[7] | joy2[7]; +wire m_coin = joy1[8] | joy2[8]; +wire m_pause = joy1[9] | joy2[9]; +reg [1:0] but_up_s; +reg [1:0] but_down_s; +reg [1:0] but_left_s; +reg [1:0] but_right_s; -wire m_up,m_down,m_left,m_right; -joyonedir jod -( - clk_sys, - 1'b0, - { - joy1[3], - joy1[2], - joy1[1], - joy1[0] - }, - {m_up,m_down,m_left,m_right} -); +// One-directional control generators for Lady Bug +wire [3:0] m_joyod_1; +wire [3:0] m_joyod_2; +joyonedir jod_1(clk_sys,1'b0,{m_up,m_down,m_left,m_right},m_joyod_1); +joyonedir jod_2(clk_sys,1'b0,{m_up_2,m_down_2,m_left_2,m_right_2},m_joyod_2); -wire m_up_2,m_down_2,m_left_2,m_right_2; -joyonedir jod_2 -( - clk_sys, - 1'b0, - { - joy2[3], - joy2[2], - joy2[1], - joy2[0] - }, - {m_up_2,m_down_2,m_left_2,m_right_2} -); +// Set game specific options +reg landscape; +always @(*) begin + landscape <= 1'b0; + but_up_s <= {m_up_2,m_up}; + but_down_s <= {m_down_2,m_down}; + but_left_s <= {m_left_2,m_left}; + but_right_s <= {m_right_2,m_right}; - -wire m_fire = 1'b0; -wire m_fire_2 = 1'b0; - -wire m_start1 = joy1[4] | joy2[4]; -wire m_start2 = joy1[5] | joy2[5]; -wire m_coin = joy1[6] | joy2[6]; -wire m_pause = joy1[7] | joy2[7]; - -// PAUSE SYSTEM -reg pause; // Pause signal (active-high) -reg pause_toggle = 1'b0; // User paused (active-high) -reg [31:0] pause_timer; // Time since pause -reg [31:0] pause_timer_dim = 32'hBEBC200; // Time until screen dim (10 seconds @ 20Mhz) -reg dim_video; // Dim video output (active-high) - -// Pause when highscore module requires access, user has pressed pause, or OSD is open and option is set -assign pause = hs_access | pause_toggle | (OSD_STATUS && ~status[6]); -assign dim_video = (pause_timer >= pause_timer_dim) ? 1'b1 : 1'b0; - -always @(posedge clk_sys) begin - reg old_pause; - old_pause <= m_pause; - if(~old_pause & m_pause) pause_toggle <= ~pause_toggle; - if(pause) - begin - if(reset) pause_toggle <= 0; - if(pause_timer> 1,g >> 1, b >> 1} : {r,g,b}; +wire [1:0] r,g, b; reg ce_pix; always @(posedge clk_40) begin @@ -418,7 +392,7 @@ assign AUDIO_L = {audio, 8'd0}; assign AUDIO_R = AUDIO_L; assign AUDIO_S = 1; -wire rom_download = ioctl_download & !ioctl_index; +wire rom_download = ioctl_download & (ioctl_index==2'd1|| ioctl_index==2'd2); wire reset = RESET | status[0] | buttons[1] | rom_download; ladybug ladybug @@ -437,22 +411,23 @@ ladybug ladybug .dn_addr(ioctl_addr[15:0]), .dn_data(ioctl_dout), - .dn_wr(ioctl_wr & rom_download), + .dn_wr(ioctl_wr), + .dn_index(ioctl_index), .O_AUDIO(audio), .but_coin_s(~{1'b0,m_coin}), .but_fire_s(~{m_fire_2,m_fire}), - .but_bomb_s(~{1'b0,1'b0}), + .but_bomb_s(~{m_bomb_2,m_bomb}), .but_tilt_s(~{1'b0,1'b0}), .but_select_s(~{m_start2,m_start1}), - .but_up_s(~{m_up_2,m_up}), - .but_down_s(~{m_down_2,m_down}), - .but_left_s(~{m_left_2,m_left}), - .but_right_s(~{m_right_2,m_right}), - .dip_block_1_s(m_dip), + .but_up_s(~but_up_s), + .but_down_s(~but_down_s), + .but_left_s(~but_left_s), + .but_right_s(~but_right_s), + .dip_block_1_s(~m_dip[0]), - .pause(pause), + .pause(pause_cpu), .hs_address(hs_address), .hs_data_out(ioctl_din), @@ -468,6 +443,7 @@ wire [15:0]hs_address; wire [7:0]hs_data_in; wire hs_write; wire hs_access; +wire hs_pause; hiscore #( .HS_ADDRESSWIDTH(16), @@ -486,7 +462,8 @@ hiscore #( .ram_address(hs_address), .data_to_ram(hs_data_in), .ram_write(hs_write), - .ram_access(hs_access) + .ram_access(hs_access), + .pause_cpu(hs_pause) ); endmodule diff --git a/files.qip b/files.qip index 06e5492..33e393c 100644 --- a/files.qip +++ b/files.qip @@ -1,7 +1,7 @@ -set_global_assignment -name VHDL_FILE rtl/ROM/prom_decrypt.vhd -set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_3.vhd -set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_2.vhd -set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_1.vhd +#set_global_assignment -name VHDL_FILE rtl/ROM/prom_decrypt.vhd +#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_3.vhd +#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_2.vhd +#set_global_assignment -name VHDL_FILE rtl/ROM/prom_10_1.vhd set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_top.vhd set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_tone.vhd set_global_assignment -name VHDL_FILE rtl/sound/sn76489/sn76489_noise.vhd @@ -37,5 +37,6 @@ set_global_assignment -name VHDL_FILE rtl/ladybug_chute.vhd set_global_assignment -name VHDL_FILE rtl/ladybug_char.vhd set_global_assignment -name VHDL_FILE rtl/ladybug_addr_dec.vhd set_global_assignment -name VHDL_FILE rtl/ladybug.vhd +set_global_assignment -name VERILOG_FILE rtl/pause.v set_global_assignment -name VERILOG_FILE rtl/hiscore.v set_global_assignment -name SYSTEMVERILOG_FILE "Arcade-LadyBug.sv" diff --git a/releases/Arcade-LadyBug_20210419.rbf b/releases/Arcade-LadyBug_20210419.rbf new file mode 100644 index 0000000..079d353 Binary files /dev/null and b/releases/Arcade-LadyBug_20210419.rbf differ diff --git a/releases/Cosmic Avenger.mra b/releases/Cosmic Avenger.mra new file mode 100644 index 0000000..b6da3de --- /dev/null +++ b/releases/Cosmic Avenger.mra @@ -0,0 +1,80 @@ + + Cosmic Avenger + 0220 + cavenger + 20200427161917 + 1981 + Universal + Space / Defender + ladybug + + + + + + + + + + 02 + + + + + + + + + + + + + + + + + + 00 + + 00 01 02 03 04 05 06 07 + 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 + 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 + 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 + 38 39 3A 3B 3C 3D 3E 3F + 40 41 42 43 44 45 46 47 + 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 + 58 59 5A 5B 5C 5D 5E 5F + 60 61 62 63 64 65 66 67 + 68 69 6A 6B 6C 6D 6E 6F + 70 71 72 73 74 75 76 77 + 78 79 7A 7B 7C 7D 7E 7F + 80 81 82 83 84 85 86 87 + 88 89 8A 8B 8C 8D 8E 8F + 90 91 92 93 94 95 96 97 + 98 99 9A 9B 9C 9D 9E 9F + A0 A1 A2 A3 A4 A5 A6 A7 + A8 A9 AA AB AC AD AE AF + B0 B1 B2 B3 B4 B5 B6 B7 + B8 B9 BA BB BC BD BE BF + C0 C1 C2 C3 C4 C5 C6 C7 + C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 D7 + D8 D9 DA DB DC DD DE DF + E0 E1 E2 E3 E4 E5 E6 E7 + E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 F7 + F8 F9 FA FB FC FD FE FF + + + + + 00 00 00 00 00 FF 00 02 00 02 00 01 00 FF 00 00 + 00 00 60 25 00 41 00 28 + + + + diff --git a/releases/Dorodon.mra b/releases/Dorodon.mra new file mode 100644 index 0000000..911911f --- /dev/null +++ b/releases/Dorodon.mra @@ -0,0 +1,80 @@ + + Dorodon (set 1) + 0220 + dorodon + 20200427161917 + 1982 + UPL (Falcon license?) + Maze + ladybug + + + + + + + + + + + + 04 + + + + + + + + + + + + + + + 00 + + 00 F1 3F 86 4F 66 07 73 + 71 64 A7 59 2B 56 FB 8B + 8F B6 9E 9D 04 11 BC 80 + 12 CB 18 5D D2 7A 85 75 + B5 BE 7E 05 6E 3E D5 4B + 2E 52 15 84 38 6A 6C 53 + FA C8 08 B8 D4 E9 5C 22 + 1D 49 BD AD 46 1F E1 0A + 19 5B 41 45 4A 2A B4 4D + 57 90 8E 3A BB 9B E4 29 + 8A EB AA F0 CE EE 88 5F + 33 31 C6 60 3C 9A 3D B7 + 63 6D AB 62 E3 78 E5 B9 + EF 5E 7B 83 94 E6 D6 A1 + D9 36 47 3B C4 DF 21 0C + 14 E7 C3 1A 1C 28 4C 9C + 50 40 91 55 D8 A4 76 9F + 98 10 6B 2F A3 43 39 B1 + 42 72 7D 65 03 8D F2 F5 + 69 27 0D CA CF 1B 35 EC + A2 F7 93 70 CD 68 97 2D + 37 F9 AE 26 96 E8 48 99 + 95 D7 B0 06 DC C9 ED 87 + 7F B3 17 A0 0F 25 DB DE + 23 74 79 89 B2 FC 24 13 + 81 8C D3 C5 BF A6 16 44 + 0B 34 F8 D1 0E E0 09 EA + 02 DD 92 F4 C1 BA 32 D0 + 7C 2C FD F3 61 A5 CC DA + 5A 67 30 6F 82 20 AF 54 + AC E2 1E C2 FE A9 58 01 + 77 C0 4E C7 A8 51 F6 FF + + + + + 03 FF FF FF 00 FF 00 02 00 02 00 01 00 FF 00 00 + 00 00 60 73 00 1B 01 00 + 00 00 D3 81 00 46 0F 17 + + + + diff --git a/releases/Lady Bug.mra b/releases/Lady Bug.mra index e6ad85e..91c7f64 100644 --- a/releases/Lady Bug.mra +++ b/releases/Lady Bug.mra @@ -8,6 +8,19 @@ Maze Maze / Bugs ladybug + + + + + + + + + + + + 00 + @@ -20,6 +33,46 @@ + + + + + 00 + + 00 01 02 03 04 05 06 07 + 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 + 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 + 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 + 38 39 3A 3B 3C 3D 3E 3F + 40 41 42 43 44 45 46 47 + 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 + 58 59 5A 5B 5C 5D 5E 5F + 60 61 62 63 64 65 66 67 + 68 69 6A 6B 6C 6D 6E 6F + 70 71 72 73 74 75 76 77 + 78 79 7A 7B 7C 7D 7E 7F + 80 81 82 83 84 85 86 87 + 88 89 8A 8B 8C 8D 8E 8F + 90 91 92 93 94 95 96 97 + 98 99 9A 9B 9C 9D 9E 9F + A0 A1 A2 A3 A4 A5 A6 A7 + A8 A9 AA AB AC AD AE AF + B0 B1 B2 B3 B4 B5 B6 B7 + B8 B9 BA BB BC BD BE BF + C0 C1 C2 C3 C4 C5 C6 C7 + C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 D7 + D8 D9 DA DB DC DD DE DF + E0 E1 E2 E3 E4 E5 E6 E7 + E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 F7 + F8 F9 FA FB FC FD FE FF + + 03 FF FF FF 00 FF 00 02 00 02 00 01 00 FF 00 00 diff --git a/releases/Snap Jack.mra b/releases/Snap Jack.mra new file mode 100644 index 0000000..a5541c8 --- /dev/null +++ b/releases/Snap Jack.mra @@ -0,0 +1,81 @@ + + Snap Jack + 0220 + snapjack + 20200427161917 + 1982 + Universal + Platform / Water Diving + ladybug + + + + + + + + + + + 01 + + + + + + + + + + + + + + + + + + 00 + + 00 01 02 03 04 05 06 07 + 08 09 0A 0B 0C 0D 0E 0F + 10 11 12 13 14 15 16 17 + 18 19 1A 1B 1C 1D 1E 1F + 20 21 22 23 24 25 26 27 + 28 29 2A 2B 2C 2D 2E 2F + 30 31 32 33 34 35 36 37 + 38 39 3A 3B 3C 3D 3E 3F + 40 41 42 43 44 45 46 47 + 48 49 4A 4B 4C 4D 4E 4F + 50 51 52 53 54 55 56 57 + 58 59 5A 5B 5C 5D 5E 5F + 60 61 62 63 64 65 66 67 + 68 69 6A 6B 6C 6D 6E 6F + 70 71 72 73 74 75 76 77 + 78 79 7A 7B 7C 7D 7E 7F + 80 81 82 83 84 85 86 87 + 88 89 8A 8B 8C 8D 8E 8F + 90 91 92 93 94 95 96 97 + 98 99 9A 9B 9C 9D 9E 9F + A0 A1 A2 A3 A4 A5 A6 A7 + A8 A9 AA AB AC AD AE AF + B0 B1 B2 B3 B4 B5 B6 B7 + B8 B9 BA BB BC BD BE BF + C0 C1 C2 C3 C4 C5 C6 C7 + C8 C9 CA CB CC CD CE CF + D0 D1 D2 D3 D4 D5 D6 D7 + D8 D9 DA DB DC DD DE DF + E0 E1 E2 E3 E4 E5 E6 E7 + E8 E9 EA EB EC ED EE EF + F0 F1 F2 F3 F4 F5 F6 F7 + F8 F9 FA FB FC FD FE FF + + + + + 00 00 00 00 00 FF 00 02 00 02 00 01 00 FF 00 00 + 00 00 6A 94 00 41 01 24 + + + + diff --git a/rtl/dpram.vhd b/rtl/dpram.vhd index 9774848..80646d2 100644 --- a/rtl/dpram.vhd +++ b/rtl/dpram.vhd @@ -15,7 +15,7 @@ entity dpram is address_b : IN STD_LOGIC_VECTOR (addr_width_g-1 DOWNTO 0); clock_a : IN STD_LOGIC := '1'; clock_b : IN STD_LOGIC ; - data_a : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0); + data_a : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) := (others => '0'); data_b : IN STD_LOGIC_VECTOR (data_width_g-1 DOWNTO 0) := (others => '0'); enable_a : IN STD_LOGIC := '1'; enable_b : IN STD_LOGIC := '1'; diff --git a/rtl/hiscore.v b/rtl/hiscore.v index 127d6ad..fcd5464 100644 --- a/rtl/hiscore.v +++ b/rtl/hiscore.v @@ -29,6 +29,7 @@ 0004 - 2021-03-15 - Fix ram_access assignment 0005 - 2021-03-18 - Add configurable score table width, clean up some stupid mistakes 0006 - 2021-03-27 - Move 'tweakable' parameters into MRA data header + 0007 - 2021-04-15 - Improve state machine maintainability, add new 'pause padding' states ============================================================================ */ @@ -56,16 +57,40 @@ module hiscore output [HS_ADDRESSWIDTH-1:0] ram_address, // Address in game RAM to read/write score data output [7:0] data_to_ram, // Data to write to game RAM output reg ram_write, // Write to game RAM (active high) - output ram_access // RAM read or write required (active high) + output ram_access, // RAM read or write required (active high) + output reg pause_cpu // Pause core CPU to prepare for/relax after RAM access ); // Parameters read from config header -reg [31:0] START_WAIT =1'b0; // Delay before beginning check process -reg [15:0] CHECK_WAIT =8'hFF; // Delay between start/end check attempts -reg [15:0] CHECK_HOLD =8'd2; // Hold time for start/end check reads -reg [15:0] WRITE_HOLD =8'd2; // Hold time for game RAM writes -reg [15:0] WRITE_REPEATCOUNT =8'b1; // Number of times to write score to game RAM -reg [15:0] WRITE_REPEATWAIT =8'b1111; // Delay between subsequent write attempts to game RAM +reg [31:0] START_WAIT =32'd0; // Delay before beginning check process +reg [15:0] CHECK_WAIT =16'hFF; // Delay between start/end check attempts +reg [15:0] CHECK_HOLD =16'd2; // Hold time for start/end check reads +reg [15:0] WRITE_HOLD =16'd2; // Hold time for game RAM writes +reg [15:0] WRITE_REPEATCOUNT =16'b1; // Number of times to write score to game RAM +reg [15:0] WRITE_REPEATWAIT =16'b1111; // Delay between subsequent write attempts to game RAM +reg [7:0] ACCESS_PAUSEPAD =8'd4; // Cycles to wait with paused CPU before and after RAM access + + +// State machine constants +localparam SM_STATEWIDTH = 4; // Width of state machine net + +localparam SM_INIT = 0; +localparam SM_TIMER = 1; + +localparam SM_CHECKPREP = 2; +localparam SM_CHECKBEGIN = 3; +localparam SM_CHECKSTARTVAL = 4; +localparam SM_CHECKENDVAL = 5; +localparam SM_CHECKCANCEL = 6; + +localparam SM_WRITEPREP = 7; +localparam SM_WRITEBEGIN = 8; +localparam SM_WRITEREADY = 9; +localparam SM_WRITEDONE = 10; +localparam SM_WRITECOMPLETE = 11; +localparam SM_WRITERETRY = 12; + +localparam SM_STOPPED = 13; /* Hiscore config data structure (version 1) @@ -107,9 +132,9 @@ Hiscore config data structure (version 1) */ -localparam HS_VERSION =6; // Version identifier for module +localparam HS_VERSION =7; // Version identifier for module localparam HS_DUMPFORMAT =1; // Version identifier for dump format -localparam HS_HEADERLENGTH =4'b1111; // Size of header chunk (default=16 bytes) +localparam HS_HEADERLENGTH =16; // Size of header chunk (default=16 bytes) // HS_DUMPFORMAT = 1 --> No header, just the extracted hiscore data @@ -132,18 +157,18 @@ assign uploading_dump = ioctl_upload && (ioctl_index==HS_DUMPINDEX); assign ram_access = uploading_dump | writing_scores | checking_scores; assign ram_address = ram_addr[HS_ADDRESSWIDTH-1:0]; -reg [3:0] state = 4'b0000; // Current state machine index -reg [3:0] next_state = 4'b0000; // Next state machine index to move to after wait timer expires +reg [(SM_STATEWIDTH-1):0] state = SM_INIT; // Current state machine index +reg [(SM_STATEWIDTH-1):0] next_state = SM_INIT; // Next state machine index to move to after wait timer expires reg [31:0] wait_timer; // Wait timer for inital/read/write delays reg [CFG_ADDRESSWIDTH-1:0] counter = 1'b0; // Index for current config table entry -reg [CFG_ADDRESSWIDTH-1:0] total_entries=1'b0; // Total count of config table entries +reg [CFG_ADDRESSWIDTH-1:0] total_entries = 1'b0; // Total count of config table entries reg reset_last = 1'b0; // Last cycle reset reg [7:0] write_counter = 1'b0; // Index of current game RAM write attempt reg [7:0] last_ioctl_index; // Last cycle HPS IO index -reg last_ioctl_download=0; // Last cycle HPS IO download -reg last_ioctl_upload=0; // Last cycle HPS IO upload +reg last_ioctl_download = 0;// Last cycle HPS IO download +reg last_ioctl_upload = 0; // Last cycle HPS IO upload reg [7:0] last_ioctl_dout; // Last cycle HPS IO data out reg [7:0] last_ioctl_dout2; // Last cycle +1 HPS IO data out reg [7:0] last_ioctl_dout3; // Last cycle +2 HPS IO data out @@ -235,12 +260,16 @@ begin // Get header chunk data if(parsing_header) begin - if(ioctl_wr & (header_chunk == 4'd3)) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout }; - if(ioctl_wr & (header_chunk == 4'd5)) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout }; - if(ioctl_wr & (header_chunk == 4'd7)) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout }; - if(ioctl_wr & (header_chunk == 4'd9)) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout }; - if(ioctl_wr & (header_chunk == 4'd11)) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout }; - if(ioctl_wr & (header_chunk == 4'd13)) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout }; + if(ioctl_wr) + begin + if(header_chunk == 4'd3) START_WAIT <= { last_ioctl_dout3, last_ioctl_dout2, last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd5) CHECK_WAIT <= { last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd7) CHECK_HOLD <= { last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd9) WRITE_HOLD <= { last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd11) WRITE_REPEATCOUNT <= { last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd13) WRITE_REPEATWAIT <= { last_ioctl_dout, ioctl_dout }; + if(header_chunk == 4'd14) ACCESS_PAUSEPAD <= ioctl_dout; + end end else begin @@ -285,8 +314,8 @@ begin if (reset_last == 1'b1 && reset == 1'b0) begin wait_timer <= START_WAIT; - next_state <= 4'b0000; - state <= 4'b1111; + next_state <= SM_INIT; + state <= SM_TIMER; counter <= 1'b0; initialised <= initialised + 1'b1; end @@ -317,34 +346,45 @@ begin begin // State machine to write data to game RAM case (state) - 4'b0000: // Start state machine + SM_INIT: // Start state machine begin - // Setup base addresses - local_addr <= 0; - base_io_addr <= 25'b0; - // Reset entry counter and states - counter <= 0; - writing_scores <= 1'b0; - checking_scores <= 1'b0; - state <= 4'b0001; + // Setup base addresses + local_addr <= 0; + base_io_addr <= 25'b0; + // Reset entry counter and states + counter <= 0; + writing_scores <= 1'b0; + checking_scores <= 1'b0; + pause_cpu <= 1'b0; + state <= SM_CHECKPREP; end - 4'b0001: // Start start/end check run + // Start/end check states + // ---------------------- + SM_CHECKPREP: // Prepare start/end check run - pause CPU in readiness for RAM access begin - checking_scores <= 1'b1; - ram_addr <= {1'b0, addr_base}; - state <= 4'b0010; - wait_timer <= CHECK_HOLD; + state <= SM_TIMER; + next_state <= SM_CHECKBEGIN; + pause_cpu <= 1'b1; + wait_timer <= ACCESS_PAUSEPAD; end - 4'b0010: // Start check + SM_CHECKBEGIN: // Begin start/end check run - enable RAM access + begin + checking_scores <= 1'b1; + ram_addr <= {1'b0, addr_base}; + state <= SM_CHECKSTARTVAL; + wait_timer <= CHECK_HOLD; + end + + SM_CHECKSTARTVAL: // Start check begin // Check for matching start value if(wait_timer != CHECK_HOLD & ioctl_din == start_val) begin // Prepare end check ram_addr <= end_addr; - state <= 4'b0100; + state <= SM_CHECKENDVAL; wait_timer <= CHECK_HOLD; end else @@ -357,24 +397,24 @@ begin else begin // - If no match after read wait then stop check run and schedule restart of state machine - next_state <= 4'b0000; - state <= 4'b1111; + next_state <= SM_CHECKCANCEL; + state <= SM_TIMER; checking_scores <= 1'b0; - wait_timer <= CHECK_WAIT; + wait_timer <= ACCESS_PAUSEPAD; end end end - 4'b0100: // End check + SM_CHECKENDVAL: // End check begin // Check for matching end value if (wait_timer != CHECK_HOLD & ioctl_din == end_val) begin if (counter == total_entries) begin - // If this was the last entry then move to phase II, copying scores into game ram + // If this was the last entry then move on to writing scores to game ram checking_scores <= 1'b0; - state <= 4'b1001; + state <= SM_WRITEBEGIN; // Bypass SM_WRITEPREP as we are already paused counter <= 1'b0; write_counter <= 1'b0; ram_write <= 1'b0; @@ -384,7 +424,7 @@ begin begin // Increment counter and restart state machine to check next entry counter <= counter + 1'b1; - state <= 4'b0001; + state <= SM_CHECKBEGIN; end end else @@ -396,25 +436,58 @@ begin end else begin - // - If no match after read wait then stop check run and reset state machine - state <= 4'b0000; + // - If no match after read wait then stop check run and schedule restart of state machine + next_state <= SM_CHECKCANCEL; + state <= SM_TIMER; checking_scores <= 1'b0; - wait_timer <= CHECK_WAIT; + wait_timer <= ACCESS_PAUSEPAD; end end end - // - // this section walks through our temporary ram and copies into game ram - // it needs to happen in chunks, because the game ram isn't necessarily consecutive - 4'b0110: + SM_CHECKCANCEL: // Cancel start/end check run - disable RAM access and keep CPU paused begin - local_addr <= local_addr + 1'b1; + pause_cpu <= 1'b0; + next_state <= SM_INIT; + state <= SM_TIMER; + wait_timer <= CHECK_WAIT; + end + + // Write to game RAM states + // ---------------------- + SM_WRITEPREP: // Prepare to write scores - pause CPU in readiness for RAM access (only used on subsequent write attempts) + begin + state <= SM_TIMER; + next_state <= SM_WRITEBEGIN; + pause_cpu <= 1'b1; + wait_timer <= ACCESS_PAUSEPAD; + end + + SM_WRITEBEGIN: // Writing scores to game RAM begins + begin + writing_scores <= 1'b1; // Enable muxes if necessary + write_counter <= write_counter + 1'b1; + state <= SM_WRITEREADY; + end + + SM_WRITEREADY: // local ram should be correct, start write to game RAM + begin + ram_addr <= addr_base + (local_addr - base_io_addr); + state <= SM_TIMER; + next_state <= SM_WRITEDONE; + wait_timer <= WRITE_HOLD; + ram_write <= 1'b1; + end + + SM_WRITEDONE: + begin + local_addr <= local_addr + 1'b1; // Increment to next byte of entry if (ram_addr == end_addr) begin + // End of entry reached if (counter == total_entries) begin - state <= 4'b1000; + state <= SM_WRITECOMPLETE; end else begin @@ -422,58 +495,49 @@ begin counter <= counter + 1'b1; write_counter <= 1'b0; base_io_addr <= local_addr + 1'b1; - state <= 4'b1001; + state <= SM_WRITEBEGIN; end end else begin - state <= 4'b1010; + state <= SM_WRITEREADY; end ram_write <= 1'b0; end - 4'b1000: // Hiscore write to RAM completed + SM_WRITECOMPLETE: // Hiscore write to RAM completed begin ram_write <= 1'b0; writing_scores <= 1'b0; + state <= SM_TIMER; if(write_counter < WRITE_REPEATCOUNT) begin // Schedule next write - state <= 4'b1111; - next_state <= 4'b1001; + next_state <= SM_WRITERETRY; local_addr <= 0; wait_timer <= WRITE_REPEATWAIT; end - end - - 4'b1001: // Writing scores to game RAM begins - begin - writing_scores <= 1'b1; // indicate that writing has begun, will hold pause until write is complete if hooked up in core - write_counter <= write_counter + 1'b1; - state <= 4'b1010; - end - - 4'b1010: // local ram is correct - begin - state <= 4'b1110; - ram_addr <= addr_base + (local_addr - base_io_addr); - ram_write <= 1'b1; - wait_timer <= WRITE_HOLD; - end - - 4'b1110: // hold write for wait_timer - begin - if (wait_timer > 1'b0) - begin - wait_timer <= wait_timer - 1'b1; - end else begin - state <= 4'b0110; + next_state <= SM_STOPPED; + wait_timer <= ACCESS_PAUSEPAD; end end - - 4'b1111: // timer wait state + + SM_WRITERETRY: // Stop pause and schedule next write + begin + pause_cpu <= 1'b0; + state <= SM_TIMER; + next_state <= SM_WRITEPREP; + wait_timer <= WRITE_REPEATWAIT; + end + + SM_STOPPED: + begin + pause_cpu <= 1'b0; + end + + SM_TIMER: // timer wait state begin if (wait_timer > 1'b0) wait_timer <= wait_timer - 1'b1; diff --git a/rtl/ladybug.vhd b/rtl/ladybug.vhd index 8b36d79..78f9b9a 100644 --- a/rtl/ladybug.vhd +++ b/rtl/ladybug.vhd @@ -57,6 +57,7 @@ port ( dn_addr : in std_logic_vector(15 downto 0); dn_data : in std_logic_vector(7 downto 0); dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0); -- VGA Interface ---------------------------------------------------------- O_VIDEO_R : out std_logic_vector( 1 downto 0); @@ -137,6 +138,8 @@ architecture struct of ladybug is signal but_chute_s : std_logic_vector( 1 downto 0) := (others=>'0'); signal rom_cpu1_cs, rom_cpu2_cs, rom_cpu3_cs, rom_sprite_l_cs, rom_sprite_u_cs, rom_char_l_cs, rom_char_u_cs : std_logic; + + signal rom_download : std_logic; begin O_PIXCE <= clk_en_5mhz_s; @@ -189,7 +192,11 @@ begin hs_data_in => hs_data_in, hs_data_out => hs_data_out, hs_write => hs_write, - hs_access => hs_access + hs_access => hs_access, + dn_addr => dn_addr, + dn_data => dn_data, + dn_wr => dn_wr, + dn_index => dn_index ); ----------------------------------------------------------------------------- @@ -211,12 +218,13 @@ begin rom_sprite_u_cs <= '1' when dn_addr(15 downto 12)=X"7" else '0'; rom_char_l_cs <= '1' when dn_addr(15 downto 12)=X"8" else '0'; rom_char_u_cs <= '1' when dn_addr(15 downto 12)=X"9" else '0'; + rom_download <= '1' when dn_wr = '1' and dn_index(7 downto 0) = "00000000" else '0'; inst_rom_spritel : work.dpram generic map (12,8) port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_sprite_l_cs, + wren_a => rom_download and rom_sprite_l_cs, address_a => dn_addr(11 downto 0), data_a => dn_data, @@ -229,7 +237,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_sprite_u_cs, + wren_a => rom_download and rom_sprite_u_cs, address_a => dn_addr(11 downto 0), data_a => dn_data, @@ -242,7 +250,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_char_l_cs, + wren_a => rom_download and rom_char_l_cs, address_a => dn_addr(11 downto 0), data_a => dn_data, @@ -255,7 +263,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_char_u_cs, + wren_a => rom_download and rom_char_u_cs, address_a => dn_addr(11 downto 0), data_a => dn_data, @@ -268,7 +276,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_cpu1_cs, + wren_a => rom_download and rom_cpu1_cs, address_a => dn_addr(12 downto 0), data_a => dn_data, @@ -281,7 +289,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_cpu2_cs, + wren_a => rom_download and rom_cpu2_cs, address_a => dn_addr(12 downto 0), data_a => dn_data, @@ -294,7 +302,7 @@ begin port map ( clock_a => clk_20mhz_s, - wren_a => dn_wr and rom_cpu3_cs, + wren_a => rom_download and rom_cpu3_cs, address_a => dn_addr(12 downto 0), data_a => dn_data, diff --git a/rtl/ladybug_cpu_unit.vhd b/rtl/ladybug_cpu_unit.vhd index cdfee15..535a6ed 100644 --- a/rtl/ladybug_cpu_unit.vhd +++ b/rtl/ladybug_cpu_unit.vhd @@ -50,6 +50,7 @@ library ieee; use ieee.std_logic_1164.all; +use ieee.numeric_std.all; entity ladybug_cpu_unit is port ( @@ -78,6 +79,11 @@ entity ladybug_cpu_unit is cs12_n_o : out std_logic; cs13_n_o : out std_logic; + dn_addr : in std_logic_vector(15 downto 0); + dn_data : in std_logic_vector(7 downto 0); + dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0); + pause : in std_logic; hs_address : in std_logic_vector(15 downto 0); @@ -114,6 +120,8 @@ architecture struct of ladybug_cpu_unit is signal ram_cpu_cs_n_s : std_logic; signal vcc_s : std_logic; + + signal decrypt_prom_wr : std_logic; begin vcc_s <= '1'; @@ -156,24 +164,24 @@ begin ----------------------------------------------------------------------------- -- The CPU RAM ----------------------------------------------------------------------------- - cpu_ram_b : entity work.ladybug_cpu_ram - port map ( - clk1_i => clk_20mhz_i, - clk_en1_i => clk_en_4mhz_i, - a1_i => a_s(11 downto 0), - cs1_n_i => cs_n_s(6), - we1_n_i => wr_n_s, - d1_i => d_from_cpu_s, - d1_o => d_from_ram_s, + cpu_ram_b : entity work.ladybug_cpu_ram + port map ( + clk1_i => clk_20mhz_i, + clk_en1_i => clk_en_4mhz_i, + a1_i => a_s(11 downto 0), + cs1_n_i => cs_n_s(6), + we1_n_i => wr_n_s, + d1_i => d_from_cpu_s, + d1_o => d_from_ram_s, - clk2_i => clk_20mhz_i, - clk_en2_i => '1', - a2_i => hs_address(11 downto 0), - cs2_n_i => '0', - we2_n_i => not hs_write, - d2_i => hs_data_in, - d2_o => hs_data_out - ); + clk2_i => clk_20mhz_i, + clk_en2_i => '1', + a2_i => hs_address(11 downto 0), + cs2_n_i => '0', + we2_n_i => not hs_write, + d2_i => hs_data_in, + d2_o => hs_data_out + ); ----------------------------------------------------------------------------- -- The Address Decoder @@ -228,12 +236,19 @@ begin -- Decrytion PROMs ----------------------------------------------------------------------------- - decrypt_prom : entity work.prom_decrypt - port map ( - CLK => clk_20mhz_i, - ADDR => rom_cpu_d_i, - DATA => d_decrypted_s - ); + decrypt_prom_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8) = '1') else '0'; + + decrypt_prom : entity work.dpram generic map(8,8) + port map ( + clock_a => clk_20mhz_i, + address_a => dn_addr(7 downto 0), + data_a => dn_data, + wren_a => decrypt_prom_wr, + + clock_b => clk_20mhz_i, + address_b => rom_cpu_d_i, + q_b => d_decrypted_s + ); ----------------------------------------------------------------------------- -- Only opcodes (i.e. instruction fetches) have to be decrypted diff --git a/rtl/ladybug_machine.vhd b/rtl/ladybug_machine.vhd index b320a93..f8cb729 100644 --- a/rtl/ladybug_machine.vhd +++ b/rtl/ladybug_machine.vhd @@ -91,6 +91,11 @@ entity ladybug_machine is rom_sprite_a_o : out std_logic_vector(11 downto 0); rom_sprite_d_i : in std_logic_vector(15 downto 0); + dn_addr : in std_logic_vector(15 downto 0); + dn_data : in std_logic_vector(7 downto 0); + dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0); + pause : in std_logic; -- Hiscore hs_address : in std_logic_vector(15 downto 0); @@ -253,7 +258,11 @@ begin hs_address => hs_address, hs_data_in => hs_data_in, hs_data_out => hs_data_out_cpu, - hs_write => hs_write and hs_cs_cpu + hs_write => hs_write and hs_cs_cpu, + dn_addr => dn_addr, + dn_data => dn_data, + dn_wr => dn_wr, + dn_index => dn_index ); ----------------------------------------------------------------------------- @@ -302,7 +311,11 @@ begin hs_address => hs_address, hs_data_in => hs_data_in, hs_data_out => hs_data_out_vram, - hs_write => hs_write and hs_cs_vram + hs_write => hs_write and hs_cs_vram, + dn_addr => dn_addr, + dn_data => dn_data, + dn_wr => dn_wr, + dn_index => dn_index ); ----------------------------------------------------------------------------- diff --git a/rtl/ladybug_rgb.vhd b/rtl/ladybug_rgb.vhd index 1bfcd53..6af521e 100644 --- a/rtl/ladybug_rgb.vhd +++ b/rtl/ladybug_rgb.vhd @@ -57,7 +57,11 @@ entity ladybug_rgb is sig_i : in std_logic_vector(4 downto 1); rgb_r_o : out std_logic_vector(1 downto 0); rgb_g_o : out std_logic_vector(1 downto 0); - rgb_b_o : out std_logic_vector(1 downto 0) + rgb_b_o : out std_logic_vector(1 downto 0); + dn_addr : in std_logic_vector(15 downto 0); + dn_data : in std_logic_vector(7 downto 0); + dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0) ); end ladybug_rgb; @@ -68,6 +72,8 @@ architecture rtl of ladybug_rgb is signal rgb_s : std_logic_vector(8 downto 1); signal rgb_n_q : std_logic_vector(8 downto 1); + signal prom_wr : std_logic; + begin ----------------------------------------------------------------------------- @@ -98,12 +104,20 @@ begin ----------------------------------------------------------------------------- -- The RGB Conversion PROM ----------------------------------------------------------------------------- - rgb_prom_b : entity work.prom_10_2 - port map ( - CLK => clk_20mhz_i, - ADDR => a_s, - DATA => rgb_s - ); + + prom_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0001") else '0'; + + rgb_prom_b : entity work.dpram generic map(5,8) + port map ( + clock_a => clk_20mhz_i, + address_a => dn_addr(4 downto 0), + data_a => dn_data, + wren_a => prom_wr, + + clock_b => clk_20mhz_i, + address_b => a_s, + q_b => rgb_s + ); ----------------------------------------------------------------------------- -- Process rgb_latch diff --git a/rtl/ladybug_sprite.vhd b/rtl/ladybug_sprite.vhd index 941d997..c67253f 100644 --- a/rtl/ladybug_sprite.vhd +++ b/rtl/ladybug_sprite.vhd @@ -81,7 +81,12 @@ port ( sig_o : out std_logic_vector( 4 downto 1); -- Sprite ROM Interface --------------------------------------------------- rom_sprite_a_o : out std_logic_vector(11 downto 0); - rom_sprite_d_i : in std_logic_vector(15 downto 0) + rom_sprite_d_i : in std_logic_vector(15 downto 0); + + dn_addr : in std_logic_vector(15 downto 0); + dn_data : in std_logic_vector(7 downto 0); + dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0) ); end ladybug_sprite; @@ -169,6 +174,9 @@ architecture rtl of ladybug_sprite is signal vram_q : std_logic_vector(15 downto 0); + signal prom_F4_wr : std_logic; + signal prom_C4_wr : std_logic; + begin ----------------------------------------------------------------------------- @@ -505,11 +513,18 @@ begin lu_a_s(1) <= qh2_s; lu_a_s(0) <= qh1_s; - prom_F4 : entity work.prom_10_1 + prom_F4_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0000") else '0'; + + prom_F4 : entity work.dpram generic map(5,8) port map ( - CLK => clk_20mhz_i, - ADDR => lu_a_s, - DATA => lu_d_s + clock_a => clk_20mhz_i, + address_a => dn_addr(4 downto 0), + data_a => dn_data, + wren_a => prom_F4_wr, + + clock_b => clk_20mhz_i, + address_b => lu_a_s, + q_b => lu_d_s ); lu_d_mux_s <= lu_d_s(3 downto 0) when cl_q(3) = '0' else lu_d_s(7 downto 4); @@ -523,13 +538,19 @@ begin ctrl_lu_a_s(3) <= h_i(0); ctrl_lu_a_s(4) <= h_i(1); - prom_C4 : entity work.prom_10_3 + prom_C4_wr <= '1' when (dn_wr = '1' and dn_index(7 downto 0) = "00000010" and dn_addr(8 downto 5) = "0010") else '0'; + prom_C4 : entity work.dpram generic map(5,8) port map ( - CLK => clk_20mhz_i, - ADDR => ctrl_lu_a_s, - DATA => ctrl_lu_d_s - ); + clock_a => clk_20mhz_i, + address_a => dn_addr(4 downto 0), + data_a => dn_data, + wren_a => prom_C4_wr, + clock_b => clk_20mhz_i, + address_b => ctrl_lu_a_s, + q_b => ctrl_lu_d_s + ); + ----------------------------------------------------------------------------- -- Process ctrl_lu_seq -- diff --git a/rtl/ladybug_video_unit.vhd b/rtl/ladybug_video_unit.vhd index e97b238..f1aa3d8 100644 --- a/rtl/ladybug_video_unit.vhd +++ b/rtl/ladybug_video_unit.vhd @@ -87,6 +87,11 @@ entity ladybug_video_unit is rom_sprite_a_o : out std_logic_vector(11 downto 0); rom_sprite_d_i : in std_logic_vector(15 downto 0); + dn_addr : in std_logic_vector(15 downto 0); + dn_data : in std_logic_vector(7 downto 0); + dn_wr : in std_logic; + dn_index : in std_logic_vector(7 downto 0); + pause : in std_logic; hs_address : in std_logic_vector(15 downto 0); @@ -220,7 +225,11 @@ begin blank_i => blank_s, sig_o => sig_s, rom_sprite_a_o => rom_sprite_a_o, - rom_sprite_d_i => rom_sprite_d_i + rom_sprite_d_i => rom_sprite_d_i, + dn_addr => dn_addr, + dn_data => dn_data, + dn_wr => dn_wr, + dn_index => dn_index ); @@ -236,10 +245,13 @@ begin sig_i => sig_s, rgb_r_o => rgb_r_o, rgb_g_o => rgb_g_o, - rgb_b_o => rgb_b_o + rgb_b_o => rgb_b_o, + dn_addr => dn_addr, + dn_data => dn_data, + dn_wr => dn_wr, + dn_index => dn_index ); - ----------------------------------------------------------------------------- -- Bus Multiplexer ----------------------------------------------------------------------------- diff --git a/rtl/pause.v b/rtl/pause.v new file mode 100644 index 0000000..4f21042 --- /dev/null +++ b/rtl/pause.v @@ -0,0 +1,93 @@ +//============================================================================ +// Generic pause handling for MiSTer cores. +// +// https://github.com/JimmyStones/Pause_MiSTer +// +// Copyright (c) 2021 Jim Gregory +// +// This program 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 program 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, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +//============================================================================ +/* + Features: + - Pause can be triggered by user input, hiscore module or OSD opening (optionally controlled by setting in OSD) + - When paused the RGB outputs will be halved after 10 seconds to reduce burn-in (optionally controlled by setting in OSD) + - Reset signal will cancel user triggered pause + + Version history: + 0001 - 2021-03-15 - First marked release +============================================================================ +*/ +module pause #( + parameter RW=8, // Width of red channel + parameter GW=8, // Width of green channel + parameter BW=8, // Width of blue channel + parameter CLKSPD = 12 // Main clock speed in MHz +) +( + input clk_sys, // Core system clock (should match HPS module) + input reset, // CPU reset signal (active-high) + input user_button, // User pause button signal (active-high) + input pause_request, // Pause requested by other code (active-high) + input [1:0] options, // Pause options from OSD + // [0] = pause in OSD (active-high) + // [1] = dim video (active-high) + input OSD_STATUS, // OSD is open (active-high) + input [(RW-1):0] r, // Red channel + input [(GW-1):0] g, // Green channel + input [(BW-1):0] b, // Blue channel + + output pause_cpu, // Pause signal to CPU (active-high) + output [(RW+GW+BW-1):0] rgb_out // RGB output to arcade_video module + +); + +// Option constants +localparam pause_in_osd = 1'b0; +localparam dim_video = 1'b1; + +reg pause_toggle = 1'b0; // User paused (active-high) +reg [31:0] pause_timer = 1'b0; // Time since pause +reg [31:0] dim_timeout = (CLKSPD*10000000); // Time until video output dim (10 seconds @ CLKSPD Mhz) + +assign pause_cpu = (pause_request | pause_toggle | (OSD_STATUS & options[pause_in_osd])) & !reset; + +always @(posedge clk_sys) begin + + // Track user pause button down + reg user_button_last; + user_button_last <= user_button; + if(!user_button_last & user_button) pause_toggle <= ~pause_toggle; + + // Clear user pause on reset + if(pause_toggle & reset) pause_toggle <= 0; + + if(pause_cpu & options[dim_video]) + begin + // Track pause duration for video dim + if((pause_timer= dim_timeout) ? {r >> 1,g >> 1, b >> 1} : {r,g,b}; + +endmodule \ No newline at end of file