mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-02-08 17:11:24 +00:00
@@ -1,779 +0,0 @@
|
||||
---------------------------------------------------------------------------------
|
||||
-- Time pilot by Dar (darfpga@aol.fr) (29/10/2017)
|
||||
-- http://darfpga.blogspot.fr
|
||||
---------------------------------------------------------------------------------
|
||||
-- gen_ram.vhd & io_ps2_keyboard
|
||||
--------------------------------
|
||||
-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
|
||||
-- http://www.syntiac.com/fpga64.html
|
||||
---------------------------------------------------------------------------------
|
||||
-- T80/T80se - Version : 0247
|
||||
-----------------------------
|
||||
-- Z80 compatible microprocessor core
|
||||
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
|
||||
---------------------------------------------------------------------------------
|
||||
-- YM2149 (AY-3-8910)
|
||||
-- Copyright (c) MikeJ - Jan 2005
|
||||
---------------------------------------------------------------------------------
|
||||
-- Educational use only
|
||||
-- Do not redistribute synthetized file with roms
|
||||
-- Do not redistribute roms whatever the form
|
||||
-- Use at your own risk
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
-- Features :
|
||||
-- TV 15KHz mode only (atm)
|
||||
-- Coctail mode ok
|
||||
-- Sound ok
|
||||
|
||||
-- Use with MAME roms from timeplt.zip
|
||||
--
|
||||
-- Use make_time_pilot_proms.bat to build vhd file from binaries
|
||||
|
||||
-- time_pilot_prog.vhd : tm1, tm2,tm3
|
||||
-- time_pilot_sprite_grphx.vhd : tm4, tm5
|
||||
-- time_pilot_char_grphx.vhd : tm6
|
||||
-- time_pilot_sound_prog.vhd : tm7
|
||||
-- time_pilot_palette_blue_green.vhd : timeplt.b4
|
||||
-- time_pilot_palette_green_red.vhd : timeplt.b5
|
||||
-- time_pilot_sprite_color_lut.vhd : timeplt.e9
|
||||
-- time_pilot_char_color_lut.vhd : timeplt.e12
|
||||
|
||||
-- Time Pilot Hardware caracteristics :
|
||||
--
|
||||
-- VIDEO : 1xZ80@3MHz CPU accessing its program rom, working ram,
|
||||
-- sprite data ram, I/O, sound board register and trigger.
|
||||
-- 24Kx8bits program rom
|
||||
--
|
||||
-- One char tile map 32x28
|
||||
-- 8Kx8bits graphics rom 2bits/pixel
|
||||
-- 4 colors/32sets among 16 colors
|
||||
--
|
||||
-- 24 sprites with priorities and flip H/V
|
||||
-- 16Kx8bits graphics rom 2bits/pixel
|
||||
-- 3 colors/64sets among 16 colors (different of char colors).
|
||||
--
|
||||
-- Char/sprites color palette 2x16 colors among 32768 colors
|
||||
-- 15bits 5red/5green/5blue
|
||||
--
|
||||
-- Working ram : 4Kx8bits
|
||||
-- Sprites data ram : 256x16bits
|
||||
-- Sprites line buffer rams : 1 scan line delay flip/flop 2x256x4bits
|
||||
|
||||
-- SOUND : 1xZ80@1.79MHz CPU accessing its program rom, working ram, 2x-AY3-8910
|
||||
-- 8Kx8bits program rom
|
||||
--
|
||||
-- 1xAY-3-8910
|
||||
-- I/O noise input and command/trigger from video board.
|
||||
-- 3 sound channels
|
||||
--
|
||||
-- 1xAY-3-8910
|
||||
-- 3 sound channels
|
||||
--
|
||||
-- 6 RC filters with 4 states : transparent or cut 600Hz, 700Hz, 3.4KHz
|
||||
--
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity power_surge is
|
||||
port(
|
||||
clock_6 : in std_logic;
|
||||
clock_12 : in std_logic;
|
||||
clock_14 : in std_logic;
|
||||
reset : in std_logic;
|
||||
video_r : out std_logic_vector(4 downto 0);
|
||||
video_g : out std_logic_vector(4 downto 0);
|
||||
video_b : out std_logic_vector(4 downto 0);
|
||||
video_clk : out std_logic;
|
||||
video_hblank : out std_logic;
|
||||
video_vblank : out std_logic;
|
||||
video_hs : out std_logic;
|
||||
video_vs : out std_logic;
|
||||
audio_out : out std_logic_vector(10 downto 0);
|
||||
roms_addr : out std_logic_vector(14 downto 0);
|
||||
roms_do : in std_logic_vector(7 downto 0);
|
||||
roms_rd : out std_logic;
|
||||
dip_switch_1 : in std_logic_vector(7 downto 0);--Cabinet Unknown Lives Lives Initial_Energy Unknown Unknown Unknown
|
||||
dip_switch_2 : in std_logic_vector(7 downto 0);--Stop_at_Junctions, Unknown, Unknown, Cheat, Coin_B Coin_B Coin_A Coin_A
|
||||
|
||||
start2 : in std_logic;
|
||||
start1 : in std_logic;
|
||||
coin1 : in std_logic;
|
||||
|
||||
fire1 : in std_logic;
|
||||
right1 : in std_logic;
|
||||
left1 : in std_logic;
|
||||
down1 : in std_logic;
|
||||
up1 : in std_logic;
|
||||
|
||||
fire2 : in std_logic;
|
||||
right2 : in std_logic;
|
||||
left2 : in std_logic;
|
||||
down2 : in std_logic;
|
||||
up2 : in std_logic
|
||||
);
|
||||
end power_surge;
|
||||
|
||||
architecture struct of power_surge is
|
||||
|
||||
signal reset_n: std_logic;
|
||||
signal clock_12n : std_logic;
|
||||
signal clock_6n : std_logic;
|
||||
signal clock_div : std_logic_vector(1 downto 0) := "00";
|
||||
|
||||
signal hcnt : std_logic_vector(5 downto 0); -- horizontal counter
|
||||
signal vcnt : std_logic_vector(8 downto 0); -- vertical counter
|
||||
signal pxcnt : std_logic_vector(2 downto 0); -- pixel counter
|
||||
signal spcnt : std_logic_vector(4 downto 0); -- sprite counter
|
||||
|
||||
signal hsync0 : std_logic;
|
||||
|
||||
signal hblank : std_logic;
|
||||
signal vblank : std_logic;
|
||||
|
||||
signal cpu_ena : std_logic;
|
||||
|
||||
signal cpu_addr : std_logic_vector(15 downto 0);
|
||||
signal cpu_di : std_logic_vector( 7 downto 0);
|
||||
signal cpu_do : std_logic_vector( 7 downto 0);
|
||||
signal cpu_wr_n : std_logic;
|
||||
signal cpu_mreq_n : std_logic;
|
||||
signal cpu_nmi_n : std_logic;
|
||||
signal cpu_int_n : std_logic;
|
||||
|
||||
signal cpu_rom_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal wram_addr : std_logic_vector(11 downto 0);
|
||||
signal wram_we : std_logic;
|
||||
signal wram_do : std_logic_vector( 7 downto 0);
|
||||
|
||||
signal ch_graphx_addr_f: std_logic_vector(12 downto 0);
|
||||
signal ch_graphx_addr : std_logic_vector(12 downto 0);
|
||||
signal ch_graphx_do : std_logic_vector( 7 downto 0);
|
||||
signal ch_pixels : std_logic_vector( 7 downto 0);
|
||||
signal ch_data1 : std_logic_vector( 7 downto 0);
|
||||
signal ch_pixel_bit1 : std_logic;
|
||||
signal ch_pixel_bit2 : std_logic;
|
||||
signal ch_color_set : std_logic_vector(4 downto 0);
|
||||
signal ch_palette_addr : std_logic_vector(7 downto 0);
|
||||
signal ch_palette_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal spram_addr : std_logic_vector(7 downto 0);
|
||||
signal spram1_we : std_logic;
|
||||
signal spram1_do : std_logic_vector(7 downto 0);
|
||||
signal spram2_we : std_logic;
|
||||
signal spram2_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal sp_graphx_addr : std_logic_vector(13 downto 0);
|
||||
signal sp_graphx_do : std_logic_vector(7 downto 0);
|
||||
signal vcnt_r : std_logic_vector(8 downto 0);
|
||||
signal sp_line : std_logic_vector(7 downto 0);
|
||||
signal sp_on_line : std_logic;
|
||||
signal sp_attr : std_logic_vector(7 downto 0);
|
||||
signal sp_posh : std_logic_vector(7 downto 0);
|
||||
signal sp_pixels : std_logic_vector(7 downto 0);
|
||||
signal sp_color_set : std_logic_vector(5 downto 0);
|
||||
signal sp_palette_addr : std_logic_vector(7 downto 0);
|
||||
signal sp_palette_do : std_logic_vector(7 downto 0);
|
||||
signal sp_read_out : std_logic_vector(3 downto 0);
|
||||
signal sp_blank : std_logic;
|
||||
|
||||
signal rgb_palette_addr : std_logic_vector(4 downto 0);
|
||||
signal rgb_palette_bg_do : std_logic_vector(7 downto 0);
|
||||
signal rgb_palette_gr_do : std_logic_vector(7 downto 0);
|
||||
|
||||
signal sp_buffer_write_addr : std_logic_vector(7 downto 0);
|
||||
signal sp_buffer_write_we : std_logic;
|
||||
signal sp_buffer_read_addr : std_logic_vector(7 downto 0);
|
||||
|
||||
signal sp_buffer_ram1_addr : std_logic_vector(7 downto 0);
|
||||
signal sp_buffer_ram1_we : std_logic;
|
||||
signal sp_buffer_ram1_di : std_logic_vector(3 downto 0);
|
||||
signal sp_buffer_ram1_do : std_logic_vector(3 downto 0);
|
||||
|
||||
signal sp_buffer_ram2_addr : std_logic_vector(7 downto 0);
|
||||
signal sp_buffer_ram2_we : std_logic;
|
||||
signal sp_buffer_ram2_di : std_logic_vector(3 downto 0);
|
||||
signal sp_buffer_ram2_do : std_logic_vector(3 downto 0);
|
||||
|
||||
signal sp_buffer_sel : std_logic;
|
||||
|
||||
signal itt_n : std_logic_vector(7 downto 0);
|
||||
signal flip : std_logic;
|
||||
signal C0xx_we : std_logic;
|
||||
signal C3xx_we : std_logic;
|
||||
signal sound_cmd : std_logic_vector(7 downto 0);
|
||||
signal sound_trig : std_logic;
|
||||
|
||||
signal input_0 : std_logic_vector(7 downto 0);
|
||||
signal input_1 : std_logic_vector(7 downto 0);
|
||||
signal input_2 : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
video_clk <= clock_6n;
|
||||
clock_12n <= not clock_12;
|
||||
clock_6n <= not clock_6;
|
||||
reset_n <= not reset;
|
||||
|
||||
--------------------------
|
||||
-- Video/sprite scanner --
|
||||
--------------------------
|
||||
|
||||
-- make hcnt and vcnt video scanner from pixel clocks and counts
|
||||
--
|
||||
-- pxcnt |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
|
||||
-- hcnt | N | N+1 |
|
||||
-- cpu_adr/do | |
|
||||
|
||||
--
|
||||
-- hcnt [0..47] => 48 x 8 = 384 pixels, 384/6.144Mhz => 1 line is 62.5us (16.000KHz)
|
||||
-- vcnt [252..255,256..511] => 260 lines, 1 frame is 260 x 62.5us = 16.250ms (61.54Hz)
|
||||
|
||||
process (reset, clock_6)
|
||||
begin
|
||||
if reset='1' then
|
||||
pxcnt <= "000";
|
||||
hcnt <= "000000";
|
||||
vcnt <= '0'&X"FC";
|
||||
spcnt <= "00000";
|
||||
else
|
||||
if rising_edge(clock_6) then
|
||||
pxcnt <= pxcnt + '1';
|
||||
if pxcnt = "111" then
|
||||
hcnt <= hcnt + '1';
|
||||
|
||||
if hcnt = "101111" then -- char from #0 to #47 (one line)
|
||||
hcnt <= "000000";
|
||||
if vcnt = '1'&X"FF" then
|
||||
vcnt <= '0'&X"FC";
|
||||
else
|
||||
vcnt <= vcnt + '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- sprite down counter
|
||||
if hcnt(0) = '1' then -- every is 16 bits (2 char)
|
||||
if hcnt = "101111" then
|
||||
spcnt <= "11111"; -- start with sprite #31
|
||||
else
|
||||
spcnt <= spcnt - '1'; -- downto sprite #8
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cpu_ena <= not pxcnt(0);
|
||||
|
||||
-- inputs
|
||||
input_0 <= "111" & not start2 & not start1 & '1' & '1' & not coin1; -- ?/ ?/ ?/ 2S/ 1S/SVC/ C2/ C1
|
||||
input_1 <= "111" & not fire1 & not down1 & not up1 & not right1 & not left1; -- ?/1FL/1SR/1SL/1DW/1UP/1RI/1LE
|
||||
input_2 <= "111" & not fire2 & not down2 & not up2 & not right2 & not left2; -- ?/2FL/2SR/2SL/2DW/2UP/2RI/2LE
|
||||
|
||||
-- cpu input address decoding (mirror mostly from Mame)
|
||||
cpu_di <= cpu_rom_do when cpu_addr(15 downto 12) < X"6" else -- 0000-5FFF
|
||||
|
||||
|
||||
X"80" when cpu_addr(15 downto 0) = "0110000000000100" else -- 6004 Protection
|
||||
|
||||
wram_do when cpu_addr(15 downto 12) = X"A" else -- A000-AFFF
|
||||
|
||||
spram1_do when cpu_addr(15 downto 12) = X"B" and
|
||||
cpu_addr(10) = '0' else -- B000-B3FF
|
||||
|
||||
spram2_do when cpu_addr(15 downto 12) = X"B" and
|
||||
cpu_addr(10) = '1' else -- B400-B7FF
|
||||
|
||||
vcnt(7 downto 0) when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "00" else -- C000-C0FF
|
||||
|
||||
X"FF" when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "01" else -- C100-C1FF
|
||||
|
||||
dip_switch_2 when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "10" else -- C200-C2FF
|
||||
|
||||
input_0 when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "11" and
|
||||
cpu_addr( 6 downto 5) = "00" else -- C300-C31F
|
||||
|
||||
input_1 when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "11" and
|
||||
cpu_addr( 6 downto 5) = "01" else -- C320-C32F
|
||||
|
||||
input_2 when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "11" and
|
||||
cpu_addr( 6 downto 5) = "10" else -- C340-C34F
|
||||
|
||||
dip_switch_1 when cpu_addr(15 downto 12) = X"C" and
|
||||
cpu_addr( 9 downto 8) = "11" and
|
||||
cpu_addr( 6 downto 5) = "11" else -- C360-C36F
|
||||
|
||||
X"FF";
|
||||
|
||||
-- working ram address multiplexer cpu/video scanner
|
||||
wram_addr <= cpu_addr(11 downto 0) when cpu_ena = '1' else
|
||||
'0' & pxcnt(1) & vcnt(7 downto 3) & hcnt(4 downto 0) when flip = '0' else
|
||||
'0' & pxcnt(1) & not vcnt(7 downto 3) & not hcnt(4 downto 0);
|
||||
|
||||
-- sprite data ram address multiplexer cpu/sprite scanner
|
||||
spram_addr <= cpu_addr(7 downto 0) when cpu_ena = '1' else "00" & spcnt & pxcnt(1);
|
||||
|
||||
-- write enable to working ram, sprite data ram and misc registers
|
||||
wram_we <= '1' when cpu_wr_n = '0' and cpu_ena = '1' and cpu_addr(15 downto 12) = X"A" else '0';
|
||||
spram1_we <= '1' when cpu_wr_n = '0' and cpu_ena = '1' and cpu_addr(15 downto 12) = X"B" and cpu_addr(10) = '0' else '0';
|
||||
spram2_we <= '1' when cpu_wr_n = '0' and cpu_ena = '1' and cpu_addr(15 downto 12) = X"B" and cpu_addr(10) = '1' else '0';
|
||||
C0xx_we <= '1' when cpu_wr_n = '0' and cpu_ena = '1' and cpu_addr(15 downto 8) = "11000000" else '0';--
|
||||
C3xx_we <= '1' when cpu_wr_n = '0' and cpu_ena = '1' and cpu_addr(15 downto 12) = X"C" and cpu_addr(9 downto 8) = "11" else '0';
|
||||
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
if C0xx_we = '1' then
|
||||
sound_cmd <= cpu_do;
|
||||
end if;
|
||||
|
||||
if C3xx_we = '1' then
|
||||
if cpu_addr(3 downto 1) = "000" then itt_n <= cpu_do; end if;
|
||||
if cpu_addr(3 downto 1) = "001" then flip <= not cpu_do(0); end if;
|
||||
if cpu_addr(3 downto 1) = "010" then sound_trig <= cpu_do(0); end if;
|
||||
end if;
|
||||
cpu_nmi_n <= vblank;
|
||||
cpu_int_n <= '1';
|
||||
-- if itt_n(0) = '0' then
|
||||
-- cpu_nmi_n <= '1';
|
||||
-- else -- lauch nmi and end of frame
|
||||
-- if (vcnt = 493) and (hcnt = "000000") and (pxcnt = "000") then
|
||||
-- cpu_nmi_n <= '0';
|
||||
-- else
|
||||
-- cpu_nmi_n <= '1';
|
||||
-- end if;
|
||||
-- end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
----------------------
|
||||
--- sprite machine ---
|
||||
----------------------
|
||||
-- sprite data rams are scanned from sprites addresse 31 to 8 at each line
|
||||
|
||||
-- latch current sprite data with respect to pixel and hcnt in relation
|
||||
-- with sprite data ram addressing
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
|
||||
if (hcnt(0) = '0') and (pxcnt = "001") then
|
||||
sp_posh <= spram1_do ; -- a.k.a. X
|
||||
sp_attr <= spram2_do ; -- color and flip x/y
|
||||
vcnt_r <= vcnt;
|
||||
end if;
|
||||
|
||||
-- sprite is on current line if sp_line is below 16
|
||||
-- and if sprite vertical position (a.k.a. Y) is below xF0
|
||||
if (hcnt(0) = '0') and (pxcnt = "011") then
|
||||
if sp_line(7 downto 4) = "0000" and spram2_do < X"F0" then
|
||||
sp_on_line <= '1';
|
||||
else
|
||||
sp_on_line <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- delay sp_color_set
|
||||
if (hcnt(0) = '0') and (pxcnt = "100") then
|
||||
sp_color_set <= sp_attr(5 downto 0);
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- sp_line (valid only when pxcnt = "011")
|
||||
sp_line <= not(vcnt_r(7 downto 0)) - spram2_do;
|
||||
|
||||
-- address sprite graphics rom with sprite code and tile number and sprite line counter
|
||||
-- with respect to sprite flip x/y controls
|
||||
with sp_attr(7 downto 6) select
|
||||
sp_graphx_addr <= spram1_do & sp_line(3) & hcnt(0) & pxcnt(2) & sp_line(2 downto 0) when "11",
|
||||
spram1_do & sp_line(3) & not hcnt(0) & not pxcnt(2) & sp_line(2 downto 0) when "10",
|
||||
spram1_do & not sp_line(3) & hcnt(0) & pxcnt(2) & not sp_line(2 downto 0) when "01",
|
||||
spram1_do & not sp_line(3) & not hcnt(0) & not pxcnt(2) & not sp_line(2 downto 0) when others;
|
||||
|
||||
-- latch and shift sprite graphics data with respect to flipx control
|
||||
-- 8bits => 4x2bits = 4pixels / 4colors (3colors + transparent)
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
|
||||
if pxcnt(1 downto 0) = "00" then
|
||||
if sp_on_line = '1' then
|
||||
if sp_attr(6) = '1' then
|
||||
sp_pixels <= sp_graphx_do;
|
||||
else
|
||||
sp_pixels(3 downto 0) <= sp_graphx_do(0) & sp_graphx_do(1) & sp_graphx_do(2) & sp_graphx_do(3);
|
||||
sp_pixels(7 downto 4) <= sp_graphx_do(4) & sp_graphx_do(5) & sp_graphx_do(6) & sp_graphx_do(7);
|
||||
end if;
|
||||
else
|
||||
sp_pixels <= (others => '0');
|
||||
end if;
|
||||
else
|
||||
sp_pixels(3 downto 0) <= sp_pixels(2 downto 0) & '0';
|
||||
sp_pixels(7 downto 4) <= sp_pixels(6 downto 4) & '0';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-- address sprite color palette 4 colors, 64 sets => 16 colors
|
||||
sp_palette_addr <= sp_color_set & sp_pixels(3) & sp_pixels(7);
|
||||
|
||||
-- write sprite to line buffer at posh position
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
if hcnt(0) = '0' and pxcnt = "101" then
|
||||
sp_buffer_write_addr <= sp_posh;
|
||||
else
|
||||
sp_buffer_write_addr <= sp_buffer_write_addr + '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- write colors to buffer when not transparent
|
||||
sp_buffer_write_we <= '0' when sp_palette_do(3 downto 0) = "0000" else '1';
|
||||
|
||||
-- read sprite line buffer and erase after read
|
||||
process (clock_12)
|
||||
begin
|
||||
if rising_edge(clock_12) then
|
||||
if hcnt = "101111" and pxcnt = "111" then
|
||||
sp_buffer_read_addr <= "11111010"; -- tune horizontal position of sprites
|
||||
else
|
||||
if clock_6 = '0' then
|
||||
sp_buffer_read_addr <= sp_buffer_read_addr + '1';
|
||||
else
|
||||
if vcnt(0) = '0' then
|
||||
sp_read_out <= sp_buffer_ram1_do;
|
||||
else
|
||||
sp_read_out <= sp_buffer_ram2_do;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- toggle read/write sprite line buffer every other line
|
||||
|
||||
-- wait pxcnt = "101" to allow last sprite (#8) to be written to line buffer
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
if pxcnt = "101" then sp_buffer_sel <= vcnt(0); end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sp_buffer_ram1_addr <= sp_buffer_read_addr when sp_buffer_sel = '0' else sp_buffer_write_addr;
|
||||
sp_buffer_ram2_addr <= sp_buffer_read_addr when sp_buffer_sel = '1' else sp_buffer_write_addr;
|
||||
|
||||
sp_buffer_ram1_di <= "0000" when sp_buffer_sel = '0' else sp_palette_do(3 downto 0);
|
||||
sp_buffer_ram2_di <= "0000" when sp_buffer_sel = '1' else sp_palette_do(3 downto 0);
|
||||
|
||||
sp_buffer_ram1_we <= not clock_6 when sp_buffer_sel = '0' else sp_buffer_write_we;
|
||||
sp_buffer_ram2_we <= not clock_6 when sp_buffer_sel = '1' else sp_buffer_write_we;
|
||||
|
||||
--------------------
|
||||
--- char machine ---
|
||||
--------------------
|
||||
|
||||
-- latch current char data with respect to vcnt and hcnt in relation
|
||||
-- with wram ram addressing
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) and pxcnt = "001" then
|
||||
ch_data1 <= wram_do ;
|
||||
end if;
|
||||
|
||||
if rising_edge(clock_6) and pxcnt = "100" then
|
||||
ch_color_set <= ch_data1(4 downto 0) ;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-- address char graphics rom with char code, pixel count and vertical line counter
|
||||
-- with respect to char flip x/y controls
|
||||
with ch_data1(7 downto 6) select
|
||||
ch_graphx_addr_f <= ch_data1(5) & wram_do & pxcnt(2) & vcnt(2 downto 0) when "00",
|
||||
ch_data1(5) & wram_do & not pxcnt(2) & vcnt(2 downto 0) when "01",
|
||||
ch_data1(5) & wram_do & pxcnt(2) & not(vcnt(2 downto 0)) when "10",
|
||||
ch_data1(5) & wram_do & not pxcnt(2) & not(vcnt(2 downto 0)) when others;
|
||||
|
||||
-- in cocktail flip mode negate h/v counters
|
||||
ch_graphx_addr <= ch_graphx_addr_f when flip ='0' else ch_graphx_addr_f xor "0000000001111";
|
||||
|
||||
-- latch and shift char graphics data with respect to flipx control and cocktail flip control
|
||||
-- 8bits => 4x2bits = 4pixels / 4colors
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
if pxcnt(1 downto 0) = "00" then
|
||||
if (ch_data1(6) xor flip) = '0' then
|
||||
ch_pixels <= ch_graphx_do;
|
||||
else
|
||||
ch_pixels(3 downto 0) <= ch_graphx_do(0) & ch_graphx_do(1) &ch_graphx_do(2) &ch_graphx_do(3);
|
||||
ch_pixels(7 downto 4) <= ch_graphx_do(4) & ch_graphx_do(5) &ch_graphx_do(6) &ch_graphx_do(7);
|
||||
end if;
|
||||
else
|
||||
ch_pixels(3 downto 0) <= ch_pixels(2 downto 0) & '0';
|
||||
ch_pixels(7 downto 4) <= ch_pixels(6 downto 4) & '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
end process;
|
||||
|
||||
-- address char color palette 4 colors, 64 sets => 16 colors
|
||||
ch_palette_addr <= '0' & ch_color_set & ch_pixels(3) & ch_pixels(7);
|
||||
|
||||
---------------------
|
||||
-- mux char/sprite --
|
||||
---------------------
|
||||
|
||||
-- char data controls sprite display/hide
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
sp_blank <= ch_color_set(4);
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- select rbg color and bank with respect to char/sprite selection
|
||||
rgb_palette_addr <=
|
||||
'1' & ch_palette_do(3 downto 0) when (sp_read_out = "0000" or sp_blank = '1') else
|
||||
'0' & sp_read_out;
|
||||
|
||||
-- register and assign rbg palette output
|
||||
process (clock_6)
|
||||
begin
|
||||
if rising_edge(clock_6) then
|
||||
if hblank = '1' or vblank = '1' then
|
||||
video_r <= "00000";
|
||||
video_g <= "00000";
|
||||
video_b <= "00000";
|
||||
else
|
||||
video_r <= rgb_palette_gr_do(5 downto 1);
|
||||
video_g <= rgb_palette_bg_do(2 downto 0) & rgb_palette_gr_do(7 downto 6);
|
||||
video_b <= rgb_palette_bg_do(7 downto 3);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
video_hblank <= hblank;
|
||||
video_vblank <= vblank;
|
||||
|
||||
----------------------------
|
||||
-- video syncs and blanks --
|
||||
----------------------------
|
||||
|
||||
process(clock_6)
|
||||
constant hcnt_base : integer := 36;
|
||||
variable vsync_cnt : std_logic_vector(3 downto 0);
|
||||
begin
|
||||
if rising_edge(clock_6) and pxcnt = "110" then
|
||||
|
||||
if hcnt = hcnt_base+0 then hsync0 <= '0';
|
||||
elsif hcnt = hcnt_base+3 then hsync0 <= '1';
|
||||
end if;
|
||||
|
||||
if hcnt = hcnt_base then
|
||||
if vcnt = 500 then
|
||||
vsync_cnt := X"0";
|
||||
else
|
||||
if vsync_cnt < X"F" then vsync_cnt := vsync_cnt + '1'; end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if hcnt = hcnt_base-4 then
|
||||
hblank <= '1';
|
||||
if vcnt = 495 then
|
||||
vblank <= '1'; -- 492 ok
|
||||
elsif vcnt = 262 then
|
||||
vblank <= '0'; -- 262 ok
|
||||
end if;
|
||||
elsif hcnt = 0 then
|
||||
hblank <= '0';
|
||||
end if;
|
||||
|
||||
video_hs <= hsync0;
|
||||
|
||||
if vsync_cnt = 0 then video_vs <= '0';
|
||||
elsif vsync_cnt = 8 then video_vs <= '1';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
------------------------------
|
||||
-- components & sound board --
|
||||
------------------------------
|
||||
|
||||
-- microprocessor Z80
|
||||
cpu : entity work.T80se
|
||||
generic map(Mode => 0, T2Write => 1, IOWait => 1)
|
||||
port map(
|
||||
RESET_n => reset_n,
|
||||
CLK_n => clock_6,
|
||||
CLKEN => cpu_ena,
|
||||
WAIT_n => '1',
|
||||
INT_n => cpu_int_n,
|
||||
NMI_n => cpu_nmi_n,
|
||||
BUSRQ_n => '1',
|
||||
M1_n => open,
|
||||
MREQ_n => cpu_mreq_n,
|
||||
IORQ_n => open,
|
||||
RD_n => open,
|
||||
WR_n => cpu_wr_n,
|
||||
RFSH_n => open,
|
||||
HALT_n => open,
|
||||
BUSAK_n => open,
|
||||
A => cpu_addr,
|
||||
DI => cpu_di,
|
||||
DO => cpu_do
|
||||
);
|
||||
|
||||
roms_addr <= cpu_addr(14 downto 0);
|
||||
cpu_rom_do <= roms_do;
|
||||
roms_rd <= '1';
|
||||
|
||||
|
||||
-- cpu1 program ROM
|
||||
--rom_cpu1 : entity work.power_surge_prog
|
||||
--port map(
|
||||
-- clk => clock_6n,
|
||||
-- addr => cpu_addr(14 downto 0),
|
||||
-- data => cpu_rom_do
|
||||
--);
|
||||
|
||||
|
||||
-- working/char RAM 0xA000-0xAFFF
|
||||
wram : entity work.gen_ram
|
||||
generic map( dWidth => 8, aWidth => 12)
|
||||
port map(
|
||||
clk => clock_6n,
|
||||
we => wram_we,
|
||||
addr => wram_addr,
|
||||
d => cpu_do,
|
||||
q => wram_do
|
||||
);
|
||||
|
||||
-- sprite RAM1 0xB000-0xB0FF
|
||||
spram1 : entity work.gen_ram
|
||||
generic map( dWidth => 8, aWidth => 8)
|
||||
port map(
|
||||
clk => clock_6n,
|
||||
we => spram1_we,
|
||||
addr => spram_addr,
|
||||
d => cpu_do,
|
||||
q => spram1_do
|
||||
);
|
||||
|
||||
-- sprite RAM2 0xB400-0xB4FF
|
||||
spram2 : entity work.gen_ram
|
||||
generic map( dWidth => 8, aWidth => 8)
|
||||
port map(
|
||||
clk => clock_6n,
|
||||
we => spram2_we,
|
||||
addr => spram_addr,
|
||||
d => cpu_do,
|
||||
q => spram2_do
|
||||
);
|
||||
|
||||
-- sprite line buffer 1
|
||||
splinebuf1 : entity work.gen_ram
|
||||
generic map( dWidth => 4, aWidth => 8)
|
||||
port map(
|
||||
clk => clock_12n,
|
||||
we => sp_buffer_ram1_we,
|
||||
addr => sp_buffer_ram1_addr,
|
||||
d => sp_buffer_ram1_di,
|
||||
q => sp_buffer_ram1_do
|
||||
);
|
||||
|
||||
-- sprite line buffer 2
|
||||
splinebuf2 : entity work.gen_ram
|
||||
generic map( dWidth => 4, aWidth => 8)
|
||||
port map(
|
||||
clk => clock_12n,
|
||||
we => sp_buffer_ram2_we,
|
||||
addr => sp_buffer_ram2_addr,
|
||||
d => sp_buffer_ram2_di,
|
||||
q => sp_buffer_ram2_do
|
||||
);
|
||||
|
||||
-- char graphics ROM
|
||||
char_graphics : entity work.power_surge_char_grphx
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => ch_graphx_addr,
|
||||
data => ch_graphx_do
|
||||
);
|
||||
|
||||
-- char palette ROM
|
||||
ch_palette : entity work.power_surge_char_color_lut
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => ch_palette_addr,
|
||||
data => ch_palette_do
|
||||
);
|
||||
|
||||
-- sprite graphics ROM
|
||||
sp_graphics : entity work.power_surge_sprite_grphx
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => sp_graphx_addr,
|
||||
data => sp_graphx_do
|
||||
);
|
||||
|
||||
-- sprite palette ROM
|
||||
sp_palette : entity work.power_surge_sprite_color_lut
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => sp_palette_addr,
|
||||
data => sp_palette_do
|
||||
);
|
||||
|
||||
-- rgb palette ROM 1
|
||||
rgb_palette_gb : entity work.power_surge_palette_blue_green
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => rgb_palette_addr,
|
||||
data => rgb_palette_bg_do
|
||||
);
|
||||
|
||||
-- rgb palette ROM 2
|
||||
rgb_palette_br : entity work.power_surge_palette_green_red
|
||||
port map(
|
||||
clk => clock_6,
|
||||
addr => rgb_palette_addr,
|
||||
data => rgb_palette_gr_do
|
||||
);
|
||||
|
||||
-- sound board
|
||||
time_pilot_sound_board : entity work.time_pilot_sound_board
|
||||
port map(
|
||||
clock_14 => clock_14,
|
||||
reset => reset,
|
||||
|
||||
sound_trig => sound_trig,
|
||||
sound_cmd => sound_cmd,
|
||||
|
||||
audio_out => audio_out
|
||||
);
|
||||
|
||||
end struct;
|
||||
@@ -34,7 +34,7 @@ module TheTowerofDruaga_mist (
|
||||
wire [6:0] core_mod;
|
||||
|
||||
localparam CONF_STR = {
|
||||
`CORE_NAME, ";ROM;",
|
||||
`CORE_NAME, ";;",
|
||||
"O2,Rotate Controls,Off,On;",
|
||||
"O34,Scanlines,Off,25%,50%,75%;",
|
||||
"O5,Blend,Off,On;",
|
||||
@@ -49,31 +49,6 @@ wire [1:0] scanlines = status[4:3];
|
||||
wire blend = status[5];
|
||||
wire flip = status[7];
|
||||
|
||||
wire dcFreeze = status[29];
|
||||
wire dcService = status[30];
|
||||
wire dcCabinet = 1'b0; // (upright only)
|
||||
|
||||
// The Tower of Druaga [t]
|
||||
wire [1:0] dtLives = status[9:8];
|
||||
|
||||
// Mappy [m]
|
||||
wire dmRoundP = status[6];
|
||||
wire [2:0] dmRank = status[12:10];
|
||||
wire dmDemoSnd = status[13];
|
||||
wire [2:0] dmExtend = status[16:14];
|
||||
wire [1:0] dmLives = status[18:17];
|
||||
|
||||
// DigDug2 [d]
|
||||
wire ddLives = status[19];
|
||||
wire [1:0] ddExtend = status[21:20];
|
||||
wire ddLevelSel = status[22];
|
||||
|
||||
// Motos [o]
|
||||
wire doLives = status[23];
|
||||
wire doRank = status[24];
|
||||
wire [1:0] doExtend = status[26:25];
|
||||
wire doDemoSnd = status[27];
|
||||
|
||||
reg [7:0] DSW0;
|
||||
reg [7:0] DSW1;
|
||||
reg [7:0] DSW2;
|
||||
|
||||
@@ -205,7 +205,7 @@ ROM Structure:
|
||||
7400-7BFF snd cpu 2k
|
||||
*/
|
||||
data_io data_io (
|
||||
.clk_sys ( clk_sys ),
|
||||
.clk_sys ( clk_mem ),
|
||||
.SPI_SCK ( SPI_SCK ),
|
||||
.SPI_SS2 ( SPI_SS2 ),
|
||||
.SPI_DI ( SPI_DI ),
|
||||
@@ -228,7 +228,7 @@ wire [11:0] snd_rom_addr;
|
||||
wire snd_vma;
|
||||
wire [15:0] snd_do;
|
||||
|
||||
sdram #(.MHZ(54)) sdram(
|
||||
sdram #(.MHZ(72)) sdram(
|
||||
.*,
|
||||
.init_n ( pll_locked ),
|
||||
.clk ( clk_mem ),
|
||||
@@ -258,9 +258,8 @@ sdram #(.MHZ(54)) sdram(
|
||||
.snd_q ( snd_do )
|
||||
);
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
always @(posedge clk_mem) begin
|
||||
reg ioctl_wr_last = 0;
|
||||
reg snd_vma_r, snd_vma_r2;
|
||||
|
||||
ioctl_wr_last <= ioctl_wr;
|
||||
if (ioctl_downl && ioctl_index == 0) begin
|
||||
@@ -269,6 +268,11 @@ always @(posedge clk_sys) begin
|
||||
port2_req <= ~port2_req;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_sys) begin
|
||||
reg snd_vma_r, snd_vma_r2;
|
||||
|
||||
snd_vma_r <= snd_vma; snd_vma_r2 <= snd_vma_r;
|
||||
if (snd_vma_r2) snd_addr <= snd_rom_addr;
|
||||
end
|
||||
@@ -314,7 +318,7 @@ defender defender (
|
||||
.snd_do ( snd_addr[0] ? snd_do[15:8] : snd_do[7:0] ),
|
||||
.snd_vma ( snd_vma ),
|
||||
|
||||
.dl_clock ( clk_sys ),
|
||||
.dl_clock ( clk_mem ),
|
||||
.dl_addr ( ioctl_addr[15:0] ),
|
||||
.dl_data ( ioctl_dout ),
|
||||
.dl_wr ( ioctl_wr && ioctl_index == 0 ),
|
||||
|
||||
@@ -1,326 +0,0 @@
|
||||
//
|
||||
// Copyright (c) MikeJ - Jan 2005
|
||||
// Copyright (c) 2016-2018 Sorgelig
|
||||
//
|
||||
// All rights reserved
|
||||
//
|
||||
// Redistribution and use in source and synthezised forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in synthesized form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
// BDIR BC MODE
|
||||
// 0 0 inactive
|
||||
// 0 1 read value
|
||||
// 1 0 write value
|
||||
// 1 1 set address
|
||||
//
|
||||
|
||||
module YM2149
|
||||
(
|
||||
input CLK, // Global clock
|
||||
input CE, // PSG Clock enable
|
||||
input RESET, // Chip RESET (set all Registers to '0', active hi)
|
||||
input BDIR, // Bus Direction (0 - read , 1 - write)
|
||||
input BC, // Bus control
|
||||
input [7:0] DI, // Data In
|
||||
output [7:0] DO, // Data Out
|
||||
output [7:0] CHANNEL_A, // PSG Output channel A
|
||||
output [7:0] CHANNEL_B, // PSG Output channel B
|
||||
output [7:0] CHANNEL_C, // PSG Output channel C
|
||||
|
||||
input SEL,
|
||||
input MODE,
|
||||
|
||||
output [5:0] ACTIVE,
|
||||
|
||||
input [7:0] IOA_in,
|
||||
output [7:0] IOA_out,
|
||||
|
||||
input [7:0] IOB_in,
|
||||
output [7:0] IOB_out
|
||||
);
|
||||
|
||||
assign ACTIVE = ~ymreg[7][5:0];
|
||||
assign IOA_out = ymreg[7][6] ? ymreg[14] : 8'hff;
|
||||
assign IOB_out = ymreg[7][7] ? ymreg[15] : 8'hff;
|
||||
|
||||
reg [7:0] addr;
|
||||
reg [7:0] ymreg[16];
|
||||
|
||||
// Write to PSG
|
||||
reg env_reset;
|
||||
always @(posedge CLK) begin
|
||||
if(RESET) begin
|
||||
ymreg <= '{default:0};
|
||||
ymreg[7] <= '1;
|
||||
addr <= '0;
|
||||
env_reset <= 0;
|
||||
end else begin
|
||||
env_reset <= 0;
|
||||
if(BDIR) begin
|
||||
if(BC) addr <= DI;
|
||||
else if(!addr[7:4]) begin
|
||||
ymreg[addr[3:0]] <= DI;
|
||||
env_reset <= (addr == 13);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Read from PSG
|
||||
assign DO = dout;
|
||||
reg [7:0] dout;
|
||||
always_comb begin
|
||||
dout = 8'hFF;
|
||||
if(~BDIR & BC & !addr[7:4]) begin
|
||||
case(addr[3:0])
|
||||
0: dout = ymreg[0];
|
||||
1: dout = ymreg[1][3:0];
|
||||
2: dout = ymreg[2];
|
||||
3: dout = ymreg[3][3:0];
|
||||
4: dout = ymreg[4];
|
||||
5: dout = ymreg[5][3:0];
|
||||
6: dout = ymreg[6][4:0];
|
||||
7: dout = ymreg[7];
|
||||
8: dout = ymreg[8][4:0];
|
||||
9: dout = ymreg[9][4:0];
|
||||
10: dout = ymreg[10][4:0];
|
||||
11: dout = ymreg[11];
|
||||
12: dout = ymreg[12];
|
||||
13: dout = ymreg[13][3:0];
|
||||
14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
|
||||
15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
reg ena_div;
|
||||
reg ena_div_noise;
|
||||
|
||||
// p_divider
|
||||
always @(posedge CLK) begin
|
||||
reg [3:0] cnt_div;
|
||||
reg noise_div;
|
||||
|
||||
if(CE) begin
|
||||
ena_div <= 0;
|
||||
ena_div_noise <= 0;
|
||||
if(!cnt_div) begin
|
||||
cnt_div <= {SEL, 3'b111};
|
||||
ena_div <= 1;
|
||||
|
||||
noise_div <= (~noise_div);
|
||||
if (noise_div) ena_div_noise <= 1;
|
||||
end else begin
|
||||
cnt_div <= cnt_div - 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
reg [2:0] noise_gen_op;
|
||||
|
||||
// p_noise_gen
|
||||
always @(posedge CLK) begin
|
||||
reg [16:0] poly17;
|
||||
reg [4:0] noise_gen_cnt;
|
||||
|
||||
if(CE) begin
|
||||
if (ena_div_noise) begin
|
||||
if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
|
||||
noise_gen_cnt <= 0;
|
||||
poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
|
||||
end else begin
|
||||
noise_gen_cnt <= noise_gen_cnt + 1'd1;
|
||||
end
|
||||
noise_gen_op <= {3{poly17[0]}};
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [11:0] tone_gen_freq[1:3];
|
||||
assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
|
||||
assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
|
||||
assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
|
||||
|
||||
reg [3:1] tone_gen_op;
|
||||
|
||||
//p_tone_gens
|
||||
always @(posedge CLK) begin
|
||||
integer i;
|
||||
reg [11:0] tone_gen_cnt[1:3];
|
||||
|
||||
if(CE) begin
|
||||
// looks like real chips count up - we need to get the Exact behaviour ..
|
||||
|
||||
for (i = 1; i <= 3; i = i + 1) begin
|
||||
if(ena_div) begin
|
||||
if (tone_gen_freq[i]) begin
|
||||
if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
|
||||
tone_gen_cnt[i] <= 0;
|
||||
tone_gen_op[i] <= ~tone_gen_op[i];
|
||||
end else begin
|
||||
tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
|
||||
end
|
||||
end else begin
|
||||
tone_gen_op[i] <= ymreg[7][i];
|
||||
tone_gen_cnt[i] <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg env_ena;
|
||||
wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
|
||||
|
||||
//p_envelope_freq
|
||||
always @(posedge CLK) begin
|
||||
reg [15:0] env_gen_cnt;
|
||||
|
||||
if(CE) begin
|
||||
env_ena <= 0;
|
||||
if(ena_div) begin
|
||||
if (env_gen_cnt >= env_gen_comp) begin
|
||||
env_gen_cnt <= 0;
|
||||
env_ena <= 1;
|
||||
end else begin
|
||||
env_gen_cnt <= (env_gen_cnt + 1'd1);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg [4:0] env_vol;
|
||||
|
||||
wire is_bot = (env_vol == 5'b00000);
|
||||
wire is_bot_p1 = (env_vol == 5'b00001);
|
||||
wire is_top_m1 = (env_vol == 5'b11110);
|
||||
wire is_top = (env_vol == 5'b11111);
|
||||
|
||||
always @(posedge CLK) begin
|
||||
reg env_hold;
|
||||
reg env_inc;
|
||||
|
||||
// envelope shapes
|
||||
// C AtAlH
|
||||
// 0 0 x x \___
|
||||
//
|
||||
// 0 1 x x /___
|
||||
//
|
||||
// 1 0 0 0 \\\\
|
||||
//
|
||||
// 1 0 0 1 \___
|
||||
//
|
||||
// 1 0 1 0 \/\/
|
||||
// ___
|
||||
// 1 0 1 1 \
|
||||
//
|
||||
// 1 1 0 0 ////
|
||||
// ___
|
||||
// 1 1 0 1 /
|
||||
//
|
||||
// 1 1 1 0 /\/\
|
||||
//
|
||||
// 1 1 1 1 /___
|
||||
|
||||
if(env_reset | RESET) begin
|
||||
// load initial state
|
||||
if(!ymreg[13][2]) begin // attack
|
||||
env_vol <= 5'b11111;
|
||||
env_inc <= 0; // -1
|
||||
end else begin
|
||||
env_vol <= 5'b00000;
|
||||
env_inc <= 1; // +1
|
||||
end
|
||||
env_hold <= 0;
|
||||
end
|
||||
else if(CE) begin
|
||||
if (env_ena) begin
|
||||
if (!env_hold) begin
|
||||
if (env_inc) env_vol <= (env_vol + 5'b00001);
|
||||
else env_vol <= (env_vol + 5'b11111);
|
||||
end
|
||||
|
||||
// envelope shape control.
|
||||
if(!ymreg[13][3]) begin
|
||||
if(!env_inc) begin // down
|
||||
if(is_bot_p1) env_hold <= 1;
|
||||
end else if (is_top) env_hold <= 1;
|
||||
end else if(ymreg[13][0]) begin // hold = 1
|
||||
if(!env_inc) begin // down
|
||||
if(ymreg[13][1]) begin // alt
|
||||
if(is_bot) env_hold <= 1;
|
||||
end else if(is_bot_p1) env_hold <= 1;
|
||||
end else if(ymreg[13][1]) begin // alt
|
||||
if(is_top) env_hold <= 1;
|
||||
end else if(is_top_m1) env_hold <= 1;
|
||||
end else if(ymreg[13][1]) begin // alternate
|
||||
if(env_inc == 1'b0) begin // down
|
||||
if(is_bot_p1) env_hold <= 1;
|
||||
if(is_bot) begin
|
||||
env_hold <= 0;
|
||||
env_inc <= 1;
|
||||
end
|
||||
end else begin
|
||||
if(is_top_m1) env_hold <= 1;
|
||||
if(is_top) begin
|
||||
env_hold <= 0;
|
||||
env_inc <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reg [5:0] A,B,C;
|
||||
always @(posedge CLK) begin
|
||||
A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
|
||||
B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
|
||||
C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
|
||||
end
|
||||
|
||||
wire [7:0] volTable[64] = '{
|
||||
//YM2149
|
||||
8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
|
||||
8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
|
||||
8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
|
||||
8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
|
||||
|
||||
//AY8910
|
||||
8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
|
||||
8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
|
||||
8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
|
||||
8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
|
||||
};
|
||||
|
||||
assign CHANNEL_A = volTable[A];
|
||||
assign CHANNEL_B = volTable[B];
|
||||
assign CHANNEL_C = volTable[C];
|
||||
|
||||
endmodule
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,79 +1,117 @@
|
||||
//
|
||||
// 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 [24:1] port1_a,
|
||||
input [1:0] port1_ds,
|
||||
input [15:0] port1_d,
|
||||
output reg [15:0] port1_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;
|
||||
parameter MHZ = 16'd80; // 80 MHz default clock, set it to proper value to calculate refresh rate
|
||||
|
||||
// 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 RASCAS_DELAY = 3'd1; // tRCD=20ns -> 1 cycle@<50MHz
|
||||
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
|
||||
|
||||
localparam sdram_startup_cycles= 14'd12100;// 100us, plus a little more, @ 100MHz
|
||||
localparam cycles_per_refresh = 14'd186; // (64000*24)/8192-1 Calc'd as (64ms @ 24MHz)/8192 rose
|
||||
localparam startup_refresh_max = 14'b11111111111111;
|
||||
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
|
||||
|
||||
// SDRAM commands
|
||||
// 64ms/8192 rows = 7.8us
|
||||
localparam RFRSH_CYCLES = 16'd78*MHZ/4'd10;
|
||||
// ---------------------------------------------------------------------
|
||||
// ------------------------ cycle state machine ------------------------
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
Simple SDRAM state machine
|
||||
1 word burst, CL2
|
||||
cmd issued registered
|
||||
0 RAS0
|
||||
1 ras0
|
||||
2 CAS0
|
||||
3 cas0
|
||||
4
|
||||
5 data0 returned
|
||||
*/
|
||||
|
||||
localparam STATE_RAS0 = 3'd0; // first state in cycle
|
||||
localparam STATE_CAS0 = STATE_RAS0 + RASCAS_DELAY + 1'd1; // CAS phase - 3
|
||||
localparam STATE_READ0 = STATE_CAS0 + CAS_LATENCY + 1'd1; // 6
|
||||
localparam STATE_LAST = 3'd5;
|
||||
|
||||
reg [2:0] t;
|
||||
|
||||
always @(posedge clk) begin
|
||||
t <= t + 1'd1;
|
||||
if (t == STATE_LAST) t <= STATE_RAS0;
|
||||
if (t == STATE_RAS0 && !init && !port1_active && !need_refresh) 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 +122,94 @@ 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
|
||||
|
||||
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;
|
||||
// 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];
|
||||
|
||||
state_t state = STATE_STARTUP;
|
||||
reg [24:1] addr_latch;
|
||||
reg [15:0] din_latch;
|
||||
reg oe_latch;
|
||||
reg we_latch;
|
||||
reg [1:0] ds;
|
||||
|
||||
reg [10:0] refresh_cnt;
|
||||
wire need_refresh = (refresh_cnt >= RFRSH_CYCLES);
|
||||
reg refresh /* synthesis noprune */;
|
||||
wire port1_active = port1_req ^ port1_ack /* synthesis keep */;
|
||||
|
||||
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 @ 24MHz
|
||||
//------------------------------------------------------------------------
|
||||
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 @ 24 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
|
||||
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
|
||||
refresh_cnt <= 0;
|
||||
refresh <= 0;
|
||||
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
|
||||
{ oe_latch, we_latch } <= 2'b00;
|
||||
refresh <= 0;
|
||||
|
||||
if (port1_active) begin
|
||||
sd_cmd <= CMD_ACTIVE;
|
||||
SDRAM_A <= port1_a[22:10];
|
||||
SDRAM_BA <= port1_a[24:23];
|
||||
addr_latch <= port1_a;
|
||||
{ oe_latch, we_latch } <= { ~port1_we, port1_we };
|
||||
ds <= port1_ds;
|
||||
din_latch <= port1_d;
|
||||
end else if (need_refresh) begin
|
||||
sd_cmd <= CMD_AUTO_REFRESH;
|
||||
refresh_cnt <= 0;
|
||||
refresh <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// CAS phase
|
||||
if(t == STATE_CAS0 && (we_latch || oe_latch)) begin
|
||||
sd_cmd <= we_latch?CMD_WRITE:CMD_READ;
|
||||
{ SDRAM_DQMH, SDRAM_DQML } <= ~ds;
|
||||
if (we_latch) begin
|
||||
SDRAM_DQ <= din_latch;
|
||||
port1_ack <= port1_req;
|
||||
end
|
||||
SDRAM_A <= { 4'b0010, addr_latch[9:1] }; // auto precharge
|
||||
SDRAM_BA <= addr_latch[24:23];
|
||||
end
|
||||
|
||||
// Data returned
|
||||
if(t == STATE_READ0 && oe_latch) begin
|
||||
port1_q <= SDRAM_DQ;
|
||||
port1_ack <= port1_req;
|
||||
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
|
||||
|
||||
@@ -180,32 +180,6 @@ end vectrex;
|
||||
|
||||
architecture syn of vectrex is
|
||||
|
||||
component YM2149
|
||||
port (
|
||||
CLK : in std_logic;
|
||||
CE : in std_logic;
|
||||
RESET : in std_logic;
|
||||
BDIR : in std_logic; -- Bus Direction (0 - read , 1 - write)
|
||||
BC : in std_logic; -- Bus control
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
CHANNEL_A : out std_logic_vector(7 downto 0);
|
||||
CHANNEL_B : out std_logic_vector(7 downto 0);
|
||||
CHANNEL_C : out std_logic_vector(7 downto 0);
|
||||
|
||||
SEL : in std_logic;
|
||||
MODE : in std_logic;
|
||||
|
||||
ACTIVE : out std_logic_vector(5 downto 0);
|
||||
|
||||
IOA_in : in std_logic_vector(7 downto 0);
|
||||
IOA_out : out std_logic_vector(7 downto 0);
|
||||
|
||||
IOB_in : in std_logic_vector(7 downto 0);
|
||||
IOB_out : out std_logic_vector(7 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component mc6809 is port
|
||||
(
|
||||
CPU : in std_logic;
|
||||
@@ -787,20 +761,29 @@ video_vblank <= vblank;
|
||||
scan_video_addr <= vcnt_video * std_logic_vector(to_unsigned(max_h,10)) + hcnt_video;
|
||||
|
||||
-- sound
|
||||
audio_1 <= ("00"&ay_chan_a) +
|
||||
("00"&ay_chan_b) +
|
||||
("00"&ay_chan_c) +
|
||||
("00"&dac_sound);
|
||||
process (clock_24)
|
||||
begin
|
||||
if rising_edge(clock_24) then
|
||||
if ay_audio_chan = "00" then ay_chan_a <= ay_audio_muxed; end if;
|
||||
if ay_audio_chan = "01" then ay_chan_b <= ay_audio_muxed; end if;
|
||||
if ay_audio_chan = "10" then ay_chan_c <= ay_audio_muxed; end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
audio_1 <= ("00"&ay_chan_a) +
|
||||
("00"&ay_chan_b) +
|
||||
("00"&ay_chan_c) +
|
||||
("00"&dac_sound);
|
||||
|
||||
audio_out <= "000"&audio_1(9 downto 3) + audio_speech;
|
||||
|
||||
-- vectrex just toggle port A forced/high Z to produce serial data
|
||||
-- when in high Z vectrex sense port A to get speech chip ready for new byte
|
||||
vectrex_serial_bit_in <= ay_ioa_out(4) and speech_mode;
|
||||
vectrex_serial_bit_in <= (ay_ioa_oe or ay_ioa_out(4)) and speech_mode;
|
||||
|
||||
-- get serial data from vectrex joystick port
|
||||
|
||||
process (cpu_clock, reset)
|
||||
process (clock_24, reset)
|
||||
begin
|
||||
if reset='1' then
|
||||
vectrex_bd_rate_div <= X"00";
|
||||
@@ -963,34 +946,37 @@ port map(
|
||||
ENA_4 => via_en_4 -- 4x system clock (4HZ) _-_-_-_-_-
|
||||
);
|
||||
|
||||
|
||||
|
||||
-- AY-3-8910
|
||||
ay_3_8910_2 : entity work.YM2149
|
||||
port map(
|
||||
-- data bus
|
||||
I_DA => via_pa_o, -- in std_logic_vector(7 downto 0);
|
||||
O_DA => ay_do, -- out std_logic_vector(7 downto 0);
|
||||
O_DA_OE_L => open, -- out std_logic;
|
||||
-- control
|
||||
I_A9_L => '0', -- in std_logic;
|
||||
I_A8 => '1', -- in std_logic;
|
||||
I_BDIR => via_pb_o(4), -- in std_logic;
|
||||
I_BC2 => '1', -- in std_logic;
|
||||
I_BC1 => via_pb_o(3), -- in std_logic;
|
||||
I_SEL_L => '1', -- in std_logic;
|
||||
|
||||
ym2149_inst: YM2149
|
||||
port map (
|
||||
CLK => clock_24,
|
||||
CE => cpu_clock_en,
|
||||
RESET => not reset_n,
|
||||
BDIR => via_pb_o(4),
|
||||
BC => via_pb_o(3),
|
||||
DI => via_pa_o,
|
||||
DO => ay_do,
|
||||
CHANNEL_A => ay_chan_a,
|
||||
CHANNEL_B => ay_chan_b,
|
||||
CHANNEL_C => ay_chan_c,
|
||||
O_AUDIO => ay_audio_muxed, -- out std_logic_vector(7 downto 0);
|
||||
O_CHAN => ay_audio_chan, -- out std_logic_vector(1 downto 0);
|
||||
|
||||
SEL => '0',
|
||||
MODE => '0',
|
||||
-- port a
|
||||
I_IOA => players_switches, -- in std_logic_vector(7 downto 0);
|
||||
O_IOA => ay_ioa_out, -- out std_logic_vector(7 downto 0);
|
||||
O_IOA_OE_L => ay_ioa_oe, -- out std_logic;
|
||||
-- port b
|
||||
I_IOB => (others => '0'), -- in std_logic_vector(7 downto 0);
|
||||
O_IOB => open, -- out std_logic_vector(7 downto 0);
|
||||
O_IOB_OE_L => open, -- out std_logic;
|
||||
|
||||
ACTIVE => open,
|
||||
|
||||
IOA_in => players_switches,
|
||||
IOA_out => ay_ioa_out,
|
||||
|
||||
IOB_in => (others => '0'),
|
||||
IOB_out => open
|
||||
);
|
||||
ENA => cpu_clock_en, -- in std_logic; -- clock enable for higher speed operation
|
||||
RESET_L => reset_n, -- in std_logic;
|
||||
CLK => clock_24 -- in std_logic
|
||||
);
|
||||
|
||||
-- select hardware speakjet or VHDL sp0256
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ localparam CONF_STR = {
|
||||
wire [31:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
wire [15:0] kbjoy;
|
||||
wire [7:0] joystick_0;
|
||||
wire [7:0] joystick_1;
|
||||
wire [15:0] joy_ana_0;
|
||||
@@ -85,23 +84,40 @@ pll pll (
|
||||
);
|
||||
|
||||
assign SDRAM_CLK = clk_24;
|
||||
wire [15:0] sdram_do;
|
||||
assign cart_do = sdram_do[7:0];
|
||||
assign SDRAM_CKE = 1;
|
||||
|
||||
sdram cart
|
||||
reg sdram_req;
|
||||
wire [24:1] sdram_a = ioctl_downl ? ioctl_addr[24:1] : cart_addr[14:1];
|
||||
wire [1:0] sdram_ds = ioctl_downl ? {ioctl_addr[0], ~ioctl_addr[0]} : 2'b11;
|
||||
wire [15:0] sdram_q;
|
||||
assign cart_do = cart_addr[0] ? sdram_q[15:8] : sdram_q[7:0];
|
||||
|
||||
sdram #(24) cart
|
||||
(
|
||||
.*,
|
||||
.init(~pll_locked),
|
||||
.clk(clk_24),
|
||||
.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()
|
||||
.*,
|
||||
.clk(clk_24),
|
||||
.init_n(pll_locked),
|
||||
.port1_req(sdram_req),
|
||||
.port1_ack(),
|
||||
.port1_a(sdram_a),
|
||||
.port1_we(ioctl_downl),
|
||||
.port1_ds(sdram_ds),
|
||||
.port1_d({ioctl_dout, ioctl_dout}),
|
||||
.port1_q(sdram_q)
|
||||
);
|
||||
|
||||
always @(posedge clk_24) begin
|
||||
reg [14:1] cart_addrD;
|
||||
|
||||
if (ioctl_downl) begin
|
||||
if (ioctl_wr) sdram_req <= !sdram_req;
|
||||
end
|
||||
else begin
|
||||
cart_addrD <= cart_addr[14:1];
|
||||
if (cart_rd & cart_addr[14:1] != cart_addrD) sdram_req <= !sdram_req;
|
||||
end
|
||||
end
|
||||
|
||||
reg reset = 0;
|
||||
reg second_reset = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user