1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-08 17:11:24 +00:00

Merge pull request #119 from gyurco/master

Just some cleanup
This commit is contained in:
Marcel
2021-06-03 20:15:52 +02:00
committed by GitHub
9 changed files with 259 additions and 11554 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 ),

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;