From 93b45fe4b04dbf4d07340fc68cf8626a91dda217 Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Mon, 30 Dec 2019 21:15:21 +0100 Subject: [PATCH] Traverse USA: add ShotRider mode + load all ROMs from SD Card --- .../TraverseUSA_MiST/ReadMe.txt | 8 +- .../TraverseUSA_MiST/TraverseUSA_MiST.qsf | 38 +- .../TraverseUSA_MiST/rtl/TraverseUSA_MiST.sv | 121 ++++- .../TraverseUSA_MiST/rtl/dpram.vhd | 81 +++ .../rtl/moon_patrol_sound_board.vhd | 20 +- .../TraverseUSA_MiST/rtl/pll_mist.vhd | 16 +- .../TraverseUSA_MiST/rtl/sdram.sv | 505 ++++++++++-------- .../TraverseUSA_MiST/rtl/traverse_usa.vhd | 212 ++++++-- 8 files changed, 679 insertions(+), 322 deletions(-) create mode 100644 Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/ReadMe.txt b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/ReadMe.txt index 1af441c9..eff56ba4 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/ReadMe.txt +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/ReadMe.txt @@ -2,13 +2,15 @@ Traverse USA by Dar (darfpga@aol.fr) (16/03/2019) Port to MiST -TRAVERSE.ROM is required at the root of the SD-Card. +TRAVRUSA.ROM or SHTRIDER.ROM is required at the root of the SD-Card. Creating in Windows: -copy /B zr1-0.m3 + zr1-5.l3 + zr1-6a.k3 + zr1-7.j3 TRAVERSE.ROM +copy /B zr1-0.m3 + zr1-5.l3 + zr1-6a.k3 + zr1-7.j3 + mr10.1a + mr10.1a + zippyrac.001 + mr8.3c + mr9.3a + zr1-8.n3 + zr1-9.l3 + zr1-10.k3 + mmi6349.ij + tbp24s10.3 + tbp18s.2 > TRAVRUSA.ROM +copy /B sr01a.bin + sr02a.bin + sr03a.bin + sr04a.bin + sr11a.bin + sr05a.bin + sr06a.bin + sr07a.bin + sr08a.bin + sr09a.bin + sr10b.bin + 1.bpr + 2.bpr + 3.bpr + 4.bpr > SHTRIDER.ROM Creating in Linux: -cat zr1-0.m3 zr1-5.l3 zr1-6a.k3 zr1-7.j3 > TRAVERSE.ROM +cat zr1-0.m3 zr1-5.l3 zr1-6a.k3 zr1-7.j3 mr10.1a mr10.1a zippyrac.001 mr8.3c mr9.3a zr1-8.n3 zr1-9.l3 zr1-10.k3 mmi6349.ij tbp24s10.3 tbp18s.2 > TRAVRUSA.ROM +cat sr01a.bin sr02a.bin sr03a.bin sr04a.bin sr11a.bin sr05a.bin sr06a.bin sr07a.bin sr08a.bin sr09a.bin sr10b.bin 1.bpr 2.bpr 3.bpr 4.bpr > SHTRIDER.ROM Some ROM files contain different names, like: zippyrac.000 diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/TraverseUSA_MiST.qsf b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/TraverseUSA_MiST.qsf index 248da9fb..dad2a1db 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/TraverseUSA_MiST.qsf +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/TraverseUSA_MiST.qsf @@ -73,7 +73,6 @@ set_location_assignment PIN_126 -to SPI_SCK set_location_assignment PIN_127 -to SPI_SS2 set_location_assignment PIN_91 -to SPI_SS3 set_location_assignment PIN_13 -to CONF_DATA0 -set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" set_location_assignment PIN_49 -to SDRAM_A[0] set_location_assignment PIN_44 -to SDRAM_A[1] set_location_assignment PIN_42 -to SDRAM_A[2] @@ -113,6 +112,40 @@ set_location_assignment PIN_66 -to SDRAM_nWE set_location_assignment PIN_59 -to SDRAM_nCS set_location_assignment PIN_33 -to SDRAM_CKE set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[0] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA[1] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQMH +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQML +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCS +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ[*] + +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_A[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQ[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_BA[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQML +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_DQMH +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nRAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCAS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nWE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_nCS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CKE +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_CLK +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_R[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_G[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_B[*] +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_HS +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_VS +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_L +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to AUDIO_R +set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO set_global_assignment -name FAMILY "Cyclone III" set_global_assignment -name DEVICE EP3C25E144C8 @@ -167,6 +200,9 @@ set_global_assignment -name VHDL_FILE rtl/proms/travusa_chr_bit3.vhd set_global_assignment -name VHDL_FILE rtl/proms/travusa_chr_bit2.vhd set_global_assignment -name VHDL_FILE rtl/proms/travusa_chr_bit1.vhd set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv +set_global_assignment -name VHDL_FILE rtl/dpram.vhd set_global_assignment -name QIP_FILE ../../../common/CPU/T80/T80.qip set_global_assignment -name QIP_FILE ../../../common/mist/mist.qip +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name ALLOW_ANY_RAM_SIZE_FOR_RECOGNITION ON 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/TraverseUSA_MiST/rtl/TraverseUSA_MiST.sv b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/TraverseUSA_MiST.sv index 926ee875..e56bb87e 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/TraverseUSA_MiST.sv +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/TraverseUSA_MiST.sv @@ -1,5 +1,5 @@ //============================================================================ -// Arcade: TraverseUSA +// Arcade: TraverseUSA, ShotRider // // DarFPGA's core ported to MiST by (C) 2019 Szombathelyi György // @@ -50,8 +50,28 @@ module TraverseUSA_MiST( `include "rtl/build_id.v" +//`define CORE_NAME "SHTRIDER" +`define CORE_NAME "TRAVRUSA" + +reg shtrider; +//TravUSA: Coinage_B(7-4) / Cont. play(3) / Fuel consumption(2) / Fuel lost when collision (1-0) +wire [7:0] dip1 = 8'hff; +reg [7:0] dip2; + +always @(*) begin + if (`CORE_NAME == "SHTRIDER") begin + shtrider = 1; + // Cocktail(3) / M-Km(1) / Flip(0) + dip2 = { 4'b1111, 2'b11, status[5], 1'b0 }; + end else begin + shtrider = 0; + // Diag(7) / Demo(6) / Zippy(5) / Freeze (4) / M-Km(3) / Coin mode (2) / Cocktail(1) / Flip(0) + dip2 = { ~status[9], ~status[8], ~status[7], ~status[6], ~status[5], 3'b110 }; + end +end + localparam CONF_STR = { - "TRAVERSE;;", + `CORE_NAME,";;", "O2,Rotate Controls,Off,On;", "O34,Scanlines,Off,25%,50%,75%;", "OA,Blending,Off,On;", @@ -60,13 +80,14 @@ localparam CONF_STR = { "O7,Game name,Traverse USA,Zippyrace;", "O8,Demo mode,Off,On;", "O9,Test mode,Off,On;", - "T1,Reset;", + "T0,Reset;", "V,v1.0.",`BUILD_DATE }; assign LED = 1; assign AUDIO_R = AUDIO_L; assign SDRAM_CLK = clk_sys; +assign SDRAM_CKE = 1; wire clk_sys, clk_aud; wire pll_locked; @@ -95,12 +116,24 @@ wire [1:0] r; wire [14:0] cart_addr; wire [15:0] sdram_do; wire cart_rd; +wire [12:0] snd_addr; +wire [15:0] snd_do; + wire ioctl_downl; wire [7:0] ioctl_index; wire ioctl_wr; wire [24:0] ioctl_addr; wire [7:0] ioctl_dout; +/* ROM structure +00000-07FFF CPU ROM 32k zr1-0.m3 zr1-5.l3 zr1-6a.k3 zr1-7.j3 +08000-09FFF SND ROM 8k mr10.1a mr10.1a +0A000-0FFFF GFX1 24k zippyrac.001 mr8.3c mr9.3a +10000-15FFF GFX2 24k zr1-8.n3 zr1-9.l3 zr1-10.k3 +16000-161FF CHR PAL 512b mmi6349.ij +16200-162FF SPR PAL 256b tbp24s10.3 +16300-1631F SPR LUT 32b tbp18s.2 +*/ data_io data_io ( .clk_sys ( clk_sys ), .SPI_SCK ( SPI_SCK ), @@ -112,21 +145,50 @@ data_io data_io ( .ioctl_addr ( ioctl_addr ), .ioctl_dout ( ioctl_dout ) ); - -sdram cart -( + +reg port1_req, port2_req; +sdram sdram( .*, - .init ( ~pll_locked ), + .init_n ( pll_locked ), .clk ( clk_sys ), - .wtbt ( 2'b00 ), - .dout ( sdram_do ), - .din ( {ioctl_dout, ioctl_dout} ), - .addr ( ioctl_downl ? ioctl_addr : cart_addr ), - .we ( ioctl_downl & ioctl_wr ), - .rd ( !ioctl_downl & cart_rd ), - .ready() + + // port1 used for main CPU + .port1_req ( port1_req ), + .port1_ack ( ), + .port1_a ( ioctl_addr[23:1] ), + .port1_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port1_we ( ioctl_downl ), + .port1_d ( {ioctl_dout, ioctl_dout} ), + .port1_q ( ), + + .cpu1_addr ( ioctl_downl ? 15'h7fff : {1'b0, cart_addr[14:1]} ), + .cpu1_q ( sdram_do ), + + // port2 for sound board + .port2_req ( port2_req ), + .port2_ack ( ), + .port2_a ( ioctl_addr[23:1] - 16'h4000 ), + .port2_ds ( {ioctl_addr[0], ~ioctl_addr[0]} ), + .port2_we ( ioctl_downl ), + .port2_d ( {ioctl_dout, ioctl_dout} ), + .port2_q ( ), + + .snd_addr ( ioctl_downl ? 15'h7fff : {3'b000, snd_addr[12:1]} ), + .snd_q ( snd_do ) ); +always @(posedge clk_sys) begin + reg ioctl_wr_last = 0; + + ioctl_wr_last <= ioctl_wr; + if (ioctl_downl) begin + if (~ioctl_wr_last && ioctl_wr) begin + port1_req <= ~port1_req; + port2_req <= ~port2_req; + end + end +end + reg reset = 1; reg rom_loaded = 0; always @(posedge clk_sys) begin @@ -134,33 +196,27 @@ always @(posedge clk_sys) begin ioctl_downlD <= ioctl_downl; if (ioctl_downlD & ~ioctl_downl) rom_loaded <= 1; - reset <= status[0] | status[1] | buttons[1] | ~rom_loaded; + reset <= status[0] | buttons[1] | ~rom_loaded; end -//Coinage_B(7-4) / Cont. play(3) / Fuel consumption(2) / Fuel lost when collision (1-0) -wire [7:0] dip1 = 8'hff; -//Diag(7) / Demo(6) / Zippy(5) / Freeze (4) / M-Km(3) / Coin mode (2) / Cocktail(1) / Flip(0) -wire [7:0] dip2 = { ~status[9], ~status[8], ~status[7], ~status[6], ~status[5], 3'b110 }; // Traverse_usa traverse_usa traverse_usa ( .clock_36 ( clk_sys ), .clock_0p895 ( clk_aud ), - .reset ( reset ), + .reset ( reset ), + .shtrider ( shtrider ), + .video_r ( r ), .video_g ( g ), .video_b ( b ), - .video_hs ( hs ), + .video_hs ( hs ), .video_vs ( vs ), .video_blankn ( blankn ), .audio_out ( audio ), - - .cpu_rom_addr ( cart_addr ), - .cpu_rom_do ( sdram_do[7:0] ), - .cpu_rom_rd ( cart_rd ), - + .dip_switch_1 ( dip1 ), .dip_switch_2 ( dip2 ), @@ -176,7 +232,16 @@ traverse_usa traverse_usa ( .right2 ( m_right ), .left2 ( m_left ), .brake2 ( m_down ), - .accel2 ( m_up ) + .accel2 ( m_up ), + + .cpu_rom_addr ( cart_addr ), + .cpu_rom_do ( cart_addr[0] ? sdram_do[15:8] : sdram_do[7:0] ), + .cpu_rom_rd ( cart_rd ), + .snd_rom_addr ( snd_addr ), + .snd_rom_do ( snd_addr[0] ? snd_do[15:8] : snd_do[7:0] ), + .dl_addr ( ioctl_addr[16:0]), + .dl_data ( ioctl_dout ), + .dl_wr ( ioctl_wr ) ); mist_video #(.COLOR_DEPTH(3), .SD_HCNT_WIDTH(10)) mist_video( @@ -227,7 +292,7 @@ dac #( .C_bits(11)) dac( .clk_i(clk_aud), - .res_n_i(1), + .res_n_i(~reset), .dac_i(audio), .dac_o(AUDIO_L) ); diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd new file mode 100644 index 00000000..284194c5 --- /dev/null +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd @@ -0,0 +1,81 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- dpram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity dpram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk_a : in std_logic; + we_a : in std_logic := '0'; + addr_a : in std_logic_vector((aWidth-1) downto 0); + d_a : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_a : out std_logic_vector((dWidth-1) downto 0); + + clk_b : in std_logic; + we_b : in std_logic := '0'; + addr_b : in std_logic_vector((aWidth-1) downto 0); + d_b : in std_logic_vector((dWidth-1) downto 0) := (others => '0'); + q_b : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of dpram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + signal addr_a_reg: std_logic_vector((aWidth-1) downto 0); + signal addr_b_reg: std_logic_vector((aWidth-1) downto 0); +begin + +-- ----------------------------------------------------------------------- + process(clk_a) + begin + if rising_edge(clk_a) then + if we_a = '1' then + ram(to_integer(unsigned(addr_a))) <= d_a; + end if; + q_a <= ram(to_integer(unsigned(addr_a))); + end if; + end process; + + process(clk_b) + begin + if rising_edge(clk_b) then + if we_b = '1' then + ram(to_integer(unsigned(addr_b))) <= d_b; + end if; + q_b <= ram(to_integer(unsigned(addr_b))); + end if; + end process; + +end architecture; + diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/moon_patrol_sound_board.vhd b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/moon_patrol_sound_board.vhd index 126fe870..509e1825 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/moon_patrol_sound_board.vhd +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/moon_patrol_sound_board.vhd @@ -32,6 +32,9 @@ port( select_sound : in std_logic_vector(7 downto 0); audio_out : out std_logic_vector(11 downto 0); + rom_addr : out std_logic_vector(12 downto 0); + rom_do : in std_logic_vector( 7 downto 0); + dbg_cpu_addr : out std_logic_vector(15 downto 0) ); end moon_patrol_sound_board; @@ -83,7 +86,7 @@ architecture struct of moon_patrol_sound_board is signal wram_do : std_logic_vector( 7 downto 0); signal rom_cs : std_logic; - signal rom_do : std_logic_vector( 7 downto 0); +-- signal rom_do : std_logic_vector( 7 downto 0); signal ay1_chan_a : std_logic_vector(7 downto 0); signal ay1_chan_b : std_logic_vector(7 downto 0); @@ -161,7 +164,7 @@ wram_cs <= '1' when cpu_addr(15 downto 7) = X"00"&'1' else '0'; -- 0080-00FF ports_cs <= '1' when cpu_addr(15 downto 4) = X"000" else '0'; -- 0000-000F adpcm_cs <= '1' when cpu_addr(14 downto 11) = "0001" else '0'; -- 0800-0FFF / 8800-8FFF irqraz_cs <= '1' when cpu_addr(14 downto 12) = "001" else '0'; -- 1000-1FFF / 9000-9FFF -rom_cs <= '1' when cpu_addr(14 downto 12) = "111" else '0'; -- 7000-7FFF / F000-FFFF +rom_cs <= '1' when cpu_addr(14 downto 13) = "11" else '0'; -- 6000-7FFF / E000-FFFF -- write enables wram_we <= '1' when cpu_rw = '0' and wram_cs = '1' else '0'; @@ -345,12 +348,13 @@ port map( ); -- cpu program rom -cpu_prog_rom : entity work.travusa_sound -port map( - clk => clock_E, - addr => cpu_addr(11 downto 0), - data => rom_do -); +--cpu_prog_rom : entity work.travusa_sound +--port map( +-- clk => clock_E, +-- addr => cpu_addr(11 downto 0), +-- data => rom_do +--); +rom_addr <= cpu_addr(12 downto 0); -- cpu wram cpu_ram : entity work.gen_ram diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/pll_mist.vhd b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/pll_mist.vhd index d34f8803..7afa03b7 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/pll_mist.vhd +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/pll_mist.vhd @@ -14,7 +14,7 @@ -- ************************************************************ -- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! -- --- 13.1.4 Build 182 03/12/2014 SJ Web Edition +-- 13.1.4 Build 182 03/12/2014 Patches 4.26 SJ Web Edition -- ************************************************************ @@ -152,9 +152,9 @@ BEGIN clk0_duty_cycle => 50, clk0_multiply_by => 41, clk0_phase_shift => "0", - clk1_divide_by => 2475, + clk1_divide_by => 1200, clk1_duty_cycle => 50, - clk1_multiply_by => 82, + clk1_multiply_by => 41, clk1_phase_shift => "0", compensate_clock => "CLK0", inclk0_input_frequency => 37037, @@ -238,11 +238,11 @@ END SYN; -- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" -- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" -- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "30" --- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "2475" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1200" -- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" -- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" -- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "36.900002" --- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "0.894545" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "0.922500" -- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" -- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" -- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" @@ -268,7 +268,7 @@ END SYN; -- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" -- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" -- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "41" --- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "82" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "41" -- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" -- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "36.86400000" -- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "0.89500000" @@ -321,9 +321,9 @@ END SYN; -- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" -- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "41" -- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" --- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "2475" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1200" -- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" --- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "82" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "41" -- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" -- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" -- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/sdram.sv b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/sdram.sv index 8f927d05..baeb7b5e 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/sdram.sv +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/sdram.sv @@ -1,79 +1,132 @@ // // sdram.v // -// Static RAM controller implementation using SDRAM MT48LC16M16A2 +// sdram controller implementation for the MiST board +// https://github.com/mist-devel/mist-board +// +// Copyright (c) 2013 Till Harbaum +// Copyright (c) 2019 Gyorgy Szombathelyi // -// Copyright (c) 2015,2016 Sorgelig -// -// Some parts of SDRAM code used from project: -// http://hamsterworks.co.nz/mediawiki/index.php/Simple_SDRAM_Controller -// -// 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 +// 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 . -// -// ------------------------------------------ -// -// v2.1 - Add universal 8/16 bit mode. +// along with this program. If not, see . // -module sdram -( - input init, // reset to initialize RAM - input clk, // clock ~100MHz - // - // SDRAM_* - signals to the MT48LC16M16 chip - inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus - output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus - output reg SDRAM_DQML, // two byte masks - output reg SDRAM_DQMH, // - output reg [1:0] SDRAM_BA, // two banks - output SDRAM_nCS, // a single chip select - output SDRAM_nWE, // write enable - output SDRAM_nRAS, // row address select - output SDRAM_nCAS, // columns address select - output SDRAM_CKE, // clock enable - // - input [1:0] wtbt, // 16bit mode: bit1 - write high byte, bit0 - write low byte, - // 8bit mode: 2'b00 - use addr[0] to decide which byte to write - // Ignored while reading. - // - input [24:0] addr, // 25 bit address for 8bit mode. addr[0] = 0 for 16bit mode for correct operations. - output [15:0] dout, // data output to cpu - input [15:0] din, // data input from cpu - input we, // cpu requests write - input rd, // cpu requests read - output reg ready // dout is valid. Ready to accept new read/write. +module sdram ( + + // interface to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // two byte masks + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + + // cpu/chipset interface + input init_n, // init signal after FPGA config to initialize RAM + input clk, // sdram clock + + input port1_req, + output reg port1_ack, + input port1_we, + input [23:1] port1_a, + input [1:0] port1_ds, + input [15:0] port1_d, + output [15:0] port1_q, + + input [15:1] cpu1_addr, + output reg [15:0] cpu1_q, + + input port2_req, + output reg port2_ack, + input port2_we, + input [23:1] port2_a, + input [1:0] port2_ds, + input [15:0] port2_d, + output [15:0] port2_q, + + input [15:1] snd_addr, + output reg [15:0] snd_q ); -assign SDRAM_nCS = command[3]; -assign SDRAM_nRAS = command[2]; -assign SDRAM_nCAS = command[1]; -assign SDRAM_nWE = command[0]; -assign SDRAM_CKE = cke; +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@<100MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write -// no burst configured -localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 -localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved -localparam CAS_LATENCY = 3'd2; // 2 for < 100MHz, 3 for >100MHz -localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed -localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write -localparam MODE = {3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; -localparam sdram_startup_cycles= 14'd12100;// 100us, plus a little more, @ 100MHz -localparam cycles_per_refresh = 14'd186; // (64000*36)/8192-1 Calc'd as (64ms @ 36MHz)/8192 rose -localparam startup_refresh_max = 14'b11111111111111; +// 64ms/8192 rows = 7.8us -> 842 cycles@108MHz +localparam RFRSH_CYCLES = 10'd842; -// SDRAM commands +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +/* + SDRAM state machine for 2 bank interleaved access + 1 word burst, CL2 +cmd issued registered + 0 RAS0 cas1 + 1 ras0 + 2 CAS0 data1 returned + 3 RAS1 cas0 + 4 ras1 + 5 CAS1 data0 returned +*/ + +localparam STATE_RAS0 = 3'd0; // first state in cycle +localparam STATE_RAS1 = 3'd3; // Second ACTIVE command after RAS0 + tRRD (15ns) +localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY; // CAS phase - 3 +localparam STATE_CAS1 = STATE_RAS1 + RASCAS_DELAY; // CAS phase - 5 +localparam STATE_READ0 = 3'd0; //STATE_CAS0 + CAS_LATENCY + 1'd1; // 7 +localparam STATE_READ1 = 3'd3; +localparam STATE_LAST = 3'd5; + +reg [2:0] t; + +always @(posedge clk) begin + t <= t + 1'd1; + if (t == STATE_LAST) t <= STATE_RAS0; +end + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +reg init = 1'b1; +always @(posedge clk, negedge init_n) begin + if(!init_n) begin + reset <= 5'h1f; + init <= 1'b1; + end else begin + if((t == STATE_LAST) && (reset != 0)) reset <= reset - 5'd1; + init <= !(reset == 0); + end +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands localparam CMD_INHIBIT = 4'b1111; localparam CMD_NOP = 4'b0111; localparam CMD_ACTIVE = 4'b0011; @@ -84,171 +137,191 @@ localparam CMD_PRECHARGE = 4'b0010; localparam CMD_AUTO_REFRESH = 4'b0001; localparam CMD_LOAD_MODE = 4'b0000; -reg [13:0] refresh_count = startup_refresh_max - sdram_startup_cycles; -reg [3:0] command = CMD_INHIBIT; -reg cke = 0; -reg [24:0] save_addr; -reg [15:0] data; +reg [3:0] sd_cmd; // current command sent to sd ram +reg [15:0] sd_din; +// drive control signals according to current command +assign SDRAM_nCS = sd_cmd[3]; +assign SDRAM_nRAS = sd_cmd[2]; +assign SDRAM_nCAS = sd_cmd[1]; +assign SDRAM_nWE = sd_cmd[0]; -assign dout = save_addr[0] ? {data[7:0], data[15:8]} : {data[15:8], data[7:0]}; -typedef enum -{ - STATE_STARTUP, - STATE_OPEN_1, - STATE_WRITE, - STATE_READ, - STATE_IDLE, STATE_IDLE_1, STATE_IDLE_2, STATE_IDLE_3, - STATE_IDLE_4, STATE_IDLE_5, STATE_IDLE_6, STATE_IDLE_7 -} state_t; +reg [24:1] addr_latch[2]; +reg [24:1] addr_latch_next[2]; +reg [15:1] addr_last[2]; +reg [15:1] addr_last2[2]; +reg [15:0] din_latch[2]; +reg [1:0] oe_latch; +reg [1:0] we_latch; +reg [1:0] ds[2]; -state_t state = STATE_STARTUP; +localparam PORT_NONE = 2'd0; +localparam PORT_CPU1 = 2'd1; +localparam PORT_REQ = 2'd2; + +localparam PORT_SND = 2'd1; + +reg [2:0] next_port[2]; +reg [2:0] port[2]; +reg port1_state; +reg port2_state; + +reg refresh; +reg [10:0] refresh_cnt; +wire need_refresh = (refresh_cnt >= RFRSH_CYCLES); + +// PORT1: bank 0,1 +always @(*) begin + if (refresh) begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end else if (port1_req ^ port1_state) begin + next_port[0] = PORT_REQ; + addr_latch_next[0] = { 1'b0, port1_a }; + end else if (cpu1_addr != addr_last[PORT_CPU1]) begin + next_port[0] = PORT_CPU1; + addr_latch_next[0] = { 9'd0, cpu1_addr }; + end else begin + next_port[0] = PORT_NONE; + addr_latch_next[0] = addr_latch[0]; + end +end + +// PORT2: bank 2,3 +always @(*) begin + if (port2_req ^ port2_state) begin + next_port[1] = PORT_REQ; + addr_latch_next[1] = { 1'b1, port2_a }; + end else if (snd_addr != addr_last2[PORT_SND]) begin + next_port[1] = PORT_SND; + addr_latch_next[1] = { 1'b1, 8'd0, snd_addr }; + end else begin + next_port[1] = PORT_NONE; + addr_latch_next[1] = addr_latch[1]; + end +end always @(posedge clk) begin - reg old_we, old_rd; - reg [CAS_LATENCY:0] data_ready_delay; - reg [15:0] new_data; - reg [1:0] new_wtbt; - reg new_we; - reg new_rd; - reg save_we = 1; - - - command <= CMD_NOP; - refresh_count <= refresh_count+1'b1; - - data_ready_delay <= {1'b0, data_ready_delay[CAS_LATENCY:1]}; - - if(data_ready_delay[0]) data <= SDRAM_DQ; - - case(state) - STATE_STARTUP: begin - //------------------------------------------------------------------------ - //-- This is the initial startup state, where we wait for at least 100us - //-- before starting the start sequence - //-- - //-- The initialisation is sequence is - //-- * de-assert SDRAM_CKE - //-- * 100us wait, - //-- * assert SDRAM_CKE - //-- * wait at least one cycle, - //-- * PRECHARGE - //-- * wait 2 cycles - //-- * REFRESH, - //-- * tREF wait - //-- * REFRESH, - //-- * tREF wait - //-- * LOAD_MODE_REG - //-- * 2 cycles wait - //------------------------------------------------------------------------ - cke <= 1; - SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; - SDRAM_DQML <= 1; - SDRAM_DQMH <= 1; - SDRAM_A <= 0; - SDRAM_BA <= 0; - - // All the commands during the startup are NOPS, except these - if(refresh_count == startup_refresh_max-31) begin - // ensure all rows are closed - command <= CMD_PRECHARGE; - SDRAM_A[10] <= 1; // all banks - SDRAM_BA <= 2'b00; - end else if (refresh_count == startup_refresh_max-23) begin - // these refreshes need to be at least tREF (66ns) apart - command <= CMD_AUTO_REFRESH; - end else if (refresh_count == startup_refresh_max-15) - command <= CMD_AUTO_REFRESH; - else if (refresh_count == startup_refresh_max-7) begin - // Now load the mode register - command <= CMD_LOAD_MODE; - SDRAM_A <= MODE; - end - - //------------------------------------------------------ - //-- if startup is complete then go into idle mode, - //-- get prepared to accept a new command, and schedule - //-- the first refresh cycle - //------------------------------------------------------ - if(!refresh_count) begin - state <= STATE_IDLE; - ready <= 1; - refresh_count <= 0; - end - end - - STATE_IDLE_7: state <= STATE_IDLE_6; - STATE_IDLE_6: state <= STATE_IDLE_5; - STATE_IDLE_5: state <= STATE_IDLE_4; - STATE_IDLE_4: state <= STATE_IDLE_3; - STATE_IDLE_3: state <= STATE_IDLE_2; - STATE_IDLE_2: state <= STATE_IDLE_1; - STATE_IDLE_1: begin - SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; - state <= STATE_IDLE; - // mask possible refresh to reduce colliding. - if(refresh_count > cycles_per_refresh) begin - //------------------------------------------------------------------------ - //-- Start the refresh cycle. - //-- This tasks tRFC (66ns), so 2 idle cycles are needed @ 36MHz - //------------------------------------------------------------------------ - state <= STATE_IDLE_2; - command <= CMD_AUTO_REFRESH; - refresh_count <= refresh_count - cycles_per_refresh + 1'd1; - end - end - - STATE_IDLE: begin - // Priority is to issue a refresh if one is outstanding - if(refresh_count > (cycles_per_refresh<<1)) state <= STATE_IDLE_1; - else if(new_rd | new_we) begin - new_we <= 0; - new_rd <= 0; - save_addr<= addr; - save_we <= new_we; - state <= STATE_OPEN_1; - command <= CMD_ACTIVE; - SDRAM_A <= addr[13:1]; - SDRAM_BA <= addr[24:23]; - end - end - - // ACTIVE-to-READ or WRITE delay >20ns (1 cycle @ 36 MHz)(-75) - STATE_OPEN_1: begin - SDRAM_A <= {4'b0010, save_addr[22:14]}; - SDRAM_DQML <= save_we & (new_wtbt ? ~new_wtbt[0] : save_addr[0]); - SDRAM_DQMH <= save_we & (new_wtbt ? ~new_wtbt[1] : ~save_addr[0]); - state <= save_we ? STATE_WRITE : STATE_READ; - end - - STATE_READ: begin - state <= STATE_IDLE_5; - command <= CMD_READ; - SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; - - // Schedule reading the data values off the bus - data_ready_delay[CAS_LATENCY] <= 1; - end - - STATE_WRITE: begin - state <= STATE_IDLE_5; - command <= CMD_WRITE; - SDRAM_DQ <= new_wtbt ? new_data : {new_data[7:0], new_data[7:0]}; - ready <= 1; - end - endcase + // permanently latch ram data to reduce delays + sd_din <= SDRAM_DQ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + { SDRAM_DQMH, SDRAM_DQML } <= 2'b11; + sd_cmd <= CMD_NOP; // default: idle + refresh_cnt <= refresh_cnt + 1'd1; if(init) begin - state <= STATE_STARTUP; - refresh_count <= startup_refresh_max - sdram_startup_cycles; + // initialization takes place at the end of the reset phase + if(t == STATE_RAS0) begin + + if(reset == 15) begin + sd_cmd <= CMD_PRECHARGE; + SDRAM_A[10] <= 1'b1; // precharge all banks + end + + if(reset == 10 || reset == 8) begin + sd_cmd <= CMD_AUTO_REFRESH; + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + SDRAM_BA <= 2'b00; + end + end + end else begin + // RAS phase + // bank 0,1 + if(t == STATE_RAS0) begin + addr_latch[0] <= addr_latch_next[0]; + port[0] <= next_port[0]; + { oe_latch[0], we_latch[0] } <= 2'b00; + + if (next_port[0] != PORT_NONE) begin + port1_state <= port1_req; + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[0][22:10]; + SDRAM_BA <= addr_latch_next[0][24:23]; + addr_last[next_port[0]] <= addr_latch_next[0][15:1]; + if (next_port[0] == PORT_REQ) begin + { oe_latch[0], we_latch[0] } <= { ~port1_we, port1_we }; + ds[0] <= port1_ds; + din_latch[0] <= port1_d; + end else begin + { oe_latch[0], we_latch[0] } <= 2'b10; + ds[0] <= 2'b11; + end + end + end + + // bank 2,3 + if(t == STATE_RAS1) begin + refresh <= 1'b0; + addr_latch[1] <= addr_latch_next[1]; + { oe_latch[1], we_latch[1] } <= 2'b00; + port[1] <= next_port[1]; + + if (next_port[1] != PORT_NONE) begin + port2_state <= port2_req; + sd_cmd <= CMD_ACTIVE; + SDRAM_A <= addr_latch_next[1][22:10]; + SDRAM_BA <= addr_latch_next[1][24:23]; + addr_last2[next_port[1]] <= addr_latch_next[1][15:1]; + if (next_port[1] == PORT_REQ) begin + { oe_latch[1], we_latch[1] } <= { ~port2_we, port2_we }; + ds[1] <= port2_ds; + din_latch[1] <= port2_d; + end else begin + { oe_latch[1], we_latch[1] } <= 2'b10; + ds[1] <= 2'b11; + end + end + + if (next_port[1] == PORT_NONE && need_refresh && !we_latch[0] && !oe_latch[0]) begin + refresh <= 1'b1; + refresh_cnt <= 0; + sd_cmd <= CMD_AUTO_REFRESH; + end + end + + // CAS phase + if(t == STATE_CAS0 && (we_latch[0] || oe_latch[0])) begin + sd_cmd <= we_latch[0]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[0]; + if (we_latch[0]) begin + SDRAM_DQ <= din_latch[0]; + port1_ack <= port1_req; + end + SDRAM_A <= { 4'b0010, addr_latch[0][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[0][24:23]; + end + + if(t == STATE_CAS1 && (we_latch[1] || oe_latch[1])) begin + sd_cmd <= we_latch[1]?CMD_WRITE:CMD_READ; + { SDRAM_DQMH, SDRAM_DQML } <= ~ds[1]; + if (we_latch[1]) begin + SDRAM_DQ <= din_latch[1]; + port2_ack <= port2_req; + end + SDRAM_A <= { 4'b0010, addr_latch[1][9:1] }; // auto precharge + SDRAM_BA <= addr_latch[1][24:23]; + end + + // Data returned + if(t == STATE_READ0 && oe_latch[0]) begin + case(port[0]) + PORT_REQ: begin port1_q <= sd_din; port1_ack <= port1_req; end + PORT_CPU1: begin cpu1_q <= sd_din; end + default: ; + endcase; + end + if(t == STATE_READ1 && oe_latch[1]) begin + case(port[1]) + PORT_REQ: begin port2_q <= sd_din; port2_ack <= port2_req; end + PORT_SND: begin snd_q <= sd_din; end + default: ; + endcase; + end end - - old_we <= we; - old_rd <= rd; - if(we & ~old_we) {ready, new_we, new_data, new_wtbt} <= {1'b0, 1'b1, din, wtbt}; - else - if((rd & ~old_rd) || (rd & old_rd & (save_addr != addr))) {ready, new_rd} <= {1'b0, 1'b1}; - end endmodule diff --git a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/traverse_usa.vhd b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/traverse_usa.vhd index 0ae13bee..6ebb5365 100644 --- a/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/traverse_usa.vhd +++ b/Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/traverse_usa.vhd @@ -112,6 +112,8 @@ port( clock_36 : in std_logic; clock_0p895 : in std_logic; reset : in std_logic; + + shtrider : in std_logic; -- Shot Rider mode -- tv15Khz_mode : in std_logic; video_r : out std_logic_vector(1 downto 0); video_g : out std_logic_vector(2 downto 0); @@ -123,10 +125,6 @@ port( video_vs : out std_logic; audio_out : out std_logic_vector(10 downto 0); - cpu_rom_addr : out std_logic_vector(14 downto 0); - cpu_rom_do : in std_logic_vector( 7 downto 0); - cpu_rom_rd : out std_logic; - dip_switch_1 : in std_logic_vector(7 downto 0); -- Coinage_B(7-4) / Cont. play(3) / Fuel consumption(2) / Fuel lost when collision (1-0) dip_switch_2 : in std_logic_vector(7 downto 0); -- Diag(7) / Demo(6) / Zippy(5) / Freeze (4) / M-Km(3) / Coin mode (2) / Cocktail(1) / Flip(0) @@ -144,6 +142,16 @@ port( accel2 : in std_logic; brake2 : in std_logic; + cpu_rom_addr : out std_logic_vector(14 downto 0); + cpu_rom_do : in std_logic_vector( 7 downto 0); + cpu_rom_rd : out std_logic; + snd_rom_addr : out std_logic_vector(12 downto 0); + snd_rom_do : in std_logic_vector( 7 downto 0); + + dl_addr : in std_logic_vector(16 downto 0); + dl_data : in std_logic_vector( 7 downto 0); + dl_wr : in std_logic; + dbg_cpu_addr : out std_logic_vector(15 downto 0) ); end traverse_usa; @@ -188,6 +196,7 @@ architecture struct of traverse_usa is signal wram_we : std_logic; signal wram_do : std_logic_vector( 7 downto 0); + signal vflip : std_logic; signal flip : std_logic; signal flip_int : std_logic; @@ -208,8 +217,9 @@ architecture struct of traverse_usa is signal chr_graphx2_do : std_logic_vector(7 downto 0); signal chr_graphx3_do : std_logic_vector(7 downto 0); signal chr_color : std_logic_vector(3 downto 0); - signal chr_palette_addr : std_logic_vector(8 downto 0); - signal chr_palette_do : std_logic_vector(7 downto 0); + signal chr_palette_addr : std_logic_vector(7 downto 0); + signal chr_palette_1_do : std_logic_vector(7 downto 0); + signal chr_palette_2_do : std_logic_vector(7 downto 0); signal sprram_addr : std_logic_vector(9 downto 0); signal sprram_we : std_logic; @@ -263,13 +273,24 @@ architecture struct of traverse_usa is signal input_1 : std_logic_vector(7 downto 0); signal input_2 : std_logic_vector(7 downto 0); + signal char_graphics_1_we : std_logic; + signal char_graphics_2_we : std_logic; + signal char_graphics_3_we : std_logic; + signal sprite_graphics_1_we : std_logic; + signal sprite_graphics_2_we : std_logic; + signal sprite_graphics_3_we : std_logic; + signal chr_palette_1_we : std_logic; + signal chr_palette_2_we : std_logic; + signal spr_palette_we : std_logic; + signal spr_lut_we : std_logic; + begin clock_36n <= not clock_36; reset_n <= not reset; -- debug -process (reset, clock_36) +process (reset, clock_36, cpu_ena, cpu_mreq_n) begin if rising_edge(clock_36) and cpu_ena ='1' and cpu_mreq_n ='0' then dbg_cpu_addr <= cpu_addr; @@ -301,7 +322,7 @@ cpu_ena <= '1' when clock_cnt = "1011" else '0'; -- (3MHz) -- hcnt [x080..x0FF-x100..x1FF] => 128+256 = 384 pixels, 384/6.144Mhz => 1 line is 62.5us (16.000KHz) -- vcnt [x0E6..x0FF-x100..x1FF] => 26+256 = 282 lines, 1 frame is 260 x 62.5us = 17.625ms (56.74Hz) -process (reset, clock_36) +process (reset, clock_36, pix_ena) begin if reset='1' then hcnt <= (others=>'0'); @@ -322,7 +343,8 @@ end process; flip <= flip_int xor dip_switch_2(0); hcnt_flip <= '0'&hcnt(7 downto 0) when flip ='1' else '0' & not hcnt(7 downto 0); -vcnt_flip <= vcnt when flip ='1' else not vcnt; +vflip <= flip xor shtrider; +vcnt_flip <= vcnt when vflip ='1' else not vcnt; -------------------- -- players inputs -- @@ -356,7 +378,7 @@ begin if cpu_m1_n = '0' and cpu_ioreq_n = '0' then cpu_irq_n <= '1'; else -- lauch irq and end of frame - if ((vcnt = 230 and flip = '0') or (vcnt = 448 and flip = '1')) and (hcnt = '0'&X"80") then + if ((vcnt = 230 and vflip = '0') or (vcnt = 448 and vflip = '1')) and (hcnt = '0'&X"80") then cpu_irq_n <= '0'; end if; end if; @@ -408,15 +430,14 @@ end process; -- from x080 to x0FF and from x1C0 to x1FF when not flipped (scrolling zone from x100 to x1BF) -- within scrolling zone sprite data ram is accessed by sprite data scanner (spr_hcnt) -cpu_has_spr_ram <= '1' when ( vcnt < '1'&x"3F" and flip = '0') or - ((vcnt > '1'&x"C0" or vcnt < '0'&x"FF") and flip = '1') else '0'; +cpu_has_spr_ram <= '1' when ( vcnt < '1'&x"3F" and vflip = '0') or + ((vcnt > '1'&x"C0" or vcnt < '0'&x"FF") and vflip = '1') else '0'; sprram_we <= '1' when cpu_wr_n = '0' and cpu_addr(15 downto 11) = X"C"&"1" and cpu_has_spr_ram = '1' else '0'; sprram_addr <= '0' & spr_hcnt(10 downto 4) & spr_hcnt(2 downto 1) when cpu_has_spr_ram = '0' else cpu_addr(9 downto 0); - -- latch current sprite data with respect to pixel and hcnt in relation with sprite data ram addressing process (clock_36) begin @@ -440,7 +461,8 @@ end process; spr_vcnt <= vcnt_flip(7 downto 0) + spr_posv_r - 1 ; spr_on_line <= '1' when spr_vcnt(7 downto 4) = x"F" and cpu_has_spr_ram = '0' else '0'; spr_line_cnt <= spr_vcnt(4 downto 0) xor (spr_attr_r(7) & spr_attr_r(7) & spr_attr_r(7) & spr_attr_r(7) & spr_attr_r(7)); -spr_code_line <= spr_code_r & (spr_attr_r(6) xor not spr_hcnt(3)) & spr_line_cnt(3 downto 0); +spr_code_line <= spr_code_r & (spr_attr_r(6) xor not spr_hcnt(3)) & spr_line_cnt(3 downto 0) when shtrider = '0' else + spr_code_r & spr_line_cnt(3) & (spr_attr_r(6) xor not spr_hcnt(3)) & spr_line_cnt(2 downto 0); -- get and serialise sprite graphics data and w.r.t enable (attr(5)) and h_flip (attr(6)) -- and compute palette address from graphics bits and color set# @@ -592,7 +614,6 @@ begin if pix_ena = '1' then chr_palette_addr(6 downto 3) <= chr_color; chr_palette_addr(7) <= '0'; - chr_palette_addr(8) <= '0'; if chr_flip_h = '0' then chr_palette_addr(0) <= chr_graphx1_do(to_integer(unsigned(not(hcnt_scrolled(2 downto 0))))); chr_palette_addr(1) <= chr_graphx2_do(to_integer(unsigned(not(hcnt_scrolled(2 downto 0))))); @@ -622,13 +643,17 @@ begin video_r <= spr_rgb_lut_do(7 downto 6); video_g <= spr_rgb_lut_do(5 downto 3); video_b <= spr_rgb_lut_do(2 downto 0); - else - video_r <= chr_palette_do(7 downto 6); - video_g <= chr_palette_do(5 downto 3); - video_b <= chr_palette_do(2 downto 0); + elsif shtrider = '0' then -- 1x8 bit in Traverse USA + video_r <= chr_palette_1_do(7 downto 6); + video_g <= chr_palette_1_do(5 downto 3); + video_b <= chr_palette_1_do(2 downto 0); + else -- 2x4 bit in Shot Rider + video_r <= chr_palette_1_do(3 downto 2); + video_g <= chr_palette_1_do(1 downto 0) & chr_palette_2_do(3); + video_b <= chr_palette_2_do(2 downto 0); end if; end if; - + end if; end process; @@ -642,7 +667,10 @@ port map( select_sound => sound_cmd, -- not(key(1)) & sw(6 downto 0), audio_out => audio, - + + rom_addr => snd_rom_addr, + rom_do => snd_rom_do, + dbg_cpu_addr => open --dbg_cpu_addr ); @@ -655,7 +683,7 @@ audio_out <= audio(11 downto 1); video_csync <= csync; -process(clock_36) +process(clock_36, pix_ena) constant hcnt_base : integer := 180; variable hsync_cnt : std_logic_vector(8 downto 0); variable vsync_cnt : std_logic_vector(3 downto 0); @@ -821,75 +849,143 @@ port map( ); -- char graphics ROM 3E -char_graphics_1 : entity work.travusa_chr_bit1 +char_graphics_1 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => chr_code_line, - data => chr_graphx1_do + clk_a => clock_36n, + addr_a => chr_code_line, + q_a => chr_graphx1_do, + clk_b => clock_36, + we_b => char_graphics_1_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +char_graphics_1_we <= '1' when dl_addr(16 downto 13) = "0101" and dl_wr = '1' else '0'; -- 0A000-0BFFF -- char graphics ROM 3E -char_graphics_2 : entity work.travusa_chr_bit2 +char_graphics_2 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => chr_code_line, - data => chr_graphx2_do + clk_a => clock_36n, + addr_a => chr_code_line, + q_a => chr_graphx2_do, + clk_b => clock_36, + we_b => char_graphics_2_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +char_graphics_2_we <= '1' when dl_addr(16 downto 13) = "0110" and dl_wr = '1' else '0'; -- 0C000-0DFFF -- char graphics ROM 3E -char_graphics_3 : entity work.travusa_chr_bit3 +char_graphics_3 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => chr_code_line, - data => chr_graphx3_do + clk_a => clock_36n, + addr_a => chr_code_line, + q_a => chr_graphx3_do, + clk_b => clock_36, + we_b => char_graphics_3_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +char_graphics_3_we <= '1' when dl_addr(16 downto 13) = "0111" and dl_wr = '1' else '0'; -- 0E000-0FFFF --char palette ROM -char_palette : entity work.travusa_chr_palette +char_palette_1 : entity work.dpram +generic map( dWidth => 8, aWidth => 8) port map( - clk => clock_36n, - addr => chr_palette_addr, - data => chr_palette_do + clk_a => clock_36n, + addr_a => chr_palette_addr, + q_a => chr_palette_1_do, + clk_b => clock_36, + we_b => chr_palette_1_we, + addr_b => dl_addr(7 downto 0), + d_b => dl_data ); +chr_palette_1_we <= '1' when dl_addr(16 downto 8) = "101100000" and dl_wr = '1' else '0'; -- 16000-160FF + +char_palette_2 : entity work.dpram +generic map( dWidth => 8, aWidth => 8) +port map( + clk_a => clock_36n, + addr_a => chr_palette_addr, + q_a => chr_palette_2_do, + clk_b => clock_36, + we_b => chr_palette_2_we, + addr_b => dl_addr(7 downto 0), + d_b => dl_data +); +chr_palette_2_we <= '1' when dl_addr(16 downto 8) = "101100001" and dl_wr = '1' else '0'; -- 16100-161FF -- sprite graphics ROM 3N -sprite_graphics_1 : entity work.travusa_spr_bit1 +sprite_graphics_1 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => spr_code_line, - data => spr_graphx1_do + clk_a => clock_36n, + addr_a => spr_code_line, + q_a => spr_graphx1_do, + clk_b => clock_36, + we_b => sprite_graphics_1_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +sprite_graphics_1_we <= '1' when dl_addr(16 downto 13) = "1000" and dl_wr = '1' else '0'; -- 10000-11FFF -- sprite graphics ROM 3L or 3M -sprite_graphics_2 : entity work.travusa_spr_bit2 +sprite_graphics_2 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => spr_code_line, - data => spr_graphx2_do + clk_a => clock_36n, + addr_a => spr_code_line, + q_a => spr_graphx2_do, + clk_b => clock_36, + we_b => sprite_graphics_2_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +sprite_graphics_2_we <= '1' when dl_addr(16 downto 13) = "1001" and dl_wr = '1' else '0'; -- 12000-13FFF -- sprite graphics ROM 3K -sprite_graphics3 : entity work.travusa_spr_bit3 +sprite_graphics_3 : entity work.dpram +generic map( dWidth => 8, aWidth => 13) port map( - clk => clock_36n, - addr => spr_code_line, - data => spr_graphx3_do + clk_a => clock_36n, + addr_a => spr_code_line, + q_a => spr_graphx3_do, + clk_b => clock_36, + we_b => sprite_graphics_3_we, + addr_b => dl_addr(12 downto 0), + d_b => dl_data ); +sprite_graphics_3_we <= '1' when dl_addr(16 downto 13) = "1010" and dl_wr = '1' else '0'; -- 14000-15FFF -- sprite palette ROM 2H -spr_palette: entity work.travusa_spr_palette +spr_palette : entity work.dpram +generic map( dWidth => 8, aWidth => 8) port map( - clk => clock_36n, - addr => spr_palette_addr, - data => spr_palette_do + clk_a => clock_36n, + addr_a => spr_palette_addr, + q_a => spr_palette_do, + clk_b => clock_36, + we_b => spr_palette_we, + addr_b => dl_addr(7 downto 0), + d_b => dl_data ); +spr_palette_we <= '1' when dl_addr(16 downto 8) = "101100010" and dl_wr = '1' else '0'; -- 16200-162FF -- sprite rgb lut ROM 1F -spr_rgb_lut: entity work.travusa_spr_rgb_lut +spr_rgb_lut : entity work.dpram +generic map( dWidth => 8, aWidth => 8) port map( - clk => clock_36n, - addr => spr_rgb_lut_addr, - data => spr_rgb_lut_do + clk_a => clock_36n, + addr_a => "000"&spr_rgb_lut_addr, -- extended to 8 bit, prevents segfault of Quartus + q_a => spr_rgb_lut_do, + clk_b => clock_36, + we_b => spr_lut_we, + addr_b => "000"&dl_addr(4 downto 0), + d_b => dl_data, + q_b => open ); +spr_lut_we <= '1' when dl_addr(16 downto 5) = "101100011000" and dl_wr = '1' else '0'; -- 16300-1631F end struct; \ No newline at end of file