mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-01-20 01:34:38 +00:00
Traverse USA: add ShotRider mode
+ load all ROMs from SD Card
This commit is contained in:
parent
b3cdaa8071
commit
93b45fe4b0
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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)
|
||||
);
|
||||
|
||||
81
Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd
Normal file
81
Arcade_MiST/IremM52 Hardware/TraverseUSA_MiST/rtl/dpram.vhd
Normal file
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 <till@harbaum.org>
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ------------------------------------------
|
||||
//
|
||||
// v2.1 - Add universal 8/16 bit mode.
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
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
|
||||
|
||||
@ -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;
|
||||
Loading…
x
Reference in New Issue
Block a user