diff --git a/GCE - Vectrex_MiST/README.TXT b/GCE - Vectrex_MiST/README.TXT new file mode 100644 index 00000000..5fd3115f --- /dev/null +++ b/GCE - Vectrex_MiST/README.TXT @@ -0,0 +1,97 @@ + +GCE(General Consumer Electronics) - Vectrex For Mist FPGA + +Controls: + Movement: Joystick, Keyboard(Arrow Keys) + Buttons: 1-2 on Joystick Fire Buttons + 1-4 on Keyboard 1-4 + +ToDo: Fix Rom Loader + + + + +--------------------------------------------------------------------------------- +-- DE10_lite Top level for vectrex by Dar (darfpga@aol.fr) (27/12/2017) +-- http://darfpga.blogspot.fr +--------------------------------------------------------------------------------- +-- Educational use only +-- Do not redistribute synthetized file with roms +-- Do not redistribute roms whatever the form +-- Use at your own risk +--------------------------------------------------------------------------------- +-- Use vectrex_de10_lite.sdc to compile (Timequest constraints) +-- /!\ +-- Don't forget to set device configuration mode with memory initialization +-- (Assignments/Device/Pin options/Configuration mode) +--------------------------------------------------------------------------------- +-- TODO : +-- sligt tune of characters drawings (too wide) +-- tune hblank to avoid persistance artifact on first 4 pixels of a line +--------------------------------------------------------------------------------- +-- +-- Main features : +-- PS2 keyboard input @gpio pins 35/34 (beware voltage translation/protection) +-- Audio pwm output @gpio pins 1/3 (beware voltage translation/protection) +-- +-- Uses 1 pll for 25/24MHz and 12.5/12MHz generation from 50MHz +-- +-- Horizontal/vertical display selection at compilation +-- 3 or no intensity level selection at compilation +-- +-- No external ram +-- FPGA ram usage as low as : +-- +-- 336.000b ( 42Ko) without cartridge, vertical display, no intensity level (minestrom) +-- 402.000b ( 50Ko) with 8Ko cartridge, vertical display, no intensity level +-- 599.000b ( 74ko) with 32Ko cartridge, vertical display, no intensity level +-- 664.000b ( 82ko) with 8Ko cartridge, horizontal display, no intensity level +-- 1.188.000b (146ko) with 8Ko cartridge, horizontal display, 3 intensity level + +-- Tested cartridge: +-- +-- berzerk ( 4ko) +-- ripoff ( 4ko) +-- scramble ( 4ko) +-- spacewar ( 4ko) +-- startrek ( 4ko) +-- pole position ( 8ko) +-- spike ( 8ko) +-- webwars ( 8ko) +-- frogger (16Ko) +-- vecmania1 (32ko) +-- war of the robot (21ko) +-- +-- Board key : +-- 0 : reset game +-- +-- Keyboard players inputs : +-- +-- F3 : button +-- F2 : button +-- F1 : button +-- SPACE : button +-- RIGHT arrow : joystick right +-- LEFT arrow : joystick left +-- UP arrow : joystick up +-- DOWN arrow : joystick down +-- +-- Other details : see vectrex.vhd +-- For USB inputs and SGT5000 audio output see my other project: xevious_de10_lite +--------------------------------------------------------------------------------- +-- Use tool\vectrex_unzip\make_vectrex_proms.bat to build vhdl rom files +-- +--make_vhdl_prom exec_rom.bin vectrex_exec_prom.vhd (always needed) +-- +--make_vhdl_prom scramble.bin vectrex_scramble_prom.vhd +--make_vhdl_prom berzerk.bin vectrex_berzerk_prom.vhd +--make_vhdl_prom frogger.bin vectrex_frogger_prom.vhd +--make_vhdl_prom spacewar.bin vectrex_spacewar_prom.vhd +--make_vhdl_prom polepos.bin vectrex_polepos_prom.vhd +--make_vhdl_prom ripoff.bin vectrex_ripoff_prom.vhd +--make_vhdl_prom spike.bin vectrex_spike_prom.vhd +--make_vhdl_prom startrek.bin vectrex_startrek_prom.vhd +--make_vhdl_prom vecmania1.bin vectrex_vecmania1_prom.vhd +--make_vhdl_prom webwars.bin vectrex_webwars_prom.vhd +--make_vhdl_prom wotr.bin vectrex_wotr_prom.vhd +--------------------------------------------------------------------------------- diff --git a/GCE - Vectrex_MiST/Snapshot/vectrex_MiST.rbf b/GCE - Vectrex_MiST/Snapshot/vectrex_MiST.rbf new file mode 100644 index 00000000..c8a478a5 Binary files /dev/null and b/GCE - Vectrex_MiST/Snapshot/vectrex_MiST.rbf differ diff --git a/GCE - Vectrex_MiST/clean.bat b/GCE - Vectrex_MiST/clean.bat new file mode 100644 index 00000000..83fb0c47 --- /dev/null +++ b/GCE - Vectrex_MiST/clean.bat @@ -0,0 +1,15 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +del PLLJ_PLLSPE_INFO.txt +del *.qws +del *.ppf +del *.qip +del *.ddb +pause diff --git a/GCE - Vectrex_MiST/rtl/YM2149_linmix_sep.vhd b/GCE - Vectrex_MiST/rtl/YM2149_linmix_sep.vhd new file mode 100644 index 00000000..6ed2498a --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/YM2149_linmix_sep.vhd @@ -0,0 +1,574 @@ +-- changes for seperate audio outputs and enable now enables cpu access as well +-- +-- A simulation model of YM2149 (AY-3-8910 with bells on) + +-- Copyright (c) MikeJ - Jan 2005 +-- +-- 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email support@fpgaarcade.com +-- +-- Revision list +-- +-- version 001 initial release +-- +-- Clues from MAME sound driver and Kazuhiro TSUJIKAWA +-- +-- These are the measured outputs from a real chip for a single Isolated channel into a 1K load (V) +-- vol 15 .. 0 +-- 3.27 2.995 2.741 2.588 2.452 2.372 2.301 2.258 2.220 2.198 2.178 2.166 2.155 2.148 2.141 2.132 +-- As the envelope volume is 5 bit, I have fitted a curve to the not quite log shape in order +-- to produced all the required values. +-- (The first part of the curve is a bit steeper and the last bit is more linear than expected) +-- +-- NOTE, this component uses LINEAR mixing of the three analogue channels, and is only +-- accurate for designs where the outputs are buffered and not simply wired together. +-- The ouput level is more complex in that case and requires a larger table. + +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_arith.all; + use ieee.std_logic_unsigned.all; + +entity YM2149 is + port ( + -- data bus + I_DA : in std_logic_vector(7 downto 0); + O_DA : out std_logic_vector(7 downto 0); + O_DA_OE_L : out std_logic; + -- control + I_A9_L : in std_logic; + I_A8 : in std_logic; + I_BDIR : in std_logic; + I_BC2 : in std_logic; + I_BC1 : in std_logic; + I_SEL_L : in std_logic; + + O_AUDIO : out std_logic_vector(7 downto 0); + O_CHAN : out std_logic_vector(1 downto 0); + -- port a + I_IOA : in std_logic_vector(7 downto 0); + O_IOA : out std_logic_vector(7 downto 0); + O_IOA_OE_L : out std_logic; + -- port b + I_IOB : in std_logic_vector(7 downto 0); + O_IOB : out std_logic_vector(7 downto 0); + O_IOB_OE_L : out std_logic; + + ENA : in std_logic; -- clock enable for higher speed operation + RESET_L : in std_logic; + CLK : in std_logic -- note 6 Mhz + ); +end; + +architecture RTL of YM2149 is + type array_16x8 is array (0 to 15) of std_logic_vector( 7 downto 0); + type array_3x12 is array (1 to 3) of std_logic_vector(11 downto 0); + + signal cnt_div : std_logic_vector(3 downto 0) := (others => '0'); + signal cnt_div_t1 : std_logic_vector(3 downto 0); + signal noise_div : std_logic := '0'; + signal ena_div : std_logic; + signal ena_div_noise : std_logic; + signal poly17 : std_logic_vector(16 downto 0) := (others => '0'); + + -- registers + signal addr : std_logic_vector(7 downto 0); + signal busctrl_addr : std_logic; + signal busctrl_we : std_logic; + signal busctrl_re : std_logic; + + signal reg : array_16x8; + signal env_reset : std_logic; + signal ioa_inreg : std_logic_vector(7 downto 0); + signal iob_inreg : std_logic_vector(7 downto 0); + + signal noise_gen_cnt : std_logic_vector(4 downto 0); + signal noise_gen_op : std_logic; + signal tone_gen_cnt : array_3x12 := (others => (others => '0')); + signal tone_gen_op : std_logic_vector(3 downto 1) := "000"; + + signal env_gen_cnt : std_logic_vector(15 downto 0); + signal env_ena : std_logic; + signal env_hold : std_logic; + signal env_inc : std_logic; + signal env_vol : std_logic_vector(4 downto 0); + + signal tone_ena_l : std_logic; + signal tone_src : std_logic; + signal noise_ena_l : std_logic; + signal chan_vol : std_logic_vector(4 downto 0); + + signal dac_amp : std_logic_vector(7 downto 0); +begin + -- cpu i/f + p_busdecode : process(I_BDIR, I_BC2, I_BC1, addr, I_A9_L, I_A8) + variable cs : std_logic; + variable sel : std_logic_vector(2 downto 0); + begin + -- BDIR BC2 BC1 MODE + -- 0 0 0 inactive + -- 0 0 1 address + -- 0 1 0 inactive + -- 0 1 1 read + -- 1 0 0 address + -- 1 0 1 inactive + -- 1 1 0 write + -- 1 1 1 read + busctrl_addr <= '0'; + busctrl_we <= '0'; + busctrl_re <= '0'; + + cs := '0'; + if (I_A9_L = '0') and (I_A8 = '1') and (addr(7 downto 4) = "0000") then + cs := '1'; + end if; + + sel := (I_BDIR & I_BC2 & I_BC1); + case sel is + when "000" => null; + when "001" => busctrl_addr <= '1'; + when "010" => null; + when "011" => busctrl_re <= cs; + when "100" => busctrl_addr <= '1'; + when "101" => null; + when "110" => busctrl_we <= cs; + when "111" => busctrl_addr <= '1'; + when others => null; + end case; + end process; + + p_oe : process(busctrl_re) + begin + -- if we are emulating a real chip, maybe clock this to fake up the tristate typ delay of 100ns + O_DA_OE_L <= not (busctrl_re); + end process; + + -- + -- CLOCKED + -- + p_waddr : process(RESET_L, CLK) + begin + -- looks like registers are latches in real chip, but the address is caught at the end of the address state. + if (RESET_L = '0') then + addr <= (others => '0'); + elsif rising_edge(CLK) then + if (ENA = '1') then + if (busctrl_addr = '1') then + addr <= I_DA; + end if; + end if; + end if; + end process; + + p_wdata : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + reg <= (others => (others => '0')); + env_reset <= '1'; + elsif rising_edge(CLK) then + if (ENA = '1') then + env_reset <= '0'; + if (busctrl_we = '1') then + case addr(3 downto 0) is + when x"0" => reg(0) <= I_DA; + when x"1" => reg(1) <= I_DA; + when x"2" => reg(2) <= I_DA; + when x"3" => reg(3) <= I_DA; + when x"4" => reg(4) <= I_DA; + when x"5" => reg(5) <= I_DA; + when x"6" => reg(6) <= I_DA; + when x"7" => reg(7) <= I_DA; + when x"8" => reg(8) <= I_DA; + when x"9" => reg(9) <= I_DA; + when x"A" => reg(10) <= I_DA; + when x"B" => reg(11) <= I_DA; + when x"C" => reg(12) <= I_DA; + when x"D" => reg(13) <= I_DA; env_reset <= '1'; + when x"E" => reg(14) <= I_DA; + when x"F" => reg(15) <= I_DA; + when others => null; + end case; + end if; + end if; + end if; + end process; + + p_rdata : process(busctrl_re, addr, reg, ioa_inreg, iob_inreg) + begin + O_DA <= (others => '0'); -- 'X' + if (busctrl_re = '1') then -- not necessary, but useful for putting 'X's in the simulator + case addr(3 downto 0) is + when x"0" => O_DA <= reg(0) ; + when x"1" => O_DA <= "0000" & reg(1)(3 downto 0) ; + when x"2" => O_DA <= reg(2) ; + when x"3" => O_DA <= "0000" & reg(3)(3 downto 0) ; + when x"4" => O_DA <= reg(4) ; + when x"5" => O_DA <= "0000" & reg(5)(3 downto 0) ; + when x"6" => O_DA <= "000" & reg(6)(4 downto 0) ; + when x"7" => O_DA <= reg(7) ; + when x"8" => O_DA <= "000" & reg(8)(4 downto 0) ; + when x"9" => O_DA <= "000" & reg(9)(4 downto 0) ; + when x"A" => O_DA <= "000" & reg(10)(4 downto 0) ; + when x"B" => O_DA <= reg(11); + when x"C" => O_DA <= reg(12); + when x"D" => O_DA <= "0000" & reg(13)(3 downto 0); + when x"E" => if (reg(7)(6) = '0') then -- input + O_DA <= ioa_inreg; + else + O_DA <= reg(14); -- read output reg + end if; + when x"F" => if (Reg(7)(7) = '0') then + O_DA <= iob_inreg; + else + O_DA <= reg(15); + end if; + when others => null; + end case; + end if; + end process; + -- + p_divider : process + begin + wait until rising_edge(CLK); + -- / 8 when SEL is high and /16 when SEL is low + if (ENA = '1') then + ena_div <= '0'; + ena_div_noise <= '0'; + if (cnt_div = "0000") then + cnt_div <= (not I_SEL_L) & "111"; + ena_div <= '1'; + + noise_div <= not noise_div; + if (noise_div = '1') then + ena_div_noise <= '1'; + end if; + else + cnt_div <= cnt_div - "1"; + end if; + end if; + end process; + + p_noise_gen : process + variable noise_gen_comp : std_logic_vector(4 downto 0); + variable poly17_zero : std_logic; + begin + wait until rising_edge(CLK); + if (reg(6)(4 downto 0) = "00000") then + noise_gen_comp := "00000"; + else + noise_gen_comp := (reg(6)(4 downto 0) - "1"); + end if; + + poly17_zero := '0'; + if (poly17 = "00000000000000000") then poly17_zero := '1'; end if; + + if (ENA = '1') then + if (ena_div_noise = '1') then -- divider ena + + if (noise_gen_cnt >= noise_gen_comp) then + noise_gen_cnt <= "00000"; + poly17 <= (poly17(0) xor poly17(2) xor poly17_zero) & poly17(16 downto 1); + else + noise_gen_cnt <= (noise_gen_cnt + "1"); + end if; + end if; + end if; + end process; + noise_gen_op <= poly17(0); + + p_tone_gens : process + variable tone_gen_freq : array_3x12; + variable tone_gen_comp : array_3x12; + begin + wait until rising_edge(CLK); + -- looks like real chips count up - we need to get the Exact behaviour .. + tone_gen_freq(1) := reg(1)(3 downto 0) & reg(0); + tone_gen_freq(2) := reg(3)(3 downto 0) & reg(2); + tone_gen_freq(3) := reg(5)(3 downto 0) & reg(4); + -- period 0 = period 1 + for i in 1 to 3 loop + if (tone_gen_freq(i) = x"000") then + tone_gen_comp(i) := x"000"; + else + tone_gen_comp(i) := (tone_gen_freq(i) - "1"); + end if; + end loop; + + if (ENA = '1') then + for i in 1 to 3 loop + if (ena_div = '1') then -- divider ena + + if (tone_gen_cnt(i) >= tone_gen_comp(i)) then + tone_gen_cnt(i) <= x"000"; + tone_gen_op(i) <= not tone_gen_op(i); + else + tone_gen_cnt(i) <= (tone_gen_cnt(i) + "1"); + end if; + end if; + end loop; + end if; + end process; + + p_envelope_freq : process + variable env_gen_freq : std_logic_vector(15 downto 0); + variable env_gen_comp : std_logic_vector(15 downto 0); + begin + wait until rising_edge(CLK); + env_gen_freq := reg(12) & reg(11); + -- envelope freqs 1 and 0 are the same. + if (env_gen_freq = x"0000") then + env_gen_comp := x"0000"; + else + env_gen_comp := (env_gen_freq - "1"); + end if; + + if (ENA = '1') then + env_ena <= '0'; + if (ena_div = '1') then -- divider ena + if (env_gen_cnt >= env_gen_comp) then + env_gen_cnt <= x"0000"; + env_ena <= '1'; + else + env_gen_cnt <= (env_gen_cnt + "1"); + end if; + end if; + end if; + end process; + + p_envelope_shape : process(env_reset, reg, CLK) + variable is_bot : boolean; + variable is_bot_p1 : boolean; + variable is_top_m1 : boolean; + variable is_top : boolean; + begin + -- 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 = '1') then + -- load initial state + if (reg(13)(2) = '0') then -- attack + env_vol <= "11111"; + env_inc <= '0'; -- -1 + else + env_vol <= "00000"; + env_inc <= '1'; -- +1 + end if; + env_hold <= '0'; + + elsif rising_edge(CLK) then + is_bot := (env_vol = "00000"); + is_bot_p1 := (env_vol = "00001"); + is_top_m1 := (env_vol = "11110"); + is_top := (env_vol = "11111"); + + if (ENA = '1') then + if (env_ena = '1') then + if (env_hold = '0') then + if (env_inc = '1') then + env_vol <= (env_vol + "00001"); + else + env_vol <= (env_vol + "11111"); + end if; + end if; + + -- envelope shape control. + if (reg(13)(3) = '0') then + if (env_inc = '0') then -- down + if is_bot_p1 then env_hold <= '1'; end if; + else + if is_top then env_hold <= '1'; end if; + end if; + else + if (reg(13)(0) = '1') then -- hold = 1 + if (env_inc = '0') then -- down + if (reg(13)(1) = '1') then -- alt + if is_bot then env_hold <= '1'; end if; + else + if is_bot_p1 then env_hold <= '1'; end if; + end if; + else + if (reg(13)(1) = '1') then -- alt + if is_top then env_hold <= '1'; end if; + else + if is_top_m1 then env_hold <= '1'; end if; + end if; + end if; + + elsif (reg(13)(1) = '1') then -- alternate + if (env_inc = '0') then -- down + if is_bot_p1 then env_hold <= '1'; end if; + if is_bot then env_hold <= '0'; env_inc <= '1'; end if; + else + if is_top_m1 then env_hold <= '1'; end if; + if is_top then env_hold <= '0'; env_inc <= '0'; end if; + end if; + end if; + + end if; + end if; + end if; + end if; + end process; + + p_chan_mixer : process(cnt_div, reg, tone_gen_op) + begin + tone_ena_l <= '1'; tone_src <= '1'; + noise_ena_l <= '1'; chan_vol <= "00000"; + case cnt_div(1 downto 0) is + when "00" => + tone_ena_l <= reg(7)(0); tone_src <= tone_gen_op(1); chan_vol <= reg(8)(4 downto 0); + noise_ena_l <= reg(7)(3); + when "01" => + tone_ena_l <= reg(7)(1); tone_src <= tone_gen_op(2); chan_vol <= reg(9)(4 downto 0); + noise_ena_l <= reg(7)(4); + when "10" => + tone_ena_l <= reg(7)(2); tone_src <= tone_gen_op(3); chan_vol <= reg(10)(4 downto 0); + noise_ena_l <= reg(7)(5); + when "11" => null; -- tone gen outputs become valid on this clock + when others => null; + end case; + end process; + + p_op_mixer : process + variable chan_mixed : std_logic; + variable chan_amp : std_logic_vector(4 downto 0); + begin + wait until rising_edge(CLK); + if (ENA = '1') then + + chan_mixed := (tone_ena_l or tone_src) and (noise_ena_l or noise_gen_op); + + chan_amp := (others => '0'); + if (chan_mixed = '1') then + if (chan_vol(4) = '0') then + if (chan_vol(3 downto 0) = "0000") then -- nothing is easy ! make sure quiet is quiet + chan_amp := "00000"; + else + chan_amp := chan_vol(3 downto 0) & '1'; -- make sure level 31 (env) = level 15 (tone) + end if; + else + chan_amp := env_vol(4 downto 0); + end if; + end if; + + dac_amp <= x"00"; + case chan_amp is + when "11111" => dac_amp <= x"FF"; + when "11110" => dac_amp <= x"D9"; + when "11101" => dac_amp <= x"BA"; + when "11100" => dac_amp <= x"9F"; + when "11011" => dac_amp <= x"88"; + when "11010" => dac_amp <= x"74"; + when "11001" => dac_amp <= x"63"; + when "11000" => dac_amp <= x"54"; + when "10111" => dac_amp <= x"48"; + when "10110" => dac_amp <= x"3D"; + when "10101" => dac_amp <= x"34"; + when "10100" => dac_amp <= x"2C"; + when "10011" => dac_amp <= x"25"; + when "10010" => dac_amp <= x"1F"; + when "10001" => dac_amp <= x"1A"; + when "10000" => dac_amp <= x"16"; + when "01111" => dac_amp <= x"13"; + when "01110" => dac_amp <= x"10"; + when "01101" => dac_amp <= x"0D"; + when "01100" => dac_amp <= x"0B"; + when "01011" => dac_amp <= x"09"; + when "01010" => dac_amp <= x"08"; + when "01001" => dac_amp <= x"07"; + when "01000" => dac_amp <= x"06"; + when "00111" => dac_amp <= x"05"; + when "00110" => dac_amp <= x"04"; + when "00101" => dac_amp <= x"03"; + when "00100" => dac_amp <= x"03"; + when "00011" => dac_amp <= x"02"; + when "00010" => dac_amp <= x"02"; + when "00001" => dac_amp <= x"01"; + when "00000" => dac_amp <= x"00"; + when others => null; + end case; + + cnt_div_t1 <= cnt_div; + end if; + end process; + + p_audio_output : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + O_AUDIO <= (others => '0'); + O_CHAN <= (others => '0'); + elsif rising_edge(CLK) then + + if (ENA = '1') then + O_AUDIO <= dac_amp(7 downto 0); + O_CHAN <= cnt_div_t1(1 downto 0); + end if; + end if; + end process; + + p_io_ports : process(reg) + begin + O_IOA <= reg(14); + O_IOA_OE_L <= not reg(7)(6); + O_IOB <= reg(15); + O_IOB_OE_L <= not reg(7)(7); + end process; + + p_io_ports_inreg : process + begin + wait until rising_edge(CLK); + if (ENA = '1') then -- resync + ioa_inreg <= I_IOA; + iob_inreg <= I_IOB; + end if; + end process; +end architecture RTL; diff --git a/GCE - Vectrex_MiST/rtl/build_id.tcl b/GCE - Vectrex_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/GCE - Vectrex_MiST/rtl/build_id.v b/GCE - Vectrex_MiST/rtl/build_id.v new file mode 100644 index 00000000..c9d3f3e7 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "180211" +`define BUILD_TIME "074838" diff --git a/GCE - Vectrex_MiST/rtl/card.qip b/GCE - Vectrex_MiST/rtl/card.qip new file mode 100644 index 00000000..53989c71 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/card.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "card.v"] diff --git a/GCE - Vectrex_MiST/rtl/card.v b/GCE - Vectrex_MiST/rtl/card.v new file mode 100644 index 00000000..b0d8bc34 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/card.v @@ -0,0 +1,177 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: card.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.0 Build 162 10/23/2013 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module card ( + address, + clock, + data, + rden, + wren, + q); + + input [13:0] address; + input clock; + input [7:0] data; + input rden; + input wren; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri1 rden; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .rden_a (rden), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 16384, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 14, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrData NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "16384" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "14" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "1" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "16384" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 14 0 INPUT NODEFVAL "address[13..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// Retrieval info: CONNECT: @address_a 0 0 14 0 address 0 0 14 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 8 0 data 0 0 8 0 +// Retrieval info: CONNECT: @rden_a 0 0 0 0 rden 0 0 0 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL card.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL card.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL card.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL card.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL card_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL card_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/GCE - Vectrex_MiST/rtl/cpu09l_128a.vhd b/GCE - Vectrex_MiST/rtl/cpu09l_128a.vhd new file mode 100644 index 00000000..47b8eddd --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/cpu09l_128a.vhd @@ -0,0 +1,5946 @@ +--===========================================================================-- +-- -- +-- Synthesizable 6809 instruction compatible VHDL CPU core -- +-- -- +--===========================================================================-- +-- +-- File name : cpu09l.vhd +-- +-- Entity name : cpu09 +-- +-- Purpose : 6809 instruction compatible CPU core written in VHDL +-- with Last Instruction Cycle, bus available, bus status, +-- and instruction fetch signals. +-- Not cycle compatible with the original 6809 CPU +-- +-- Dependencies : ieee.std_logic_1164 +-- ieee.std_logic_unsigned +-- +-- Author : John E. Kent +-- +-- Email : dilbert57@opencores.org +-- +-- Web : http://opencores.org/project,system09 +-- +-- Description : VMA (valid memory address) is hight whenever a valid memory +-- access is made by an instruction fetch, interrupt vector fetch +-- or a data read or write otherwise it is low indicating an idle +-- bus cycle. +-- IFETCH (instruction fetch output) is high whenever an +-- instruction byte is read i.e. the program counter is applied +-- to the address bus. +-- LIC (last instruction cycle output) is normally low +-- but goes high on the last cycle of an instruction. +-- BA (bus available output) is normally low but goes high while +-- waiting in a Sync instruction state or the CPU is halted +-- i.e. a DMA grant. +-- BS (bus status output) is normally low but goes high during an +-- interrupt or reset vector fetch or the processor is halted +-- i.e. a DMA grant. +-- +-- Copyright (C) 2003 - 2010 John Kent +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see . +-- +--===========================================================================-- +-- -- +-- Revision History -- +-- -- +--===========================================================================-- +-- +-- Version 0.1 - 26 June 2003 - John Kent +-- Added extra level in state stack +-- fixed some calls to the extended addressing state +-- +-- Version 0.2 - 5 Sept 2003 - John Kent +-- Fixed 16 bit indexed offset (was doing read rather than fetch) +-- Added/Fixed STY and STS instructions. +-- ORCC_STATE ANDed CC state rather than ORed it - Now fixed +-- CMPX Loaded ACCA and ACCB - Now fixed +-- +-- Version 1.0 - 6 Sep 2003 - John Kent +-- Initial release to Open Cores +-- reversed clock edge +-- +-- Version 1.1 - 29 November 2003 John kent +-- ACCA and ACCB indexed offsets are 2's complement. +-- ALU Right Mux now sign extends ACCA & ACCB offsets +-- Absolute Indirect addressing performed a read on the +-- second byte of the address rather than a fetch +-- so it formed an incorrect address. Now fixed. +-- +-- Version 1.2 - 29 November 2003 John Kent +-- LEAX and LEAY affect the Z bit only +-- LEAS and LEAU do not affect any condition codes +-- added an extra ALU control for LEA. +-- +-- Version 1.3 - 12 December 2003 John Kent +-- CWAI did not work, was missed a PUSH_ST on calling +-- the ANDCC_STATE. Thanks go to Ghassan Kraidy for +-- finding this fault. +-- +-- Version 1.4 - 12 December 2003 John Kent +-- Missing cc_ctrl assignment in otherwise case of +-- lea_state resulted in cc_ctrl being latched in +-- that state. +-- The otherwise statement should never be reached, +-- and has been fixed simply to resolve synthesis warnings. +-- +-- Version 1.5 - 17 january 2004 John kent +-- The clear instruction used "alu_ld8" to control the ALU +-- rather than "alu_clr". This mean the Carry was not being +-- cleared correctly. +-- +-- Version 1.6 - 24 January 2004 John Kent +-- Fixed problems in PSHU instruction +-- +-- Version 1.7 - 25 January 2004 John Kent +-- removed redundant "alu_inx" and "alu_dex' +-- Removed "test_alu" and "test_cc" +-- STD instruction did not set condition codes +-- JMP direct was not decoded properly +-- CLR direct performed an unwanted read cycle +-- Bogus "latch_md" in Page2 indexed addressing +-- +-- Version 1.8 - 27 January 2004 John Kent +-- CWAI in decode1_state should increment the PC. +-- ABX is supposed to be an unsigned addition. +-- Added extra ALU function +-- ASR8 slightly changed in the ALU. +-- +-- Version 1.9 - 20 August 2005 +-- LSR8 is now handled in ASR8 and ROR8 case in the ALU, +-- rather than LSR16. There was a problem with single +-- operand instructions using the MD register which is +-- sign extended on the first 8 bit fetch. +-- +-- Version 1.10 - 13 September 2005 +-- TFR & EXG instructions did not work for the Condition Code Register +-- An extra case has been added to the ALU for the alu_tfr control +-- to assign the left ALU input (alu_left) to the condition code +-- outputs (cc_out). +-- +-- Version 1.11 - 16 September 2005 +-- JSR ,X should not predecrement S before calculating the jump address. +-- The reason is that JSR [0,S] needs S to point to the top of the stack +-- to fetch a valid vector address. The solution is to have the addressing +-- mode microcode called before decrementing S and then decrementing S in +-- JSR_STATE. JSR_STATE in turn calls PUSH_RETURN_LO_STATE rather than +-- PUSH_RETURN_HI_STATE so that both the High & Low halves of the PC are +-- pushed on the stack. This adds one extra bus cycle, but resolves the +-- addressing conflict. I've also removed the pre-decement S in +-- JSR EXTENDED as it also calls JSR_STATE. +-- +-- Version 1.12 - 6th June 2006 +-- 6809 Programming reference manual says V is not affected by ASR, LSR and ROR +-- This is different to the 6800. CLR should reset the V bit. +-- +-- Version 1.13 - 7th July 2006 +-- Disable NMI on reset until S Stack pointer has been loaded. +-- Added nmi_enable signal in sp_reg process and nmi_handler process. +-- +-- Version 1.14 - 11th July 2006 +-- 1. Added new state to RTI called rti_entire_state. +-- This state tests the CC register after it has been loaded +-- from the stack. Previously the current CC was tested which +-- was incorrect. The Entire Flag should be set before the +-- interrupt stacks the CC. +-- 2. On bogus Interrupts, int_cc_state went to rti_state, +-- which was an enumerated state, but not defined anywhere. +-- rti_state has been changed to rti_cc_state so that bogus interrupt +-- will perform an RTI after entering that state. +-- 3. Sync should generate an interrupt if the interrupt masks +-- are cleared. If the interrupt masks are set, then an interrupt +-- will cause the the PC to advance to the next instruction. +-- Note that I don't wait for an interrupt to be asserted for +-- three clock cycles. +-- 4. Added new ALU control state "alu_mul". "alu_mul" is used in +-- the Multiply instruction replacing "alu_add16". This is similar +-- to "alu_add16" except it sets the Carry bit to B7 of the result +-- in ACCB, sets the Zero bit if the 16 bit result is zero, but +-- does not affect The Half carry (H), Negative (N) or Overflow (V) +-- flags. The logic was re-arranged so that it adds md or zero so +-- that the Carry condition code is set on zero multiplicands. +-- 5. DAA (Decimal Adjust Accumulator) should set the Negative (N) +-- and Zero Flags. It will also affect the Overflow (V) flag although +-- the operation is undefined. It's anyones guess what DAA does to V. +-- +-- Version 1.15 - 25th Feb 2007 - John Kent +-- line 9672 changed "if Halt <= '1' then" to "if Halt = '1' then" +-- Changed sensitivity lists. +-- +-- Version 1.16 - 5th February 2008 - John Kent +-- FIRQ interrupts should take priority over IRQ Interrupts. +-- This presumably means they should be tested for before IRQ +-- when they happen concurrently. +-- +-- Version 1.17 - 18th February 2008 - John Kent +-- NMI in CWAI should mask IRQ and FIRQ interrupts +-- +-- Version 1.18 - 21st February 2008 - John Kent +-- Removed default register settings in each case statement +-- and placed them at the beginning of the state sequencer. +-- Modified the SYNC instruction so that the interrupt vector(iv) +-- is not set unless an unmasked FIRQ or IRQ is received. +-- +-- Version 1.19 - 25th February 2008 - John Kent +-- Enumerated separate states for FIRQ/FAST and NMIIRQ/ENTIRE +-- Enumerated separate states for MASKI and MASKIF states +-- Removed code on BSR/JSR in fetch cycle +-- +-- Version 1.20 - 8th October 2011 - John Kent +-- added fetch output which should go high during the fetch cycle +-- +-- Version 1.21 - 8th October 2011 - John Kent +-- added Last Instruction Cycle signal +-- replaced fetch with ifetch (instruction fetch) signal +-- added ba & bs (bus available & bus status) signals +-- +-- Version 1.22 - 2011-10-29 John Kent +-- The halt state isn't correct. +-- The halt state is entered into from the fetch_state +-- It returned to the fetch state which may re-run an execute cycle +-- on the accumulator and it won't necessarily be the last instruction cycle +-- I've changed the halt state to return to the decode1_state +-- +-- Version 1.23 - 2011-10-30 John Kent +-- sample halt in the change_state process if lic is high (last instruction cycle) +-- +-- Version 1.24 - 2011-11-01 John Kent +-- Handle interrupts in change_state process +-- Sample interrupt inputs on last instruction cycle +-- Remove iv_ctrl and implement iv (interrupt vector) in change_state process. +-- Generate fic (first instruction cycle) from lic (last instruction cycle) +-- and use it to complete the dual operand execute cycle before servicing +-- halt or interrupts requests. +-- rename lic to lic_out on the entity declaration so that lic can be tested internally. +-- add int_firq1_state and int_nmirq1_state to allow for the dual operand execute cycle +-- integrated nmi_ctrl into change_state process +-- Reduces the microcode state stack to one entry (saved_state) +-- imm16_state jumps directly to the fetch_state +-- pull_return_lo states jumps directly to the fetch_state +-- duplicate andcc_state as cwai_state +-- rename exg1_state as exg2 state and duplicate tfr_state as exg1_state +-- +-- Version 1.25 - 2011-11-27 John Kent +-- Changed the microcode for saving registers on an interrupt into a microcode subroutine. +-- Removed SWI servicing from the change state process and made SWI, SWI2 & SWI3 +-- call the interrupt microcode subroutine. +-- Added additional states for nmi, and irq for interrupt servicing. +-- Added additional states for nmi/irq, firq, and swi interrupts to mask I & F flags. +-- +-- Version 1.26 - 2013-03-18 John Kent +-- pre-initialized cond_true variable to true in state sequencer +-- re-arranged change_state process slightly +-- +-- Version 1.27 - 2015-05-30 John Kent +-- Added test in state machine for masked IRQ and FIRQ in Sync_state. +-- +-- Version 1.28 - 2015-05-30 John Kent. +-- Moved IRQ and FIRQ test from state machine to the state sequencer Sync_state. +-- +-- Version 1.28a - Temporary tweaked release - 2018-02-08 DarFPGA +-- Add wait_cycles process to retrieve original cycle count for some (few) instructions. +-- Only those used by vectrex exec_rom (and spike rom) during drawing. +-- Beware that external hold (hold_in) is no more active. +-- +-- +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; + +entity cpu09 is + port ( + clk : in std_logic; -- E clock input (falling edge) + rst : in std_logic; -- reset input (active high) + vma : out std_logic; -- valid memory address (active high) + lic_out : out std_logic; -- last instruction cycle (active high) + ifetch : out std_logic; -- instruction fetch cycle (active high) + opfetch : out std_logic; -- opcode fetch (active high) + ba : out std_logic; -- bus available (high on sync wait or DMA grant) + bs : out std_logic; -- bus status (high on interrupt or reset vector fetch or DMA grant) + addr : out std_logic_vector(15 downto 0); -- address bus output + rw : out std_logic; -- read not write output + data_out : out std_logic_vector(7 downto 0); -- data bus output + data_in : in std_logic_vector(7 downto 0); -- data bus input + irq : in std_logic; -- interrupt request input (active high) + firq : in std_logic; -- fast interrupt request input (active high) + nmi : in std_logic; -- non maskable interrupt request input (active high) + halt : in std_logic; -- halt input (active high) grants DMA + hold_in : in std_logic -- hold input (active high) extend bus cycle + ); +end cpu09; + +architecture rtl of cpu09 is + + constant EBIT : integer := 7; + constant FBIT : integer := 6; + constant HBIT : integer := 5; + constant IBIT : integer := 4; + constant NBIT : integer := 3; + constant ZBIT : integer := 2; + constant VBIT : integer := 1; + constant CBIT : integer := 0; + + -- + -- Interrupt vector modifiers + -- + constant RST_VEC : std_logic_vector(2 downto 0) := "111"; + constant NMI_VEC : std_logic_vector(2 downto 0) := "110"; + constant SWI_VEC : std_logic_vector(2 downto 0) := "101"; + constant IRQ_VEC : std_logic_vector(2 downto 0) := "100"; + constant FIRQ_VEC : std_logic_vector(2 downto 0) := "011"; + constant SWI2_VEC : std_logic_vector(2 downto 0) := "010"; + constant SWI3_VEC : std_logic_vector(2 downto 0) := "001"; + constant RESV_VEC : std_logic_vector(2 downto 0) := "000"; + + type state_type is (-- Start off in Reset + reset_state, + -- Fetch Interrupt Vectors (including reset) + vect_lo_state, vect_hi_state, vect_idle_state, + -- Fetch Instruction Cycle + fetch_state, + -- Decode Instruction Cycles + decode1_state, decode2_state, decode3_state, + -- Calculate Effective Address + imm16_state, + indexed_state, index8_state, index16_state, index16_2_state, + pcrel8_state, pcrel16_state, pcrel16_2_state, + indexaddr_state, indexaddr2_state, + postincr1_state, postincr2_state, + indirect_state, indirect2_state, indirect3_state, + extended_state, + -- single ops + single_op_read_state, + single_op_exec_state, + single_op_write_state, + -- Dual op states + dual_op_read8_state, dual_op_read16_state, dual_op_read16_2_state, + dual_op_write8_state, dual_op_write16_state, + -- + sync_state, halt_state, cwai_state, + -- + andcc_state, orcc_state, + tfr_state, + exg_state, exg1_state, exg2_state, + lea_state, + -- Multiplication + mul_state, mulea_state, muld_state, + mul0_state, mul1_state, mul2_state, mul3_state, + mul4_state, mul5_state, mul6_state, mul7_state, + -- Branches + lbranch_state, sbranch_state, + -- Jumps, Subroutine Calls and Returns + jsr_state, jmp_state, + push_return_hi_state, push_return_lo_state, + pull_return_hi_state, pull_return_lo_state, + -- Interrupt cycles + int_nmi_state, int_nmi1_state, + int_irq_state, int_irq1_state, + int_firq_state, int_firq1_state, + int_entire_state, int_fast_state, + int_pcl_state, int_pch_state, + int_upl_state, int_uph_state, + int_iyl_state, int_iyh_state, + int_ixl_state, int_ixh_state, + int_dp_state, + int_accb_state, int_acca_state, + int_cc_state, + int_cwai_state, + int_nmimask_state, int_firqmask_state, int_swimask_state, int_irqmask_state, + -- Return From Interrupt + rti_cc_state, rti_entire_state, + rti_acca_state, rti_accb_state, + rti_dp_state, + rti_ixl_state, rti_ixh_state, + rti_iyl_state, rti_iyh_state, + rti_upl_state, rti_uph_state, + rti_pcl_state, rti_pch_state, + -- Push Registers using SP + pshs_state, + pshs_pcl_state, pshs_pch_state, + pshs_upl_state, pshs_uph_state, + pshs_iyl_state, pshs_iyh_state, + pshs_ixl_state, pshs_ixh_state, + pshs_dp_state, + pshs_acca_state, pshs_accb_state, + pshs_cc_state, + -- Pull Registers using SP + puls_state, + puls_cc_state, + puls_acca_state, puls_accb_state, + puls_dp_state, + puls_ixl_state, puls_ixh_state, + puls_iyl_state, puls_iyh_state, + puls_upl_state, puls_uph_state, + puls_pcl_state, puls_pch_state, + -- Push Registers using UP + pshu_state, + pshu_pcl_state, pshu_pch_state, + pshu_spl_state, pshu_sph_state, + pshu_iyl_state, pshu_iyh_state, + pshu_ixl_state, pshu_ixh_state, + pshu_dp_state, + pshu_acca_state, pshu_accb_state, + pshu_cc_state, + -- Pull Registers using UP + pulu_state, + pulu_cc_state, + pulu_acca_state, pulu_accb_state, + pulu_dp_state, + pulu_ixl_state, pulu_ixh_state, + pulu_iyl_state, pulu_iyh_state, + pulu_spl_state, pulu_sph_state, + pulu_pcl_state, pulu_pch_state ); + + type st_type is (reset_st, push_st, idle_st ); + type iv_type is (latch_iv, swi3_iv, swi2_iv, firq_iv, irq_iv, swi_iv, nmi_iv, reset_iv); + type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, pushu_ad, pullu_ad, pushs_ad, pulls_ad, int_hi_ad, int_lo_ad ); + type dout_type is (cc_dout, acca_dout, accb_dout, dp_dout, + ix_lo_dout, ix_hi_dout, iy_lo_dout, iy_hi_dout, + up_lo_dout, up_hi_dout, sp_lo_dout, sp_hi_dout, + pc_lo_dout, pc_hi_dout, md_lo_dout, md_hi_dout ); + type op_type is (reset_op, fetch_op, latch_op ); + type pre_type is (reset_pre, fetch_pre, latch_pre ); + type cc_type is (reset_cc, load_cc, pull_cc, latch_cc ); + type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca ); + type accb_type is (reset_accb, load_accb, pull_accb, latch_accb ); + type dp_type is (reset_dp, load_dp, pull_dp, latch_dp ); + type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix ); + type iy_type is (reset_iy, load_iy, pull_lo_iy, pull_hi_iy, latch_iy ); + type sp_type is (reset_sp, latch_sp, load_sp, pull_hi_sp, pull_lo_sp ); + type up_type is (reset_up, latch_up, load_up, pull_hi_up, pull_lo_up ); + type pc_type is (reset_pc, latch_pc, load_pc, pull_lo_pc, pull_hi_pc, incr_pc ); + type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md ); + type ea_type is (reset_ea, latch_ea, load_ea, fetch_first_ea, fetch_next_ea ); + type left_type is (cc_left, acca_left, accb_left, dp_left, + ix_left, iy_left, up_left, sp_left, + accd_left, md_left, pc_left, ea_left ); + type right_type is (ea_right, zero_right, one_right, two_right, + acca_right, accb_right, accd_right, + md_right, md_sign5_right, md_sign8_right ); + type alu_type is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc, + alu_and, alu_ora, alu_eor, + alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com, + alu_lsr16, alu_lsl16, + alu_ror8, alu_rol8, alu_mul, + alu_asr8, alu_asl8, alu_lsr8, + alu_andcc, alu_orcc, alu_sex, alu_tfr, alu_abx, + alu_seif, alu_sei, alu_see, alu_cle, + alu_ld8, alu_st8, alu_ld16, alu_st16, alu_lea, alu_nop, alu_daa ); + + signal op_code: std_logic_vector(7 downto 0); + signal pre_code: std_logic_vector(7 downto 0); + signal acca: std_logic_vector(7 downto 0); + signal accb: std_logic_vector(7 downto 0); + signal cc: std_logic_vector(7 downto 0); + signal cc_out: std_logic_vector(7 downto 0); + signal dp: std_logic_vector(7 downto 0); + signal xreg: std_logic_vector(15 downto 0); + signal yreg: std_logic_vector(15 downto 0); + signal sp: std_logic_vector(15 downto 0); + signal up: std_logic_vector(15 downto 0); + signal ea: std_logic_vector(15 downto 0); + signal pc: std_logic_vector(15 downto 0); + signal md: std_logic_vector(15 downto 0); + signal left: std_logic_vector(15 downto 0); + signal right: std_logic_vector(15 downto 0); + signal out_alu: std_logic_vector(15 downto 0); + signal iv: std_logic_vector(2 downto 0); + signal nmi_req: std_logic; + signal nmi_ack: std_logic; + signal nmi_enable: std_logic; + signal fic: std_logic; -- first instruction cycle + signal lic: std_logic; -- last instruction cycle + + signal state: state_type; + signal next_state: state_type; + signal return_state: state_type; + signal saved_state: state_type; + signal st_ctrl: st_type; + signal iv_ctrl: iv_type; + signal pc_ctrl: pc_type; + signal ea_ctrl: ea_type; + signal op_ctrl: op_type; + signal pre_ctrl: pre_type; + signal md_ctrl: md_type; + signal acca_ctrl: acca_type; + signal accb_ctrl: accb_type; + signal ix_ctrl: ix_type; + signal iy_ctrl: iy_type; + signal cc_ctrl: cc_type; + signal dp_ctrl: dp_type; + signal sp_ctrl: sp_type; + signal up_ctrl: up_type; + signal left_ctrl: left_type; + signal right_ctrl: right_type; + signal alu_ctrl: alu_type; + signal addr_ctrl: addr_type; + signal dout_ctrl: dout_type; + + + signal cnt_cycles : std_logic_vector(3 downto 0) := "0000" ; + signal hold : std_logic; + +begin + +wait_cycles: process(clk) +begin + if clk'event and clk = '0' then + + if lic = '1' then + case op_code is + when X"A6" => hold <= '1'; cnt_cycles <= X"1"; -- additional cycles for vectrex tuning + when X"97" => hold <= '1'; cnt_cycles <= X"1"; + when X"8C" => hold <= '1'; cnt_cycles <= X"1"; + when X"D7" => hold <= '1'; cnt_cycles <= X"1"; + when X"1F" => hold <= '1'; cnt_cycles <= X"3"; + when X"B3" => hold <= '1'; cnt_cycles <= X"2"; + when X"0A" => hold <= '1'; cnt_cycles <= X"2"; + when X"0C" => hold <= '1'; cnt_cycles <= X"2"; + when X"1E" => hold <= '1'; cnt_cycles <= X"3"; -- exg @117A/7C spike (allow time enough for timer to end before pc=11A4) + when others=> null; + end case; + end if; + + if hold = '1' then + if cnt_cycles = X"1" then + hold <= '0'; + end if; + cnt_cycles <= cnt_cycles - '1'; + end if; + + end if; +end process; + +---------------------------------- +-- +-- State machine stack +-- +---------------------------------- +--state_stack_proc: process( clk, hold, state_stack, st_ctrl, +-- return_state, fetch_state ) +state_stack_proc: process( clk, st_ctrl, return_state ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case st_ctrl is + when reset_st => + saved_state <= fetch_state; + when push_st => + saved_state <= return_state; + when others => + null; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- Interrupt Vector control +-- +---------------------------------- +-- +int_vec_proc: process( clk, iv_ctrl ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case iv_ctrl is + when reset_iv => + iv <= RST_VEC; + when nmi_iv => + iv <= NMI_VEC; + when swi_iv => + iv <= SWI_VEC; + when irq_iv => + iv <= IRQ_VEC; + when firq_iv => + iv <= FIRQ_VEC; + when swi2_iv => + iv <= SWI2_VEC; + when swi3_iv => + iv <= SWI3_VEC; + when others => + null; + end case; + end if; -- hold + end if; -- clk +end process; + +---------------------------------- +-- +-- Program Counter Control +-- +---------------------------------- + +--pc_reg: process( clk, pc_ctrl, hold, pc, out_alu, data_in ) +pc_reg: process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case pc_ctrl is + when reset_pc => + pc <= (others=>'0'); + when load_pc => + pc <= out_alu(15 downto 0); + when pull_lo_pc => + pc(7 downto 0) <= data_in; + when pull_hi_pc => + pc(15 downto 8) <= data_in; + when incr_pc => + pc <= pc + 1; + when others => + null; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- Effective Address Control +-- +---------------------------------- + +--ea_reg: process( clk, ea_ctrl, hold, ea, out_alu, data_in, dp ) +ea_reg: process( clk ) +begin + + if clk'event and clk = '0' then + if hold= '0' then + case ea_ctrl is + when reset_ea => + ea <= (others=>'0'); + when fetch_first_ea => + ea(7 downto 0) <= data_in; + ea(15 downto 8) <= dp; + when fetch_next_ea => + ea(15 downto 8) <= ea(7 downto 0); + ea(7 downto 0) <= data_in; + when load_ea => + ea <= out_alu(15 downto 0); + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator A +-- +-------------------------------- +--acca_reg : process( clk, acca_ctrl, hold, out_alu, acca, data_in ) +acca_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case acca_ctrl is + when reset_acca => + acca <= (others=>'0'); + when load_acca => + acca <= out_alu(7 downto 0); + when load_hi_acca => + acca <= out_alu(15 downto 8); + when pull_acca => + acca <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Accumulator B +-- +-------------------------------- +--accb_reg : process( clk, accb_ctrl, hold, out_alu, accb, data_in ) +accb_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case accb_ctrl is + when reset_accb => + accb <= (others=>'0'); + when load_accb => + accb <= out_alu(7 downto 0); + when pull_accb => + accb <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- X Index register +-- +-------------------------------- +--ix_reg : process( clk, ix_ctrl, hold, out_alu, xreg, data_in ) +ix_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case ix_ctrl is + when reset_ix => + xreg <= (others=>'0'); + when load_ix => + xreg <= out_alu(15 downto 0); + when pull_hi_ix => + xreg(15 downto 8) <= data_in; + when pull_lo_ix => + xreg(7 downto 0) <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Y Index register +-- +-------------------------------- +--iy_reg : process( clk, iy_ctrl, hold, out_alu, yreg, data_in ) +iy_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case iy_ctrl is + when reset_iy => + yreg <= (others=>'0'); + when load_iy => + yreg <= out_alu(15 downto 0); + when pull_hi_iy => + yreg(15 downto 8) <= data_in; + when pull_lo_iy => + yreg(7 downto 0) <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- S stack pointer +-- +-------------------------------- +--sp_reg : process( clk, sp_ctrl, hold, sp, out_alu, data_in, nmi_enable ) +sp_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case sp_ctrl is + when reset_sp => + sp <= (others=>'0'); + nmi_enable <= '0'; + when load_sp => + sp <= out_alu(15 downto 0); + nmi_enable <= '1'; + when pull_hi_sp => + sp(15 downto 8) <= data_in; + when pull_lo_sp => + sp(7 downto 0) <= data_in; + nmi_enable <= '1'; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- U stack pointer +-- +-------------------------------- +--up_reg : process( clk, up_ctrl, hold, up, out_alu, data_in ) +up_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case up_ctrl is + when reset_up => + up <= (others=>'0'); + when load_up => + up <= out_alu(15 downto 0); + when pull_hi_up => + up(15 downto 8) <= data_in; + when pull_lo_up => + up(7 downto 0) <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- Memory Data +-- +-------------------------------- +--md_reg : process( clk, md_ctrl, hold, out_alu, data_in, md ) +md_reg : process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case md_ctrl is + when reset_md => + md <= (others=>'0'); + when load_md => + md <= out_alu(15 downto 0); + when fetch_first_md => -- sign extend md for branches + md(15 downto 8) <= data_in(7) & data_in(7) & data_in(7) & data_in(7) & + data_in(7) & data_in(7) & data_in(7) & data_in(7) ; + md(7 downto 0) <= data_in; + when fetch_next_md => + md(15 downto 8) <= md(7 downto 0); + md(7 downto 0) <= data_in; + when shiftl_md => + md(15 downto 1) <= md(14 downto 0); + md(0) <= '0'; + when others => + null; + end case; + end if; + end if; +end process; + + +---------------------------------- +-- +-- Condition Codes +-- +---------------------------------- + +--cc_reg: process( clk, cc_ctrl, hold, cc_out, cc, data_in ) +cc_reg: process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case cc_ctrl is + when reset_cc => + cc <= "11010000"; -- set EBIT, FBIT & IBIT + when load_cc => + cc <= cc_out; + when pull_cc => + cc <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +---------------------------------- +-- +-- Direct Page register +-- +---------------------------------- + +--dp_reg: process( clk, dp_ctrl, hold, out_alu, dp, data_in ) +dp_reg: process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case dp_ctrl is + when reset_dp => + dp <= (others=>'0'); + when load_dp => + dp <= out_alu(7 downto 0); + when pull_dp => + dp <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + + +---------------------------------- +-- +-- op code register +-- +---------------------------------- + +--op_reg: process( clk, op_ctrl, hold, op_code, data_in ) +op_reg: process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case op_ctrl is + when reset_op => + op_code <= "00010010"; + when fetch_op => + op_code <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + + +---------------------------------- +-- +-- pre byte op code register +-- +---------------------------------- + +--pre_reg: process( clk, pre_ctrl, hold, pre_code, data_in ) +pre_reg: process( clk ) +begin + if clk'event and clk = '0' then + if hold = '0' then + case pre_ctrl is + when reset_pre => + pre_code <= (others=>'0'); + when fetch_pre => + pre_code <= data_in; + when others => + null; + end case; + end if; + end if; +end process; + +-------------------------------- +-- +-- state machine +-- +-------------------------------- + +--change_state: process( clk, rst, state, hold, next_state ) +change_state: process( clk ) +begin + if clk'event and clk = '0' then + + if rst = '1' then + fic <= '0'; + nmi_ack <= '0'; + state <= reset_state; + elsif hold = '0' then + + fic <= lic; + -- + -- nmi request is not cleared until nmi input goes low + -- + if (nmi_req = '0') and (nmi_ack='1') then + nmi_ack <= '0'; + end if; + + if (nmi_req = '1') and (nmi_ack = '0') and (state = int_nmimask_state) then + nmi_ack <= '1'; + end if; + + if lic = '1' then + if halt = '1' then + state <= halt_state; + + -- service non maskable interrupts + elsif (nmi_req = '1') and (nmi_ack = '0') then + state <= int_nmi_state; + -- + -- FIRQ & IRQ are level sensitive + -- + elsif (firq = '1') and (cc(FBIT) = '0') then + state <= int_firq_state; + + elsif (irq = '1') and (cc(IBIT) = '0') then + state <= int_irq_state; + -- + -- Version 1.27 2015-05-30 + -- Exit sync_state on masked interrupt. + -- + -- Version 1.28 2015-05-30 + -- Move this code to the state sequencer + -- near line 5566. + -- + -- elsif (state = sync_state) and ((firq = '1') or (irq = '1'))then + -- state <= fetch_state; + -- + else + state <= next_state; + end if; -- halt, nmi, firq, irq + else + state <= next_state; + end if; -- lic + end if; -- reset/hold + end if; -- clk +end process; + +------------------------------------ +-- +-- Detect Edge of NMI interrupt +-- +------------------------------------ + +--nmi_handler : process( clk, rst, nmi, nmi_ack, nmi_req, nmi_enable ) +nmi_handler : process( rst, clk ) +begin + if rst='1' then + nmi_req <= '0'; + elsif clk'event and clk='0' then + if (nmi='1') and (nmi_ack='0') and (nmi_enable='1') then + nmi_req <= '1'; + else + if (nmi='0') and (nmi_ack='1') then + nmi_req <= '0'; + end if; + end if; + end if; +end process; + + +---------------------------------- +-- +-- Address output multiplexer +-- +---------------------------------- + +addr_mux: process( addr_ctrl, pc, ea, up, sp, iv ) +begin + ifetch <= '0'; + vma <= '1'; + case addr_ctrl is + when fetch_ad => + addr <= pc; + rw <= '1'; + ifetch <= '1'; + when read_ad => + addr <= ea; + rw <= '1'; + when write_ad => + addr <= ea; + rw <= '0'; + when pushs_ad => + addr <= sp; + rw <= '0'; + when pulls_ad => + addr <= sp; + rw <= '1'; + when pushu_ad => + addr <= up; + rw <= '0'; + when pullu_ad => + addr <= up; + rw <= '1'; + when int_hi_ad => + addr <= "111111111111" & iv & "0"; + rw <= '1'; + when int_lo_ad => + addr <= "111111111111" & iv & "1"; + rw <= '1'; + when others => + addr <= "1111111111111111"; + rw <= '1'; + vma <= '0'; + end case; +end process; + +-------------------------------- +-- +-- Data Bus output +-- +-------------------------------- +dout_mux : process( dout_ctrl, md, acca, accb, dp, xreg, yreg, sp, up, pc, cc ) +begin + case dout_ctrl is + when cc_dout => -- condition code register + data_out <= cc; + when acca_dout => -- accumulator a + data_out <= acca; + when accb_dout => -- accumulator b + data_out <= accb; + when dp_dout => -- direct page register + data_out <= dp; + when ix_lo_dout => -- X index reg + data_out <= xreg(7 downto 0); + when ix_hi_dout => -- X index reg + data_out <= xreg(15 downto 8); + when iy_lo_dout => -- Y index reg + data_out <= yreg(7 downto 0); + when iy_hi_dout => -- Y index reg + data_out <= yreg(15 downto 8); + when up_lo_dout => -- U stack pointer + data_out <= up(7 downto 0); + when up_hi_dout => -- U stack pointer + data_out <= up(15 downto 8); + when sp_lo_dout => -- S stack pointer + data_out <= sp(7 downto 0); + when sp_hi_dout => -- S stack pointer + data_out <= sp(15 downto 8); + when md_lo_dout => -- alu output + data_out <= md(7 downto 0); + when md_hi_dout => -- alu output + data_out <= md(15 downto 8); + when pc_lo_dout => -- low order pc + data_out <= pc(7 downto 0); + when pc_hi_dout => -- high order pc + data_out <= pc(15 downto 8); + end case; +end process; + +---------------------------------- +-- +-- Left Mux +-- +---------------------------------- + +left_mux: process( left_ctrl, acca, accb, cc, dp, xreg, yreg, up, sp, pc, ea, md ) +begin + case left_ctrl is + when cc_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= cc; + when acca_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= acca; + when accb_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= accb; + when dp_left => + left(15 downto 8) <= "00000000"; + left(7 downto 0) <= dp; + when accd_left => + left(15 downto 8) <= acca; + left(7 downto 0) <= accb; + when md_left => + left <= md; + when ix_left => + left <= xreg; + when iy_left => + left <= yreg; + when sp_left => + left <= sp; + when up_left => + left <= up; + when pc_left => + left <= pc; + when others => +-- when ea_left => + left <= ea; + end case; +end process; + +---------------------------------- +-- +-- Right Mux +-- +---------------------------------- + +right_mux: process( right_ctrl, md, acca, accb, ea ) +begin + case right_ctrl is + when ea_right => + right <= ea; + when zero_right => + right <= "0000000000000000"; + when one_right => + right <= "0000000000000001"; + when two_right => + right <= "0000000000000010"; + when acca_right => + if acca(7) = '0' then + right <= "00000000" & acca(7 downto 0); + else + right <= "11111111" & acca(7 downto 0); + end if; + when accb_right => + if accb(7) = '0' then + right <= "00000000" & accb(7 downto 0); + else + right <= "11111111" & accb(7 downto 0); + end if; + when accd_right => + right <= acca & accb; + when md_sign5_right => + if md(4) = '0' then + right <= "00000000000" & md(4 downto 0); + else + right <= "11111111111" & md(4 downto 0); + end if; + when md_sign8_right => + if md(7) = '0' then + right <= "00000000" & md(7 downto 0); + else + right <= "11111111" & md(7 downto 0); + end if; + when others => +-- when md_right => + right <= md; + end case; +end process; + +---------------------------------- +-- +-- Arithmetic Logic Unit +-- +---------------------------------- + +alu: process( alu_ctrl, cc, left, right, out_alu, cc_out ) +variable valid_lo, valid_hi : boolean; +variable carry_in : std_logic; +variable daa_reg : std_logic_vector(7 downto 0); +begin + + case alu_ctrl is + when alu_adc | alu_sbc | + alu_rol8 | alu_ror8 => + carry_in := cc(CBIT); + when alu_asr8 => + carry_in := left(7); + when others => + carry_in := '0'; + end case; + + valid_lo := left(3 downto 0) <= 9; + valid_hi := left(7 downto 4) <= 9; + + -- + -- CBIT HBIT VHI VLO DAA + -- 0 0 0 0 66 (!VHI : hi_nybble>8) + -- 0 0 0 1 60 + -- 0 0 1 1 00 + -- 0 0 1 0 06 ( VHI : hi_nybble<=8) + -- + -- 0 1 1 0 06 + -- 0 1 1 1 06 + -- 0 1 0 1 66 + -- 0 1 0 0 66 + -- + -- 1 1 0 0 66 + -- 1 1 0 1 66 + -- 1 1 1 1 66 + -- 1 1 1 0 66 + -- + -- 1 0 1 0 66 + -- 1 0 1 1 60 + -- 1 0 0 1 60 + -- 1 0 0 0 66 + -- + -- 66 = (!VHI & !VLO) + (CBIT & HBIT) + (HBIT & !VHI) + (CBIT & !VLO) + -- = (CBIT & (HBIT + !VLO)) + (!VHI & (HBIT + !VLO)) + -- = (!VLO & (CBIT + !VHI)) + (HBIT & (CBIT + !VHI)) + -- 60 = (CBIT & !HBIT & VLO) + (!HBIT & !VHI & VLO) + -- = (!HBIT & VLO & (CBIT + !VHI)) + -- 06 = (!CBIT & VHI & (!VLO + VHI) + -- 00 = (!CBIT & !HBIT & VHI & VLO) + -- + if (cc(CBIT) = '0') then + -- CBIT=0 + if( cc(HBIT) = '0' ) then + -- HBIT=0 + if valid_lo then + -- lo <= 9 (no overflow in low nybble) + if valid_hi then + -- hi <= 9 (no overflow in either low or high nybble) + daa_reg := "00000000"; + else + -- hi > 9 (overflow in high nybble only) + daa_reg := "01100000"; + end if; + else + -- lo > 9 (overflow in low nybble) + -- + -- since there is already an overflow in the low nybble + -- you need to make room in the high nybble for the low nybble carry + -- so compare the high nybble with 8 rather than 9 + -- if the high nybble is 9 there will be an overflow on the high nybble + -- after the decimal adjust which means it will roll over to an invalid BCD digit + -- + if( left(7 downto 4) <= 8 ) then + -- hi <= 8 (overflow in low nybble only) + daa_reg := "00000110"; + else + -- hi > 8 (overflow in low and high nybble) + daa_reg := "01100110"; + end if; + end if; + else + -- HBIT=1 (overflow in low nybble) + if valid_hi then + -- hi <= 9 (overflow in low nybble only) + daa_reg := "00000110"; + else + -- hi > 9 (overflow in low and high nybble) + daa_reg := "01100110"; + end if; + end if; + else + -- CBIT=1 (carry => overflow in high nybble) + if ( cc(HBIT) = '0' )then + -- HBIT=0 (half carry clear => may or may not be an overflow in the low nybble) + if valid_lo then + -- lo <=9 (overflow in high nybble only) + daa_reg := "01100000"; + else + -- lo >9 (overflow in low and high nybble) + daa_reg := "01100110"; + end if; + else + -- HBIT=1 (overflow in low and high nybble) + daa_reg := "01100110"; + end if; + end if; + + case alu_ctrl is + when alu_add8 | alu_inc | + alu_add16 | alu_adc | alu_mul => + out_alu <= left + right + ("000000000000000" & carry_in); + when alu_sub8 | alu_dec | + alu_sub16 | alu_sbc => + out_alu <= left - right - ("000000000000000" & carry_in); + when alu_abx => + out_alu <= left + ("00000000" & right(7 downto 0)) ; + when alu_and => + out_alu <= left and right; -- and/bit + when alu_ora => + out_alu <= left or right; -- or + when alu_eor => + out_alu <= left xor right; -- eor/xor + when alu_lsl16 | alu_asl8 | alu_rol8 => + out_alu <= left(14 downto 0) & carry_in; -- rol8/asl8/lsl16 + when alu_lsr16 => + out_alu <= carry_in & left(15 downto 1); -- lsr16 + when alu_lsr8 | alu_asr8 | alu_ror8 => + out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror8/asr8/lsr8 + when alu_neg => + out_alu <= right - left; -- neg (right=0) + when alu_com => + out_alu <= not left; + when alu_clr | alu_ld8 | alu_ld16 | alu_lea => + out_alu <= right; -- clr, ld + when alu_st8 | alu_st16 | alu_andcc | alu_orcc | alu_tfr => + out_alu <= left; + when alu_daa => + out_alu <= left + ("00000000" & daa_reg); + when alu_sex => + if left(7) = '0' then + out_alu <= "00000000" & left(7 downto 0); + else + out_alu <= "11111111" & left(7 downto 0); + end if; + when others => + out_alu <= left; -- nop + end case; + + -- + -- carry bit + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(CBIT) <= (left(7) and right(7)) or + (left(7) and not out_alu(7)) or + (right(7) and not out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(CBIT) <= ((not left(7)) and right(7)) or + ((not left(7)) and out_alu(7)) or + (right(7) and out_alu(7)); + when alu_add16 => + cc_out(CBIT) <= (left(15) and right(15)) or + (left(15) and not out_alu(15)) or + (right(15) and not out_alu(15)); + when alu_sub16 => + cc_out(CBIT) <= ((not left(15)) and right(15)) or + ((not left(15)) and out_alu(15)) or + (right(15) and out_alu(15)); + when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 => + cc_out(CBIT) <= left(0); + when alu_rol8 | alu_asl8 => + cc_out(CBIT) <= left(7); + when alu_lsl16 => + cc_out(CBIT) <= left(15); + when alu_com => + cc_out(CBIT) <= '1'; + when alu_neg | alu_clr => + cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0); + when alu_mul => + cc_out(CBIT) <= out_alu(7); + when alu_daa => + if ( daa_reg(7 downto 4) = "0110" ) then + cc_out(CBIT) <= '1'; + else + cc_out(CBIT) <= '0'; + end if; + when alu_andcc => + cc_out(CBIT) <= left(CBIT) and cc(CBIT); + when alu_orcc => + cc_out(CBIT) <= left(CBIT) or cc(CBIT); + when alu_tfr => + cc_out(CBIT) <= left(CBIT); + when others => + cc_out(CBIT) <= cc(CBIT); + end case; + -- + -- Zero flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_inc | alu_dec | + alu_neg | alu_com | alu_clr | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_ld8 | alu_st8 | alu_sex | alu_daa => + cc_out(ZBIT) <= not( out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_add16 | alu_sub16 | alu_mul | + alu_lsl16 | alu_lsr16 | + alu_ld16 | alu_st16 | alu_lea => + cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or + out_alu(11) or out_alu(10) or out_alu(9) or out_alu(8) or + out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or + out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) ); + when alu_andcc => + cc_out(ZBIT) <= left(ZBIT) and cc(ZBIT); + when alu_orcc => + cc_out(ZBIT) <= left(ZBIT) or cc(ZBIT); + when alu_tfr => + cc_out(ZBIT) <= left(ZBIT); + when others => + cc_out(ZBIT) <= cc(ZBIT); + end case; + + -- + -- negative flag + -- + case alu_ctrl is + when alu_add8 | alu_sub8 | + alu_adc | alu_sbc | + alu_and | alu_ora | alu_eor | + alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 | + alu_inc | alu_dec | alu_neg | alu_com | alu_clr | + alu_ld8 | alu_st8 | alu_sex | alu_daa => + cc_out(NBIT) <= out_alu(7); + when alu_add16 | alu_sub16 | + alu_lsl16 | alu_lsr16 | + alu_ld16 | alu_st16 => + cc_out(NBIT) <= out_alu(15); + when alu_andcc => + cc_out(NBIT) <= left(NBIT) and cc(NBIT); + when alu_orcc => + cc_out(NBIT) <= left(NBIT) or cc(NBIT); + when alu_tfr => + cc_out(NBIT) <= left(NBIT); + when others => + cc_out(NBIT) <= cc(NBIT); + end case; + + -- + -- Interrupt mask flag + -- + case alu_ctrl is + when alu_andcc => + cc_out(IBIT) <= left(IBIT) and cc(IBIT); + when alu_orcc => + cc_out(IBIT) <= left(IBIT) or cc(IBIT); + when alu_tfr => + cc_out(IBIT) <= left(IBIT); + when alu_seif | alu_sei => + cc_out(IBIT) <= '1'; + when others => + cc_out(IBIT) <= cc(IBIT); -- interrupt mask + end case; + + -- + -- Half Carry flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(HBIT) <= (left(3) and right(3)) or + (right(3) and not out_alu(3)) or + (left(3) and not out_alu(3)); + when alu_andcc => + cc_out(HBIT) <= left(HBIT) and cc(HBIT); + when alu_orcc => + cc_out(HBIT) <= left(HBIT) or cc(HBIT); + when alu_tfr => + cc_out(HBIT) <= left(HBIT); + when others => + cc_out(HBIT) <= cc(HBIT); + end case; + + -- + -- Overflow flag + -- + case alu_ctrl is + when alu_add8 | alu_adc => + cc_out(VBIT) <= (left(7) and right(7) and (not out_alu(7))) or + ((not left(7)) and (not right(7)) and out_alu(7)); + when alu_sub8 | alu_sbc => + cc_out(VBIT) <= (left(7) and (not right(7)) and (not out_alu(7))) or + ((not left(7)) and right(7) and out_alu(7)); + when alu_add16 => + cc_out(VBIT) <= (left(15) and right(15) and (not out_alu(15))) or + ((not left(15)) and (not right(15)) and out_alu(15)); + when alu_sub16 => + cc_out(VBIT) <= (left(15) and (not right(15)) and (not out_alu(15))) or + ((not left(15)) and right(15) and out_alu(15)); + when alu_inc => + cc_out(VBIT) <= ((not left(7)) and left(6) and left(5) and left(4) and + left(3) and left(2) and left(1) and left(0)); + when alu_dec | alu_neg => + cc_out(VBIT) <= (left(7) and (not left(6)) and (not left(5)) and (not left(4)) and + (not left(3)) and (not left(2)) and (not left(1)) and (not left(0))); +-- 6809 Programming reference manual says +-- V not affected by ASR, LSR and ROR +-- This is different to the 6800 +-- John Kent 6th June 2006 +-- when alu_asr8 => +-- cc_out(VBIT) <= left(0) xor left(7); +-- when alu_lsr8 | alu_lsr16 => +-- cc_out(VBIT) <= left(0); +-- when alu_ror8 => +-- cc_out(VBIT) <= left(0) xor cc(CBIT); + when alu_lsl16 => + cc_out(VBIT) <= left(15) xor left(14); + when alu_rol8 | alu_asl8 => + cc_out(VBIT) <= left(7) xor left(6); +-- +-- 11th July 2006 - John Kent +-- What DAA does with V is anyones guess +-- It is undefined in the 6809 programming manual +-- + when alu_daa => + cc_out(VBIT) <= left(7) xor out_alu(7) xor cc(CBIT); +-- CLR resets V Bit +-- John Kent 6th June 2006 + when alu_and | alu_ora | alu_eor | alu_com | alu_clr | + alu_st8 | alu_st16 | alu_ld8 | alu_ld16 | alu_sex => + cc_out(VBIT) <= '0'; + when alu_andcc => + cc_out(VBIT) <= left(VBIT) and cc(VBIT); + when alu_orcc => + cc_out(VBIT) <= left(VBIT) or cc(VBIT); + when alu_tfr => + cc_out(VBIT) <= left(VBIT); + when others => + cc_out(VBIT) <= cc(VBIT); + end case; + + case alu_ctrl is + when alu_andcc => + cc_out(FBIT) <= left(FBIT) and cc(FBIT); + when alu_orcc => + cc_out(FBIT) <= left(FBIT) or cc(FBIT); + when alu_tfr => + cc_out(FBIT) <= left(FBIT); + when alu_seif => + cc_out(FBIT) <= '1'; + when others => + cc_out(FBIT) <= cc(FBIT); + end case; + + case alu_ctrl is + when alu_andcc => + cc_out(EBIT) <= left(EBIT) and cc(EBIT); + when alu_orcc => + cc_out(EBIT) <= left(EBIT) or cc(EBIT); + when alu_tfr => + cc_out(EBIT) <= left(EBIT); + when alu_see => + cc_out(EBIT) <= '1'; + when alu_cle => + cc_out(EBIT) <= '0'; + when others => + cc_out(EBIT) <= cc(EBIT); + end case; +end process; + +------------------------------------ +-- +-- state sequencer +-- +------------------------------------ +process( state, saved_state, + op_code, pre_code, + cc, ea, md, iv, fic, halt, + nmi_req, firq, irq, lic ) +variable cond_true : boolean; -- variable used to evaluate coditional branches +begin + cond_true := (1=1); + ba <= '0'; + bs <= '0'; + lic <= '0'; + opfetch <= '0'; + iv_ctrl <= latch_iv; + -- Registers preserved + cc_ctrl <= latch_cc; + acca_ctrl <= latch_acca; + accb_ctrl <= latch_accb; + dp_ctrl <= latch_dp; + ix_ctrl <= latch_ix; + iy_ctrl <= latch_iy; + up_ctrl <= latch_up; + sp_ctrl <= latch_sp; + pc_ctrl <= latch_pc; + md_ctrl <= latch_md; + ea_ctrl <= latch_ea; + op_ctrl <= latch_op; + pre_ctrl <= latch_pre; + -- ALU Idle + left_ctrl <= pc_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + -- Bus idle + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + -- Next State Fetch + st_ctrl <= idle_st; + return_state <= fetch_state; + next_state <= fetch_state; + + case state is + when reset_state => -- released from reset + -- reset the registers + iv_ctrl <= reset_iv; + op_ctrl <= reset_op; + pre_ctrl <= reset_pre; + cc_ctrl <= reset_cc; + acca_ctrl <= reset_acca; + accb_ctrl <= reset_accb; + dp_ctrl <= reset_dp; + ix_ctrl <= reset_ix; + iy_ctrl <= reset_iy; + up_ctrl <= reset_up; + sp_ctrl <= reset_sp; + pc_ctrl <= reset_pc; + ea_ctrl <= reset_ea; + md_ctrl <= reset_md; + st_ctrl <= reset_st; + next_state <= vect_hi_state; + + -- + -- Jump via interrupt vector + -- iv holds interrupt type + -- fetch PC hi from vector location + -- + when vect_hi_state => + -- fetch pc low interrupt vector + pc_ctrl <= pull_hi_pc; + addr_ctrl <= int_hi_ad; + bs <= '1'; + next_state <= vect_lo_state; + + -- + -- jump via interrupt vector + -- iv holds vector type + -- fetch PC lo from vector location + -- + when vect_lo_state => + -- fetch the vector low byte + pc_ctrl <= pull_lo_pc; + addr_ctrl <= int_lo_ad; + bs <= '1'; + next_state <= fetch_state; + + when vect_idle_state => + -- + -- Last Instruction Cycle for SWI, SWI2 & SWI3 + -- + if op_code = "00111111" then + lic <= '1'; + end if; + next_state <= fetch_state; + + -- + -- Here to fetch an instruction + -- PC points to opcode + -- + when fetch_state => + -- fetch the op code + opfetch <= '1'; + op_ctrl <= fetch_op; + pre_ctrl <= fetch_pre; + ea_ctrl <= reset_ea; + -- Fetch op code + addr_ctrl <= fetch_ad; + -- Advance the PC to fetch next instruction byte + pc_ctrl <= incr_pc; + next_state <= decode1_state; + + -- + -- Here to decode instruction + -- and fetch next byte of intruction + -- whether it be necessary or not + -- + when decode1_state => + -- fetch first byte of address or immediate data + ea_ctrl <= fetch_first_ea; + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + case op_code(7 downto 4) is + -- + -- direct single op (2 bytes) + -- 6809 => 6 cycles + -- cpu09 => 5 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 ea_hi=dp / ea_lo=(pc) / pc=pc+1 + -- 3 md_lo=(ea) / pc=pc + -- 4 alu_left=md / md=alu_out / pc=pc + -- 5 (ea)=md_lo / pc=pc + -- + -- Exception is JMP + -- 6809 => 3 cycles + -- cpu09 => 3 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 ea_hi=dp / ea_lo=(pc) / pc=pc+1 + -- 3 pc=ea + -- + when "0000" => + -- advance the PC + pc_ctrl <= incr_pc; + + case op_code(3 downto 0) is + when "1110" => -- jmp + next_state <= jmp_state; + + when "1111" => -- clr + next_state <= single_op_exec_state; + + when others => + next_state <= single_op_read_state; + + end case; + + -- acca / accb inherent instructions + when "0001" => + case op_code(3 downto 0) is + -- + -- Page2 pre byte + -- pre=(pc) / pc=pc+1 + -- op=(pc) / pc=pc+1 + -- + when "0000" => -- page2 + opfetch <= '1'; + op_ctrl <= fetch_op; + -- advance pc + pc_ctrl <= incr_pc; + next_state <= decode2_state; + + -- + -- Page3 pre byte + -- pre=(pc) / pc=pc+1 + -- op=(pc) / pc=pc+1 + -- + when "0001" => -- page3 + opfetch <= '1'; + op_ctrl <= fetch_op; + -- advance pc + pc_ctrl <= incr_pc; + next_state <= decode3_state; + + -- + -- nop - No operation ( 1 byte ) + -- 6809 => 2 cycles + -- cpu09 => 2 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 decode + -- + when "0010" => -- nop + lic <= '1'; + next_state <= fetch_state; + + -- + -- sync - halt execution until an interrupt is received + -- interrupt may be NMI, IRQ or FIRQ + -- program execution continues if the + -- interrupt is asserted for 3 clock cycles + -- note that registers are not pushed onto the stack + -- CPU09 => Interrupts need only be asserted for one clock cycle + -- + when "0011" => -- sync + next_state <= sync_state; + + -- + -- lbra -- long branch (3 bytes) + -- 6809 => 5 cycles + -- cpu09 => 4 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 + -- 3 md_hi=md_lo / md_lo=(pc) / pc=pc+1 + -- 4 pc=pc+md + -- + when "0110" => + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= lbranch_state; + + -- + -- lbsr - long branch to subroutine (3 bytes) + -- 6809 => 9 cycles + -- cpu09 => 6 cycles + -- 1 op=(pc) /pc=pc+1 + -- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 / sp=sp-1 + -- 3 md_hi=md_lo / md_lo=(pc) / pc=pc+1 + -- 4 (sp)= pc_lo / sp=sp-1 / pc=pc + -- 5 (sp)=pc_hi / pc=pc + -- 6 pc=pc+md + -- + when "0111" => + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= lbranch_state; + + -- + -- Decimal Adjust Accumulator + -- + when "1001" => -- daa + left_ctrl <= acca_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_daa; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + lic <= '1'; + next_state <= fetch_state; + + -- + -- OR Condition Codes + -- + when "1010" => -- orcc + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= orcc_state; + + -- + -- AND Condition Codes + -- + when "1100" => -- andcc + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= andcc_state; + + -- + -- Sign Extend + -- + when "1101" => -- sex + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_sex; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Exchange Registers + -- + when "1110" => -- exg + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= exg_state; + + -- + -- Transfer Registers + -- + when "1111" => -- tfr + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= tfr_state; + + when others => + -- increment the pc + pc_ctrl <= incr_pc; + lic <= '1'; + next_state <= fetch_state; + end case; + + -- + -- Short branch conditional + -- 6809 => always 3 cycles + -- cpu09 => always = 3 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 / test cc + -- 3 if cc tru pc=pc+md else pc=pc + -- + when "0010" => -- branch conditional + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= sbranch_state; + + -- + -- Single byte stack operators + -- Do not advance PC + -- + when "0011" => + -- + -- lea - load effective address (2+ bytes) + -- 6809 => 4 cycles + addressing mode + -- cpu09 => 4 cycles + addressing mode + -- 1 op=(pc) / pc=pc+1 + -- 2 md_lo=(pc) / pc=pc+1 + -- 3 calculate ea + -- 4 ix/iy/sp/up = ea + -- + case op_code(3 downto 0) is + when "0000" | -- leax + "0001" | -- leay + "0010" | -- leas + "0011" => -- leau + -- advance PC + pc_ctrl <= incr_pc; + st_ctrl <= push_st; + return_state <= lea_state; + next_state <= indexed_state; + + -- + -- pshs - push registers onto sp stack + -- 6809 => 5 cycles + registers + -- cpu09 => 3 cycles + registers + -- 1 op=(pc) / pc=pc+1 + -- 2 ea_lo=(pc) / pc=pc+1 + -- 3 if ea(7 downto 0) != "00000000" then sp=sp-1 + -- 4 if ea(7) = 1 (sp)=pcl, sp=sp-1 + -- 5 if ea(7) = 1 (sp)=pch + -- if ea(6 downto 0) != "0000000" then sp=sp-1 + -- 6 if ea(6) = 1 (sp)=upl, sp=sp-1 + -- 7 if ea(6) = 1 (sp)=uph + -- if ea(5 downto 0) != "000000" then sp=sp-1 + -- 8 if ea(5) = 1 (sp)=iyl, sp=sp-1 + -- 9 if ea(5) = 1 (sp)=iyh + -- if ea(4 downto 0) != "00000" then sp=sp-1 + -- 10 if ea(4) = 1 (sp)=ixl, sp=sp-1 + -- 11 if ea(4) = 1 (sp)=ixh + -- if ea(3 downto 0) != "0000" then sp=sp-1 + -- 12 if ea(3) = 1 (sp)=dp + -- if ea(2 downto 0) != "000" then sp=sp-1 + -- 13 if ea(2) = 1 (sp)=accb + -- if ea(1 downto 0) != "00" then sp=sp-1 + -- 14 if ea(1) = 1 (sp)=acca + -- if ea(0 downto 0) != "0" then sp=sp-1 + -- 15 if ea(0) = 1 (sp)=cc + -- + when "0100" => -- pshs + -- advance PC + pc_ctrl <= incr_pc; + next_state <= pshs_state; + + -- + -- puls - pull registers of sp stack + -- 6809 => 5 cycles + registers + -- cpu09 => 3 cycles + registers + -- + when "0101" => -- puls + -- advance PC + pc_ctrl <= incr_pc; + next_state <= puls_state; + + -- + -- pshu - push registers onto up stack + -- 6809 => 5 cycles + registers + -- cpu09 => 3 cycles + registers + -- + when "0110" => -- pshu + -- advance PC + pc_ctrl <= incr_pc; + next_state <= pshu_state; + + -- + -- pulu - pull registers of up stack + -- 6809 => 5 cycles + registers + -- cpu09 => 3 cycles + registers + -- + when "0111" => -- pulu + -- advance PC + pc_ctrl <= incr_pc; + next_state <= pulu_state; + + -- + -- rts - return from subroutine + -- 6809 => 5 cycles + -- cpu09 => 4 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 decode op + -- 3 pc_hi = (sp) / sp=sp+1 + -- 4 pc_lo = (sp) / sp=sp+1 + -- + when "1001" => + next_state <= pull_return_hi_state; + + -- + -- ADD accb to index register + -- *** Note: this is an unsigned addition. + -- does not affect any condition codes + -- 6809 => 3 cycles + -- cpu09 => 2 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 alu_left=ix / alu_right=accb / ix=alu_out / pc=pc + -- + when "1010" => -- abx + lic <= '1'; + left_ctrl <= ix_left; + right_ctrl <= accb_right; + alu_ctrl <= alu_abx; + ix_ctrl <= load_ix; + next_state <= fetch_state; + + -- + -- Return From Interrupt + -- + when "1011" => -- rti + next_state <= rti_cc_state; + + -- + -- CWAI + -- + when "1100" => -- cwai #$ + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- increment pc + pc_ctrl <= incr_pc; + next_state <= cwai_state; + + -- + -- MUL Multiply + -- + when "1101" => -- mul + next_state <= mul_state; + + -- + -- SWI Software Interrupt + -- + when "1111" => -- swi + -- predecrement SP + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= swi_iv; + st_ctrl <= push_st; + return_state <= int_swimask_state; + next_state <= int_entire_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + -- + -- Accumulator A Single operand + -- source = acca, dest = acca + -- Do not advance PC + -- Typically 2 cycles 1 bytes + -- 1 opcode fetch + -- 2 post byte fetch / instruction decode + -- Note that there is no post byte + -- so do not advance PC in decode cycle + -- Re-run opcode fetch cycle after decode + -- + when "0100" => -- acca single op + left_ctrl <= acca_left; + case op_code(3 downto 0) is + + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "1010" => -- dec + right_ctrl <= one_right; + alu_ctrl <= alu_dec; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + + when "1100" => -- inc + right_ctrl <= one_right; + alu_ctrl <= alu_inc; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + acca_ctrl <= latch_acca; + cc_ctrl <= load_cc; + + when "1110" => -- jmp (not defined) + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + acca_ctrl <= load_acca; + cc_ctrl <= load_cc; + + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + acca_ctrl <= latch_acca; + cc_ctrl <= latch_cc; + + end case; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Single Operand accb + -- source = accb, dest = accb + -- Typically 2 cycles 1 bytes + -- 1 opcode fetch + -- 2 post byte fetch / instruction decode + -- Note that there is no post byte + -- so do not advance PC in decode cycle + -- Re-run opcode fetch cycle after decode + -- + when "0101" => + left_ctrl <= accb_left; + case op_code(3 downto 0) is + when "0000" => -- neg + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "0011" => -- com + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "0100" => -- lsr + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "0110" => -- ror + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "0111" => -- asr + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "1000" => -- asl + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "1001" => -- rol + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "1010" => -- dec + right_ctrl <= one_right; + alu_ctrl <= alu_dec; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "1011" => -- undefined + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + + when "1100" => -- inc + right_ctrl <= one_right; + alu_ctrl <= alu_inc; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when "1101" => -- tst + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + accb_ctrl <= latch_accb; + cc_ctrl <= load_cc; + + when "1110" => -- jmp (undefined) + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + + when "1111" => -- clr + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + accb_ctrl <= load_accb; + cc_ctrl <= load_cc; + + when others => + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + accb_ctrl <= latch_accb; + cc_ctrl <= latch_cc; + end case; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Single operand indexed + -- Two byte instruction so advance PC + -- EA should hold index offset + -- + when "0110" => -- indexed single op + -- increment the pc + pc_ctrl <= incr_pc; + st_ctrl <= push_st; + + case op_code(3 downto 0) is + when "1110" => -- jmp + return_state <= jmp_state; + + when "1111" => -- clr + return_state <= single_op_exec_state; + + when others => + return_state <= single_op_read_state; + + end case; + next_state <= indexed_state; + + -- + -- Single operand extended addressing + -- three byte instruction so advance the PC + -- Low order EA holds high order address + -- + when "0111" => -- extended single op + -- increment PC + pc_ctrl <= incr_pc; + st_ctrl <= push_st; + + case op_code(3 downto 0) is + when "1110" => -- jmp + return_state <= jmp_state; + + when "1111" => -- clr + return_state <= single_op_exec_state; + + when others => + return_state <= single_op_read_state; + + end case; + next_state <= extended_state; + + when "1000" => -- acca immediate + -- increment the pc + pc_ctrl <= incr_pc; + + case op_code(3 downto 0) is + when "0011" | -- subd # + "1100" | -- cmpx # + "1110" => -- ldx # + next_state <= imm16_state; + + -- + -- bsr offset - Branch to subroutine (2 bytes) + -- 6809 => 7 cycles + -- cpu09 => 5 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 md_hi=sign(pc) / md_lo=(pc) / sp=sp-1 / pc=pc+1 + -- 3 (sp)=pc_lo / sp=sp-1 + -- 4 (sp)=pc_hi + -- 5 pc=pc+md + -- + when "1101" => -- bsr + -- pre decrement SP + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- + st_ctrl <= push_st; + return_state <= sbranch_state; + next_state <= push_return_lo_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1001" => -- acca direct + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- subd + "1100" | -- cmpx + "1110" => -- ldx + next_state <= dual_op_read16_state; + + when "0111" => -- sta direct + next_state <= dual_op_write8_state; + + -- + -- jsr direct - Jump to subroutine in direct page (2 bytes) + -- 6809 => 7 cycles + -- cpu09 => 5 cycles + -- 1 op=(pc) / pc=pc+1 + -- 2 ea_hi=0 / ea_lo=(pc) / sp=sp-1 / pc=pc+1 + -- 3 (sp)=pc_lo / sp=sp-1 + -- 4 (sp)=pc_hi + -- 5 pc=ea + -- + when "1101" => -- jsr direct + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- + st_ctrl <= push_st; + return_state <= jmp_state; + next_state <= push_return_lo_state; + + + when "1111" => -- stx direct + -- idle ALU + left_ctrl <= ix_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_nop; + cc_ctrl <= latch_cc; + sp_ctrl <= latch_sp; + next_state <= dual_op_write16_state; + + when others => + next_state <= dual_op_read8_state; + + end case; + + when "1010" => -- acca indexed + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- subd + "1100" | -- cmpx + "1110" => -- ldx + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= indexed_state; + + when "0111" => -- staa ,x + st_ctrl <= push_st; + return_state <= dual_op_write8_state; + next_state <= indexed_state; + + when "1101" => -- jsr ,x + -- DO NOT pre decrement SP + st_ctrl <= push_st; + return_state <= jsr_state; + next_state <= indexed_state; + + when "1111" => -- stx ,x + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= indexed_state; + + when others => + st_ctrl <= push_st; + return_state <= dual_op_read8_state; + next_state <= indexed_state; + + end case; + + when "1011" => -- acca extended + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- subd + "1100" | -- cmpx + "1110" => -- ldx + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= extended_state; + + when "0111" => -- staa > + st_ctrl <= push_st; + return_state <= dual_op_write8_state; + next_state <= extended_state; + + when "1101" => -- jsr >extended + -- DO NOT pre decrement sp + st_ctrl <= push_st; + return_state <= jsr_state; + next_state <= extended_state; + + when "1111" => -- stx > + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= extended_state; + + when others => + st_ctrl <= push_st; + return_state <= dual_op_read8_state; + next_state <= extended_state; + + end case; + + when "1100" => -- accb immediate + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- addd # + "1100" | -- ldd # + "1110" => -- ldu # + next_state <= imm16_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1101" => -- accb direct + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- addd + "1100" | -- ldd + "1110" => -- ldu + next_state <= dual_op_read16_state; + + when "0111" => -- stab direct + next_state <= dual_op_write8_state; + + when "1101" => -- std direct + next_state <= dual_op_write16_state; + + when "1111" => -- stu direct + next_state <= dual_op_write16_state; + + when others => + next_state <= dual_op_read8_state; + + end case; + + when "1110" => -- accb indexed + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- addd + "1100" | -- ldd + "1110" => -- ldu + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= indexed_state; + + when "0111" => -- stab indexed + st_ctrl <= push_st; + return_state <= dual_op_write8_state; + next_state <= indexed_state; + + when "1101" => -- std indexed + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= indexed_state; + + when "1111" => -- stu indexed + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= indexed_state; + + when others => + st_ctrl <= push_st; + return_state <= dual_op_read8_state; + next_state <= indexed_state; + + end case; + + when "1111" => -- accb extended + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- addd + "1100" | -- ldd + "1110" => -- ldu + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= extended_state; + + when "0111" => -- stab extended + st_ctrl <= push_st; + return_state <= dual_op_write8_state; + next_state <= extended_state; + + when "1101" => -- std extended + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= extended_state; + + when "1111" => -- stu extended + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= extended_state; + + when others => + st_ctrl <= push_st; + return_state <= dual_op_read8_state; + next_state <= extended_state; + end case; + -- + -- not sure why I need this + -- + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + -- + -- Here to decode prefix 2 instruction + -- and fetch next byte of intruction + -- whether it be necessary or not + -- + when decode2_state => + -- fetch first byte of address or immediate data + ea_ctrl <= fetch_first_ea; + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + case op_code(7 downto 4) is + -- + -- lbcc -- long branch conditional + -- 6809 => branch 6 cycles, no branch 5 cycles + -- cpu09 => always 5 cycles + -- 1 pre=(pc) / pc=pc+1 + -- 2 op=(pc) / pc=pc+1 + -- 3 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 + -- 4 md_hi=md_lo / md_lo=(pc) / pc=pc+1 + -- 5 if cond pc=pc+md else pc=pc + -- + when "0010" => + -- increment the pc + pc_ctrl <= incr_pc; + next_state <= lbranch_state; + + -- + -- Single byte stack operators + -- Do not advance PC + -- + when "0011" => + case op_code(3 downto 0) is + when "1111" => -- swi 2 + -- predecrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= swi2_iv; + st_ctrl <= push_st; + return_state <= vect_hi_state; + next_state <= int_entire_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when "1000" => -- acca immediate + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpd # + "1100" | -- cmpy # + "1110" => -- ldy # + next_state <= imm16_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1001" => -- acca direct + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpd < + "1100" | -- cmpy < + "1110" => -- ldy < + next_state <= dual_op_read16_state; + + when "1111" => -- sty < + next_state <= dual_op_write16_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1010" => -- acca indexed + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpd ,ind + "1100" | -- cmpy ,ind + "1110" => -- ldy ,ind + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= indexed_state; + + when "1111" => -- sty ,ind + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= indexed_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when "1011" => -- acca extended + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpd < + "1100" | -- cmpy < + "1110" => -- ldy < + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= extended_state; + + when "1111" => -- sty > + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= extended_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1100" => -- accb immediate + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- undef # + "1100" | -- undef # + "1110" => -- lds # + next_state <= imm16_state; + + when others => + next_state <= fetch_state; + + end case; + + when "1101" => -- accb direct + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- undef < + "1100" | -- undef < + "1110" => -- lds < + next_state <= dual_op_read16_state; + + when "1111" => -- sts < + next_state <= dual_op_write16_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1110" => -- accb indexed + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- undef ,ind + "1100" | -- undef ,ind + "1110" => -- lds ,ind + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= indexed_state; + + when "1111" => -- sts ,ind + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= indexed_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1111" => -- accb extended + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- undef > + "1100" | -- undef > + "1110" => -- lds > + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= extended_state; + + when "1111" => -- sts > + st_ctrl <= push_st; + return_state <= dual_op_write16_state; + next_state <= extended_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + -- + -- Here to decode instruction + -- and fetch next byte of intruction + -- whether it be necessary or not + -- + when decode3_state => + ea_ctrl <= fetch_first_ea; + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + dout_ctrl <= md_lo_dout; + case op_code(7 downto 4) is + -- + -- Single byte stack operators + -- Do not advance PC + -- + when "0011" => + case op_code(3 downto 0) is + when "1111" => -- swi3 + -- predecrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= swi3_iv; + st_ctrl <= push_st; + return_state <= vect_hi_state; + next_state <= int_entire_state; + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when "1000" => -- acca immediate + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpu # + "1100" | -- cmps # + "1110" => -- undef # + next_state <= imm16_state; + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when "1001" => -- acca direct + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpu < + "1100" | -- cmps < + "1110" => -- undef < + next_state <= dual_op_read16_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1010" => -- acca indexed + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpu ,X + "1100" | -- cmps ,X + "1110" => -- undef ,X + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= indexed_state; + + when others => + lic <= '1'; + next_state <= fetch_state; + + end case; + + when "1011" => -- acca extended + -- increment the pc + pc_ctrl <= incr_pc; + case op_code(3 downto 0) is + when "0011" | -- cmpu > + "1100" | -- cmps > + "1110" => -- undef > + st_ctrl <= push_st; + return_state <= dual_op_read16_state; + next_state <= extended_state; + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + + -- + -- here if ea holds low byte + -- Direct + -- Extended + -- Indexed + -- read memory location + -- + when single_op_read_state => + -- read memory into md + md_ctrl <= fetch_first_md; + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + next_state <= single_op_exec_state; + + when single_op_exec_state => + case op_code(3 downto 0) is + when "0000" => -- neg + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_neg; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "0011" => -- com + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_com; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "0100" => -- lsr + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_lsr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "0110" => -- ror + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_ror8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "0111" => -- asr + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_asr8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "1000" => -- asl + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_asl8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "1001" => -- rol + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_rol8; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "1010" => -- dec + left_ctrl <= md_left; + right_ctrl <= one_right; + alu_ctrl <= alu_dec; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "1011" => -- undefined + lic <= '1'; + next_state <= fetch_state; + when "1100" => -- inc + left_ctrl <= md_left; + right_ctrl <= one_right; + alu_ctrl <= alu_inc; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when "1101" => -- tst + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + lic <= '1'; + next_state <= fetch_state; + when "1110" => -- jmp + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_ld16; + pc_ctrl <= load_pc; + lic <= '1'; + next_state <= fetch_state; + when "1111" => -- clr + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_clr; + cc_ctrl <= load_cc; + md_ctrl <= load_md; + next_state <= single_op_write_state; + when others => + lic <= '1'; + next_state <= fetch_state; + end case; + -- + -- single operand 8 bit write + -- Write low 8 bits of ALU output + -- EA holds address + -- MD holds data + -- + when single_op_write_state => + -- write ALU low byte output + addr_ctrl <= write_ad; + dout_ctrl <= md_lo_dout; + lic <= '1'; + next_state <= fetch_state; + + -- + -- here if ea holds address of low byte + -- read memory location + -- + when dual_op_read8_state => + -- read first data byte from ea + md_ctrl <= fetch_first_md; + addr_ctrl <= read_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Here to read a 16 bit value into MD + -- pointed to by the EA register + -- The first byte is read + -- and the EA is incremented + -- + when dual_op_read16_state => + -- increment the effective address + left_ctrl <= ea_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- read the high byte of the 16 bit data + md_ctrl <= fetch_first_md; + addr_ctrl <= read_ad; + next_state <= dual_op_read16_2_state; + + -- + -- here to read the second byte + -- pointed to by EA into MD + -- + when dual_op_read16_2_state => + -- read the low byte of the 16 bit data + md_ctrl <= fetch_next_md; + addr_ctrl <= read_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- 16 bit Write state + -- EA hold address of memory to write to + -- Advance the effective address in ALU + -- decode op_code to determine which + -- register to write + -- + when dual_op_write16_state => + -- increment the effective address + left_ctrl <= ea_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- write the ALU hi byte at ea + addr_ctrl <= write_ad; + if op_code(6) = '0' then + case op_code(3 downto 0) is + when "1111" => -- stx / sty + case pre_code is + when "00010000" => -- page 2 -- sty + dout_ctrl <= iy_hi_dout; + when others => -- page 1 -- stx + dout_ctrl <= ix_hi_dout; + end case; + when others => + dout_ctrl <= md_hi_dout; + end case; + else + case op_code(3 downto 0) is + when "1101" => -- std + dout_ctrl <= acca_dout; -- acca is high byte of ACCD + when "1111" => -- stu / sts + case pre_code is + when "00010000" => -- page 2 -- sts + dout_ctrl <= sp_hi_dout; + when others => -- page 1 -- stu + dout_ctrl <= up_hi_dout; + end case; + when others => + dout_ctrl <= md_hi_dout; + end case; + end if; + next_state <= dual_op_write8_state; + + -- + -- Dual operand 8 bit write + -- Write 8 bit accumulator + -- or low byte of 16 bit register + -- EA holds address + -- decode opcode to determine + -- which register to apply to the bus + -- Also set the condition codes here + -- + when dual_op_write8_state => + if op_code(6) = '0' then + case op_code(3 downto 0) is + when "0111" => -- sta + dout_ctrl <= acca_dout; + when "1111" => -- stx / sty + case pre_code is + when "00010000" => -- page 2 -- sty + dout_ctrl <= iy_lo_dout; + when others => -- page 1 -- stx + dout_ctrl <= ix_lo_dout; + end case; + when others => + dout_ctrl <= md_lo_dout; + end case; + else + case op_code(3 downto 0) is + when "0111" => -- stb + dout_ctrl <= accb_dout; + when "1101" => -- std + dout_ctrl <= accb_dout; -- accb is low byte of accd + when "1111" => -- stu / sts + case pre_code is + when "00010000" => -- page 2 -- sts + dout_ctrl <= sp_lo_dout; + when others => -- page 1 -- stu + dout_ctrl <= up_lo_dout; + end case; + when others => + dout_ctrl <= md_lo_dout; + end case; + end if; + -- write ALU low byte output + addr_ctrl <= write_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- 16 bit immediate addressing mode + -- + when imm16_state => + -- increment pc + pc_ctrl <= incr_pc; + -- fetch next immediate byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- md & ea holds 8 bit index offset + -- calculate the effective memory address + -- using the alu + -- + when indexed_state => + -- + -- decode indexing mode + -- + if md(7) = '0' then + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= md_sign5_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + next_state <= saved_state; + + else + case md(3 downto 0) is + when "0000" => -- ,R+ + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + left_ctrl <= sp_left; + end case; + -- + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + next_state <= postincr1_state; + + when "0001" => -- ,R++ + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + next_state <= postincr2_state; + + when "0010" => -- ,-R + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + ix_ctrl <= load_ix; + when "01" => + left_ctrl <= iy_left; + iy_ctrl <= load_iy; + when "10" => + left_ctrl <= up_left; + up_ctrl <= load_up; + when others => + -- when "11" => + left_ctrl <= sp_left; + sp_ctrl <= load_sp; + end case; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + ea_ctrl <= load_ea; + next_state <= saved_state; + + when "0011" => -- ,--R + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + ix_ctrl <= load_ix; + when "01" => + left_ctrl <= iy_left; + iy_ctrl <= load_iy; + when "10" => + left_ctrl <= up_left; + up_ctrl <= load_up; + when others => + -- when "11" => + left_ctrl <= sp_left; + sp_ctrl <= load_sp; + end case; + right_ctrl <= two_right; + alu_ctrl <= alu_sub16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "0100" => -- ,R (zero offset) + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "0101" => -- ACCB,R + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= accb_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "0110" => -- ACCA,R + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= acca_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "0111" => -- undefined + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "1000" => -- offset8,R + md_ctrl <= fetch_first_md; -- pick up 8 bit offset + addr_ctrl <= fetch_ad; + pc_ctrl <= incr_pc; + next_state <= index8_state; + + when "1001" => -- offset16,R + md_ctrl <= fetch_first_md; -- pick up first byte of 16 bit offset + addr_ctrl <= fetch_ad; + pc_ctrl <= incr_pc; + next_state <= index16_state; + + when "1010" => -- undefined + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "1011" => -- ACCD,R + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= accd_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when "1100" => -- offset8,PC + -- fetch 8 bit offset + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + pc_ctrl <= incr_pc; + next_state <= pcrel8_state; + + when "1101" => -- offset16,PC + -- fetch offset + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + pc_ctrl <= incr_pc; + next_state <= pcrel16_state; + + when "1110" => -- undefined + case md(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + when others => +-- when "1111" => -- [,address] + -- advance PC to pick up address + md_ctrl <= fetch_first_md; + addr_ctrl <= fetch_ad; + pc_ctrl <= incr_pc; + next_state <= indexaddr_state; + end case; + end if; + + -- load index register with ea plus one + when postincr1_state => + left_ctrl <= ea_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + case md(6 downto 5) is + when "00" => + ix_ctrl <= load_ix; + when "01" => + iy_ctrl <= load_iy; + when "10" => + up_ctrl <= load_up; + when others => + -- when "11" => + sp_ctrl <= load_sp; + end case; + -- return to previous state + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + -- load index register with ea plus two + when postincr2_state => + -- increment register by two (address) + left_ctrl <= ea_left; + right_ctrl <= two_right; + alu_ctrl <= alu_add16; + case md(6 downto 5) is + when "00" => + ix_ctrl <= load_ix; + when "01" => + iy_ctrl <= load_iy; + when "10" => + up_ctrl <= load_up; + when others => + -- when "11" => + sp_ctrl <= load_sp; + end case; + -- return to previous state + if md(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + -- + -- ea = index register + md (8 bit signed offset) + -- ea holds post byte + -- + when index8_state => + case ea(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + -- ea = index reg + md + right_ctrl <= md_sign8_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- return to previous state + if ea(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + -- fetch low byte of 16 bit indexed offset + when index16_state => + -- advance pc + pc_ctrl <= incr_pc; + -- fetch low byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + next_state <= index16_2_state; + + -- ea = index register + md (16 bit offset) + -- ea holds post byte + when index16_2_state => + case ea(6 downto 5) is + when "00" => + left_ctrl <= ix_left; + when "01" => + left_ctrl <= iy_left; + when "10" => + left_ctrl <= up_left; + when others => + -- when "11" => + left_ctrl <= sp_left; + end case; + -- ea = index reg + md + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- return to previous state + if ea(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + -- + -- pc relative with 8 bit signed offest + -- md holds signed offset + -- + when pcrel8_state => + -- ea = pc + signed md + left_ctrl <= pc_left; + right_ctrl <= md_sign8_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- return to previous state + if ea(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + -- pc relative addressing with 16 bit offset + -- pick up the low byte of the offset in md + -- advance the pc + when pcrel16_state => + -- advance pc + pc_ctrl <= incr_pc; + -- fetch low byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + next_state <= pcrel16_2_state; + + -- pc relative with16 bit signed offest + -- md holds signed offset + when pcrel16_2_state => + -- ea = pc + md + left_ctrl <= pc_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- return to previous state + if ea(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + -- indexed to address + -- pick up the low byte of the address + -- advance the pc + when indexaddr_state => + -- advance pc + pc_ctrl <= incr_pc; + -- fetch low byte + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + next_state <= indexaddr2_state; + + -- indexed to absolute address + -- md holds address + -- ea hold indexing mode byte + when indexaddr2_state => + -- ea = md + left_ctrl <= pc_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + ea_ctrl <= load_ea; + -- return to previous state + if ea(4) = '0' then + next_state <= saved_state; + else + next_state <= indirect_state; + end if; + + -- + -- load md with high byte of indirect address + -- pointed to by ea + -- increment ea + -- + when indirect_state => + -- increment ea + left_ctrl <= ea_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + ea_ctrl <= load_ea; + -- fetch high byte + md_ctrl <= fetch_first_md; + addr_ctrl <= read_ad; + next_state <= indirect2_state; + -- + -- load md with low byte of indirect address + -- pointed to by ea + -- ea has previously been incremented + -- + when indirect2_state => + -- fetch high byte + md_ctrl <= fetch_next_md; + addr_ctrl <= read_ad; + dout_ctrl <= md_lo_dout; + next_state <= indirect3_state; + -- + -- complete idirect addressing + -- by loading ea with md + -- + when indirect3_state => + -- load ea with md + left_ctrl <= ea_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + ea_ctrl <= load_ea; + -- return to previous state + next_state <= saved_state; + + -- + -- ea holds the low byte of the absolute address + -- Move ea low byte into ea high byte + -- load new ea low byte to for absolute 16 bit address + -- advance the program counter + -- + when extended_state => -- fetch ea low byte + -- increment pc + pc_ctrl <= incr_pc; + -- fetch next effective address bytes + ea_ctrl <= fetch_next_ea; + addr_ctrl <= fetch_ad; + -- return to previous state + next_state <= saved_state; + + when lea_state => -- here on load effective address + -- load index register with effective address + left_ctrl <= pc_left; + right_ctrl <= ea_right; + alu_ctrl <= alu_lea; + case op_code(3 downto 0) is + when "0000" => -- leax + cc_ctrl <= load_cc; + ix_ctrl <= load_ix; + when "0001" => -- leay + cc_ctrl <= load_cc; + iy_ctrl <= load_iy; + when "0010" => -- leas + sp_ctrl <= load_sp; + when "0011" => -- leau + up_ctrl <= load_up; + when others => + null; + end case; + lic <= '1'; + next_state <= fetch_state; + + -- + -- jump to subroutine + -- sp=sp-1 + -- call push_return_lo_state to save pc + -- return to jmp_state + -- + when jsr_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- call push_return_state + st_ctrl <= push_st; + return_state <= jmp_state; + next_state <= push_return_lo_state; + + -- + -- Load pc with ea + -- (JMP) + -- + when jmp_state => + -- load PC with effective address + left_ctrl <= pc_left; + right_ctrl <= ea_right; + alu_ctrl <= alu_ld16; + pc_ctrl <= load_pc; + lic <= '1'; + next_state <= fetch_state; + + -- + -- long branch or branch to subroutine + -- pick up next md byte + -- md_hi = md_lo + -- md_lo = (pc) + -- pc=pc+1 + -- if a lbsr push return address + -- continue to sbranch_state + -- to evaluate conditional branches + -- + when lbranch_state => + pc_ctrl <= incr_pc; + -- fetch the next byte into md_lo + md_ctrl <= fetch_next_md; + addr_ctrl <= fetch_ad; + -- if lbsr - push return address + -- then continue on to short branch + if op_code = "00010111" then + st_ctrl <= push_st; + return_state <= sbranch_state; + next_state <= push_return_lo_state; + else + next_state <= sbranch_state; + end if; + + -- + -- here to execute conditional branch + -- short conditional branch md = signed 8 bit offset + -- long branch md = 16 bit offset + -- + when sbranch_state => + left_ctrl <= pc_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + -- Test condition for branch + if op_code(7 downto 4) = "0010" then -- conditional branch + case op_code(3 downto 0) is + when "0000" => -- bra + cond_true := (1 = 1); + when "0001" => -- brn + cond_true := (1 = 0); + when "0010" => -- bhi + cond_true := ((cc(CBIT) or cc(ZBIT)) = '0'); + when "0011" => -- bls + cond_true := ((cc(CBIT) or cc(ZBIT)) = '1'); + when "0100" => -- bcc/bhs + cond_true := (cc(CBIT) = '0'); + when "0101" => -- bcs/blo + cond_true := (cc(CBIT) = '1'); + when "0110" => -- bne + cond_true := (cc(ZBIT) = '0'); + when "0111" => -- beq + cond_true := (cc(ZBIT) = '1'); + when "1000" => -- bvc + cond_true := (cc(VBIT) = '0'); + when "1001" => -- bvs + cond_true := (cc(VBIT) = '1'); + when "1010" => -- bpl + cond_true := (cc(NBIT) = '0'); + when "1011" => -- bmi + cond_true := (cc(NBIT) = '1'); + when "1100" => -- bge + cond_true := ((cc(NBIT) xor cc(VBIT)) = '0'); + when "1101" => -- blt + cond_true := ((cc(NBIT) xor cc(VBIT)) = '1'); + when "1110" => -- bgt + cond_true := ((cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '0'); + when "1111" => -- ble + cond_true := ((cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '1'); + when others => + null; + end case; + end if; + if cond_true then + pc_ctrl <= load_pc; + end if; + lic <= '1'; + next_state <= fetch_state; + + -- + -- push return address onto the S stack + -- + -- (sp) = pc_lo + -- sp = sp - 1 + -- + when push_return_lo_state => + -- decrement the sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write PC low + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_lo_dout; + next_state <= push_return_hi_state; + + -- + -- push program counter hi byte onto the stack + -- (sp) = pc_hi + -- sp = sp + -- return to originating state + -- + when push_return_hi_state => + -- write pc hi bytes + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_hi_dout; + next_state <= saved_state; + + -- + -- RTS pull return address from stack + -- + when pull_return_hi_state => + -- increment the sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pulls_ad; + next_state <= pull_return_lo_state; + + when pull_return_lo_state => + -- increment the SP + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pulls_ad; + dout_ctrl <= pc_lo_dout; + -- + lic <= '1'; + next_state <= fetch_state; + + when andcc_state => + -- AND CC with md + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_andcc; + cc_ctrl <= load_cc; + -- + lic <= '1'; + next_state <= fetch_state; + + when orcc_state => + -- OR CC with md + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_orcc; + cc_ctrl <= load_cc; + -- + lic <= '1'; + next_state <= fetch_state; + + when tfr_state => + -- select source register + case md(7 downto 4) is + when "0000" => + left_ctrl <= accd_left; + when "0001" => + left_ctrl <= ix_left; + when "0010" => + left_ctrl <= iy_left; + when "0011" => + left_ctrl <= up_left; + when "0100" => + left_ctrl <= sp_left; + when "0101" => + left_ctrl <= pc_left; + when "1000" => + left_ctrl <= acca_left; + when "1001" => + left_ctrl <= accb_left; + when "1010" => + left_ctrl <= cc_left; + when "1011" => + left_ctrl <= dp_left; + when others => + left_ctrl <= md_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_tfr; + -- select destination register + case md(3 downto 0) is + when "0000" => -- accd + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + when "0001" => -- ix + ix_ctrl <= load_ix; + when "0010" => -- iy + iy_ctrl <= load_iy; + when "0011" => -- up + up_ctrl <= load_up; + when "0100" => -- sp + sp_ctrl <= load_sp; + when "0101" => -- pc + pc_ctrl <= load_pc; + when "1000" => -- acca + acca_ctrl <= load_acca; + when "1001" => -- accb + accb_ctrl <= load_accb; + when "1010" => -- cc + cc_ctrl <= load_cc; + when "1011" => --dp + dp_ctrl <= load_dp; + when others => + null; + end case; + -- + lic <= '1'; + next_state <= fetch_state; + + when exg_state => + -- save destination register + case md(3 downto 0) is + when "0000" => + left_ctrl <= accd_left; + when "0001" => + left_ctrl <= ix_left; + when "0010" => + left_ctrl <= iy_left; + when "0011" => + left_ctrl <= up_left; + when "0100" => + left_ctrl <= sp_left; + when "0101" => + left_ctrl <= pc_left; + when "1000" => + left_ctrl <= acca_left; + when "1001" => + left_ctrl <= accb_left; + when "1010" => + left_ctrl <= cc_left; + when "1011" => + left_ctrl <= dp_left; + when others => + left_ctrl <= md_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_tfr; + ea_ctrl <= load_ea; + -- call tranfer microcode + next_state <= exg1_state; + + when exg1_state => + -- select source register + case md(7 downto 4) is + when "0000" => + left_ctrl <= accd_left; + when "0001" => + left_ctrl <= ix_left; + when "0010" => + left_ctrl <= iy_left; + when "0011" => + left_ctrl <= up_left; + when "0100" => + left_ctrl <= sp_left; + when "0101" => + left_ctrl <= pc_left; + when "1000" => + left_ctrl <= acca_left; + when "1001" => + left_ctrl <= accb_left; + when "1010" => + left_ctrl <= cc_left; + when "1011" => + left_ctrl <= dp_left; + when others => + left_ctrl <= md_left; + end case; + right_ctrl <= zero_right; + alu_ctrl <= alu_tfr; + -- select destination register + case md(3 downto 0) is + when "0000" => -- accd + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + when "0001" => -- ix + ix_ctrl <= load_ix; + when "0010" => -- iy + iy_ctrl <= load_iy; + when "0011" => -- up + up_ctrl <= load_up; + when "0100" => -- sp + sp_ctrl <= load_sp; + when "0101" => -- pc + pc_ctrl <= load_pc; + when "1000" => -- acca + acca_ctrl <= load_acca; + when "1001" => -- accb + accb_ctrl <= load_accb; + when "1010" => -- cc + cc_ctrl <= load_cc; + when "1011" => --dp + dp_ctrl <= load_dp; + when others => + null; + end case; + next_state <= exg2_state; + + when exg2_state => + -- restore destination + left_ctrl <= ea_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_tfr; + -- save as source register + case md(7 downto 4) is + when "0000" => -- accd + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + when "0001" => -- ix + ix_ctrl <= load_ix; + when "0010" => -- iy + iy_ctrl <= load_iy; + when "0011" => -- up + up_ctrl <= load_up; + when "0100" => -- sp + sp_ctrl <= load_sp; + when "0101" => -- pc + pc_ctrl <= load_pc; + when "1000" => -- acca + acca_ctrl <= load_acca; + when "1001" => -- accb + accb_ctrl <= load_accb; + when "1010" => -- cc + cc_ctrl <= load_cc; + when "1011" => --dp + dp_ctrl <= load_dp; + when others => + null; + end case; + lic <= '1'; + next_state <= fetch_state; + + when mul_state => + -- move acca to md + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + md_ctrl <= load_md; + next_state <= mulea_state; + + when mulea_state => + -- move accb to ea + left_ctrl <= accb_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_st16; + ea_ctrl <= load_ea; + next_state <= muld_state; + + when muld_state => + -- clear accd + left_ctrl <= acca_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_ld8; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + next_state <= mul0_state; + + when mul0_state => + -- if bit 0 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(0) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul1_state; + + when mul1_state => + -- if bit 1 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(1) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul2_state; + + when mul2_state => + -- if bit 2 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(2) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul3_state; + + when mul3_state => + -- if bit 3 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(3) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul4_state; + + when mul4_state => + -- if bit 4 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(4) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul5_state; + + when mul5_state => + -- if bit 5 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(5) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul6_state; + + when mul6_state => + -- if bit 6 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(6) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + next_state <= mul7_state; + + when mul7_state => + -- if bit 7 of ea set, add accd to md + left_ctrl <= accd_left; + if ea(7) = '1' then + right_ctrl <= md_right; + else + right_ctrl <= zero_right; + end if; + alu_ctrl <= alu_mul; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + md_ctrl <= shiftl_md; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Enter here on pushs + -- ea holds post byte + -- + when pshs_state => + -- decrement sp if any registers to be pushed + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + -- idle address + addr_ctrl <= idle_ad; + dout_ctrl <= cc_dout; + if ea(7 downto 0) = "00000000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + if ea(7) = '1' then + next_state <= pshs_pcl_state; + elsif ea(6) = '1' then + next_state <= pshs_upl_state; + elsif ea(5) = '1' then + next_state <= pshs_iyl_state; + elsif ea(4) = '1' then + next_state <= pshs_ixl_state; + elsif ea(3) = '1' then + next_state <= pshs_dp_state; + elsif ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_pcl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_lo_dout; + next_state <= pshs_pch_state; + + when pshs_pch_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(6 downto 0) = "0000000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write pc hi + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_hi_dout; + if ea(6) = '1' then + next_state <= pshs_upl_state; + elsif ea(5) = '1' then + next_state <= pshs_iyl_state; + elsif ea(4) = '1' then + next_state <= pshs_ixl_state; + elsif ea(3) = '1' then + next_state <= pshs_dp_state; + elsif ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + + when pshs_upl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= pushs_ad; + dout_ctrl <= up_lo_dout; + next_state <= pshs_uph_state; + + when pshs_uph_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(5 downto 0) = "000000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write pc hi + addr_ctrl <= pushs_ad; + dout_ctrl <= up_hi_dout; + if ea(5) = '1' then + next_state <= pshs_iyl_state; + elsif ea(4) = '1' then + next_state <= pshs_ixl_state; + elsif ea(3) = '1' then + next_state <= pshs_dp_state; + elsif ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_iyl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write iy low + addr_ctrl <= pushs_ad; + dout_ctrl <= iy_lo_dout; + next_state <= pshs_iyh_state; + + when pshs_iyh_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(4 downto 0) = "00000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write iy hi + addr_ctrl <= pushs_ad; + dout_ctrl <= iy_hi_dout; + if ea(4) = '1' then + next_state <= pshs_ixl_state; + elsif ea(3) = '1' then + next_state <= pshs_dp_state; + elsif ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_ixl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= pushs_ad; + dout_ctrl <= ix_lo_dout; + next_state <= pshs_ixh_state; + + when pshs_ixh_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(3 downto 0) = "0000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write ix hi + addr_ctrl <= pushs_ad; + dout_ctrl <= ix_hi_dout; + if ea(3) = '1' then + next_state <= pshs_dp_state; + elsif ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_dp_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(2 downto 0) = "000" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write dp + addr_ctrl <= pushs_ad; + dout_ctrl <= dp_dout; + if ea(2) = '1' then + next_state <= pshs_accb_state; + elsif ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_accb_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(1 downto 0) = "00" then + sp_ctrl <= latch_sp; + else + sp_ctrl <= load_sp; + end if; + -- write accb + addr_ctrl <= pushs_ad; + dout_ctrl <= accb_dout; + if ea(1) = '1' then + next_state <= pshs_acca_state; + elsif ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_acca_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(0) = '1' then + sp_ctrl <= load_sp; + else + sp_ctrl <= latch_sp; + end if; + -- write acca + addr_ctrl <= pushs_ad; + dout_ctrl <= acca_dout; + if ea(0) = '1' then + next_state <= pshs_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshs_cc_state => + -- idle sp + -- write cc + addr_ctrl <= pushs_ad; + dout_ctrl <= cc_dout; + lic <= '1'; + next_state <= fetch_state; + + -- + -- enter here on PULS + -- ea hold register mask + -- + when puls_state => + if ea(0) = '1' then + next_state <= puls_cc_state; + elsif ea(1) = '1' then + next_state <= puls_acca_state; + elsif ea(2) = '1' then + next_state <= puls_accb_state; + elsif ea(3) = '1' then + next_state <= puls_dp_state; + elsif ea(4) = '1' then + next_state <= puls_ixh_state; + elsif ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_cc_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read cc + cc_ctrl <= pull_cc; + addr_ctrl <= pulls_ad; + if ea(1) = '1' then + next_state <= puls_acca_state; + elsif ea(2) = '1' then + next_state <= puls_accb_state; + elsif ea(3) = '1' then + next_state <= puls_dp_state; + elsif ea(4) = '1' then + next_state <= puls_ixh_state; + elsif ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_acca_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pulls_ad; + if ea(2) = '1' then + next_state <= puls_accb_state; + elsif ea(3) = '1' then + next_state <= puls_dp_state; + elsif ea(4) = '1' then + next_state <= puls_ixh_state; + elsif ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_accb_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pulls_ad; + if ea(3) = '1' then + next_state <= puls_dp_state; + elsif ea(4) = '1' then + next_state <= puls_ixh_state; + elsif ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_dp_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read dp + dp_ctrl <= pull_dp; + addr_ctrl <= pulls_ad; + if ea(4) = '1' then + next_state <= puls_ixh_state; + elsif ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_ixh_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pulls_ad; + next_state <= puls_ixl_state; + + when puls_ixl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pulls_ad; + if ea(5) = '1' then + next_state <= puls_iyh_state; + elsif ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_iyh_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull iy hi + iy_ctrl <= pull_hi_iy; + addr_ctrl <= pulls_ad; + next_state <= puls_iyl_state; + + when puls_iyl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read iy low + iy_ctrl <= pull_lo_iy; + addr_ctrl <= pulls_ad; + if ea(6) = '1' then + next_state <= puls_uph_state; + elsif ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_uph_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull up hi + up_ctrl <= pull_hi_up; + addr_ctrl <= pulls_ad; + next_state <= puls_upl_state; + + when puls_upl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read up low + up_ctrl <= pull_lo_up; + addr_ctrl <= pulls_ad; + if ea(7) = '1' then + next_state <= puls_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when puls_pch_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pulls_ad; + next_state <= puls_pcl_state; + + when puls_pcl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pulls_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- Enter here on pshu + -- ea holds post byte + -- + when pshu_state => + -- decrement up if any registers to be pushed + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(7 downto 0) = "00000000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write idle bus + if ea(7) = '1' then + next_state <= pshu_pcl_state; + elsif ea(6) = '1' then + next_state <= pshu_spl_state; + elsif ea(5) = '1' then + next_state <= pshu_iyl_state; + elsif ea(4) = '1' then + next_state <= pshu_ixl_state; + elsif ea(3) = '1' then + next_state <= pshu_dp_state; + elsif ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + -- + -- push PC onto U stack + -- + when pshu_pcl_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + up_ctrl <= load_up; + -- write pc low + addr_ctrl <= pushu_ad; + dout_ctrl <= pc_lo_dout; + next_state <= pshu_pch_state; + + when pshu_pch_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(6 downto 0) = "0000000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write pc hi + addr_ctrl <= pushu_ad; + dout_ctrl <= pc_hi_dout; + if ea(6) = '1' then + next_state <= pshu_spl_state; + elsif ea(5) = '1' then + next_state <= pshu_iyl_state; + elsif ea(4) = '1' then + next_state <= pshu_ixl_state; + elsif ea(3) = '1' then + next_state <= pshu_dp_state; + elsif ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_spl_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + up_ctrl <= load_up; + -- write sp low + addr_ctrl <= pushu_ad; + dout_ctrl <= sp_lo_dout; + next_state <= pshu_sph_state; + + when pshu_sph_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(5 downto 0) = "000000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write sp hi + addr_ctrl <= pushu_ad; + dout_ctrl <= sp_hi_dout; + if ea(5) = '1' then + next_state <= pshu_iyl_state; + elsif ea(4) = '1' then + next_state <= pshu_ixl_state; + elsif ea(3) = '1' then + next_state <= pshu_dp_state; + elsif ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_iyl_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + up_ctrl <= load_up; + -- write iy low + addr_ctrl <= pushu_ad; + dout_ctrl <= iy_lo_dout; + next_state <= pshu_iyh_state; + + when pshu_iyh_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(4 downto 0) = "00000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write iy hi + addr_ctrl <= pushu_ad; + dout_ctrl <= iy_hi_dout; + if ea(4) = '1' then + next_state <= pshu_ixl_state; + elsif ea(3) = '1' then + next_state <= pshu_dp_state; + elsif ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_ixl_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + up_ctrl <= load_up; + -- write ix low + addr_ctrl <= pushu_ad; + dout_ctrl <= ix_lo_dout; + next_state <= pshu_ixh_state; + + when pshu_ixh_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(3 downto 0) = "0000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write ix hi + addr_ctrl <= pushu_ad; + dout_ctrl <= ix_hi_dout; + if ea(3) = '1' then + next_state <= pshu_dp_state; + elsif ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_dp_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(2 downto 0) = "000" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write dp + addr_ctrl <= pushu_ad; + dout_ctrl <= dp_dout; + if ea(2) = '1' then + next_state <= pshu_accb_state; + elsif ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_accb_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(1 downto 0) = "00" then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write accb + addr_ctrl <= pushu_ad; + dout_ctrl <= accb_dout; + if ea(1) = '1' then + next_state <= pshu_acca_state; + elsif ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_acca_state => + -- decrement up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + if ea(0) = '0' then + up_ctrl <= latch_up; + else + up_ctrl <= load_up; + end if; + -- write acca + addr_ctrl <= pushu_ad; + dout_ctrl <= acca_dout; + if ea(0) = '1' then + next_state <= pshu_cc_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pshu_cc_state => + -- idle up + -- write cc + addr_ctrl <= pushu_ad; + dout_ctrl <= cc_dout; + lic <= '1'; + next_state <= fetch_state; + + -- + -- enter here on PULU + -- ea hold register mask + -- + when pulu_state => + -- idle UP + -- idle bus + if ea(0) = '1' then + next_state <= pulu_cc_state; + elsif ea(1) = '1' then + next_state <= pulu_acca_state; + elsif ea(2) = '1' then + next_state <= pulu_accb_state; + elsif ea(3) = '1' then + next_state <= pulu_dp_state; + elsif ea(4) = '1' then + next_state <= pulu_ixh_state; + elsif ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_cc_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read cc + cc_ctrl <= pull_cc; + addr_ctrl <= pullu_ad; + if ea(1) = '1' then + next_state <= pulu_acca_state; + elsif ea(2) = '1' then + next_state <= pulu_accb_state; + elsif ea(3) = '1' then + next_state <= pulu_dp_state; + elsif ea(4) = '1' then + next_state <= pulu_ixh_state; + elsif ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_acca_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pullu_ad; + if ea(2) = '1' then + next_state <= pulu_accb_state; + elsif ea(3) = '1' then + next_state <= pulu_dp_state; + elsif ea(4) = '1' then + next_state <= pulu_ixh_state; + elsif ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_accb_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pullu_ad; + if ea(3) = '1' then + next_state <= pulu_dp_state; + elsif ea(4) = '1' then + next_state <= pulu_ixh_state; + elsif ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_dp_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read dp + dp_ctrl <= pull_dp; + addr_ctrl <= pullu_ad; + if ea(4) = '1' then + next_state <= pulu_ixh_state; + elsif ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_ixh_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pullu_ad; + next_state <= pulu_ixl_state; + + when pulu_ixl_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pullu_ad; + if ea(5) = '1' then + next_state <= pulu_iyh_state; + elsif ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_iyh_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read iy hi + iy_ctrl <= pull_hi_iy; + addr_ctrl <= pullu_ad; + next_state <= pulu_iyl_state; + + when pulu_iyl_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read iy low + iy_ctrl <= pull_lo_iy; + addr_ctrl <= pullu_ad; + if ea(6) = '1' then + next_state <= pulu_sph_state; + elsif ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_sph_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read sp hi + sp_ctrl <= pull_hi_sp; + addr_ctrl <= pullu_ad; + next_state <= pulu_spl_state; + + when pulu_spl_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read sp low + sp_ctrl <= pull_lo_sp; + addr_ctrl <= pullu_ad; + if ea(7) = '1' then + next_state <= pulu_pch_state; + else + lic <= '1'; + next_state <= fetch_state; + end if; + + when pulu_pch_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- pull pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pullu_ad; + next_state <= pulu_pcl_state; + + when pulu_pcl_state => + -- increment up + left_ctrl <= up_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + up_ctrl <= load_up; + -- read pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pullu_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- pop the Condition codes + -- + when rti_cc_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read cc + cc_ctrl <= pull_cc; + addr_ctrl <= pulls_ad; + next_state <= rti_entire_state; + + -- + -- Added RTI cycle 11th July 2006 John Kent. + -- test the "Entire" Flag + -- that has just been popped off the stack + -- + when rti_entire_state => + -- + -- The Entire flag must be recovered from the stack + -- before testing. + -- + if cc(EBIT) = '1' then + next_state <= rti_acca_state; + else + next_state <= rti_pch_state; + end if; + + when rti_acca_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read acca + acca_ctrl <= pull_acca; + addr_ctrl <= pulls_ad; + next_state <= rti_accb_state; + + when rti_accb_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read accb + accb_ctrl <= pull_accb; + addr_ctrl <= pulls_ad; + next_state <= rti_dp_state; + + when rti_dp_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read dp + dp_ctrl <= pull_dp; + addr_ctrl <= pulls_ad; + next_state <= rti_ixh_state; + + when rti_ixh_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read ix hi + ix_ctrl <= pull_hi_ix; + addr_ctrl <= pulls_ad; + next_state <= rti_ixl_state; + + when rti_ixl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read ix low + ix_ctrl <= pull_lo_ix; + addr_ctrl <= pulls_ad; + next_state <= rti_iyh_state; + + when rti_iyh_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read iy hi + iy_ctrl <= pull_hi_iy; + addr_ctrl <= pulls_ad; + next_state <= rti_iyl_state; + + when rti_iyl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read iy low + iy_ctrl <= pull_lo_iy; + addr_ctrl <= pulls_ad; + next_state <= rti_uph_state; + + + when rti_uph_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read up hi + up_ctrl <= pull_hi_up; + addr_ctrl <= pulls_ad; + next_state <= rti_upl_state; + + when rti_upl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- read up low + up_ctrl <= pull_lo_up; + addr_ctrl <= pulls_ad; + next_state <= rti_pch_state; + + when rti_pch_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull pc hi + pc_ctrl <= pull_hi_pc; + addr_ctrl <= pulls_ad; + next_state <= rti_pcl_state; + + when rti_pcl_state => + -- increment sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_add16; + sp_ctrl <= load_sp; + -- pull pc low + pc_ctrl <= pull_lo_pc; + addr_ctrl <= pulls_ad; + lic <= '1'; + next_state <= fetch_state; + + -- + -- here on NMI interrupt + -- Complete execute cycle of the last instruction. + -- If it was a dual operand instruction + -- + when int_nmi_state => + next_state <= int_nmi1_state; + + -- Idle bus cycle + when int_nmi1_state => + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= nmi_iv; + st_ctrl <= push_st; + return_state <= int_nmimask_state; + next_state <= int_entire_state; + + -- + -- here on IRQ interrupt + -- Complete execute cycle of the last instruction. + -- If it was a dual operand instruction + -- + when int_irq_state => + next_state <= int_irq1_state; + + -- pre decrement the sp + -- Idle bus cycle + when int_irq1_state => + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= irq_iv; + st_ctrl <= push_st; + return_state <= int_irqmask_state; + next_state <= int_entire_state; + + -- + -- here on FIRQ interrupt + -- Complete execution cycle of the last instruction + -- if it was a dual operand instruction + -- + when int_firq_state => + next_state <= int_firq1_state; + + -- Idle bus cycle + when int_firq1_state => + -- pre decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + iv_ctrl <= firq_iv; + st_ctrl <= push_st; + return_state <= int_firqmask_state; + next_state <= int_fast_state; + + -- + -- CWAI entry point + -- stack pointer already pre-decremented + -- mask condition codes + -- + when cwai_state => + -- AND CC with md + left_ctrl <= md_left; + right_ctrl <= zero_right; + alu_ctrl <= alu_andcc; + cc_ctrl <= load_cc; + st_ctrl <= push_st; + return_state <= int_cwai_state; + next_state <= int_entire_state; + + -- + -- wait here for an interrupt + -- + when int_cwai_state => + if (nmi_req = '1') then + iv_ctrl <= nmi_iv; + next_state <= int_nmimask_state; + -- + -- FIRQ & IRQ are level sensitive + -- + elsif (firq = '1') and (cc(FBIT) = '0') then + iv_ctrl <= firq_iv; + next_state <= int_firqmask_state; + + elsif (irq = '1') and (cc(IBIT) = '0') then + iv_ctrl <= irq_iv; + next_state <= int_irqmask_state; + else + next_state <= int_cwai_state; + end if; + + -- + -- State to mask I Flag and F Flag (NMI) + -- + when int_nmimask_state => + alu_ctrl <= alu_seif; + cc_ctrl <= load_cc; + next_state <= vect_hi_state; + + -- + -- State to mask I Flag and F Flag (FIRQ) + -- + when int_firqmask_state => + alu_ctrl <= alu_seif; + cc_ctrl <= load_cc; + next_state <= vect_hi_state; + + + -- + -- State to mask I Flag and F Flag (SWI) + -- + when int_swimask_state => + alu_ctrl <= alu_seif; + cc_ctrl <= load_cc; + next_state <= vect_hi_state; + + -- + -- State to mask I Flag only (IRQ) + -- + when int_irqmask_state => + alu_ctrl <= alu_sei; + cc_ctrl <= load_cc; + next_state <= vect_hi_state; + + -- + -- set Entire Flag on SWI, SWI2, SWI3 and CWAI, IRQ and NMI + -- before stacking all registers + -- + when int_entire_state => + -- set entire flag + alu_ctrl <= alu_see; + cc_ctrl <= load_cc; + next_state <= int_pcl_state; + + -- + -- clear Entire Flag on FIRQ + -- before stacking all registers + -- + when int_fast_state => + -- clear entire flag + alu_ctrl <= alu_cle; + cc_ctrl <= load_cc; + next_state <= int_pcl_state; + + when int_pcl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write pc low + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_lo_dout; + next_state <= int_pch_state; + + when int_pch_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write pc hi + addr_ctrl <= pushs_ad; + dout_ctrl <= pc_hi_dout; + if cc(EBIT) = '1' then + next_state <= int_upl_state; + else + next_state <= int_cc_state; + end if; + + when int_upl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write up low + addr_ctrl <= pushs_ad; + dout_ctrl <= up_lo_dout; + next_state <= int_uph_state; + + when int_uph_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= pushs_ad; + dout_ctrl <= up_hi_dout; + next_state <= int_iyl_state; + + when int_iyl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= pushs_ad; + dout_ctrl <= iy_lo_dout; + next_state <= int_iyh_state; + + when int_iyh_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= pushs_ad; + dout_ctrl <= iy_hi_dout; + next_state <= int_ixl_state; + + when int_ixl_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix low + addr_ctrl <= pushs_ad; + dout_ctrl <= ix_lo_dout; + next_state <= int_ixh_state; + + when int_ixh_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write ix hi + addr_ctrl <= pushs_ad; + dout_ctrl <= ix_hi_dout; + next_state <= int_dp_state; + + when int_dp_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= pushs_ad; + dout_ctrl <= dp_dout; + next_state <= int_accb_state; + + when int_accb_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write accb + addr_ctrl <= pushs_ad; + dout_ctrl <= accb_dout; + next_state <= int_acca_state; + + when int_acca_state => + -- decrement sp + left_ctrl <= sp_left; + right_ctrl <= one_right; + alu_ctrl <= alu_sub16; + sp_ctrl <= load_sp; + -- write acca + addr_ctrl <= pushs_ad; + dout_ctrl <= acca_dout; + next_state <= int_cc_state; + + when int_cc_state => + -- write cc + addr_ctrl <= pushs_ad; + dout_ctrl <= cc_dout; + next_state <= saved_state; + + -- + -- According to the 6809 programming manual: + -- If an interrupt is received and is masked + -- or lasts for less than three cycles, the PC + -- will advance to the next instruction. + -- If an interrupt is unmasked and lasts + -- for more than three cycles, an interrupt + -- will be generated. + -- Note that I don't wait 3 clock cycles. + -- John Kent 11th July 2006 + -- + when sync_state => + lic <= '1'; + ba <= '1'; + -- + -- Version 1.28 2015-05-30 + -- Exit sync_state on interrupt. + -- If the interrupts are active + -- they will be caught in the state_machine process + -- and the interrupt service routine microcode will be executed. + -- Masked interrupts will exit the sync_state. + -- Moved from the state_machine process to the state_sequencer process + -- + if (firq = '1') or (irq = '1') then + next_state <= fetch_state; + else + next_state <= sync_state; + end if; + + when halt_state => + -- + -- 2011-10-30 John Kent + -- ba & bs should be high + ba <= '1'; + bs <= '1'; + if halt = '1' then + next_state <= halt_state; + else + next_state <= fetch_state; + end if; + + end case; + +-- +-- Ver 1.23 2011-10-30 John Kent +-- First instruction cycle might be +-- fetch_state +-- halt_state +-- int_nmirq_state +-- int_firq_state +-- + if fic = '1' then + -- + case op_code(7 downto 6) is + when "10" => -- acca + case op_code(3 downto 0) is + when "0000" => -- suba + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "0001" => -- cmpa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + when "0010" => -- sbca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "0011" => + case pre_code is + when "00010000" => -- page 2 -- cmpd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + when "00010001" => -- page 3 -- cmpu + left_ctrl <= up_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + when others => -- page 1 -- subd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + end case; + when "0100" => -- anda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "0101" => -- bita + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + when "0110" => -- ldaa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "0111" => -- staa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + when "1000" => -- eora + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "1001" => -- adca + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "1010" => -- oraa + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "1011" => -- adda + left_ctrl <= acca_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + acca_ctrl <= load_acca; + when "1100" => + case pre_code is + when "00010000" => -- page 2 -- cmpy + left_ctrl <= iy_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + when "00010001" => -- page 3 -- cmps + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + when others => -- page 1 -- cmpx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub16; + cc_ctrl <= load_cc; + end case; + when "1101" => -- bsr / jsr + null; + when "1110" => -- ldx + case pre_code is + when "00010000" => -- page 2 -- ldy + left_ctrl <= iy_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + iy_ctrl <= load_iy; + when others => -- page 1 -- ldx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + ix_ctrl <= load_ix; + end case; + when "1111" => -- stx + case pre_code is + when "00010000" => -- page 2 -- sty + left_ctrl <= iy_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + when others => -- page 1 -- stx + left_ctrl <= ix_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + end case; + when others => + null; + end case; + when "11" => -- accb dual op + case op_code(3 downto 0) is + when "0000" => -- subb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "0001" => -- cmpb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sub8; + cc_ctrl <= load_cc; + when "0010" => -- sbcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_sbc; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "0011" => -- addd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + when "0100" => -- andb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "0101" => -- bitb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_and; + cc_ctrl <= load_cc; + when "0110" => -- ldab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld8; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "0111" => -- stab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st8; + cc_ctrl <= load_cc; + when "1000" => -- eorb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_eor; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "1001" => -- adcb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_adc; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "1010" => -- orab + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ora; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "1011" => -- addb + left_ctrl <= accb_left; + right_ctrl <= md_right; + alu_ctrl <= alu_add8; + cc_ctrl <= load_cc; + accb_ctrl <= load_accb; + when "1100" => -- ldd + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + acca_ctrl <= load_hi_acca; + accb_ctrl <= load_accb; + when "1101" => -- std + left_ctrl <= accd_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + when "1110" => -- ldu + case pre_code is + when "00010000" => -- page 2 -- lds + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + sp_ctrl <= load_sp; + when others => -- page 1 -- ldu + left_ctrl <= up_left; + right_ctrl <= md_right; + alu_ctrl <= alu_ld16; + cc_ctrl <= load_cc; + up_ctrl <= load_up; + end case; + when "1111" => + case pre_code is + when "00010000" => -- page 2 -- sts + left_ctrl <= sp_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + when others => -- page 1 -- stu + left_ctrl <= up_left; + right_ctrl <= md_right; + alu_ctrl <= alu_st16; + cc_ctrl <= load_cc; + end case; + when others => + null; + end case; + when others => + null; + end case; + + end if; -- first instruction cycle (fic) + lic_out <= lic; +end process; + +end rtl; + diff --git a/GCE - Vectrex_MiST/rtl/dac.vhd b/GCE - Vectrex_MiST/rtl/dac.vhd new file mode 100644 index 00000000..83d1861e --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/dac.vhd @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------- +-- +-- Delta-Sigma DAC +-- +-- $Id: dac.vhd,v 1.1 2005/10/25 21:09:42 arnim Exp $ +-- +-- Refer to Xilinx Application Note XAPP154. +-- +-- This DAC requires an external RC low-pass filter: +-- +-- dac_o 0---XXXXX---+---0 analog audio +-- 3k3 | +-- === 4n7 +-- | +-- GND +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity dac is + + generic ( + msbi_g : integer := 9 + ); + port ( + clk_i : in std_logic; + res_n_i : in std_logic; + dac_i : in std_logic_vector(msbi_g downto 0); + dac_o : out std_logic + ); + +end dac; + +library ieee; +use ieee.numeric_std.all; + +architecture rtl of dac is + + signal DACout_q : std_logic; + signal DeltaAdder_s, + SigmaAdder_s, + SigmaLatch_q, + DeltaB_s : unsigned(msbi_g+2 downto 0); + +begin + + DeltaB_s(msbi_g+2 downto msbi_g+1) <= SigmaLatch_q(msbi_g+2) & + SigmaLatch_q(msbi_g+2); + DeltaB_s(msbi_g downto 0) <= (others => '0'); + + DeltaAdder_s <= unsigned('0' & '0' & dac_i) + DeltaB_s; + + SigmaAdder_s <= DeltaAdder_s + SigmaLatch_q; + + seq: process (clk_i, res_n_i) + begin + if res_n_i = '0' then + SigmaLatch_q <= to_unsigned(2**(msbi_g+1), SigmaLatch_q'length); + DACout_q <= '0'; + + elsif clk_i'event and clk_i = '1' then + SigmaLatch_q <= SigmaAdder_s; + DACout_q <= SigmaLatch_q(msbi_g+2); + end if; + end process seq; + + dac_o <= DACout_q; + +end rtl; diff --git a/GCE - Vectrex_MiST/rtl/gen_ram.vhd b/GCE - Vectrex_MiST/rtl/gen_ram.vhd new file mode 100644 index 00000000..f1a95608 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/gen_ram.vhd @@ -0,0 +1,84 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- gen_rwram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity gen_ram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk : in std_logic; + we : in std_logic; + addr : in std_logic_vector((aWidth-1) downto 0); + d : in std_logic_vector((dWidth-1) downto 0); + q : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of gen_ram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + + signal rAddrReg : std_logic_vector((aWidth-1) downto 0); + signal qReg : std_logic_vector((dWidth-1) downto 0); +begin +-- ----------------------------------------------------------------------- +-- Signals to entity interface +-- ----------------------------------------------------------------------- +-- q <= qReg; + +-- ----------------------------------------------------------------------- +-- Memory write +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if we = '1' then + ram(to_integer(unsigned(addr))) <= d; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Memory read +-- ----------------------------------------------------------------------- +process(clk) + begin + if rising_edge(clk) then +-- qReg <= ram(to_integer(unsigned(rAddrReg))); +-- rAddrReg <= addr; +---- qReg <= ram(to_integer(unsigned(addr))); + q <= ram(to_integer(unsigned(addr))); + end if; + end process; +--q <= ram(to_integer(unsigned(addr))); +end architecture; + diff --git a/GCE - Vectrex_MiST/rtl/hq2x.sv b/GCE - Vectrex_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/hq2x.sv @@ -0,0 +1,454 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output [DWIDTH:0] q +); + + altsyncram altsyncram_component ( + .address_a (wraddress), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .address_b (rdaddress), + .q_b(q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({(DWIDTH+1){1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = NUMWORDS, + altsyncram_component.numwords_b = NUMWORDS, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = AWIDTH+1, + altsyncram_component.widthad_b = AWIDTH+1, + altsyncram_component.width_a = DWIDTH+1, + altsyncram_component.width_b = DWIDTH+1, + altsyncram_component.width_byteena_a = 1; + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [17:0] rgb1, + input [17:0] rgb2, + output result +); + + wire [5:0] r = rgb1[5:1] - rgb2[5:1]; + wire [5:0] g = rgb1[11:7] - rgb2[11:7]; + wire [5:0] b = rgb1[17:13] - rgb2[17:13]; + wire [6:0] t = $signed(r) + $signed(b); + wire [6:0] gx = {g[5], g}; + wire [7:0] y = $signed(t) + $signed(gx); + wire [6:0] u = $signed(r) - $signed(b); + wire [7:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-24..24) + wire y_inside = (y < 8'h18 || y >= 8'he8); + + // if u is inside (-4, 4) + wire u_inside = (u < 7'h4 || u >= 7'h7c); + + // if v is inside (-6, 6) + wire v_inside = (v < 8'h6 || v >= 8'hfA); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [5:0] A, + input [5:0] B, + input [5:0] C, + output [5:0] O +); + + function [8:0] mul6x3; + input [5:0] op1; + input [2:0] op2; + begin + mul6x3 = 9'd0; + if(op2[0]) mul6x3 = mul6x3 + op1; + if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0}; + if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [8:0] Amul = mul6x3(A, Op[7:5]); + wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0}); + wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0}); + wire [8:0] At = Amul; + wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [9:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[9:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [17:0] E, + input [17:0] A, + input [17:0] B, + input [17:0] D, + input [17:0] F, + input [17:0] H, + output [17:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = 11'bx; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [17:0] Input1 = E; + wire [17:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [17:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]); + InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]); + InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]); +endmodule + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 8 : 17; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [17:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [17:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [17:0] h2rgb; + input [8:0] v; +begin + h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]}; +end +endfunction + +function [8:0] rgb2h; + input [17:0] v; +begin + rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule // Hq2x diff --git a/GCE - Vectrex_MiST/rtl/keyboard.v b/GCE - Vectrex_MiST/rtl/keyboard.v new file mode 100644 index 00000000..8dde73d6 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/keyboard.v @@ -0,0 +1,79 @@ + + +module keyboard +( + input clk, + input reset, + input ps2_kbd_clk, + input ps2_kbd_data, + + output reg[7:0] joystick +); + +reg [11:0] shift_reg = 12'hFFF; +wire[11:0] kdata = {ps2_kbd_data,shift_reg[11:1]}; +wire [7:0] kcode = kdata[9:2]; +reg release_btn = 0; + +reg [7:0] code; +reg input_strobe = 0; + +always @(negedge clk) begin + reg old_reset = 0; + + old_reset <= reset; + + if(~old_reset & reset)begin + joystick <= 0; + end + + if(input_strobe) begin + case(code) + 'h16: joystick[4] <= ~release_btn; // 1 + 'h1E: joystick[5] <= ~release_btn; // 2 + 'h26: joystick[6] <= ~release_btn; // 3 + 'h25: joystick[7] <= ~release_btn; // 4 + + 'h75: joystick[3] <= ~release_btn; // arrow up + 'h72: joystick[2] <= ~release_btn; // arrow down + 'h6B: joystick[1] <= ~release_btn; // arrow left + 'h74: joystick[0] <= ~release_btn; // arrow right + endcase + end +end + +always @(posedge clk) begin + reg [3:0] prev_clk = 0; + reg old_reset = 0; + reg action = 0; + + old_reset <= reset; + input_strobe <= 0; + + if(~old_reset & reset)begin + prev_clk <= 0; + shift_reg <= 12'hFFF; + end else begin + prev_clk <= {ps2_kbd_clk,prev_clk[3:1]}; + if(prev_clk == 1) begin + if (kdata[11] & ^kdata[10:2] & ~kdata[1] & kdata[0]) begin + shift_reg <= 12'hFFF; + if (kcode == 8'he0) ; + // Extended key code follows + else if (kcode == 8'hf0) + // Release code follows + action <= 1; + else begin + // Cancel extended/release flags for next time + action <= 0; + release_btn <= action; + code <= kcode; + input_strobe <= 1; + end + end else begin + shift_reg <= kdata; + end + end + end +end +endmodule diff --git a/GCE - Vectrex_MiST/rtl/m6522a.vhd b/GCE - Vectrex_MiST/rtl/m6522a.vhd new file mode 100644 index 00000000..b650d971 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/m6522a.vhd @@ -0,0 +1,903 @@ +-- +-- A simulation model of VIC20 hardware +-- Copyright (c) MikeJ - March 2003 +-- +-- 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. +-- +-- You are responsible for any legal issues arising from your use of this code. +-- +-- The latest version of this file can be found at: www.fpgaarcade.com +-- +-- Email vic20@fpgaarcade.com +-- +-- +-- Revision list +-- +-- Arnim Laeuger, 12-Jan-2009: +-- Ported to numeric_std and simulation fix for signal initializations +-- version 002 fix from Mark McDougall, untested +-- version 001 initial release +-- not very sure about the shift register, documentation is a bit light. +-- +-- DarFPGA, 08-fev-2018 - m6522a.vhd +-- fixe Port_B(7) control with respect to T1 and ACR(7) for vectrex. +-- + +library ieee ; + use ieee.std_logic_1164.all ; + use ieee.numeric_std.all; + +entity M6522 is + port ( + + I_RS : in std_logic_vector(3 downto 0); + I_DATA : in std_logic_vector(7 downto 0); + O_DATA : out std_logic_vector(7 downto 0); + O_DATA_OE_L : out std_logic; + + I_RW_L : in std_logic; + I_CS1 : in std_logic; + I_CS2_L : in std_logic; + + O_IRQ_L : out std_logic; -- note, not open drain + -- port a + I_CA1 : in std_logic; + I_CA2 : in std_logic; + O_CA2 : out std_logic; + O_CA2_OE_L : out std_logic; + + I_PA : in std_logic_vector(7 downto 0); + O_PA : out std_logic_vector(7 downto 0); + O_PA_OE_L : out std_logic_vector(7 downto 0); + + -- port b + I_CB1 : in std_logic; + O_CB1 : out std_logic; + O_CB1_OE_L : out std_logic; + + I_CB2 : in std_logic; + O_CB2 : out std_logic; + O_CB2_OE_L : out std_logic; + + I_PB : in std_logic_vector(7 downto 0); + O_PB : out std_logic_vector(7 downto 0); + O_PB_OE_L : out std_logic_vector(7 downto 0); + + I_P2_H : in std_logic; -- high for phase 2 clock ____----__ + RESET_L : in std_logic; + ENA_4 : in std_logic; -- clk enable + CLK : in std_logic + ); +end; + +architecture RTL of M6522 is + + signal phase : std_logic_vector(1 downto 0); + signal p2_h_t1 : std_logic; + signal cs : std_logic; + + -- registers + signal r_ddra : std_logic_vector(7 downto 0); + signal r_ora : std_logic_vector(7 downto 0); + signal r_ira : std_logic_vector(7 downto 0); + + signal r_ddrb : std_logic_vector(7 downto 0); + signal r_orb : std_logic_vector(7 downto 0); + signal r_orb_in : std_logic_vector(7 downto 0); -- DAR 2018-01-18 + signal r_irb : std_logic_vector(7 downto 0); + + signal r_t1l_l : std_logic_vector(7 downto 0) := (others => '0'); + signal r_t1l_h : std_logic_vector(7 downto 0) := (others => '0'); + signal r_t2l_l : std_logic_vector(7 downto 0) := (others => '0'); + signal r_t2l_h : std_logic_vector(7 downto 0) := (others => '0'); -- not in real chip + signal r_sr : std_logic_vector(7 downto 0); + signal r_acr : std_logic_vector(7 downto 0); + signal r_pcr : std_logic_vector(7 downto 0); + signal r_ifr : std_logic_vector(7 downto 0); + signal r_ier : std_logic_vector(6 downto 0); + + signal sr_write_ena : boolean; + signal sr_read_ena : boolean; + signal ifr_write_ena : boolean; + signal ier_write_ena : boolean; + signal clear_irq : std_logic_vector(7 downto 0); + signal load_data : std_logic_vector(7 downto 0); + + -- timer 1 + signal t1c : std_logic_vector(15 downto 0) := (others => '0'); + signal t1c_active : boolean; + signal t1c_done : boolean; + signal t1_w_reset_int : boolean; + signal t1_r_reset_int : boolean; + signal t1_load_counter : boolean; + signal t1_reload_counter : boolean; + signal t1_toggle : std_logic; + signal t1_irq : std_logic := '0'; + + -- timer 2 + signal t2c : std_logic_vector(15 downto 0) := (others => '0'); + signal t2c_active : boolean; + signal t2c_done : boolean; + signal t2_pb6 : std_logic; + signal t2_pb6_t1 : std_logic; + signal t2_w_reset_int : boolean; + signal t2_r_reset_int : boolean; + signal t2_load_counter : boolean; + signal t2_reload_counter : boolean; + signal t2_irq : std_logic := '0'; + signal t2_sr_ena : boolean; + + -- shift reg + signal sr_cnt : std_logic_vector(3 downto 0); + signal sr_cb1_oe_l : std_logic; + signal sr_cb1_out : std_logic; + signal sr_drive_cb2 : std_logic; + signal sr_strobe : std_logic; + signal sr_strobe_t1 : std_logic; + signal sr_strobe_falling : boolean; + signal sr_strobe_rising : boolean; + signal sr_irq : std_logic; + signal sr_out : std_logic; + signal sr_off_delay : std_logic; + + -- io + signal w_orb_hs : std_logic; + signal w_ora_hs : std_logic; + signal r_irb_hs : std_logic; + signal r_ira_hs : std_logic; + + signal ca_hs_sr : std_logic; + signal ca_hs_pulse : std_logic; + signal cb_hs_sr : std_logic; + signal cb_hs_pulse : std_logic; + + signal cb1_in_mux : std_logic; + signal ca1_ip_reg : std_logic; + signal cb1_ip_reg : std_logic; + signal ca1_int : boolean; + signal cb1_int : boolean; + signal ca1_irq : std_logic; + signal cb1_irq : std_logic; + + signal ca2_ip_reg : std_logic; + signal cb2_ip_reg : std_logic; + signal ca2_int : boolean; + signal cb2_int : boolean; + signal ca2_irq : std_logic; + signal cb2_irq : std_logic; + + signal final_irq : std_logic; +begin + + p_phase : process + begin + -- internal clock phase + wait until rising_edge(CLK); + if (ENA_4 = '1') then + p2_h_t1 <= I_P2_H; + if (p2_h_t1 = '0') and (I_P2_H = '1') then + phase <= "11"; + else + phase <= std_logic_vector(unsigned(phase) + 1); + end if; + end if; + end process; + + p_cs : process(I_CS1, I_CS2_L, I_P2_H) + begin + cs <= '0'; + if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then + cs <= '1'; + end if; + end process; + + -- peripheral control reg (pcr) + -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge) + -- 3..1 ca2 operation + -- 000 input -ve edge + -- 001 independend interrupt input -ve edge + -- 010 input +ve edge + -- 011 independend interrupt input +ve edge + -- 100 handshake output + -- 101 pulse output + -- 110 low output + -- 111 high output + -- 7..4 as 3..0 for cb1,cb2 + + -- auxiliary control reg (acr) + -- 0 input latch PA (0 disable, 1 enable) + -- 1 input latch PB (0 disable, 1 enable) + -- 4..2 shift reg control + -- 000 disable + -- 001 shift in using t2 + -- 010 shift in using o2 + -- 011 shift in using ext clk + -- 100 shift out free running t2 rate + -- 101 shift out using t2 + -- 101 shift out using o2 + -- 101 shift out using ext clk + -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6) + -- 7..6 t1 timer control + -- 00 timed interrupt each time t1 is loaded pb7 disable + -- 01 continuous interrupts pb7 disable + -- 00 timed interrupt each time t1 is loaded pb7 one shot output + -- 01 continuous interrupts pb7 square wave output + -- + + p_write_reg_reset : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + r_ora <= x"00"; r_orb <= x"00"; + r_ddra <= x"00"; r_ddrb <= x"00"; + r_acr <= x"00"; r_pcr <= x"00"; + + w_orb_hs <= '0'; + w_ora_hs <= '0'; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + w_orb_hs <= '0'; + w_ora_hs <= '0'; + if (cs = '1') and (I_RW_L = '0') then + case I_RS is + when x"0" => r_orb <= I_DATA; w_orb_hs <= '1'; + r_orb_in <= I_DATA; -- DAR 2018-01-18 + when x"1" => r_ora <= I_DATA; w_ora_hs <= '1'; + when x"2" => r_ddrb <= I_DATA; + when x"3" => r_ddra <= I_DATA; + when x"B" => r_acr <= I_DATA; + when x"C" => r_pcr <= I_DATA; + when x"F" => r_ora <= I_DATA; + + when others => null; + end case; + end if; + + if r_acr(7) = '1' then -- DAR 2018-01-18 + if t1c_active = true then + r_orb(7) <= '0'; -- DAR 2018-01-18 + else + r_orb(7) <= '1'; -- DAR 2018-01-18 + end if; + else + r_orb(7) <= r_orb_in(7); -- DAR 2018-01-18 + end if; + + end if; + end if; + end process; + + p_write_reg : process + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + t1_w_reset_int <= false; + t1_load_counter <= false; + + t2_w_reset_int <= false; + t2_load_counter <= false; + + load_data <= x"00"; + sr_write_ena <= false; + ifr_write_ena <= false; + ier_write_ena <= false; + + if (cs = '1') and (I_RW_L = '0') then + load_data <= I_DATA; + case I_RS is + when x"4" => r_t1l_l <= I_DATA; + when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; + t1_load_counter <= true; + + when x"6" => r_t1l_l <= I_DATA; + when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; + + when x"8" => r_t2l_l <= I_DATA; + when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true; + t2_load_counter <= true; + + when x"A" => sr_write_ena <= true; + when x"D" => ifr_write_ena <= true; + when x"E" => ier_write_ena <= true; + + when others => null; + end case; + end if; + end if; + end process; + + p_oe : process(cs, I_RW_L) + begin + O_DATA_OE_L <= '1'; + if (cs = '1') and (I_RW_L = '1') then + O_DATA_OE_L <= '0'; + end if; + end process; + + p_read : process(cs, I_RW_L, I_RS, r_irb, r_ira, r_ddrb, r_ddra, t1c, r_t1l_l, + r_t1l_h, t2c, r_sr, r_acr, r_pcr, r_ifr, r_ier, r_orb) + begin + t1_r_reset_int <= false; + t2_r_reset_int <= false; + sr_read_ena <= false; + r_irb_hs <= '0'; + r_ira_hs <= '0'; + O_DATA <= x"00"; -- default + if (cs = '1') and (I_RW_L = '1') then + case I_RS is + --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1'; + -- fix from Mark McDougall, untested + when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1'; + --when x"1" => O_DATA <= r_ira; r_ira_hs <= '1'; + when x"1" => O_DATA <= (r_ira and not r_ddra) or (r_ora and r_ddra); r_ira_hs <= '1'; + when x"2" => O_DATA <= r_ddrb; + when x"3" => O_DATA <= r_ddra; + when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true; + when x"5" => O_DATA <= t1c(15 downto 8); + when x"6" => O_DATA <= r_t1l_l; + when x"7" => O_DATA <= r_t1l_h; + when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true; + when x"9" => O_DATA <= t2c(15 downto 8); + when x"A" => O_DATA <= r_sr; sr_read_ena <= true; + when x"B" => O_DATA <= r_acr; + when x"C" => O_DATA <= r_pcr; + when x"D" => O_DATA <= r_ifr; + when x"E" => O_DATA <= ('0' & r_ier); + when x"F" => O_DATA <= r_ira; + when others => null; + end case; + end if; + + end process; + -- + -- IO + -- + p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1) + begin + -- if the shift register is enabled, cb1 may be an output + -- in this case, we should listen to the CB1_OUT for the interrupt + if (sr_cb1_oe_l = '1') then + cb1_in_mux <= I_CB1; + else + cb1_in_mux <= sr_cb1_out; + end if; + end process; + + p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux) + begin + if (r_pcr(0) = '0') then -- ca1 control + -- negative edge + ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0'); + else + -- positive edge + ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1'); + end if; + + if (r_pcr(4) = '0') then -- cb1 control + -- negative edge + cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0'); + else + -- positive edge + cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1'); + end if; + end process; + + p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2) + begin + ca2_int <= false; + if (r_pcr(3) = '0') then -- ca2 input + if (r_pcr(2) = '0') then -- ca2 edge + -- negative edge + ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0'); + else + -- positive edge + ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1'); + end if; + end if; + + cb2_int <= false; + if (r_pcr(7) = '0') then -- cb2 input + if (r_pcr(6) = '0') then -- cb2 edge + -- negative edge + cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0'); + else + -- positive edge + cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1'); + end if; + end if; + end process; + + p_ca2_cb2 : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + O_CA2 <= '0'; + O_CA2_OE_L <= '1'; + O_CB2 <= '0'; + O_CB2_OE_L <= '1'; + + ca_hs_sr <= '0'; + ca_hs_pulse <= '0'; + cb_hs_sr <= '0'; + cb_hs_pulse <= '0'; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + -- ca + if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then + ca_hs_sr <= '1'; + elsif ca1_int then + ca_hs_sr <= '0'; + end if; + + if (phase = "00") then + ca_hs_pulse <= w_ora_hs or r_ira_hs; + end if; + + O_CA2_OE_L <= not r_pcr(3); -- ca2 output + case r_pcr(3 downto 1) is + when "000" => O_CA2 <= '0'; -- input + when "001" => O_CA2 <= '0'; -- input + when "010" => O_CA2 <= '0'; -- input + when "011" => O_CA2 <= '0'; -- input + when "100" => O_CA2 <= not (ca_hs_sr); -- handshake + when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse + when "110" => O_CA2 <= '0'; -- low + when "111" => O_CA2 <= '1'; -- high + when others => null; + end case; + + -- cb + if (phase = "00") and (w_orb_hs = '1') then + cb_hs_sr <= '1'; + elsif cb1_int then + cb_hs_sr <= '0'; + end if; + + if (phase = "00") then + cb_hs_pulse <= w_orb_hs; + end if; + + O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial + if (sr_drive_cb2 = '1') then -- serial output + O_CB2 <= sr_out; + else + case r_pcr(7 downto 5) is + when "000" => O_CB2 <= '0'; -- input + when "001" => O_CB2 <= '0'; -- input + when "010" => O_CB2 <= '0'; -- input + when "011" => O_CB2 <= '0'; -- input + when "100" => O_CB2 <= not (cb_hs_sr); -- handshake + when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse + when "110" => O_CB2 <= '0'; -- low + when "111" => O_CB2 <= '1'; -- high + when others => null; + end case; + end if; + end if; + end if; + end process; + O_CB1 <= sr_cb1_out; + O_CB1_OE_L <= sr_cb1_oe_l; + + p_ca_cb_irq : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + ca1_irq <= '0'; + ca2_irq <= '0'; + cb1_irq <= '0'; + cb2_irq <= '0'; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + -- not pretty + if ca1_int then + ca1_irq <= '1'; + elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then + ca1_irq <= '0'; + end if; + + if ca2_int then + ca2_irq <= '1'; + else + if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or + (clear_irq(0) = '1') then + ca2_irq <= '0'; + end if; + end if; + + if cb1_int then + cb1_irq <= '1'; + elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then + cb1_irq <= '0'; + end if; + + if cb2_int then + cb2_irq <= '1'; + else + if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or + (clear_irq(3) = '1') then + cb2_irq <= '0'; + end if; + end if; + end if; + end if; + end process; + + p_input_reg : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + ca1_ip_reg <= '0'; + cb1_ip_reg <= '0'; + + ca2_ip_reg <= '0'; + cb2_ip_reg <= '0'; + + r_ira <= x"00"; + r_irb <= x"00"; + + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + -- we have a fast clock, so we can have input registers + ca1_ip_reg <= I_CA1; + cb1_ip_reg <= cb1_in_mux; + + ca2_ip_reg <= I_CA2; + cb2_ip_reg <= I_CB2; + + if (r_acr(0) = '0') then + r_ira <= I_PA; + else -- enable latching + if ca1_int then + r_ira <= I_PA; + end if; + end if; + + if (r_acr(1) = '0') then + r_irb <= I_PB; + else -- enable latching + if cb1_int then + r_irb <= I_PB; + end if; + end if; + end if; + end if; + end process; + + + p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb) + begin + -- data direction reg (ddr) 0 = input, 1 = output + O_PA <= r_ora; + O_PA_OE_L <= not r_ddra; + + if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well + O_PB_OE_L(7) <= '0'; -- an output if under t1 control + else + O_PB_OE_L(7) <= not (r_ddrb(7)); + end if; + + O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0); + O_PB(7 downto 0) <= r_orb(7 downto 0); + + end process; + -- + -- Timer 1 + -- + p_timer1_done : process + variable done : boolean; + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + done := (t1c = x"0000"); + t1c_done <= done and (phase = "11"); + if (phase = "11") then + t1_reload_counter <= done and (r_acr(6) = '1'); + end if; + end if; + end process; + + p_timer1 : process + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + if t1_load_counter or (t1_reload_counter and phase = "11") then + t1c( 7 downto 0) <= r_t1l_l; + t1c(15 downto 8) <= r_t1l_h; + elsif (phase="11") then + t1c <= std_logic_vector(unsigned(t1c) - 1); + end if; + + if t1_load_counter or t1_reload_counter then + t1c_active <= true; + elsif t1c_done then + t1c_active <= false; + end if; + + t1_toggle <= '0'; + if t1c_active and t1c_done then + t1_toggle <= '1'; + t1_irq <= '1'; + elsif t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then + t1_irq <= '0'; + end if; + end if; + end process; + -- + -- Timer2 + -- + p_timer2_pb6_input : process + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + if (phase = "01") then -- leading edge p2_h + t2_pb6 <= I_PB(6); + t2_pb6_t1 <= t2_pb6; + end if; + end if; + end process; + + p_timer2_done : process + variable done : boolean; + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + done := (t2c = x"0000"); + t2c_done <= done and (phase = "11"); + if (phase = "11") then + t2_reload_counter <= done; + end if; + end if; + end process; + + p_timer2 : process + variable ena : boolean; + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + if (r_acr(5) = '0') then + ena := true; + else + ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge + end if; + + if t2_load_counter or (t2_reload_counter and phase = "11") then + -- not sure if t2c_reload should be here. Does timer2 just continue to + -- count down, or is it reloaded ? Reloaded makes more sense if using + -- it to generate a clock for the shift register. + t2c( 7 downto 0) <= r_t2l_l; + t2c(15 downto 8) <= r_t2l_h; + else + if (phase="11") and ena then -- or count mode + t2c <= std_logic_vector(unsigned(t2c) - 1); + end if; + end if; + + t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11"); + + if t2_load_counter then + t2c_active <= true; + elsif t2c_done then + t2c_active <= false; + end if; + + + if t2c_active and t2c_done then + t2_irq <= '1'; + elsif t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then + t2_irq <= '0'; + end if; + end if; + end process; + -- + -- Shift Register + -- + p_sr : process(RESET_L, CLK) + variable dir_out : std_logic; + variable ena : std_logic; + variable cb1_op : std_logic; + variable cb1_ip : std_logic; + variable use_t2 : std_logic; + variable free_run : std_logic; + variable sr_count_ena : boolean; + begin + if (RESET_L = '0') then + r_sr <= x"00"; + sr_drive_cb2 <= '0'; + sr_cb1_oe_l <= '1'; + sr_cb1_out <= '0'; + sr_strobe <= '1'; + sr_cnt <= "0000"; + sr_irq <= '0'; + sr_out <= '1'; + sr_off_delay <= '0'; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + -- decode mode + dir_out := r_acr(4); -- output on cb2 + cb1_op := '0'; + cb1_ip := '0'; + use_t2 := '0'; + free_run := '0'; + + case r_acr(4 downto 2) is + when "000" => ena := '0'; + when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1'; + when "010" => ena := '1'; cb1_op := '1'; + when "011" => ena := '1'; cb1_ip := '1'; + when "100" => ena := '1'; use_t2 := '1'; free_run := '1'; + when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1'; +-- when "110" => ena := '1'; free_run := '1'; -- hack + when "110" => ena := '1'; -- DAR 2018_01_24 + when "111" => ena := '1'; cb1_ip := '1'; + when others => null; + end case; + + -- clock select + if (ena = '0') then + sr_strobe <= '1'; + else + if (cb1_ip = '1') then + sr_strobe <= I_CB1; + else + if (sr_cnt(3) = '0') and (free_run = '0') then + sr_strobe <= '1'; + else + if ((use_t2 = '1') and t2_sr_ena) or + ((use_t2 = '0') and (phase = "00")) then + sr_strobe <= not sr_strobe; + end if; + end if; + end if; + end if; + + -- latch on rising edge, shift on falling edge + if sr_write_ena then + r_sr <= load_data; + elsif (ena = '1') then -- use shift reg + + if (dir_out = '0') then + -- input + if (sr_cnt(3) = '1') or (cb1_ip = '1') then + if sr_strobe_rising then + r_sr(0) <= I_CB2; + elsif sr_strobe_falling then + r_sr(7 downto 1) <= r_sr(6 downto 0); + end if; + end if; + sr_out <= '1'; + else + -- output + if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then + if sr_strobe_falling then + r_sr(7 downto 1) <= r_sr(6 downto 0); + r_sr(0) <= r_sr(7); + sr_out <= r_sr(7); + end if; + else +-- sr_out <= '1'; + sr_out <= r_sr(7); -- DAR 2018-01-25 + end if; + end if; + end if; + + sr_count_ena := sr_strobe_rising; + + if sr_write_ena or sr_read_ena then + -- some documentation says sr bit in IFR must be set as well ? +-- sr_cnt <= "1000"; + sr_cnt <= "1001"; -- DAR 2018-01-25 + elsif sr_count_ena and (sr_cnt(3) = '1') then + sr_cnt <= std_logic_vector(unsigned(sr_cnt) + 1); + end if; + + if (phase = "00") then + sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out + end if; + + if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then + sr_irq <= '1'; + elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then + sr_irq <= '0'; + end if; + + -- assign ops + sr_drive_cb2 <= dir_out; + sr_cb1_oe_l <= not cb1_op; + sr_cb1_out <= sr_strobe; + end if; + end if; + end process; + + p_sr_strobe_rise_fall : process + begin + wait until rising_edge(CLK); + if (ENA_4 = '1') then + sr_strobe_t1 <= sr_strobe; + sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1'); + sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0'); + end if; + end process; + -- + -- Interrupts + -- + p_ier : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + r_ier <= "0000000"; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + if ier_write_ena then + if (load_data(7) = '1') then + -- set + r_ier <= r_ier or load_data(6 downto 0); + else + -- clear + r_ier <= r_ier and not load_data(6 downto 0); + end if; + end if; + end if; + end if; + end process; + + p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq, + cb1_irq, cb2_irq) + begin + r_ifr(7) <= final_irq; + r_ifr(6) <= t1_irq; + r_ifr(5) <= t2_irq; + r_ifr(4) <= cb1_irq; + r_ifr(3) <= cb2_irq; + r_ifr(2) <= sr_irq; + r_ifr(1) <= ca1_irq; + r_ifr(0) <= ca2_irq; + + O_IRQ_L <= not final_irq; + end process; + + p_irq : process(RESET_L, CLK) + begin + if (RESET_L = '0') then + final_irq <= '0'; + elsif rising_edge(CLK) then + if (ENA_4 = '1') then + if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then + final_irq <= '0'; -- no interrupts + else + final_irq <= '1'; + end if; + end if; + end if; + end process; + + p_clear_irq : process(ifr_write_ena, load_data) + begin + clear_irq <= x"00"; + if ifr_write_ena then + clear_irq <= load_data; + end if; + end process; + +end architecture RTL; diff --git a/GCE - Vectrex_MiST/rtl/mist_io.v b/GCE - Vectrex_MiST/rtl/mist_io.v new file mode 100644 index 00000000..ad233a3b --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/mist_io.v @@ -0,0 +1,491 @@ +// +// mist_io.v +// +// mist_io for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2014 Till Harbaum +// +// 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 . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK +// (Sorgelig) +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = clk_sys/(PS2DIV*2) +// + +module mist_io #(parameter STRLEN=0, parameter PS2DIV=100) +( + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + // Global clock. It should be around 100MHz (higher is better). + input clk_sys, + + // Global SPI clock from ARM. 24MHz + input SPI_SCK, + + input CONF_DATA0, + input SPI_SS2, + output SPI_DO, + input SPI_DI, + + output reg [7:0] joystick_0, + output reg [7:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + output [1:0] buttons, + output [1:0] switches, + output scandoubler_disable, + output ypbpr, + + output reg [31:0] status, + + // SD config + input sd_conf, + input sd_sdhc, + output img_mounted, // signaling that new image has been mounted + output reg [31:0] img_size, // size of image in bytes + + // SD block level access + input [31:0] sd_lba, + input sd_rd, + input sd_wr, + output reg sd_ack, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [8:0] sd_buff_addr, + output reg [7:0] sd_buff_dout, + input [7:0] sd_buff_din, + output reg sd_buff_wr, + + // ps2 keyboard emulation + output ps2_kbd_clk, + output reg ps2_kbd_data, + output ps2_mouse_clk, + output reg ps2_mouse_data, + input ps2_caps_led, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output ioctl_wr, + output reg [24:0] ioctl_addr, + output reg [7:0] ioctl_dout +); + +reg [7:0] b_data; +reg [6:0] sbuf; +reg [7:0] cmd; +reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... +reg [9:0] byte_cnt; // counts bytes +reg [7:0] but_sw; +reg [2:0] stick_idx; + +reg mount_strobe = 0; +assign img_mounted = mount_strobe; + +assign buttons = but_sw[1:0]; +assign switches = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; +assign ypbpr = but_sw[5]; + +wire [7:0] spi_dout = { sbuf, SPI_DI}; + +// this variant of user_io is for 8 bit cores (type == a4) only +wire [7:0] core_type = 8'ha4; + +// command byte read by the io controller +wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd }; + +reg spi_do; +assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do; + +wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1}; + +// drive MISO only when transmitting core id +always@(negedge SPI_SCK) begin + if(!CONF_DATA0) begin + // first byte returned is always core type, further bytes are + // command dependent + if(byte_cnt == 0) begin + spi_do <= core_type[~bit_cnt]; + + end else begin + case(cmd) + // reading config string + 8'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card status + 8'h16: begin + if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt]; + else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}]; + else spi_do <= 0; + end + + // reading sd card write data + 8'h18: + spi_do <= b_data[~bit_cnt]; + + // reading keyboard LED status + 8'h1f: + spi_do <= kbd_led[~bit_cnt]; + + default: + spi_do <= 0; + endcase + end + end +end + +reg b_wr2,b_wr3; +always @(negedge clk_sys) begin + b_wr3 <= b_wr2; + sd_buff_wr <= b_wr3; +end + +// SPI receiver +always@(posedge SPI_SCK or posedge CONF_DATA0) begin + + if(CONF_DATA0) begin + b_wr2 <= 0; + bit_cnt <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + end else begin + b_wr2 <= 0; + + sbuf <= spi_dout[6:0]; + bit_cnt <= bit_cnt + 1'd1; + if(bit_cnt == 5) begin + if (byte_cnt == 0) sd_buff_addr <= 0; + if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1; + if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0; + end + + // finished reading command byte + if(bit_cnt == 7) begin + if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1; + if(byte_cnt == 0) begin + cmd <= spi_dout; + + if(spi_dout == 8'h19) begin + sd_ack_conf <= 1; + sd_buff_addr <= 0; + end + if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin + sd_ack <= 1; + sd_buff_addr <= 0; + end + if(spi_dout == 8'h18) b_data <= sd_buff_din; + + mount_strobe <= 0; + + end else begin + + case(cmd) + // buttons and switches + 8'h01: but_sw <= spi_dout; + 8'h02: joystick_0 <= spi_dout; + 8'h03: joystick_1 <= spi_dout; + + // store incoming ps2 mouse bytes + 8'h04: begin + ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; + ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1; + end + + // store incoming ps2 keyboard bytes + 8'h05: begin + ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; + ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1; + end + + 8'h15: status[7:0] <= spi_dout; + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 8'h19, + // send sector IO -> FPGA + // flag that download begins + 8'h17: begin + sd_buff_dout <= spi_dout; + b_wr2 <= 1; + end + + 8'h18: b_data <= sd_buff_din; + + // joystick analog + 8'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= spi_dout[2:0]; + else if(byte_cnt == 2) begin + // second byte is x axis + if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout; + end else if(byte_cnt == 3) begin + // third byte is y axis + if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout; + else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout; + end + end + + // notify image selection + 8'h1c: mount_strobe <= 1; + + // send image info + 8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout; + + // status, 32bit version + 8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout; + default: ; + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +// 8 byte fifos to store ps2 bytes +localparam PS2_FIFO_BITS = 3; + +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +// keyboard +reg [7:0] ps2_kbd_fifo[1<= 1)&&(ps2_kbd_tx_state < 9)) begin + ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits + ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down + if(ps2_kbd_tx_byte[0]) + ps2_kbd_parity <= !ps2_kbd_parity; + end + + // transmission of parity + if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity; + + // transmission of stop bit + if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1; + else ps2_kbd_tx_state <= 0; + end + end +end + +// mouse +reg [7:0] ps2_mouse_fifo[1<= 1)&&(ps2_mouse_tx_state < 9)) begin + ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits + ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down + if(ps2_mouse_tx_byte[0]) + ps2_mouse_parity <= !ps2_mouse_parity; + end + + // transmission of parity + if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity; + + // transmission of stop bit + if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1 + + // advance state machine + if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1; + else ps2_mouse_tx_state <= 0; + end + end +end + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +reg [7:0] data_w; +reg [24:0] addr_w; +reg rclk = 0; + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +// data_io has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS2) begin + reg [6:0] sbuf; + reg [7:0] cmd; + reg [4:0] cnt; + reg [24:0] addr; + + if(SPI_SS2) cnt <= 0; + else begin + rclk <= 0; + + // don't shift in last bit. It is evaluated directly + // when writing to ram + if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI}; + + // increase target address after write + if(rclk) addr <= addr + 1'd1; + + // count 0-7 8-15 8-15 ... + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + // finished command byte + if(cnt == 7) cmd <= {sbuf, SPI_DI}; + + // prepare/end transmission + if((cmd == UIO_FILE_TX) && (cnt == 15)) begin + // prepare + if(SPI_DI) begin + addr <= 0; + ioctl_download <= 1; + end else begin + addr_w <= addr; + ioctl_download <= 0; + end + end + + // command 0x54: UIO_FILE_TX + if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin + addr_w <= addr; + data_w <= {sbuf, SPI_DI}; + rclk <= 1; + end + + // expose file (menu) index + if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI}; + end +end + +assign ioctl_wr = |ioctl_wrd; +reg [1:0] ioctl_wrd; + +always@(negedge clk_sys) begin + reg rclkD, rclkD2; + + rclkD <= rclk; + rclkD2 <= rclkD; + ioctl_wrd<= {ioctl_wrd[0],1'b0}; + + if(rclkD & ~rclkD2) begin + ioctl_dout <= data_w; + ioctl_addr <= addr_w; + ioctl_wrd <= 2'b11; + end +end + +endmodule diff --git a/GCE - Vectrex_MiST/rtl/osd.v b/GCE - Vectrex_MiST/rtl/osd.v new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/osd.v @@ -0,0 +1,179 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd ( + // OSDs pixel clock, should be synchronous to cores pixel clock to + // avoid jitter. + input clk_sys, + + // SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // VGA signals coming from core + input [5:0] R_in, + input [5:0] G_in, + input [5:0] B_in, + input HSync, + input VSync, + + // VGA signals going to video connector + output [5:0] R_out, + output [5:0] G_out, + output [5:0] B_out +); + +parameter OSD_X_OFFSET = 10'd0; +parameter OSD_Y_OFFSET = 10'd0; +parameter OSD_COLOR = 3'd0; + +localparam OSD_WIDTH = 10'd256; +localparam OSD_HEIGHT = 10'd128; + +// ********************************************************************************* +// spi client +// ********************************************************************************* + +// this core supports only the display related OSD commands +// of the minimig +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself + +// the OSD has its own SPI interface to the io controller +always@(posedge SPI_SCK, posedge SPI_SS3) begin + reg [4:0] cnt; + reg [10:0] bcnt; + reg [7:0] sbuf; + reg [7:0] cmd; + + if(SPI_SS3) begin + cnt <= 0; + bcnt <= 0; + end else begin + sbuf <= {sbuf[6:0], SPI_DI}; + + // 0:7 is command, rest payload + if(cnt < 15) cnt <= cnt + 1'd1; + else cnt <= 8; + + if(cnt == 7) begin + cmd <= {sbuf[6:0], SPI_DI}; + + // lower three command bits are line address + bcnt <= {sbuf[1:0], SPI_DI, 8'h00}; + + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI; + end + + // command 0x20: OSDCMDWRITE + if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin + osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI}; + bcnt <= bcnt + 1'd1; + end + end +end + +// ********************************************************************************* +// video timing and sync polarity anaylsis +// ********************************************************************************* + +// horizontal counter +reg [9:0] h_cnt; +reg [9:0] hs_low, hs_high; +wire hs_pol = hs_high < hs_low; +wire [9:0] dsp_width = hs_pol ? hs_low : hs_high; + +// vertical counter +reg [9:0] v_cnt; +reg [9:0] vs_low, vs_high; +wire vs_pol = vs_high < vs_low; +wire [9:0] dsp_height = vs_pol ? vs_low : vs_high; + +wire doublescan = (dsp_height>350); + +reg ce_pix; +always @(negedge clk_sys) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg hs; + + cnt <= cnt + 1; + hs <= HSync; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(hs && ~HSync) begin + cnt <= 0; + pixsz <= (cnt >> 9) - 1; + pixcnt <= 0; + ce_pix <= 1; + end +end + +always @(posedge clk_sys) begin + reg hsD, hsD2; + reg vsD, vsD2; + + if(ce_pix) begin + // bring hsync into local clock domain + hsD <= HSync; + hsD2 <= hsD; + + // falling edge of HSync + if(!hsD && hsD2) begin + h_cnt <= 0; + hs_high <= h_cnt; + end + + // rising edge of HSync + else if(hsD && !hsD2) begin + h_cnt <= 0; + hs_low <= h_cnt; + v_cnt <= v_cnt + 1'd1; + end else begin + h_cnt <= h_cnt + 1'd1; + end + + vsD <= VSync; + vsD2 <= vsD; + + // falling edge of VSync + if(!vsD && vsD2) begin + v_cnt <= 0; + vs_high <= v_cnt; + end + + // rising edge of VSync + else if(vsD && !vsD2) begin + v_cnt <= 0; + vs_low <= v_cnt; + end + end +end + +// area in which OSD is being displayed +wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET; +wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= h_osd_start) && (h_cnt < h_osd_end) && + (VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +reg [7:0] osd_byte; +always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}]; + +wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]]; + +assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]}; +assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]}; +assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]}; + +endmodule diff --git a/GCE - Vectrex_MiST/rtl/pll.qip b/GCE - Vectrex_MiST/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/GCE - Vectrex_MiST/rtl/pll.v b/GCE - Vectrex_MiST/rtl/pll.v new file mode 100644 index 00000000..cbd56df8 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/pll.v @@ -0,0 +1,376 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.0 Build 162 10/23/2013 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2013 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + c2, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output c2; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire7 = 1'h0; + wire [2:2] sub_wire4 = sub_wire0[2:2]; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire c2 = sub_wire4; + wire sub_wire5 = inclk0; + wire [1:0] sub_wire6 = {sub_wire7, sub_wire5}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire6), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 44, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 41, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 88, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 41, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 176, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 41, + altpll_component.clk2_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0" +// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8" +// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "44" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "88" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "176" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "25.159090" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.579545" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "6.289773" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "41" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "41" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "41" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.17500000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.58750000" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "6.29375000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_CLK0 STRING "1" +// Retrieval info: PRIVATE: USE_CLK1 STRING "1" +// Retrieval info: PRIVATE: USE_CLK2 STRING "1" +// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "44" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "41" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "88" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "41" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "176" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "41" +// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/GCE - Vectrex_MiST/rtl/scandoubler.v b/GCE - Vectrex_MiST/rtl/scandoubler.v new file mode 100644 index 00000000..36e71ed2 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/scandoubler.v @@ -0,0 +1,194 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// 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 . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + input ce_pix_actual, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input line_start, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <=1024 ? 9 : 10 ) + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +assign vs_out = vs_in; + +reg [2:0] phase; +reg [2:0] ce_div; +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +wire ls_in = hs_in | line_start; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place c_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + phase <= phase + 1'd1; + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + phase <= phase + 1'd1; + + ce_cnt <= ce_cnt + 1'd1; + if(ce_pix_actual) begin + phase <= 0; + ce_div <= ce_cnt + 1'd1; + ce_cnt <= 0; + req_line_reset <= 0; + end + + if(ls_in) req_line_reset <= 1; + end +end + +reg ce_sd; +always @(*) begin + case(ce_div) + 2: ce_sd = !phase[0]; + 4: ce_sd = !phase[1:0]; + default: ce_sd <= 1; + endcase +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4 & ce_sd), + .inputpixel({b_in,g_in,r_in}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h_actual), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h_actual; +always @(*) begin + case(ce_div) + 2: sd_h_actual = sd_h[10:1]; + 4: sd_h_actual = sd_h[10:2]; + default: sd_h_actual = sd_h; + endcase +end + +reg [10:0] sd_h; +reg [1:0] sd_line; +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise,hs_ls; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + + reg hs, hs2, vs, ls; + + if(ce_x1) begin + hs <= hs_in; + ls <= ls_in; + + if(ls && !ls_in) hs_ls <= {hcnt,1'b1}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + if(ls && !ls_in) hs_ls <= {10'd0,1'b1}; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + sd_h <= sd_h + 1'd1; + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + + if(sd_hcnt == hs_ls) sd_h <= 0; + if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1; + end +end + +endmodule diff --git a/GCE - Vectrex_MiST/rtl/vectrex.vhd b/GCE - Vectrex_MiST/rtl/vectrex.vhd new file mode 100644 index 00000000..7b290527 --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/vectrex.vhd @@ -0,0 +1,805 @@ +--------------------------------------------------------------------------------- +-- Vectrex by Dar (darfpga@aol.fr) (27/12/2017) +-- http://darfpga.blogspot.fr +--------------------------------------------------------------------------------- +-- Educational use only +-- Do not redistribute synthetized file with roms +-- Do not redistribute roms whatever the form +-- Use at your own risk +--------------------------------------------------------------------------------- +--------------------------------------------------------------------------------- +-- gen_ram.vhd & io_ps2_keyboard +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +--------------------------------------------------------------------------------- +-- VIA m6522 +-- Copyright (c) MikeJ - March 2003 +-- + modification +--------------------------------------------------------------------------------- +-- YM2149 (AY-3-8910) +-- Copyright (c) MikeJ - Jan 2005 +--------------------------------------------------------------------------------- +-- cpu09l_128 +-- Copyright (C) 2003 - 2010 John Kent +-- + modification +--------------------------------------------------------------------------------- +-- Use vectrex_de10_lite.sdc to compile (Timequest constraints) +-- /!\ +-- Don't forget to set device configuration mode with memory initialization +-- (Assignments/Device/Pin options/Configuration mode) +--------------------------------------------------------------------------------- +-- Vectrex beam control hardware +-- Uses via port_A, dac and capacitor to set beam x/y displacement speed +-- when done beam displacement is released (port_B_7 = 0) +-- beam displacement duration is controled by Timer 1 (that drive port_B_7) +-- or by 6809 instructions execution duration. +-- +-- Uses via port_A, dac and capacitor to set beam intensity before displacment + +-- Before drawing any object (or text) the beam position is reset to screen center. +-- via_CA2 is used to reset beam position. +-- +-- Uses via_CB2 to set pen ON/OFF. CB2 is always driven by via shift register (SR) +-- output. SR is loaded with 0xFF for plain line drawing. SR is loaded with 0x00 +-- for displacement with no drawing. SR is loaded with characters graphics +-- (character by character and line by line). SR is ALWAYS used in one shot mode +-- although SR bits are recirculated, SR shift stops on the last data bit (and +-- not on the first bit of data recirculated) +-- +-- Exec_rom uses line drawing with Timer 1 and FF/00 SR loading (FF or 00 with +-- recirculation always output respectively 1 or 0). Timer 1 timeout is checked +-- by software polling loop. +-- +-- Exec_rom draw characters in the following manner : start displacement and feed +-- SR with character grahics (at the right time) till the end of the complete line. +-- Then move down one line and then backward up to the begining of the next line +-- with no drawing. Then start drawing the second line... ans so on 7 times. +-- CPU has enough time to get the next character and the corresponding graphics +-- line data between each SR feed. T1 is not used. +-- +-- Most games seems to use those exec_rom routines. +-- +-- During cut scene of spike sound sample have to be interlaced (through dac) while +-- drawing. Spike uses it's own routine for that job. That routine prepare drawing +-- data (graphics and vx/vy speeds) within working ram before cut scene start to be +-- able to feed sound sample between each movement segment. T1 and SR are used but +-- T1 timeout is not check. CPU expect there is enough time from T1 start to next +-- dac modification (dac ouput is alway vx during move). Modifying dac before T1 +-- timeout will corrupt drawing. eg : when starting from @1230 (clr T1h), T1 must +-- have finished before reaching @11A4 (put sound sample value on dac). Drawing +-- characters with this routine is done by going backward between each character +-- graphic. Beam position is reset to screen center after/before each graphic line. +-- one sound sample is sent to dac after each character graphic. + +--------------------------------------------------------------------------------- +-- Video raster 588*444 < 256k running at 24MHz(25MHz) for VGA 640x480-60Hz +-- (horizontal display) +-- +-- requires 3 access per cycle => +-- | read video scan buffer| Write video scan buffer | write vector beam | +-- => 75Mhz ram access with single ram (13ns access time) +-- +-- implemented here as 4 separated buffers for 4 consecutives pixels +-- 4 phases acces at 24MHz(25MHz) +-- +-- 1) Read 1 pixel from each 4 buffers at video address => 4 pixels to be displayed +-- 2) Write one pixel at beam vector address (ie to one buffer only) +-- 3) Write 1 pixel to each 4 buffers at video address => 4 pixels updated +-- 4) Write one pixel at beam vector address (ie to one buffer only) +-- +-- thus video refresh (VGA) is ok : 4 pixels every 4 clock periods (25MHz) +-- vector beam is continuously written at 12MHz (seems to be ok) +-- +-- Each vram buffer is 64k (256k/4) x 2bits or 4bits +-- +-- 2bits witdh video raster (vram_width) buffer : +-- vector beam write value = 2 +-- video scan decrease this value by 1 after reading at each video frame (60Hz) +-- pixel is displayed full intensity as long as value not equal to 0 +-- +-- 4bits witdh video raster (vram_width) buffer : +-- vector beam write value = 2 in lower bits and intensity (0-3) in upper bits +-- video scan decrease the 2 lower bits by 1 after reading at each video frame (60Hz) +-- pixel is displayed upper bits intensity as long as lower bits value not equal to 0 +-- +--------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.ALL; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity vectrex is +port +( + clock_24 : in std_logic; + clock_12 : in std_logic; + reset : in std_logic; + cpu_clock_o : out std_logic; + + video_r : out std_logic_vector(3 downto 0); + video_g : out std_logic_vector(3 downto 0); + video_b : out std_logic_vector(3 downto 0); + + video_hs : out std_logic; + video_vs : out std_logic; + video_blankn : out std_logic; + video_csync : out std_logic; + + audio_out : out std_logic_vector(9 downto 0); + cart_addr : out std_logic_vector(14 downto 0); + cart_do : in std_logic_vector( 7 downto 0); + cart_rd : out std_logic; + up_1 : in std_logic; + dn_1 : in std_logic; + lf_1 : in std_logic; + rt_1 : in std_logic; + pot_x_1 : in signed(7 downto 0); + pot_y_1 : in signed(7 downto 0); + + up_2 : in std_logic; + dn_2 : in std_logic; + lf_2 : in std_logic; + rt_2 : in std_logic; + pot_x_2 : in signed(7 downto 0); + pot_y_2 : in signed(7 downto 0); + + leds : out std_logic_vector(9 downto 0); + dbg_cpu_addr: out std_logic_vector(15 downto 0) + ); +end vectrex; + +architecture syn of vectrex is + +-------------------------------------------------------------- +-- Configuration +-------------------------------------------------------------- +-- Select catridge rom around line 700 +-------------------------------------------------------------- +-- intensity level : more or less ram +------------------------------------- +-- requires also comment/uncomment at two other places below +-- + constant vram_width : integer := 2; -- no intensity level +-- constant vram_width : integer := 4; -- 3 intensity level +-------------------------------------------------------------- +-- horizontal display (comment/uncomment whole section) +--------------------- +-- constant horizontal_display : integer := 1; +-- constant max_h : integer := 588; -- have to be multiple of 4 +-- constant max_v : integer := 444; +-- constant max_x : integer := 16875*8; +-- constant max_y : integer := 22500*8; +-- constant vram_addr_width : integer := 16; -- 64k vram buffer (x4) +-- constant video_start_h : integer := 160; +-- constant video_start_v : integer := 50; +-------------------------------------------------------------- +-- vertical display (comment/uncomment whole section) +------------------- + constant horizontal_display : integer := 0; + constant max_h : integer := 312; -- have to be multiple of 4 + constant max_v : integer := 416; + constant max_x : integer := 22500*8; + constant max_y : integer := 16875*8; + constant vram_addr_width : integer := 15; -- 32k vram buffer (x4) + constant video_start_h : integer := 300; + constant video_start_v : integer := 70; +-------------------------------------------------------------- + + signal clock_24n : std_logic; + signal clock_div : std_logic_vector(2 downto 0); + signal reset_n : std_logic; + + signal cpu_clock : 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_rw : std_logic; + signal cpu_irq : std_logic; + signal cpu_firq : std_logic; + signal cpu_fetch : std_logic; + + signal ram_cs : std_logic; + signal ram_do : std_logic_vector( 7 downto 0); + signal ram_we : std_logic; + + signal rom_cs : std_logic; + signal rom_do : std_logic_vector( 7 downto 0); + + signal cart_cs : std_logic; + --signal cart_do : std_logic_vector( 7 downto 0); + + signal via_cs_n : std_logic; + signal via_do : std_logic_vector(7 downto 0); + signal via_ca1_i : std_logic; + signal via_ca2_o : std_logic; + signal via_cb2_o : std_logic; + signal via_pa_i : std_logic_vector(7 downto 0); + signal via_pa_o : std_logic_vector(7 downto 0); + signal via_pb_i : std_logic_vector(7 downto 0); + signal via_pb_o : std_logic_vector(7 downto 0); + signal via_irq_n : std_logic; + signal via_en_4 : std_logic; + + signal sh_dac : std_logic; + signal dac_mux : std_logic_vector(2 downto 1); + signal zero_integrator_n : std_logic; + signal ramp_integrator_n : std_logic; + signal beam_blank_n : std_logic; + + signal dac : signed(8 downto 0); + signal dac_y : signed(8 downto 0); + signal dac_z : unsigned(7 downto 0); + signal ref_level : signed(8 downto 0); + signal z_level : std_logic_vector(1 downto 0); + signal dac_sound : std_logic_vector(7 downto 0); + + signal integrator_x : signed(19 downto 0); + signal integrator_y : signed(19 downto 0); + + signal shifted_x : signed(19 downto 0); + signal shifted_y : signed(19 downto 0); + + signal limited_x : unsigned(19 downto 0); + signal limited_y : unsigned(19 downto 0); + + signal beam_h : unsigned(9 downto 0); + signal beam_v : unsigned(9 downto 0); + + constant offset_y : integer := 0; + constant offset_x : integer := 0; + + constant scale_x : integer := max_v*256*256/(2*max_x); + constant scale_y : integer := max_h*256*256/(2*max_y); + + signal beam_blank_buffer : std_logic_vector(5 downto 0); + signal beam_blank_n_delayed : std_logic; + + signal beam_video_addr : std_logic_vector(19 downto 0); + signal scan_video_addr : std_logic_vector(19 downto 0); + signal video_addr : std_logic_vector(16 downto 0); + + signal phase : std_logic_vector(1 downto 0); + + signal video_we_0 : std_logic; + signal video_we_1 : std_logic; + signal video_we_2 : std_logic; + signal video_we_3 : std_logic; + signal video_rd : std_logic; + signal video_pixel: std_logic_vector(3 downto 0); + + signal read_0 : std_logic_vector(vram_width-1 downto 0); + signal read_0b: std_logic_vector(vram_width-1 downto 0); + signal read_1 : std_logic_vector(vram_width-1 downto 0); + signal read_1b: std_logic_vector(vram_width-1 downto 0); + signal read_2 : std_logic_vector(vram_width-1 downto 0); + signal read_2b: std_logic_vector(vram_width-1 downto 0); + signal read_3 : std_logic_vector(vram_width-1 downto 0); + signal read_3b: std_logic_vector(vram_width-1 downto 0); + signal pixel : std_logic_vector(vram_width-1 downto 0); + + signal write_0 : std_logic_vector(vram_width-1 downto 0); + signal write_1 : std_logic_vector(vram_width-1 downto 0); + signal write_2 : std_logic_vector(vram_width-1 downto 0); + signal write_3 : std_logic_vector(vram_width-1 downto 0); + + signal hcnt : std_logic_vector(9 downto 0); + signal vcnt : std_logic_vector(9 downto 0); + signal hcnt_video : std_logic_vector(9 downto 0); + signal vcnt_video : std_logic_vector(9 downto 0); + + signal hblank : std_logic; + signal vblank : std_logic; + + signal frame_line : std_logic; + + signal ay_do : std_logic_vector(7 downto 0); + signal ay_audio_muxed : std_logic_vector(7 downto 0); + signal ay_audio_chan : std_logic_vector(1 downto 0); + signal ay_chan_a : std_logic_vector(7 downto 0); + signal ay_chan_b : std_logic_vector(7 downto 0); + signal ay_chan_c : std_logic_vector(7 downto 0); + + signal pot : signed(7 downto 0); + signal compare : std_logic; + signal players_switches : std_logic_vector(7 downto 0); + +begin + +-- debug +process (clock_12, cpu_fetch) +begin + if rising_edge(clock_12) then + dbg_cpu_addr <= cpu_addr; + end if; +end process; + +leds(7 downto 0) <= dac_sound; +-------------------- + +-- clocks +reset_n <= not reset; +clock_24n <= not clock_24; + +process (clock_12, reset) + begin + if reset='1' then + clock_div <= "000"; + else + if rising_edge(clock_12) then + if clock_div = "111" then + clock_div <= "000"; + else + clock_div <= clock_div + '1'; + end if; + end if; + end if; +end process; + +via_en_4 <= clock_div(0); +cpu_clock <= clock_div(2); +cpu_clock_o <= clock_div(2); + +--static ADDRESS_MAP_START(vectrex_map, AS_PROGRAM, 8, vectrex_state ) +-- AM_RANGE(0x0000, 0x7fff) AM_NOP // cart area, handled at machine_start +-- AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_SHARE("gce_vectorram") +-- AM_RANGE(0xd000, 0xd7ff) AM_READWRITE(vectrex_via_r, vectrex_via_w) +-- AM_RANGE(0xe000, 0xffff) AM_ROM AM_REGION("maincpu", 0) +--ADDRESS_MAP_END + +-- chip select +cart_cs <= '1' when cpu_addr(15) = '0' else '0'; +ram_cs <= '1' when cpu_addr(15 downto 12) = X"C" else '0'; +via_cs_n <= '0' when cpu_addr(15 downto 12) = X"D" else '1'; +rom_cs <= '1' when cpu_addr(15 downto 13) = "111" else '0'; + +-- write enable working ram +ram_we <= '1' when cpu_rw = '0' and ram_cs = '1' else '0'; + +-- misc +cpu_irq <= not via_irq_n; +cpu_firq <= '0'; +cart_rd <= cart_cs; +cpu_di <= cart_do when cart_cs = '1' else + ram_do when ram_cs = '1' else + via_do when via_cs_n = '0' else + rom_do when rom_cs = '1' else + X"00"; + +via_pa_i <= ay_do; +via_pb_i <= "00"&compare&"00000"; + +-- players controls +players_switches <= not(rt_2&lf_2&dn_2&up_2&rt_1&lf_1&dn_1&up_1); + +with dac_mux select +pot <= pot_x_1 when "00", + pot_y_1 when "01", + pot_x_2 when "10", + pot_y_2 when others; + +compare <= '1' when (pot(7)&pot) > dac else '0'; + +-- beam control +sh_dac <= via_pb_o(0); +dac_mux <= via_pb_o(2 downto 1); +zero_integrator_n <= via_ca2_o; +ramp_integrator_n <= via_pb_o(7); +beam_blank_n <= via_cb2_o; + +dac <= signed(via_pa_o(7)&via_pa_o); -- must ensure sign extension for 0x80 value to be used in integrator equation + +z_level <= "11" when dac_z > 128 else + "10" when dac_Z > 64 else + "01" when dac_z > 0 else + "00"; + +process (clock_12, reset) + variable limit_n : std_logic; +begin + if reset='1' then + null; + else + if rising_edge(clock_12) then + if sh_dac = '0' then + case dac_mux is + when "00" => dac_y <= dac; + when "01" => ref_level <= dac; + when "10" => dac_z <= unsigned(via_pa_o); + when others => dac_sound <= via_pa_o; + end case; + end if; + + if zero_integrator_n = '0' then + integrator_x <= (others=>'0'); + integrator_y <= (others=>'0'); + else + if ramp_integrator_n = '0' then + if horizontal_display = 1 then + integrator_x <= integrator_x + (ref_level - dac); -- horizontal display + integrator_y <= integrator_y + (ref_level - dac_y); -- horizontal display + else + integrator_x <= integrator_x + (ref_level - dac_y); -- vertical display + integrator_y <= integrator_y - (ref_level - dac); -- vertical display + end if; + end if; + end if; + + -- set 'preserve registers' wihtin assignments editor to ease signaltap debuging + + shifted_x <= integrator_x+max_x-offset_x; + shifted_y <= integrator_y+max_y-offset_y; + + -- limit and scaling should be enhanced + + limit_n := '1'; + if shifted_x > 2*max_x then limited_x <= to_unsigned(2*max_x,20); + limit_n := '0'; + elsif shifted_x < 0 then limited_x <= (others=>'0'); + limit_n := '0'; + else limited_x <= unsigned(shifted_x); end if; + + if shifted_y > 2*max_y then limited_y <= to_unsigned(2*max_y,20); + limit_n := '0'; + elsif shifted_y < 0 then limited_y <= (others=>'0'); + limit_n := '0'; + else limited_y <= unsigned(shifted_y); end if; + + -- integer computation to try making rounding computation during division + + beam_v <= to_unsigned(to_integer(limited_x*to_unsigned(scale_x,10))/(256*256),10); + beam_h <= to_unsigned(to_integer(limited_y*to_unsigned(scale_y,10))/(256*256),10); + + beam_video_addr <= std_logic_vector(beam_v * to_unsigned(max_h,10) + beam_h); + + -- compense beam_video_addr computation delay vs beam_blank + + beam_blank_buffer <= beam_blank_buffer(4 downto 0) & beam_blank_n; + + beam_blank_n_delayed <= beam_blank_buffer(3) and limit_n; + + end if; + end if; +end process; + +-- video buffer +-- +-- 4 phases : (beam is fully asynchrone with video scanner) +-- +-- |read previous pixels| write beam pixel | write updated pixels | write beam pixel | +-- |from the 4 buffers | to one buffer | to the 4 buffers | to one buffer | +-- +-- Persistance simulation : +-- beam pixel are written as value 2 +-- updated pixels is written as previous value-1 +-- previous pixels are demuxed (serialized) and send to display +-- pixel is ON if value > 0 +-- +-- Intensity simulation : +-- if used (vram_witdh = 4) intensity is written by beam or read by scanner simultaneoulsy +-- with pixels. Its value is never modified. +-- +-- Compared to real hardware : +-- - fixed beam position has no effect on diplayed intensity. +-- - persitance management may show double trace for fast moving object +-- - flicker may appear where only lower intensity will be seen +-- +process (reset, clock_24) +begin + if reset='1' then + phase <= (others => '0'); + else + if rising_edge(clock_24) then + phase <= hcnt_video(1 downto 0); + + video_we_0 <= '0'; + video_we_1 <= '0'; + video_we_2 <= '0'; + video_we_3 <= '0'; + + case phase is + when "00" => + video_addr <= scan_video_addr(18 downto 2); + + when "10" => + video_addr <= scan_video_addr(18 downto 2); + if hblank = '0' and vblank = '0' then + if read_0(1 downto 0) > "00" then video_we_0 <= '1'; write_0 <= read_0 - '1'; end if; + if read_1(1 downto 0) > "00" then video_we_1 <= '1'; write_1 <= read_1 - '1'; end if; + if read_2(1 downto 0) > "00" then video_we_2 <= '1'; write_2 <= read_2 - '1'; end if; + if read_3(1 downto 0) > "00" then video_we_3 <= '1'; write_3 <= read_3 - '1'; end if; + end if; + + when others => + video_addr <= beam_video_addr(18 downto 2); + if beam_blank_n_delayed = '1' then + case beam_video_addr(1 downto 0) is + +-- uncomment when vram_width is 4 +-- when "00" => video_we_0 <= '1'; write_0 <= z_level&"10"; +-- when "01" => video_we_1 <= '1'; write_1 <= z_level&"10"; +-- when "10" => video_we_2 <= '1'; write_2 <= z_level&"10"; +-- when others => video_we_3 <= '1'; write_3 <= z_level&"10"; +-- +-- uncomment when vram_width is 2 + when "00" => video_we_0 <= '1'; write_0 <= "10"; + when "01" => video_we_1 <= '1'; write_1 <= "10"; + when "10" => video_we_2 <= '1'; write_2 <= "10"; + when others => video_we_3 <= '1'; write_3 <= "10"; +-- + end case; + end if; + end case; + + if phase = "01" then + read_0 <= read_0b; + read_1 <= read_1b; + read_2 <= read_2b; + read_3 <= read_3b; + end if; + + case phase is + when "10" => pixel <= read_0; + when "11" => pixel <= read_1; + when "00" => pixel <= read_2; + when others => pixel <= read_3; + end case; + + end if; + end if; +end process; + +-- uncomment when vram_width is 4 +-- +--video_pixel <= pixel(3 downto 2)&"00" when (pixel(1 downto 0) > "00") and (hblank = '0') else "0000"; +-- +-- uncomment when vram_width is 2 +-- +video_pixel <= "1100" when (pixel(1 downto 0) > "00") and (hblank = '0') else "0000"; +-- + +video_g <= video_pixel when frame_line = '0' else video_pixel or "0000"; +video_b <= video_pixel when frame_line = '0' else video_pixel or "0000"; +video_r <= video_pixel when frame_line = '0' else video_pixel or "0100"; + +buf_0 : entity work.gen_ram +generic map( dWidth => vram_width, aWidth => vram_addr_width) +port map( clk => clock_24n, we => video_we_0, addr => video_addr(vram_addr_width-1 downto 0), + d => write_0, q => read_0b); + +buf_1 : entity work.gen_ram +generic map( dWidth => vram_width, aWidth => vram_addr_width) +port map( clk => clock_24n, we => video_we_1, addr => video_addr(vram_addr_width-1 downto 0), + d => write_1, q => read_1b); + +buf_2 : entity work.gen_ram +generic map( dWidth => vram_width, aWidth => vram_addr_width) +port map( clk => clock_24n, we => video_we_2, addr => video_addr(vram_addr_width-1 downto 0), + d => write_2, q => read_2b); + +buf_3 : entity work.gen_ram +generic map( dWidth => vram_width, aWidth => vram_addr_width) +port map( clk => clock_24n, we => video_we_3, addr => video_addr(vram_addr_width-1 downto 0), + d => write_3, q => read_3b); + +------------------- +-- Video scanner -- +------------------- +process (reset, clock_24) +begin + if reset='1' then + hcnt <= (others => '0'); + vcnt <= (others => '0'); + else + if rising_edge(clock_24) then + + hcnt <= hcnt + '1'; + if hcnt = 799 then + hcnt <= (others => '0'); + if vcnt = 523 then + vcnt <= (others => '0'); + else + vcnt <= vcnt + '1'; + end if; + if vcnt = 523 then video_vs <= '0'; end if; + if vcnt = 1 then video_vs <= '1'; end if; + end if; + + if hcnt = 799 then video_hs <= '0'; end if; + if hcnt = 90 then video_hs <= '1'; end if; + + if vcnt_video = 0 or vcnt_video = (max_v-1) then + if hcnt_video = 3 then frame_line <= '1'; end if; + if hcnt_video = max_h+3 then frame_line <= '0'; end if; + elsif vcnt_video > 0 and vcnt_video < (max_v-1) then + if hcnt_video = 3 or hcnt_video = max_h+2 then frame_line <= '1'; + else frame_line <= '0'; end if; + else frame_line <= '0'; end if; + + if hcnt = video_start_h then + hcnt_video <= (others => '0'); + if vcnt = video_start_v then + vcnt_video <= (others => '0'); + else + vcnt_video <= vcnt_video + '1'; + end if; + else + hcnt_video <= hcnt_video + '1'; + end if; + + if hcnt_video = 3 then hblank <= '0'; end if; + if hcnt_video = max_h+3 then hblank <= '1'; end if; + if vcnt_video = 0 then vblank <= '0'; end if; + if vcnt_video = max_v then vblank <= '1'; end if; + + end if; + end if; +end process; + +video_blankn <= not (hblank or vblank); + +scan_video_addr <= vcnt_video * std_logic_vector(to_unsigned(max_h,10)) + hcnt_video; + +-- sound +process (cpu_clock) +begin + if rising_edge(cpu_clock) 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_out <= ("00"&ay_chan_a) + + ("00"&ay_chan_b) + + ("00"&ay_chan_c) + + ("00"&dac_sound); + +--------------------------- +-- components +--------------------------- + +-- microprocessor 6809 +main_cpu : entity work.cpu09 +port map( + clk => cpu_clock,-- E clock input (falling edge) + rst => reset, -- reset input (active high) + vma => open, -- valid memory address (active high) + lic_out => open, -- last instruction cycle (active high) + ifetch => open, -- instruction fetch cycle (active high) + opfetch => cpu_fetch,-- opcode fetch (active high) + ba => open, -- bus available (high on sync wait or DMA grant) + bs => open, -- bus status (high on interrupt or reset vector fetch or DMA grant) + addr => cpu_addr, -- address bus output + rw => cpu_rw, -- read not write output + data_out => cpu_do, -- data bus output + data_in => cpu_di, -- data bus input + irq => cpu_irq, -- interrupt request input (active high) + firq => cpu_firq, -- fast interrupt request input (active high) + nmi => '0', -- non maskable interrupt request input (active high) + halt => '0', -- halt input (active high) grants DMA + hold_in => '0' -- hold input (active high) extend bus cycle +); + + +cpu_prog_rom : entity work.vectrex_exec_prom +port map( + clk => cpu_clock, + addr => cpu_addr(12 downto 0), + data => rom_do +); + +-------------------------------------------------------------------- +-- Select cartridge here, select right rom length within port map + +--cart_do <= (others => '0'); -- no cartridge + +--cart_rom : entity work.vectrex_AGT_prom +--cart_rom : entity work.vectrex_scramble_prom +--cart_rom : entity work.vectrex_berzerk_prom +--cart_rom : entity work.vectrex_spacewar_prom +--cart_rom : entity work.vectrex_frogger_prom +--cart_rom : entity work.vectrex_polepos_prom +--cart_rom : entity work.vectrex_ripoff_prom +--cart_rom : entity work.vectrex_spike_prom +--cart_rom : entity work.vectrex_startrek_prom +--cart_rom : entity work.vectrex_vecmania1_prom +--cart_rom : entity work.vectrex_webwars_prom +--cart_rom : entity work.vectrex_wotr_prom + +--port map( +-- clk => cpu_clock, +-- addr => cpu_addr(11 downto 0), -- scramble,berzerk,ripoff,spacewar,startrek +-- addr => cpu_addr(12 downto 0), -- polepos,spike,webwars +-- addr => cpu_addr(13 downto 0), -- frogger,AGT +-- addr => cpu_addr(14 downto 0), -- vecmania,wotr + --data => cart_do +--); +-------------------------------------------------------------------- + + cart_addr <= cpu_addr(14 downto 0); + +working_ram : entity work.gen_ram +generic map( dWidth => 8, aWidth => 10) +port map( + clk => cpu_clock, + we => ram_we, + addr => cpu_addr(9 downto 0), + d => cpu_do, + q => ram_do +); + +via6522_inst : entity work.M6522 +port map( + I_RS => cpu_addr(3 downto 0), + I_DATA => cpu_do, + O_DATA => via_do, + O_DATA_OE_L => open, + + I_RW_L => cpu_rw, + I_CS1 => cpu_addr(12), + I_CS2_L => via_cs_n, + + O_IRQ_L => via_irq_n, + + -- port a + I_CA1 => via_ca1_i, + I_CA2 => '0', + O_CA2 => via_ca2_o, + O_CA2_OE_L => open, + + I_PA => via_pa_i, + O_PA => via_pa_o, + O_PA_OE_L => open, + + -- port b + I_CB1 => '0', + O_CB1 => open, + O_CB1_OE_L => open, + + I_CB2 => '0', + O_CB2 => via_cb2_o, + O_CB2_OE_L => open, + + I_PB => via_pb_i, + O_PB => via_pb_o, + O_PB_OE_L => open, + + RESET_L => reset_n, + CLK => clock_12, + I_P2_H => cpu_clock, -- high for phase 2 clock ____----__ + 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 => '0', -- in std_logic; + + O_AUDIO => ay_audio_muxed, -- out std_logic_vector(7 downto 0); + O_CHAN => ay_audio_chan, -- out std_logic_vector(1 downto 0); + + -- port a + I_IOA => players_switches, -- in std_logic_vector(7 downto 0); + O_IOA => open, -- out std_logic_vector(7 downto 0); + O_IOA_OE_L => open, -- 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; + + ENA => '1', --cpu_ena, -- in std_logic; -- clock enable for higher speed operation + RESET_L => reset_n, -- in std_logic; + CLK => cpu_clock -- in std_logic -- note 6 Mhz +); + +end SYN; diff --git a/GCE - Vectrex_MiST/rtl/vectrex_exec_prom.vhd b/GCE - Vectrex_MiST/rtl/vectrex_exec_prom.vhd new file mode 100644 index 00000000..4431ba3c --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/vectrex_exec_prom.vhd @@ -0,0 +1,534 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity vectrex_exec_prom is +port ( + clk : in std_logic; + addr : in std_logic_vector(12 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of vectrex_exec_prom is + type rom is array(0 to 8191) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"ED",X"77",X"F8",X"50",X"30",X"E8",X"4D",X"49",X"4E",X"45",X"80",X"F8",X"50",X"00",X"DE",X"53", + X"54",X"4F",X"52",X"4D",X"80",X"00",X"8E",X"C8",X"83",X"6F",X"80",X"8C",X"CB",X"C5",X"26",X"F9", + X"BD",X"E8",X"E3",X"7C",X"C8",X"24",X"86",X"BB",X"B7",X"C8",X"80",X"8E",X"01",X"01",X"BF",X"C8", + X"81",X"8E",X"C8",X"83",X"6F",X"80",X"8C",X"CB",X"70",X"26",X"F9",X"20",X"00",X"BD",X"F1",X"AF", + X"CC",X"02",X"00",X"BD",X"F7",X"A9",X"0A",X"79",X"0F",X"56",X"0F",X"9B",X"8E",X"C8",X"A8",X"BD", + X"F8",X"4F",X"8E",X"C8",X"AF",X"BD",X"F8",X"4F",X"8E",X"C8",X"F9",X"BD",X"F8",X"4F",X"CC",X"00", + X"01",X"BD",X"F8",X"7C",X"8E",X"C9",X"00",X"BD",X"F8",X"4F",X"CC",X"00",X"01",X"BD",X"F8",X"7C", + X"8E",X"ED",X"AB",X"9F",X"C4",X"9F",X"C6",X"86",X"05",X"97",X"D9",X"97",X"DA",X"97",X"DB",X"20", + X"24",X"BD",X"E8",X"66",X"10",X"8E",X"C8",X"C4",X"96",X"9B",X"AE",X"A6",X"30",X"04",X"AF",X"A6", + X"8E",X"ED",X"A7",X"96",X"9B",X"AE",X"86",X"A6",X"05",X"84",X"03",X"26",X"02",X"0C",X"D9",X"CC", + X"00",X"01",X"BD",X"F8",X"7C",X"BD",X"E7",X"E4",X"8E",X"C8",X"C4",X"96",X"9B",X"AE",X"86",X"A6", + X"84",X"2B",X"05",X"BD",X"E1",X"29",X"20",X"41",X"DC",X"F0",X"83",X"00",X"01",X"DD",X"F0",X"27", + X"14",X"34",X"08",X"BD",X"F1",X"AA",X"BD",X"EA",X"CF",X"CE",X"EE",X"2F",X"BD",X"EA",X"9D",X"35", + X"08",X"96",X"0F",X"27",X"24",X"8E",X"C8",X"A8",X"CE",X"CB",X"EB",X"BD",X"F8",X"D8",X"8E",X"C8", + X"AF",X"CE",X"CB",X"EB",X"BD",X"F8",X"D8",X"DC",X"F0",X"10",X"26",X"FF",X"44",X"BD",X"F1",X"8B", + X"0F",X"3B",X"10",X"CE",X"CB",X"EA",X"7E",X"F0",X"1C",X"34",X"08",X"BD",X"EA",X"F0",X"BD",X"E5", + X"1E",X"BD",X"E2",X"62",X"BD",X"E4",X"B8",X"BD",X"E3",X"53",X"35",X"08",X"BD",X"EB",X"43",X"BD", + X"EC",X"46",X"BD",X"EC",X"95",X"BD",X"E6",X"47",X"25",X"DF",X"96",X"BD",X"10",X"27",X"FF",X"61", + X"96",X"BE",X"10",X"26",X"FF",X"92",X"7E",X"E0",X"A5",X"9F",X"C2",X"CC",X"7F",X"00",X"DD",X"DC", + X"97",X"B7",X"86",X"20",X"97",X"9C",X"8E",X"E1",X"E7",X"9F",X"9D",X"8E",X"C9",X"33",X"9F",X"B9", + X"86",X"1D",X"97",X"B8",X"0F",X"56",X"CE",X"ED",X"77",X"BD",X"F6",X"8D",X"34",X"08",X"BD",X"E7", + X"11",X"BD",X"F6",X"87",X"96",X"26",X"85",X"01",X"26",X"02",X"0A",X"B7",X"BD",X"EA",X"F0",X"BD", + X"EA",X"CF",X"BD",X"F2",X"89",X"BD",X"E5",X"1E",X"BD",X"F2",X"A5",X"F6",X"C8",X"B7",X"27",X"1C", + X"8E",X"EF",X"26",X"10",X"BE",X"C8",X"DC",X"BD",X"EA",X"7F",X"8E",X"EF",X"5D",X"BD",X"EA",X"7F", + X"8E",X"EF",X"94",X"BD",X"EA",X"7F",X"35",X"08",X"0A",X"DC",X"20",X"C0",X"35",X"08",X"0F",X"9C", + X"86",X"04",X"97",X"B7",X"86",X"7F",X"97",X"B8",X"96",X"B7",X"27",X"4A",X"D6",X"B8",X"27",X"04", + X"0A",X"B8",X"20",X"12",X"D6",X"26",X"C4",X"1F",X"26",X"0C",X"4A",X"97",X"B7",X"9E",X"C2",X"A6", + X"86",X"C6",X"03",X"BD",X"E9",X"A1",X"34",X"08",X"BD",X"EA",X"F0",X"BD",X"F2",X"A9",X"CE",X"EE", + X"20",X"BD",X"EA",X"9D",X"10",X"8E",X"E0",X"F8",X"CE",X"ED",X"A7",X"B6",X"C8",X"9B",X"EE",X"C6", + X"BD",X"EA",X"A8",X"BD",X"E5",X"1E",X"BD",X"E2",X"62",X"BD",X"E4",X"B8",X"35",X"08",X"BD",X"EB", + X"43",X"BD",X"E6",X"47",X"20",X"B2",X"39",X"0A",X"B8",X"27",X"4E",X"0C",X"ED",X"BD",X"F5",X"17", + X"84",X"07",X"8B",X"04",X"97",X"9C",X"DE",X"B9",X"86",X"80",X"A7",X"C4",X"DC",X"DC",X"8B",X"08", + X"A7",X"44",X"6F",X"45",X"E7",X"46",X"6F",X"47",X"BD",X"F5",X"17",X"4D",X"2B",X"0C",X"81",X"10", + X"2C",X"02",X"8B",X"0C",X"81",X"60",X"2F",X"0E",X"20",X"EE",X"81",X"F0",X"2F",X"02",X"80",X"0C", + X"81",X"A0",X"2C",X"02",X"20",X"E2",X"A7",X"C8",X"11",X"1F",X"89",X"1D",X"8A",X"01",X"A7",X"C8", + X"10",X"6F",X"42",X"31",X"C8",X"12",X"10",X"9F",X"B9",X"39",X"00",X"02",X"07",X"10",X"00",X"20", + X"18",X"10",X"01",X"00",X"05",X"00",X"03",X"25",X"07",X"50",X"00",X"00",X"01",X"00",X"00",X"35", + X"00",X"00",X"00",X"00",X"04",X"04",X"08",X"08",X"0D",X"0D",X"EE",X"3D",X"EE",X"53",X"EE",X"6F", + X"EE",X"8E",X"34",X"08",X"86",X"C8",X"1F",X"8B",X"96",X"BD",X"10",X"26",X"00",X"9C",X"96",X"EE", + X"10",X"26",X"00",X"A7",X"96",X"13",X"10",X"26",X"00",X"92",X"96",X"14",X"27",X"32",X"96",X"D4", + X"91",X"D6",X"27",X"1C",X"91",X"D8",X"27",X"08",X"96",X"D5",X"27",X"14",X"96",X"D7",X"26",X"20", + X"96",X"D7",X"8B",X"0C",X"81",X"7F",X"22",X"18",X"97",X"D7",X"96",X"D4",X"97",X"D8",X"20",X"0E", + X"96",X"D5",X"8B",X"0C",X"81",X"7F",X"22",X"08",X"97",X"D5",X"96",X"D4",X"97",X"D6",X"0C",X"F2", + X"96",X"D5",X"27",X"0E",X"80",X"02",X"97",X"D5",X"D6",X"D6",X"BD",X"E7",X"B5",X"10",X"9F",X"CC", + X"9F",X"CE",X"96",X"D7",X"27",X"0E",X"80",X"02",X"97",X"D7",X"D6",X"D8",X"BD",X"E7",X"B5",X"10", + X"9F",X"D0",X"9F",X"D2",X"DC",X"C8",X"D3",X"CC",X"D3",X"D0",X"DD",X"C8",X"DC",X"CA",X"D3",X"CE", + X"D3",X"D2",X"DD",X"CA",X"96",X"1B",X"27",X"0F",X"2B",X"04",X"0A",X"D4",X"20",X"06",X"0C",X"D4", + X"20",X"02",X"34",X"08",X"BD",X"E8",X"4C",X"86",X"D0",X"1F",X"8B",X"BD",X"F2",X"A5",X"C6",X"0C", + X"10",X"8E",X"C8",X"C8",X"8E",X"CB",X"89",X"BD",X"EA",X"8D",X"35",X"88",X"86",X"80",X"97",X"EE", + X"BD",X"F5",X"17",X"84",X"03",X"8B",X"03",X"97",X"EF",X"0C",X"F6",X"96",X"EE",X"2A",X"19",X"0A", + X"EF",X"27",X"0D",X"BD",X"E9",X"8A",X"97",X"C8",X"0F",X"C9",X"D7",X"CA",X"0F",X"CB",X"35",X"88", + X"04",X"EE",X"86",X"1F",X"97",X"EF",X"35",X"88",X"D6",X"EF",X"C1",X"E0",X"2F",X"0C",X"96",X"EF", + X"80",X"04",X"97",X"EF",X"4F",X"BD",X"E9",X"4A",X"35",X"88",X"0F",X"EF",X"0F",X"EE",X"BD",X"E8", + X"37",X"35",X"88",X"B6",X"C8",X"E7",X"27",X"2B",X"34",X"08",X"86",X"C8",X"1F",X"8B",X"96",X"E7", + X"27",X"21",X"DC",X"DE",X"D3",X"E2",X"DD",X"DE",X"97",X"DC",X"DC",X"E0",X"D3",X"E4",X"DD",X"E0", + X"97",X"DD",X"35",X"08",X"BD",X"F2",X"A5",X"C6",X"08",X"10",X"BE",X"C8",X"DC",X"8E",X"EF",X"B3", + X"BD",X"EA",X"7F",X"39",X"8E",X"E3",X"A1",X"9F",X"A3",X"BD",X"F5",X"17",X"8E",X"E4",X"48",X"84", + X"06",X"AE",X"86",X"EC",X"81",X"DD",X"DC",X"97",X"DE",X"0F",X"DF",X"D7",X"E0",X"0F",X"E1",X"20", + X"58",X"96",X"BF",X"26",X"19",X"BD",X"F5",X"17",X"84",X"7F",X"8B",X"30",X"97",X"A2",X"BD",X"F5", + X"17",X"84",X"3F",X"97",X"E6",X"BD",X"F5",X"17",X"8B",X"10",X"97",X"E7",X"20",X"49",X"96",X"BD", + X"26",X"E3",X"C6",X"1C",X"CE",X"C9",X"33",X"A6",X"C4",X"27",X"08",X"33",X"C8",X"12",X"5A",X"26", + X"F6",X"20",X"34",X"0C",X"ED",X"0A",X"BF",X"9E",X"DE",X"AF",X"44",X"9E",X"E0",X"AF",X"46",X"86", + X"40",X"A7",X"C4",X"96",X"C0",X"26",X"10",X"8E",X"E4",X"12",X"9F",X"9D",X"BD",X"F5",X"17",X"84", + X"7F",X"8B",X"40",X"97",X"9C",X"0C",X"C0",X"9E",X"E8",X"A6",X"80",X"97",X"A2",X"A6",X"80",X"97", + X"E6",X"A6",X"80",X"97",X"E7",X"9F",X"E8",X"D6",X"E6",X"BD",X"E7",X"B5",X"10",X"9F",X"E2",X"9F", + X"E4",X"39",X"CE",X"C8",X"C4",X"96",X"9B",X"EE",X"C6",X"A6",X"C4",X"C6",X"03",X"BD",X"E9",X"A1", + X"8E",X"E4",X"26",X"9F",X"9D",X"39",X"0A",X"C1",X"27",X"06",X"86",X"FF",X"97",X"9C",X"20",X"17", + X"BD",X"F5",X"17",X"1F",X"89",X"C4",X"03",X"26",X"02",X"CB",X"01",X"CE",X"C8",X"C4",X"96",X"9B", + X"EE",X"C6",X"A6",X"C4",X"BD",X"E9",X"A1",X"39",X"E4",X"50",X"E4",X"6A",X"E4",X"84",X"E4",X"9E", + X"7F",X"00",X"28",X"20",X"30",X"40",X"28",X"30",X"28",X"00",X"10",X"30",X"10",X"40",X"18",X"20", + X"50",X"40",X"30",X"28",X"30",X"08",X"60",X"7F",X"38",X"70",X"80",X"00",X"40",X"00",X"30",X"20", + X"10",X"50",X"20",X"28",X"40",X"30",X"3E",X"70",X"18",X"30",X"60",X"20",X"18",X"40",X"30",X"24", + X"50",X"7F",X"06",X"70",X"00",X"7F",X"40",X"10",X"60",X"28",X"38",X"30",X"28",X"08",X"40",X"30", + X"28",X"7F",X"20",X"18",X"30",X"30",X"08",X"68",X"40",X"20",X"50",X"7F",X"38",X"70",X"00",X"80", + X"40",X"30",X"60",X"38",X"18",X"30",X"30",X"20",X"18",X"20",X"38",X"40",X"28",X"10",X"60",X"20", + X"00",X"30",X"40",X"38",X"50",X"7F",X"1C",X"70",X"86",X"04",X"CE",X"C9",X"0B",X"8E",X"C8",X"15", + X"B7",X"C8",X"8F",X"BD",X"F2",X"A9",X"A6",X"C4",X"27",X"22",X"6A",X"49",X"27",X"19",X"EC",X"45", + X"E3",X"41",X"ED",X"45",X"EC",X"47",X"E3",X"43",X"ED",X"47",X"31",X"45",X"BD",X"EA",X"6D",X"33", + X"4A",X"7A",X"C8",X"8F",X"26",X"E0",X"39",X"6F",X"C4",X"7A",X"C8",X"EA",X"B6",X"C8",X"BD",X"26", + X"EE",X"B6",X"C8",X"EE",X"26",X"E9",X"A6",X"84",X"27",X"E5",X"6F",X"84",X"7C",X"C8",X"B6",X"6C", + X"C4",X"FC",X"C8",X"C8",X"ED",X"45",X"FC",X"C8",X"CA",X"ED",X"47",X"FC",X"C9",X"07",X"ED",X"41", + X"FC",X"C9",X"09",X"ED",X"43",X"86",X"18",X"A7",X"49",X"7C",X"C8",X"EA",X"20",X"C1",X"86",X"1C", + X"B7",X"C8",X"8F",X"CE",X"C9",X"33",X"A6",X"C4",X"26",X"09",X"33",X"C8",X"12",X"7A",X"C8",X"8F", + X"26",X"F4",X"39",X"10",X"2B",X"00",X"9C",X"85",X"40",X"10",X"26",X"00",X"A4",X"85",X"20",X"10", + X"26",X"00",X"A9",X"85",X"10",X"10",X"26",X"00",X"D4",X"85",X"01",X"10",X"26",X"00",X"D8",X"A6", + X"41",X"81",X"04",X"27",X"56",X"85",X"01",X"27",X"31",X"B6",X"C8",X"EE",X"26",X"2C",X"B6",X"C8", + X"BD",X"26",X"27",X"34",X"08",X"BD",X"F1",X"AF",X"96",X"C8",X"A0",X"44",X"D6",X"CA",X"E0",X"46", + X"BD",X"F5",X"93",X"80",X"10",X"97",X"83",X"8E",X"E2",X"3E",X"E6",X"43",X"A6",X"85",X"D6",X"83", + X"BD",X"E7",X"B5",X"10",X"AF",X"48",X"AF",X"4A",X"35",X"08",X"EC",X"44",X"E3",X"48",X"ED",X"44", + X"EC",X"46",X"E3",X"4A",X"ED",X"46",X"BD",X"F2",X"A5",X"8E",X"E2",X"5A",X"A6",X"41",X"48",X"AE", + X"86",X"31",X"44",X"E6",X"42",X"BD",X"EA",X"8D",X"7E",X"E5",X"2A",X"EC",X"44",X"E3",X"48",X"29", + X"1A",X"ED",X"44",X"EC",X"46",X"E3",X"4A",X"29",X"12",X"ED",X"46",X"BD",X"F2",X"A9",X"31",X"44", + X"8E",X"CB",X"A7",X"C6",X"04",X"BD",X"EA",X"8D",X"7E",X"E5",X"2A",X"6F",X"C4",X"7A",X"C8",X"EB", + X"7E",X"E5",X"2A",X"A6",X"46",X"AB",X"C8",X"10",X"A7",X"46",X"A1",X"C8",X"11",X"26",X"02",X"64", + X"C4",X"BD",X"F2",X"A5",X"31",X"44",X"BD",X"EA",X"6D",X"7E",X"E5",X"2A",X"A6",X"43",X"81",X"03", + X"26",X"0D",X"A6",X"42",X"A1",X"C8",X"10",X"2C",X"06",X"8B",X"08",X"A7",X"42",X"20",X"1B",X"64", + X"C4",X"A6",X"C8",X"10",X"A7",X"42",X"86",X"18",X"A7",X"C8",X"10",X"B6",X"C8",X"ED",X"26",X"0A", + X"B6",X"C8",X"C0",X"26",X"05",X"86",X"7F",X"B7",X"C8",X"A2",X"7E",X"E5",X"96",X"6A",X"C8",X"10", + X"26",X"02",X"64",X"C4",X"7E",X"E5",X"96",X"6F",X"C4",X"A6",X"41",X"81",X"04",X"27",X"15",X"E6", + X"43",X"5A",X"27",X"10",X"34",X"0A",X"86",X"C8",X"1F",X"8B",X"A6",X"E4",X"BD",X"E9",X"A1",X"BD", + X"E9",X"A1",X"35",X"0A",X"7E",X"E5",X"2A",X"34",X"08",X"BD",X"F1",X"AA",X"BD",X"F2",X"A9",X"CE", + X"CB",X"2B",X"86",X"0E",X"B7",X"C8",X"8F",X"A6",X"C4",X"10",X"27",X"00",X"A6",X"E6",X"44",X"E1", + X"41",X"24",X"0D",X"CB",X"03",X"E7",X"44",X"10",X"AE",X"42",X"8E",X"EE",X"BA",X"BD",X"EA",X"7F", + X"4D",X"10",X"2A",X"00",X"83",X"7A",X"C8",X"F7",X"10",X"27",X"00",X"37",X"B6",X"C8",X"26",X"84", + X"01",X"26",X"03",X"7C",X"C8",X"F8",X"B6",X"C8",X"F8",X"10",X"8E",X"7F",X"00",X"8E",X"EF",X"04", + X"BD",X"E7",X"6A",X"10",X"8E",X"60",X"80",X"8E",X"EF",X"0B",X"BD",X"E7",X"6A",X"10",X"8E",X"80", + X"50",X"8E",X"EF",X"15",X"BD",X"E7",X"6A",X"10",X"8E",X"A0",X"80",X"8E",X"EF",X"1C",X"BD",X"E7", + X"6A",X"20",X"50",X"7A",X"C8",X"D9",X"7F",X"C8",X"EB",X"7F",X"C8",X"ED",X"B6",X"C8",X"79",X"27", + X"2B",X"B6",X"C8",X"9B",X"44",X"8E",X"C8",X"DA",X"F6",X"C8",X"D9",X"E7",X"86",X"B6",X"C8",X"DA", + X"26",X"05",X"B6",X"C8",X"DB",X"27",X"1A",X"B6",X"C8",X"9B",X"8B",X"02",X"84",X"02",X"B7",X"C8", + X"9B",X"44",X"8E",X"C8",X"DA",X"E6",X"86",X"F7",X"C8",X"D9",X"27",X"EB",X"B6",X"C8",X"D9",X"26", + X"0D",X"86",X"01",X"B7",X"C8",X"BE",X"20",X"06",X"E6",X"44",X"E1",X"41",X"25",X"05",X"6F",X"C4", + X"7A",X"C8",X"EC",X"33",X"45",X"7A",X"C8",X"8F",X"10",X"26",X"FF",X"4B",X"BD",X"EC",X"C9",X"20", + X"05",X"34",X"08",X"BD",X"F1",X"AA",X"BD",X"F2",X"A5",X"8E",X"80",X"38",X"BF",X"C8",X"90",X"B6", + X"C8",X"D9",X"27",X"1E",X"B7",X"C8",X"8F",X"7A",X"C8",X"8F",X"27",X"16",X"B6",X"C8",X"91",X"8B", + X"06",X"B7",X"C8",X"91",X"C6",X"04",X"10",X"BE",X"C8",X"90",X"8E",X"EE",X"EB",X"BD",X"EA",X"7F", + X"20",X"E5",X"35",X"08",X"96",X"26",X"84",X"01",X"48",X"48",X"48",X"8E",X"EE",X"AD",X"CE",X"CB", + X"A7",X"BD",X"F6",X"1F",X"D6",X"EC",X"26",X"0F",X"96",X"BD",X"26",X"08",X"D6",X"EB",X"26",X"07", + X"D6",X"ED",X"26",X"03",X"1C",X"FE",X"39",X"1A",X"01",X"39",X"34",X"32",X"8E",X"C8",X"C8",X"BD", + X"F2",X"F2",X"A6",X"E4",X"97",X"04",X"1F",X"20",X"BD",X"F3",X"12",X"C6",X"0C",X"AE",X"61",X"BD", + X"F4",X"0E",X"35",X"B2",X"34",X"16",X"8E",X"CB",X"2B",X"86",X"0E",X"E6",X"84",X"27",X"07",X"30", + X"05",X"4A",X"26",X"F7",X"20",X"1D",X"A6",X"E4",X"84",X"80",X"4C",X"A7",X"84",X"2A",X"02",X"0C", + X"BD",X"A6",X"E4",X"84",X"7F",X"A7",X"04",X"A6",X"61",X"A7",X"01",X"EC",X"62",X"ED",X"02",X"0C", + X"EC",X"0C",X"F3",X"35",X"96",X"34",X"36",X"BD",X"F6",X"01",X"A7",X"64",X"1D",X"58",X"49",X"58", + X"49",X"58",X"49",X"ED",X"62",X"E6",X"64",X"1D",X"58",X"49",X"58",X"49",X"58",X"49",X"ED",X"64", + X"35",X"B6",X"34",X"36",X"8D",X"DF",X"EC",X"7C",X"58",X"49",X"ED",X"64",X"EC",X"7A",X"58",X"49", + X"ED",X"62",X"35",X"B6",X"86",X"D0",X"1F",X"8B",X"BD",X"F2",X"72",X"86",X"C8",X"1F",X"8B",X"0F", + X"9C",X"0F",X"9F",X"0F",X"A2",X"0F",X"A5",X"8E",X"C9",X"0B",X"6F",X"80",X"8C",X"CB",X"71",X"26", + X"F9",X"CC",X"00",X"00",X"DD",X"DE",X"DD",X"E0",X"DD",X"E2",X"DD",X"E4",X"97",X"E7",X"97",X"BD", + X"97",X"BE",X"97",X"EA",X"97",X"EB",X"97",X"EC",X"97",X"F8",X"C6",X"40",X"D7",X"F7",X"97",X"ED", + X"97",X"C0",X"8E",X"08",X"00",X"9F",X"F0",X"86",X"07",X"97",X"BF",X"8E",X"E3",X"84",X"9F",X"A3", + X"CC",X"00",X"00",X"DD",X"C8",X"DD",X"CA",X"CC",X"00",X"00",X"97",X"D4",X"DD",X"CC",X"DD",X"CE", + X"97",X"D5",X"97",X"D6",X"DD",X"D0",X"DD",X"D2",X"97",X"D7",X"97",X"D8",X"96",X"D4",X"8E",X"EE", + X"EB",X"CE",X"CB",X"89",X"BD",X"F6",X"1F",X"86",X"7F",X"D6",X"D4",X"BD",X"E7",X"D2",X"10",X"BF", + X"C9",X"07",X"BF",X"C9",X"09",X"39",X"34",X"30",X"34",X"08",X"BD",X"F1",X"AA",X"BD",X"F2",X"72", + X"35",X"08",X"86",X"A0",X"97",X"8F",X"96",X"C8",X"27",X"0A",X"2B",X"03",X"4A",X"20",X"01",X"4C", + X"97",X"C8",X"0F",X"C9",X"96",X"CA",X"27",X"0A",X"2B",X"03",X"4A",X"20",X"01",X"4C",X"97",X"CA", + X"0F",X"CB",X"96",X"D4",X"27",X"0C",X"81",X"1F",X"2E",X"03",X"4A",X"20",X"01",X"4C",X"84",X"3F", + X"97",X"D4",X"BD",X"E2",X"F2",X"8E",X"CB",X"81",X"C6",X"08",X"A6",X"84",X"8B",X"03",X"A7",X"80", + X"5A",X"26",X"F7",X"34",X"08",X"BD",X"F1",X"AA",X"BD",X"EA",X"CF",X"5F",X"86",X"20",X"BD",X"E9", + X"0B",X"BD",X"E8",X"FD",X"35",X"08",X"96",X"C8",X"10",X"26",X"FF",X"AA",X"96",X"CA",X"10",X"26", + X"FF",X"A4",X"96",X"D4",X"10",X"26",X"FF",X"9E",X"0A",X"8F",X"10",X"26",X"FF",X"98",X"BD",X"E7", + X"E4",X"35",X"B0",X"8E",X"ED",X"E0",X"10",X"8E",X"CB",X"71",X"CE",X"CB",X"81",X"C6",X"08",X"86", + X"16",X"AF",X"A1",X"30",X"08",X"A7",X"C0",X"8B",X"0F",X"5A",X"26",X"F5",X"39",X"34",X"1E",X"8E", + X"CB",X"81",X"86",X"08",X"6C",X"80",X"4A",X"26",X"FB",X"20",X"02",X"34",X"1E",X"86",X"D0",X"1F", + X"8B",X"86",X"09",X"34",X"02",X"6A",X"E4",X"26",X"07",X"BD",X"F3",X"54",X"35",X"02",X"35",X"9E", + X"BD",X"F3",X"54",X"86",X"03",X"B7",X"C8",X"23",X"A6",X"E4",X"4A",X"8E",X"CB",X"81",X"E6",X"86", + X"C4",X"7F",X"E1",X"61",X"23",X"DF",X"E0",X"62",X"2F",X"DB",X"D7",X"04",X"8E",X"CB",X"71",X"48", + X"AE",X"86",X"BD",X"F2",X"A9",X"BD",X"F2",X"D5",X"20",X"CB",X"34",X"1E",X"86",X"D0",X"1F",X"8B", + X"86",X"09",X"34",X"02",X"6A",X"E4",X"26",X"07",X"BD",X"F3",X"54",X"35",X"02",X"35",X"9E",X"BD", + X"F3",X"54",X"86",X"03",X"B7",X"C8",X"23",X"8E",X"C8",X"C8",X"BD",X"F2",X"F2",X"E6",X"E4",X"58", + X"58",X"EB",X"62",X"2F",X"DF",X"C4",X"7F",X"D7",X"04",X"8E",X"CB",X"71",X"A6",X"E4",X"4A",X"48", + X"AE",X"86",X"BD",X"F2",X"A9",X"BD",X"F2",X"D5",X"20",X"CA",X"34",X"06",X"BD",X"F5",X"17",X"A7", + X"E4",X"BD",X"F5",X"17",X"81",X"60",X"2E",X"F9",X"81",X"A0",X"2D",X"F5",X"A7",X"61",X"35",X"06", + X"39",X"34",X"76",X"96",X"ED",X"10",X"27",X"00",X"93",X"0A",X"ED",X"BD",X"F5",X"17",X"84",X"1F", + X"97",X"8B",X"81",X"1B",X"23",X"04",X"80",X"04",X"20",X"F6",X"C6",X"12",X"3D",X"C3",X"C9",X"33", + X"1F",X"03",X"A6",X"C4",X"84",X"C0",X"26",X"0D",X"0C",X"8B",X"96",X"8B",X"81",X"1B",X"2F",X"EA", + X"0F",X"8B",X"4F",X"20",X"E5",X"A6",X"E4",X"A7",X"41",X"8E",X"E2",X"42",X"48",X"10",X"AE",X"86", + X"10",X"9F",X"89",X"C6",X"20",X"E7",X"C4",X"8E",X"E2",X"3E",X"A6",X"61",X"E6",X"86",X"D7",X"8B", + X"8E",X"E2",X"3A",X"E6",X"86",X"E7",X"C8",X"10",X"A7",X"43",X"8E",X"E2",X"52",X"48",X"10",X"AE", + X"86",X"10",X"AF",X"4C",X"8E",X"E2",X"4A",X"10",X"AE",X"86",X"10",X"9F",X"87",X"81",X"06",X"26", + X"02",X"0C",X"F4",X"96",X"88",X"9B",X"8A",X"19",X"A7",X"4F",X"96",X"87",X"99",X"89",X"19",X"A7", + X"4E",X"96",X"8B",X"BD",X"EA",X"3E",X"BD",X"E7",X"B5",X"10",X"AF",X"48",X"AF",X"4A",X"0C",X"EB", + X"96",X"C0",X"27",X"08",X"86",X"FF",X"97",X"9C",X"86",X"03",X"97",X"C1",X"35",X"F6",X"34",X"06", + X"BD",X"F5",X"17",X"1F",X"89",X"84",X"30",X"A7",X"61",X"C4",X"0F",X"C1",X"04",X"24",X"02",X"CB", + X"04",X"C1",X"0C",X"23",X"02",X"C0",X"04",X"EB",X"61",X"E7",X"61",X"35",X"86",X"34",X"06",X"86", + X"7F",X"97",X"04",X"1F",X"20",X"BD",X"F2",X"C3",X"BD",X"F3",X"54",X"35",X"86",X"34",X"06",X"86", + X"7F",X"97",X"04",X"A6",X"A4",X"E6",X"22",X"BD",X"F2",X"C3",X"BD",X"F3",X"54",X"35",X"86",X"34", + X"16",X"1F",X"20",X"BD",X"F2",X"FC",X"E6",X"61",X"BD",X"F4",X"0E",X"35",X"96",X"34",X"16",X"1F", + X"21",X"BD",X"F2",X"F2",X"E6",X"61",X"AE",X"62",X"BD",X"F4",X"0E",X"35",X"96",X"34",X"56",X"86", + X"7F",X"97",X"04",X"BD",X"F3",X"73",X"35",X"D6",X"34",X"56",X"1F",X"20",X"BD",X"F2",X"FC",X"BD", + X"F4",X"95",X"35",X"B6",X"BD",X"F2",X"A9",X"CC",X"FC",X"38",X"FD",X"C8",X"2A",X"B6",X"C8",X"9B", + X"10",X"8E",X"ED",X"A3",X"10",X"AE",X"A6",X"CE",X"ED",X"9F",X"EE",X"C6",X"8D",X"DA",X"39",X"BD", + X"F2",X"A9",X"CC",X"FC",X"38",X"FD",X"C8",X"2A",X"10",X"8E",X"7F",X"A0",X"CE",X"C8",X"A8",X"8D", + X"C7",X"B6",X"C8",X"79",X"27",X"09",X"10",X"8E",X"7F",X"10",X"CE",X"C8",X"AF",X"8D",X"B9",X"39", + X"BD",X"F1",X"92",X"34",X"08",X"BD",X"F2",X"E6",X"BD",X"EA",X"B4",X"B6",X"C8",X"80",X"BD",X"F1", + X"B4",X"FC",X"C8",X"81",X"FD",X"C8",X"1F",X"FD",X"C8",X"21",X"BD",X"F1",X"F8",X"86",X"C8",X"1F", + X"8B",X"96",X"9C",X"27",X"08",X"0A",X"9C",X"26",X"04",X"AD",X"9F",X"C8",X"9D",X"96",X"9F",X"27", + X"08",X"0A",X"9F",X"26",X"04",X"AD",X"9F",X"C8",X"A0",X"96",X"A2",X"27",X"08",X"0A",X"A2",X"26", + X"04",X"AD",X"9F",X"C8",X"A3",X"96",X"A5",X"27",X"08",X"0A",X"A5",X"26",X"04",X"AD",X"9F",X"C8", + X"A6",X"35",X"88",X"96",X"EA",X"27",X"12",X"10",X"8E",X"C9",X"0B",X"86",X"04",X"97",X"8F",X"6D", + X"A4",X"26",X"07",X"31",X"2A",X"0A",X"8F",X"26",X"F6",X"39",X"96",X"E7",X"27",X"35",X"34",X"20", + X"A6",X"25",X"E6",X"27",X"1F",X"01",X"CC",X"06",X"16",X"10",X"9E",X"DC",X"BD",X"F8",X"FF",X"35", + X"20",X"24",X"20",X"6F",X"A4",X"0F",X"E7",X"0F",X"A2",X"8E",X"ED",X"9F",X"96",X"9B",X"AE",X"86", + X"CC",X"10",X"00",X"BD",X"F8",X"7C",X"86",X"30",X"C6",X"70",X"9E",X"DC",X"BD",X"E7",X"84",X"0A", + X"EA",X"20",X"C6",X"CE",X"C9",X"33",X"86",X"1C",X"97",X"90",X"A6",X"C4",X"84",X"3F",X"26",X"09", + X"33",X"C8",X"12",X"0A",X"90",X"26",X"F3",X"20",X"AA",X"34",X"20",X"A6",X"25",X"E6",X"27",X"1F", + X"01",X"A6",X"44",X"E6",X"46",X"1F",X"02",X"EC",X"4C",X"BD",X"F8",X"FF",X"35",X"20",X"24",X"E0", + X"A6",X"41",X"84",X"02",X"27",X"5A",X"8E",X"ED",X"9F",X"96",X"9B",X"AE",X"86",X"EC",X"4E",X"BD", + X"F8",X"7C",X"0C",X"F5",X"A6",X"44",X"E6",X"46",X"1F",X"01",X"A6",X"42",X"C6",X"20",X"BD",X"E7", + X"84",X"CC",X"01",X"10",X"ED",X"4E",X"96",X"C8",X"A0",X"44",X"D6",X"CA",X"E0",X"46",X"BD",X"F5", + X"93",X"80",X"10",X"1F",X"89",X"34",X"20",X"86",X"3F",X"BD",X"E7",X"B5",X"10",X"AF",X"48",X"AF", + X"4A",X"35",X"20",X"6F",X"A4",X"CC",X"04",X"04",X"ED",X"4C",X"A6",X"41",X"E6",X"43",X"5A",X"27", + X"06",X"BD",X"E9",X"A1",X"BD",X"E9",X"A1",X"86",X"04",X"A7",X"41",X"0A",X"EA",X"7E",X"EB",X"53", + X"86",X"01",X"A7",X"C4",X"6F",X"A4",X"8E",X"ED",X"9F",X"96",X"9B",X"AE",X"86",X"EC",X"4E",X"BD", + X"F8",X"7C",X"A6",X"44",X"E6",X"46",X"1F",X"01",X"A6",X"42",X"C6",X"40",X"BD",X"E7",X"84",X"0A", + X"EB",X"0A",X"EA",X"7E",X"EB",X"53",X"96",X"BD",X"26",X"19",X"96",X"EE",X"26",X"15",X"10",X"8E", + X"C9",X"33",X"86",X"1C",X"97",X"8F",X"A6",X"A4",X"84",X"3F",X"26",X"08",X"31",X"A8",X"12",X"0A", + X"8F",X"26",X"F3",X"39",X"34",X"20",X"96",X"C8",X"D6",X"CA",X"1F",X"01",X"A6",X"24",X"E6",X"26", + X"10",X"AE",X"2C",X"1E",X"20",X"BD",X"F8",X"FF",X"35",X"20",X"24",X"E0",X"6F",X"A4",X"0F",X"ED", + X"96",X"C8",X"D6",X"CA",X"1F",X"01",X"A6",X"22",X"8A",X"80",X"C6",X"30",X"BD",X"E7",X"84",X"0C", + X"F3",X"0A",X"EB",X"20",X"CE",X"96",X"BD",X"26",X"19",X"96",X"EE",X"26",X"15",X"96",X"E7",X"27", + X"11",X"96",X"C8",X"D6",X"CA",X"1F",X"01",X"CC",X"06",X"16",X"10",X"9E",X"DC",X"BD",X"F8",X"FF", + X"25",X"01",X"39",X"0F",X"E7",X"0F",X"A2",X"96",X"C8",X"D6",X"CA",X"1F",X"01",X"86",X"08",X"8A", + X"80",X"C6",X"30",X"BD",X"E7",X"84",X"0C",X"F3",X"39",X"B6",X"C8",X"F2",X"27",X"08",X"7F",X"C8", + X"F2",X"CE",X"ED",X"37",X"20",X"31",X"B6",X"C8",X"F3",X"27",X"08",X"7F",X"C8",X"F3",X"CE",X"ED", + X"4D",X"20",X"24",X"B6",X"C8",X"B6",X"27",X"08",X"7F",X"C8",X"B6",X"CE",X"ED",X"42",X"20",X"17", + X"B6",X"C8",X"F4",X"27",X"0B",X"7F",X"C8",X"F4",X"7F",X"C8",X"F6",X"CE",X"ED",X"5A",X"20",X"07", + X"B6",X"C8",X"F6",X"26",X"F0",X"20",X"03",X"BD",X"F2",X"7D",X"F6",X"C8",X"00",X"CB",X"10",X"C1", + X"A0",X"24",X"07",X"86",X"00",X"BD",X"F2",X"56",X"20",X"06",X"CC",X"08",X"00",X"BD",X"F2",X"56", + X"F6",X"C8",X"02",X"CB",X"20",X"C1",X"F0",X"24",X"07",X"86",X"02",X"BD",X"F2",X"56",X"20",X"06", + X"CC",X"09",X"00",X"BD",X"F2",X"56",X"39",X"00",X"10",X"01",X"00",X"06",X"1F",X"07",X"06",X"08", + X"0F",X"FF",X"02",X"39",X"03",X"00",X"06",X"1F",X"07",X"05",X"09",X"0F",X"FF",X"06",X"1F",X"07", + X"07",X"0A",X"10",X"0B",X"00",X"0C",X"38",X"0D",X"00",X"FF",X"00",X"00",X"01",X"00",X"02",X"30", + X"03",X"00",X"04",X"00",X"05",X"00",X"06",X"1F",X"07",X"3D",X"08",X"00",X"09",X"0F",X"0A",X"00", + X"0B",X"00",X"0C",X"00",X"0D",X"00",X"FF",X"ED",X"8F",X"FE",X"B6",X"00",X"19",X"01",X"19",X"00", + X"19",X"01",X"32",X"00",X"19",X"01",X"19",X"00",X"19",X"06",X"19",X"05",X"19",X"00",X"80",X"FF", + X"EE",X"DD",X"CC",X"BB",X"AA",X"99",X"88",X"77",X"77",X"77",X"77",X"77",X"77",X"77",X"77",X"C8", + X"A8",X"C8",X"AF",X"7F",X"A0",X"7F",X"10",X"C8",X"F9",X"C9",X"00",X"00",X"00",X"00",X"00",X"02", + X"00",X"00",X"00",X"01",X"00",X"00",X"00",X"03",X"00",X"00",X"00",X"02",X"01",X"00",X"00",X"02", + X"03",X"00",X"00",X"01",X"03",X"00",X"00",X"02",X"02",X"00",X"00",X"01",X"01",X"00",X"00",X"03", + X"03",X"00",X"00",X"02",X"02",X"02",X"00",X"01",X"01",X"01",X"00",X"03",X"03",X"03",X"00",X"80", + X"C8",X"40",X"3F",X"00",X"20",X"80",X"10",X"1F",X"3F",X"3F",X"00",X"BF",X"BF",X"BF",X"C0",X"20", + X"48",X"08",X"F8",X"30",X"A8",X"10",X"D0",X"A0",X"BF",X"BF",X"00",X"3F",X"3F",X"48",X"20",X"80", + X"00",X"B0",X"48",X"38",X"FB",X"38",X"80",X"28",X"30",X"48",X"80",X"80",X"45",X"F0",X"28",X"7F", + X"3F",X"BF",X"A5",X"00",X"D0",X"60",X"20",X"28",X"B8",X"40",X"15",X"80",X"40",X"F8",X"40",X"18", + X"FA",X"38",X"E0",X"C8",X"4D",X"49",X"4E",X"45",X"20",X"46",X"49",X"45",X"4C",X"44",X"80",X"FA", + X"38",X"E0",X"D8",X"47",X"41",X"4D",X"45",X"20",X"4F",X"56",X"45",X"52",X"80",X"00",X"10",X"00", + X"FF",X"20",X"A0",X"FF",X"C0",X"40",X"FF",X"90",X"20",X"FF",X"70",X"20",X"FF",X"50",X"50",X"FF", + X"D0",X"90",X"01",X"00",X"20",X"00",X"FF",X"30",X"B0",X"FF",X"B0",X"30",X"FF",X"B0",X"D0",X"FF", + X"30",X"50",X"FF",X"D0",X"50",X"FF",X"50",X"D0",X"FF",X"50",X"30",X"FF",X"D0",X"B0",X"01",X"FF", + X"00",X"00",X"00",X"30",X"00",X"FF",X"10",X"C0",X"FF",X"C0",X"10",X"FF",X"C0",X"F0",X"FF",X"10", + X"40",X"FF",X"F0",X"40",X"FF",X"40",X"F0",X"FF",X"40",X"10",X"FF",X"F0",X"C0",X"01",X"FF",X"00", + X"00",X"00",X"F0",X"D0",X"FF",X"C0",X"40",X"FF",X"20",X"00",X"FF",X"40",X"40",X"FF",X"00",X"E0", + X"FF",X"40",X"C0",X"FF",X"E0",X"00",X"FF",X"C0",X"C0",X"FF",X"00",X"20",X"01",X"00",X"3F",X"00", + X"FF",X"80",X"00",X"00",X"3F",X"3F",X"FF",X"00",X"80",X"01",X"FF",X"7F",X"20",X"00",X"C0",X"10", + X"FF",X"C0",X"D0",X"FF",X"20",X"7F",X"00",X"E0",X"C0",X"FF",X"00",X"C0",X"FF",X"E0",X"30",X"00", + X"C0",X"00",X"FF",X"60",X"CD",X"FF",X"A0",X"00",X"00",X"20",X"D0",X"FF",X"3C",X"30",X"FF",X"00", + X"82",X"00",X"30",X"30",X"FF",X"D0",X"50",X"FF",X"20",X"F0",X"01",X"00",X"3F",X"00",X"FF",X"C4", + X"08",X"FF",X"D8",X"D8",X"FF",X"20",X"00",X"00",X"00",X"40",X"FF",X"E0",X"00",X"FF",X"28",X"D8", + X"FF",X"3C",X"08",X"01",X"00",X"3F",X"00",X"FF",X"C4",X"08",X"01",X"00",X"04",X"08",X"FF",X"D8", + X"D8",X"FF",X"20",X"00",X"01",X"00",X"3F",X"00",X"FF",X"C4",X"F8",X"01",X"00",X"04",X"F8",X"FF", + X"D8",X"28",X"FF",X"20",X"00",X"01",X"00",X"20",X"00",X"FF",X"00",X"D8",X"FF",X"D0",X"A8",X"FF", + X"F0",X"40",X"FF",X"08",X"18",X"FF",X"18",X"F0",X"FF",X"F0",X"B8",X"00",X"10",X"48",X"FF",X"08", + X"00",X"FF",X"E8",X"10",X"FF",X"F8",X"00",X"00",X"08",X"00",X"FF",X"00",X"06",X"00",X"10",X"FA", + X"FF",X"08",X"00",X"FF",X"00",X"F0",X"00",X"10",X"18",X"FF",X"F0",X"08",X"01",X"00",X"20",X"00", + X"FF",X"00",X"28",X"FF",X"D0",X"58",X"FF",X"F0",X"C0",X"FF",X"08",X"E8",X"FF",X"18",X"10",X"FF", + X"F0",X"48",X"00",X"10",X"B8",X"FF",X"08",X"00",X"FF",X"E8",X"F0",X"FF",X"F8",X"00",X"FF",X"08", + X"00",X"FF",X"00",X"FA",X"00",X"10",X"06",X"FF",X"08",X"00",X"FF",X"00",X"10",X"00",X"10",X"E8", + X"FF",X"F0",X"F8",X"01",X"FF",X"00",X"D8",X"FF",X"E8",X"08",X"FF",X"00",X"40",X"FF",X"18",X"08", + X"FF",X"00",X"D8",X"00",X"08",X"E0",X"FF",X"10",X"00",X"FF",X"00",X"40",X"FF",X"F0",X"00",X"FF", + X"00",X"C0",X"01",X"00",X"18",X"00",X"FF",X"00",X"20",X"FF",X"C8",X"70",X"FF",X"10",X"A0",X"FF", + X"00",X"A0",X"FF",X"EC",X"A4",X"FF",X"39",X"6D",X"FF",X"00",X"20",X"01",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"10",X"CE",X"CB",X"EA",X"BD",X"F1",X"8B",X"CC",X"73",X"21",X"10",X"B3",X"CB",X"FE",X"27",X"5C", + X"FD",X"CB",X"FE",X"7C",X"C8",X"3B",X"8E",X"CB",X"EB",X"BD",X"F8",X"4F",X"BD",X"F1",X"AF",X"DC", + X"25",X"10",X"83",X"01",X"01",X"26",X"02",X"D7",X"56",X"57",X"C4",X"03",X"8E",X"F0",X"FD",X"E6", + X"85",X"D7",X"29",X"C6",X"02",X"D7",X"24",X"CE",X"FD",X"0D",X"BD",X"F6",X"87",X"BD",X"F1",X"92", + X"BD",X"F2",X"89",X"BD",X"F2",X"A9",X"B6",X"C8",X"26",X"CE",X"F1",X"0C",X"85",X"20",X"27",X"02", + X"33",X"4C",X"BD",X"F3",X"85",X"8E",X"F0",X"E9",X"BD",X"F3",X"08",X"86",X"03",X"BD",X"F4",X"34", + X"7A",X"C8",X"24",X"26",X"F3",X"B6",X"C8",X"25",X"81",X"01",X"23",X"B0",X"BD",X"F1",X"AF",X"86", + X"CC",X"97",X"29",X"CC",X"F1",X"01",X"DD",X"39",X"0F",X"25",X"0F",X"26",X"CE",X"00",X"00",X"8E", + X"F1",X"01",X"C6",X"0B",X"A6",X"C0",X"A1",X"80",X"27",X"0D",X"C1",X"01",X"27",X"04",X"C1",X"05", + X"23",X"05",X"CE",X"E0",X"00",X"20",X"07",X"5A",X"26",X"EA",X"D7",X"39",X"D7",X"3A",X"0C",X"56", + X"DF",X"37",X"EE",X"C4",X"BD",X"F1",X"AF",X"CC",X"F8",X"48",X"DD",X"2A",X"BD",X"F6",X"87",X"BD", + X"F1",X"92",X"BD",X"F2",X"89",X"BD",X"F2",X"A9",X"CC",X"C0",X"C0",X"FE",X"C8",X"39",X"BD",X"F3", + X"7A",X"B6",X"C8",X"3B",X"26",X"0C",X"4A",X"CE",X"CB",X"EB",X"A7",X"46",X"CC",X"68",X"D0",X"BD", + X"F3",X"7A",X"FE",X"C8",X"37",X"33",X"42",X"BD",X"F3",X"85",X"B6",X"C8",X"56",X"26",X"C5",X"BE", + X"C8",X"25",X"8C",X"00",X"7D",X"23",X"BD",X"6E",X"41",X"40",X"D6",X"00",X"56",X"81",X"00",X"00", + X"A9",X"7E",X"00",X"39",X"DC",X"8E",X"00",X"00",X"4A",X"72",X"00",X"00",X"B6",X"E0",X"38",X"0E", + X"03",X"67",X"20",X"47",X"43",X"45",X"20",X"31",X"39",X"38",X"32",X"80",X"F1",X"60",X"27",X"CF", + X"56",X"45",X"43",X"54",X"52",X"45",X"58",X"80",X"F3",X"60",X"26",X"CF",X"56",X"45",X"43",X"54", + X"52",X"45",X"58",X"80",X"FC",X"60",X"DF",X"E9",X"47",X"43",X"45",X"80",X"FC",X"38",X"CC",X"D1", + X"45",X"4E",X"54",X"45",X"52",X"54",X"41",X"49",X"4E",X"49",X"4E",X"47",X"80",X"FC",X"38",X"BC", + X"DC",X"4E",X"45",X"57",X"20",X"49",X"44",X"45",X"41",X"53",X"80",X"00",X"8D",X"5C",X"CC",X"9F", + X"FF",X"DD",X"02",X"CC",X"01",X"00",X"DD",X"00",X"CC",X"98",X"7F",X"97",X"0B",X"D7",X"04",X"BD", + X"F3",X"54",X"20",X"3E",X"8D",X"49",X"C6",X"7A",X"8E",X"C8",X"00",X"BD",X"F5",X"3F",X"CC",X"C8", + X"7D",X"DD",X"7B",X"0C",X"7D",X"27",X"FC",X"86",X"05",X"97",X"28",X"CC",X"30",X"75",X"DD",X"3D", + X"CC",X"01",X"03",X"DD",X"1F",X"CC",X"05",X"07",X"DD",X"21",X"39",X"8D",X"D7",X"8D",X"BD",X"7E", + X"F2",X"72",X"BE",X"C8",X"25",X"30",X"01",X"BF",X"C8",X"25",X"8D",X"0E",X"86",X"20",X"95",X"0D", + X"27",X"FC",X"FC",X"C8",X"3D",X"DD",X"08",X"7E",X"F2",X"E6",X"86",X"D0",X"1F",X"8B",X"39",X"86", + X"C8",X"1F",X"8B",X"39",X"B4",X"C8",X"0F",X"B7",X"C8",X"0F",X"8E",X"C8",X"12",X"A6",X"1D",X"A7", + X"1E",X"86",X"0E",X"97",X"01",X"CC",X"19",X"01",X"97",X"00",X"12",X"D7",X"00",X"0F",X"03",X"CC", + X"09",X"01",X"97",X"00",X"12",X"96",X"01",X"43",X"A7",X"1D",X"D7",X"00",X"C6",X"FF",X"D7",X"03", + X"43",X"AA",X"1E",X"43",X"A7",X"1F",X"34",X"02",X"C6",X"01",X"1F",X"98",X"A4",X"E4",X"A7",X"80", + X"58",X"26",X"F7",X"35",X"82",X"7A",X"C8",X"23",X"8E",X"C8",X"1F",X"A6",X"80",X"26",X"0C",X"8C", + X"C8",X"23",X"26",X"F7",X"6F",X"84",X"86",X"01",X"97",X"00",X"39",X"97",X"00",X"0F",X"01",X"0A", + X"00",X"C6",X"60",X"5C",X"2A",X"FD",X"B6",X"C8",X"23",X"2B",X"25",X"86",X"20",X"0C",X"00",X"95", + X"00",X"27",X"0A",X"C6",X"40",X"D7",X"01",X"95",X"00",X"26",X"0B",X"20",X"08",X"C6",X"C0",X"D7", + X"01",X"95",X"00",X"27",X"01",X"5F",X"E7",X"1B",X"20",X"C5",X"1F",X"98",X"9A",X"01",X"97",X"01", + X"86",X"20",X"95",X"00",X"26",X"06",X"1F",X"98",X"98",X"01",X"97",X"01",X"54",X"F1",X"C8",X"1A", + X"26",X"E8",X"D6",X"01",X"20",X"E0",X"8E",X"C8",X"00",X"E7",X"86",X"97",X"01",X"86",X"19",X"97", + X"00",X"86",X"01",X"97",X"00",X"96",X"01",X"D7",X"01",X"C6",X"11",X"D7",X"00",X"C6",X"01",X"D7", + X"00",X"39",X"CC",X"0E",X"00",X"8D",X"DF",X"4A",X"2A",X"FB",X"7E",X"F5",X"33",X"8E",X"C8",X"00", + X"20",X"02",X"8D",X"D5",X"EC",X"C1",X"2A",X"FA",X"39",X"8E",X"C8",X"00",X"CE",X"C8",X"3F",X"86", + X"0D",X"E6",X"C0",X"E1",X"86",X"27",X"02",X"8D",X"C0",X"4A",X"2A",X"F5",X"39",X"86",X"1F",X"20", + X"0A",X"86",X"3F",X"20",X"06",X"86",X"5F",X"20",X"02",X"86",X"7F",X"97",X"01",X"B7",X"C8",X"27", + X"CC",X"05",X"04",X"97",X"00",X"D7",X"00",X"D7",X"00",X"C6",X"01",X"D7",X"00",X"39",X"F7",X"C8", + X"28",X"EC",X"81",X"8D",X"4D",X"86",X"FF",X"97",X"0A",X"F6",X"C8",X"28",X"5A",X"26",X"FD",X"0F", + X"0A",X"39",X"7A",X"C8",X"23",X"8D",X"EA",X"B6",X"C8",X"23",X"26",X"F6",X"20",X"76",X"A6",X"80", + X"2E",X"72",X"8D",X"DD",X"20",X"F8",X"8E",X"F9",X"F0",X"8D",X"1D",X"BD",X"F3",X"6B",X"8D",X"20", + X"20",X"62",X"C6",X"7F",X"D7",X"04",X"A6",X"84",X"E6",X"02",X"20",X"16",X"97",X"01",X"34",X"06", + X"86",X"7F",X"97",X"04",X"0F",X"00",X"20",X"10",X"C6",X"FF",X"20",X"02",X"C6",X"7F",X"D7",X"04", + X"EC",X"81",X"97",X"01",X"0F",X"00",X"34",X"06",X"86",X"CE",X"97",X"0C",X"0F",X"0A",X"0C",X"00", + X"D7",X"01",X"0F",X"05",X"35",X"06",X"BD",X"F5",X"84",X"E7",X"7F",X"AA",X"7F",X"C6",X"40",X"81", + X"40",X"23",X"12",X"81",X"64",X"23",X"04",X"86",X"08",X"20",X"02",X"86",X"04",X"D5",X"0D",X"27", + X"FC",X"4A",X"26",X"FD",X"39",X"D5",X"0D",X"27",X"FC",X"39",X"BD",X"F1",X"AA",X"20",X"05",X"B6", + X"C8",X"24",X"27",X"16",X"CC",X"00",X"CC",X"D7",X"0C",X"97",X"0A",X"CC",X"03",X"02",X"0F",X"01", + X"97",X"00",X"D7",X"00",X"D7",X"00",X"C6",X"01",X"D7",X"00",X"39",X"CC",X"00",X"CC",X"D7",X"0C", + X"97",X"0A",X"39",X"EC",X"C1",X"FD",X"C8",X"2A",X"EC",X"C1",X"BD",X"F2",X"FC",X"BD",X"F5",X"75", + X"7E",X"F4",X"95",X"8D",X"EE",X"A6",X"C4",X"26",X"FA",X"39",X"8D",X"EC",X"A6",X"C4",X"26",X"FA", + X"39",X"AE",X"84",X"34",X"04",X"C6",X"80",X"33",X"78",X"36",X"06",X"35",X"02",X"81",X"09",X"23", + X"02",X"86",X"3C",X"8B",X"30",X"C6",X"2D",X"36",X"06",X"36",X"10",X"20",X"CB",X"A6",X"80",X"20", + X"08",X"D7",X"04",X"20",X"07",X"EC",X"81",X"D7",X"04",X"B7",X"C8",X"23",X"EC",X"84",X"97",X"01", + X"0F",X"00",X"30",X"02",X"12",X"0C",X"00",X"D7",X"01",X"CC",X"00",X"00",X"20",X"1F",X"A6",X"80", + X"20",X"08",X"D7",X"04",X"20",X"07",X"EC",X"81",X"D7",X"04",X"B7",X"C8",X"23",X"EC",X"84",X"97", + X"01",X"0F",X"00",X"30",X"02",X"12",X"0C",X"00",X"D7",X"01",X"CC",X"FF",X"00",X"97",X"0A",X"D7", + X"05",X"CC",X"00",X"40",X"D5",X"0D",X"27",X"FC",X"12",X"97",X"0A",X"B6",X"C8",X"23",X"4A",X"2A", + X"D9",X"7E",X"F3",X"4F",X"C6",X"FF",X"20",X"06",X"C6",X"7F",X"20",X"02",X"E6",X"80",X"D7",X"04", + X"EC",X"01",X"97",X"01",X"0F",X"00",X"A6",X"84",X"30",X"03",X"0C",X"00",X"D7",X"01",X"97",X"0A", + X"0F",X"05",X"CC",X"00",X"40",X"D5",X"0D",X"27",X"FC",X"12",X"97",X"0A",X"A6",X"84",X"2F",X"E0", + X"7E",X"F3",X"4F",X"4A",X"B7",X"C8",X"23",X"EC",X"84",X"97",X"01",X"0F",X"00",X"30",X"02",X"0C", + X"00",X"D7",X"01",X"B6",X"C8",X"29",X"C6",X"40",X"97",X"0A",X"0F",X"05",X"F5",X"D0",X"0D",X"27", + X"0B",X"0F",X"0A",X"B6",X"C8",X"23",X"26",X"DB",X"39",X"B6",X"C8",X"29",X"97",X"0A",X"12",X"D5", + X"0D",X"27",X"F6",X"B6",X"C8",X"23",X"0F",X"0A",X"4D",X"26",X"C8",X"7E",X"F3",X"4F",X"B6",X"C8", + X"24",X"34",X"02",X"7F",X"C8",X"24",X"A6",X"80",X"2A",X"04",X"8D",X"BB",X"20",X"F8",X"26",X"05", + X"BD",X"F3",X"BC",X"20",X"F1",X"4A",X"27",X"05",X"BD",X"F3",X"DD",X"20",X"E9",X"35",X"02",X"B7", + X"C8",X"24",X"7E",X"F3",X"4F",X"FF",X"C8",X"2C",X"8E",X"F9",X"D4",X"CC",X"18",X"83",X"0F",X"01", + X"97",X"0B",X"8E",X"F9",X"D4",X"D7",X"00",X"0A",X"00",X"CC",X"80",X"81",X"12",X"0C",X"00",X"D7", + X"00",X"97",X"00",X"7D",X"C8",X"00",X"0C",X"00",X"B6",X"C8",X"2B",X"97",X"01",X"CC",X"01",X"00", + X"FE",X"C8",X"2C",X"97",X"00",X"20",X"04",X"A6",X"86",X"97",X"0A",X"A6",X"C0",X"2A",X"F8",X"86", + X"81",X"97",X"00",X"00",X"01",X"86",X"01",X"97",X"00",X"8C",X"FB",X"B4",X"27",X"2C",X"30",X"88", + X"50",X"1F",X"30",X"B3",X"C8",X"2C",X"C0",X"02",X"58",X"21",X"00",X"86",X"81",X"12",X"5A",X"26", + X"FA",X"97",X"00",X"F6",X"C8",X"2A",X"D7",X"01",X"0A",X"00",X"CC",X"81",X"01",X"12",X"97",X"00", + X"0F",X"01",X"D7",X"00",X"97",X"00",X"C6",X"03",X"20",X"9B",X"86",X"98",X"97",X"0B",X"7E",X"F3", + X"54",X"34",X"14",X"C6",X"02",X"20",X"03",X"34",X"14",X"5F",X"BE",X"C8",X"7B",X"A6",X"01",X"49", + X"49",X"49",X"49",X"A8",X"02",X"46",X"69",X"84",X"69",X"01",X"69",X"02",X"5A",X"2A",X"EE",X"A6", + X"84",X"35",X"94",X"C6",X"0D",X"8E",X"C8",X"3F",X"8D",X"05",X"86",X"3F",X"A7",X"06",X"39",X"4F", + X"20",X"06",X"8E",X"C8",X"00",X"CC",X"00",X"FF",X"6F",X"8B",X"83",X"00",X"01",X"2A",X"F9",X"39", + X"86",X"80",X"A7",X"85",X"5A",X"26",X"FB",X"A7",X"84",X"39",X"C6",X"02",X"20",X"02",X"C6",X"05", + X"8E",X"C8",X"2E",X"6D",X"85",X"27",X"02",X"6A",X"85",X"5A",X"2A",X"F7",X"39",X"C6",X"03",X"20", + X"09",X"C6",X"02",X"20",X"05",X"C6",X"01",X"20",X"01",X"5F",X"5A",X"2A",X"FD",X"39",X"8E",X"F9", + X"DC",X"A6",X"86",X"39",X"4D",X"2A",X"04",X"40",X"28",X"01",X"4A",X"5D",X"2A",X"04",X"50",X"28", + X"01",X"5A",X"39",X"34",X"10",X"DD",X"34",X"59",X"C6",X"00",X"59",X"49",X"59",X"58",X"D7",X"36", + X"DC",X"34",X"8D",X"E0",X"97",X"34",X"D1",X"34",X"23",X"08",X"0C",X"36",X"1E",X"89",X"20",X"02", + X"44",X"54",X"81",X"09",X"22",X"FA",X"DD",X"34",X"D6",X"36",X"8E",X"FC",X"24",X"E6",X"85",X"8E", + X"FC",X"2C",X"A6",X"86",X"9B",X"35",X"8B",X"0A",X"C5",X"01",X"26",X"04",X"EB",X"86",X"20",X"03", + X"5A",X"E0",X"86",X"D7",X"36",X"96",X"36",X"35",X"90",X"8B",X"10",X"8E",X"FC",X"6D",X"5F",X"85", + X"20",X"27",X"02",X"C6",X"80",X"84",X"1F",X"81",X"10",X"26",X"01",X"5C",X"A6",X"86",X"39",X"34", + X"10",X"96",X"36",X"8D",X"E6",X"DD",X"37",X"96",X"36",X"8D",X"DE",X"DD",X"39",X"35",X"90",X"C0", + X"10",X"D7",X"36",X"97",X"3B",X"8D",X"E8",X"8D",X"54",X"40",X"34",X"02",X"8D",X"55",X"35",X"84", + X"B7",X"C8",X"36",X"F7",X"C8",X"23",X"34",X"08",X"BD",X"F1",X"AF",X"8D",X"D2",X"20",X"18",X"B7", + X"C8",X"36",X"34",X"08",X"BD",X"F1",X"AF",X"97",X"23",X"8D",X"C4",X"A6",X"80",X"A7",X"C0",X"2F", + X"06",X"0F",X"23",X"35",X"88",X"0A",X"23",X"A6",X"80",X"8D",X"26",X"A7",X"C4",X"A6",X"84",X"8D", + X"1A",X"AB",X"C4",X"A7",X"C0",X"A6",X"1F",X"8D",X"12",X"A7",X"C4",X"A6",X"80",X"8D",X"12",X"A0", + X"C4",X"A7",X"C0",X"96",X"23",X"2B",X"D4",X"26",X"DC",X"35",X"88",X"97",X"3B",X"DC",X"37",X"20", + X"04",X"97",X"3B",X"DC",X"39",X"D7",X"3C",X"C5",X"01",X"27",X"04",X"96",X"3B",X"20",X"0A",X"D6", + X"3B",X"2A",X"03",X"03",X"3C",X"50",X"3D",X"89",X"00",X"D6",X"3C",X"2A",X"01",X"40",X"39",X"E6", + X"C6",X"E7",X"86",X"4A",X"2A",X"F9",X"39",X"96",X"56",X"2B",X"28",X"27",X"F9",X"8E",X"FC",X"8D", + X"9F",X"4D",X"86",X"80",X"97",X"56",X"EC",X"C1",X"DD",X"4F",X"EC",X"C1",X"DD",X"51",X"DF",X"53", + X"BD",X"F5",X"33",X"CC",X"1F",X"1F",X"DD",X"5F",X"CC",X"00",X"00",X"DD",X"63",X"DD",X"65",X"97", + X"55",X"20",X"39",X"CE",X"C8",X"5E",X"C6",X"02",X"A6",X"C5",X"81",X"1F",X"27",X"02",X"6C",X"C5", + X"5A",X"2A",X"F5",X"9E",X"51",X"CE",X"C8",X"58",X"86",X"07",X"6C",X"C4",X"A1",X"C4",X"2C",X"02", + X"6F",X"C4",X"E6",X"C0",X"C4",X"07",X"E6",X"85",X"E7",X"C0",X"4C",X"81",X"09",X"23",X"EB",X"0A", + X"57",X"26",X"6B",X"96",X"55",X"4A",X"2A",X"02",X"86",X"02",X"97",X"55",X"E6",X"9F",X"C8",X"53", + X"CE",X"C8",X"5E",X"6F",X"C6",X"C5",X"40",X"27",X"19",X"8E",X"F9",X"E4",X"A6",X"86",X"94",X"45", + X"97",X"45",X"96",X"55",X"8B",X"03",X"A6",X"86",X"9A",X"45",X"97",X"45",X"C4",X"1F",X"D7",X"46", + X"20",X"23",X"8E",X"F9",X"EA",X"A6",X"86",X"94",X"45",X"97",X"45",X"96",X"55",X"8B",X"03",X"A6", + X"86",X"9A",X"45",X"97",X"45",X"96",X"55",X"48",X"8B",X"03",X"33",X"C6",X"C4",X"3F",X"58",X"9E", + X"4D",X"EC",X"85",X"ED",X"C4",X"9E",X"53",X"E6",X"80",X"9F",X"53",X"5D",X"2B",X"A5",X"E6",X"80", + X"2A",X"06",X"BD",X"F5",X"33",X"0F",X"56",X"39",X"9F",X"53",X"C4",X"3F",X"D7",X"57",X"10",X"9E", + X"4F",X"CE",X"C8",X"5E",X"8E",X"C8",X"42",X"86",X"02",X"E6",X"C0",X"C5",X"01",X"27",X"07",X"54", + X"E6",X"A5",X"C4",X"0F",X"20",X"07",X"54",X"E6",X"A5",X"54",X"54",X"54",X"54",X"E7",X"86",X"4A", + X"2A",X"E7",X"CE",X"C8",X"67",X"8E",X"C8",X"47",X"EC",X"C3",X"6D",X"58",X"2A",X"0A",X"60",X"58", + X"E0",X"58",X"82",X"00",X"60",X"58",X"20",X"04",X"EB",X"58",X"89",X"00",X"ED",X"81",X"8C",X"C8", + X"4D",X"26",X"E5",X"39",X"20",X"C0",X"40",X"C0",X"50",X"4C",X"41",X"59",X"45",X"52",X"80",X"E0", + X"C0",X"01",X"C0",X"20",X"47",X"41",X"4D",X"45",X"80",X"FD",X"C8",X"4F",X"4D",X"27",X"02",X"86", + X"01",X"5D",X"27",X"02",X"C6",X"01",X"FD",X"C8",X"79",X"BD",X"F1",X"AF",X"CC",X"F8",X"50",X"DD", + X"2A",X"97",X"3C",X"20",X"67",X"BD",X"F1",X"92",X"4F",X"BD",X"F1",X"B4",X"BD",X"F5",X"5A",X"BD", + X"F2",X"A9",X"B6",X"C8",X"79",X"10",X"8E",X"F7",X"94",X"8D",X"5A",X"B6",X"C8",X"7A",X"10",X"8E", + X"F7",X"9F",X"8D",X"51",X"BD",X"F1",X"AF",X"96",X"3C",X"27",X"06",X"96",X"0F",X"26",X"3D",X"0F", + X"3C",X"96",X"2F",X"27",X"9E",X"96",X"2E",X"26",X"CC",X"96",X"15",X"26",X"96",X"96",X"12",X"27", + X"0F",X"96",X"79",X"27",X"0B",X"4C",X"91",X"4F",X"23",X"02",X"86",X"01",X"97",X"79",X"20",X"1C", + X"96",X"7A",X"27",X"B1",X"D6",X"13",X"27",X"09",X"4C",X"91",X"50",X"23",X"0D",X"86",X"01",X"20", + X"09",X"D6",X"14",X"27",X"A0",X"4A",X"26",X"02",X"96",X"50",X"97",X"7A",X"86",X"F3",X"97",X"2F", + X"43",X"97",X"2E",X"20",X"90",X"8E",X"C8",X"5E",X"34",X"02",X"8D",X"13",X"A6",X"E0",X"27",X"0E", + X"8D",X"1C",X"1F",X"13",X"EC",X"A1",X"BD",X"F3",X"7A",X"1F",X"23",X"BD",X"F3",X"78",X"39",X"CC", + X"20",X"20",X"ED",X"84",X"ED",X"02",X"A7",X"04",X"CC",X"30",X"80",X"ED",X"05",X"39",X"CE",X"00", + X"00",X"81",X"63",X"23",X"08",X"80",X"64",X"33",X"C9",X"01",X"00",X"20",X"F4",X"81",X"09",X"23", + X"07",X"80",X"0A",X"33",X"C8",X"10",X"20",X"F5",X"33",X"C6",X"1F",X"30",X"34",X"02",X"34",X"04", + X"C6",X"05",X"4F",X"C1",X"01",X"23",X"10",X"C5",X"01",X"27",X"04",X"A6",X"E4",X"20",X"06",X"A6", + X"E0",X"44",X"44",X"44",X"44",X"84",X"0F",X"BB",X"C8",X"23",X"7F",X"C8",X"23",X"AB",X"85",X"81", + X"2F",X"2E",X"02",X"8B",X"10",X"81",X"39",X"23",X"05",X"80",X"0A",X"7C",X"C8",X"23",X"A7",X"85", + X"5A",X"2A",X"CF",X"7F",X"C8",X"23",X"5F",X"A6",X"85",X"81",X"30",X"26",X"09",X"86",X"20",X"A7", + X"85",X"5C",X"C1",X"05",X"2D",X"F1",X"39",X"34",X"50",X"4F",X"E6",X"80",X"2B",X"08",X"E1",X"C0", + X"27",X"F8",X"22",X"01",X"4C",X"4C",X"35",X"D0",X"8D",X"ED",X"81",X"01",X"26",X"06",X"A6",X"80", + X"A7",X"C0",X"2A",X"FA",X"39",X"34",X"20",X"34",X"36",X"EC",X"64",X"AB",X"C4",X"EB",X"41",X"ED", + X"64",X"20",X"10",X"34",X"20",X"34",X"36",X"1F",X"30",X"AB",X"64",X"EB",X"65",X"20",X"F0",X"34", + X"20",X"34",X"36",X"1F",X"41",X"5F",X"3A",X"A6",X"04",X"AB",X"84",X"28",X"02",X"86",X"7F",X"A1", + X"02",X"2D",X"15",X"A6",X"04",X"A0",X"84",X"28",X"02",X"86",X"80",X"A1",X"02",X"2E",X"09",X"5C", + X"C1",X"02",X"25",X"E2",X"1A",X"01",X"20",X"02",X"1C",X"FE",X"35",X"36",X"35",X"A0",X"96",X"67", + X"2A",X"29",X"84",X"7F",X"97",X"67",X"8E",X"C8",X"58",X"86",X"04",X"BD",X"F6",X"83",X"54",X"54", + X"54",X"DA",X"58",X"C4",X"07",X"D7",X"54",X"D6",X"58",X"C4",X"38",X"D7",X"53",X"D6",X"58",X"C4", + X"07",X"D7",X"5D",X"C6",X"02",X"D7",X"5C",X"86",X"7F",X"20",X"0D",X"96",X"77",X"27",X"6A",X"90", + X"5B",X"2A",X"05",X"5F",X"D7",X"77",X"20",X"62",X"97",X"77",X"44",X"44",X"D6",X"53",X"27",X"0D", + X"97",X"46",X"D6",X"59",X"2B",X"05",X"27",X"05",X"1F",X"89",X"53",X"D7",X"46",X"44",X"81",X"07", + X"23",X"05",X"81",X"0F",X"27",X"01",X"4C",X"D6",X"5A",X"2B",X"06",X"27",X"02",X"88",X"0F",X"1F", + X"89",X"8D",X"37",X"D6",X"5D",X"27",X"2B",X"96",X"5C",X"4A",X"2A",X"02",X"86",X"02",X"97",X"5C", + X"BD",X"F5",X"7E",X"95",X"5D",X"27",X"F0",X"D6",X"5C",X"58",X"50",X"8E",X"C8",X"4B",X"30",X"85", + X"BD",X"F5",X"17",X"84",X"0F",X"81",X"05",X"22",X"03",X"48",X"8B",X"05",X"A7",X"84",X"96",X"7E", + X"A7",X"01",X"96",X"58",X"43",X"94",X"45",X"97",X"45",X"39",X"96",X"54",X"8E",X"C8",X"45",X"4D", + X"27",X"09",X"30",X"1F",X"44",X"24",X"F8",X"E7",X"84",X"20",X"F4",X"39",X"01",X"02",X"04",X"08", + X"10",X"20",X"40",X"80",X"F7",X"EF",X"DF",X"01",X"02",X"04",X"FE",X"FD",X"FB",X"08",X"10",X"20", + X"7F",X"7F",X"80",X"80",X"00",X"20",X"50",X"50",X"20",X"C8",X"20",X"10",X"10",X"40",X"20",X"00", + X"00",X"00",X"00",X"08",X"30",X"20",X"70",X"70",X"10",X"F8",X"30",X"F8",X"70",X"70",X"00",X"60", + X"00",X"00",X"00",X"70",X"70",X"20",X"F0",X"70",X"F0",X"F8",X"F8",X"78",X"88",X"70",X"08",X"88", + X"80",X"88",X"88",X"F8",X"F0",X"70",X"F0",X"70",X"F8",X"88",X"88",X"88",X"88",X"88",X"F8",X"70", + X"80",X"70",X"20",X"00",X"00",X"20",X"08",X"20",X"00",X"00",X"00",X"38",X"10",X"20",X"44",X"44", + X"00",X"FE",X"FF",X"FE",X"00",X"70",X"50",X"50",X"78",X"C8",X"50",X"20",X"20",X"20",X"A8",X"20", + X"00",X"00",X"00",X"08",X"48",X"60",X"88",X"88",X"30",X"80",X"40",X"08",X"88",X"88",X"60",X"60", + X"10",X"00",X"40",X"88",X"88",X"50",X"48",X"88",X"48",X"80",X"80",X"80",X"88",X"20",X"08",X"90", + X"80",X"D8",X"C8",X"88",X"88",X"88",X"88",X"88",X"A8",X"88",X"88",X"88",X"88",X"88",X"08",X"40", + X"80",X"08",X"50",X"00",X"00",X"70",X"0C",X"20",X"70",X"70",X"00",X"44",X"10",X"70",X"00",X"00", + X"6C",X"82",X"FF",X"FE",X"00",X"70",X"50",X"F8",X"A0",X"10",X"50",X"40",X"40",X"10",X"70",X"20", + X"00",X"00",X"00",X"10",X"48",X"20",X"08",X"08",X"50",X"F0",X"80",X"10",X"88",X"88",X"60",X"00", + X"20",X"78",X"20",X"08",X"A8",X"88",X"48",X"80",X"48",X"80",X"80",X"80",X"88",X"20",X"08",X"A0", + X"80",X"A8",X"A8",X"88",X"88",X"88",X"88",X"40",X"20",X"88",X"88",X"88",X"50",X"50",X"10",X"40", + X"40",X"08",X"88",X"00",X"70",X"A8",X"0A",X"20",X"88",X"F8",X"60",X"BA",X"38",X"20",X"00",X"00", + X"92",X"82",X"FF",X"FE",X"00",X"20",X"00",X"50",X"70",X"20",X"60",X"00",X"40",X"10",X"A8",X"F8", + X"00",X"70",X"00",X"20",X"48",X"20",X"70",X"30",X"90",X"08",X"F0",X"20",X"70",X"78",X"00",X"60", + X"40",X"00",X"10",X"10",X"B8",X"88",X"70",X"80",X"48",X"E0",X"E0",X"98",X"F8",X"20",X"08",X"C0", + X"80",X"A8",X"98",X"88",X"F0",X"88",X"F0",X"20",X"20",X"88",X"50",X"A8",X"20",X"20",X"20",X"40", + X"20",X"08",X"00",X"00",X"FE",X"20",X"08",X"20",X"88",X"F8",X"F0",X"A2",X"38",X"F8",X"82",X"38", + X"92",X"82",X"FF",X"FE",X"00",X"00",X"00",X"F8",X"70",X"40",X"A8",X"00",X"40",X"10",X"A8",X"20", + X"40",X"00",X"00",X"40",X"48",X"20",X"80",X"08",X"F8",X"08",X"88",X"40",X"88",X"08",X"60",X"60", + X"20",X"78",X"20",X"20",X"B0",X"F8",X"48",X"80",X"48",X"80",X"80",X"88",X"88",X"20",X"08",X"A0", + X"80",X"88",X"88",X"88",X"80",X"A8",X"A0",X"10",X"20",X"88",X"50",X"A8",X"50",X"20",X"40",X"40", + X"10",X"08",X"00",X"00",X"FE",X"20",X"78",X"A8",X"88",X"F8",X"F0",X"BA",X"7C",X"20",X"44",X"44", + X"6C",X"82",X"FF",X"FE",X"00",X"00",X"00",X"50",X"28",X"98",X"90",X"00",X"20",X"20",X"00",X"20", + X"40",X"00",X"00",X"80",X"48",X"20",X"80",X"88",X"10",X"88",X"88",X"80",X"88",X"10",X"60",X"20", + X"10",X"00",X"40",X"00",X"80",X"88",X"48",X"88",X"48",X"80",X"80",X"88",X"88",X"20",X"88",X"90", + X"88",X"88",X"88",X"88",X"80",X"90",X"90",X"88",X"20",X"88",X"20",X"A8",X"88",X"20",X"80",X"40", + X"08",X"08",X"00",X"00",X"48",X"20",X"F0",X"70",X"70",X"70",X"60",X"44",X"6C",X"50",X"38",X"82", + X"00",X"82",X"FF",X"FE",X"00",X"20",X"00",X"50",X"F8",X"98",X"68",X"00",X"10",X"40",X"00",X"00", + X"80",X"00",X"80",X"80",X"30",X"70",X"F8",X"70",X"10",X"70",X"70",X"80",X"70",X"60",X"00",X"40", + X"00",X"00",X"00",X"20",X"78",X"88",X"F0",X"70",X"F0",X"F8",X"80",X"78",X"88",X"70",X"70",X"88", + X"F8",X"88",X"88",X"F8",X"80",X"68",X"88",X"70",X"20",X"70",X"20",X"50",X"88",X"20",X"F8",X"70", + X"08",X"70",X"00",X"F8",X"00",X"20",X"60",X"20",X"00",X"00",X"00",X"38",X"82",X"88",X"00",X"00", + X"00",X"FE",X"FF",X"FE",X"00",X"11",X"41",X"30",X"21",X"10",X"20",X"31",X"00",X"01",X"03",X"06", + X"0A",X"0F",X"15",X"1C",X"24",X"2D",X"08",X"10",X"08",X"10",X"0B",X"08",X"10",X"0D",X"0A",X"08", + X"10",X"0E",X"0B",X"09",X"08",X"10",X"0E",X"0C",X"0A",X"09",X"08",X"10",X"0E",X"0D",X"0B",X"0A", + X"09",X"08",X"10",X"0F",X"0D",X"0C",X"0B",X"0A",X"09",X"08",X"10",X"0F",X"0E",X"0C",X"0B",X"0A", + X"09",X"09",X"08",X"10",X"0F",X"0E",X"0D",X"0C",X"0B",X"0A",X"09",X"09",X"08",X"00",X"19",X"32", + X"4A",X"62",X"79",X"8E",X"A2",X"B5",X"C6",X"D5",X"E2",X"ED",X"F5",X"FB",X"FF",X"FF",X"FF",X"FB", + X"F5",X"ED",X"E2",X"D5",X"C6",X"B5",X"A2",X"8E",X"79",X"62",X"4A",X"32",X"19",X"03",X"BD",X"03", + X"87",X"03",X"54",X"03",X"24",X"02",X"F7",X"02",X"CD",X"02",X"A4",X"02",X"7E",X"02",X"5B",X"02", + X"39",X"02",X"19",X"01",X"FB",X"01",X"DE",X"01",X"C3",X"01",X"AA",X"01",X"92",X"01",X"7C",X"01", + X"66",X"01",X"52",X"01",X"3F",X"01",X"2D",X"01",X"1C",X"01",X"0C",X"00",X"FD",X"00",X"EF",X"00", + X"E2",X"00",X"D5",X"00",X"C9",X"00",X"BE",X"00",X"B3",X"00",X"A9",X"00",X"A0",X"00",X"97",X"00", + X"8E",X"00",X"86",X"00",X"7F",X"00",X"78",X"00",X"71",X"00",X"6B",X"00",X"65",X"00",X"5F",X"00", + X"5A",X"00",X"55",X"00",X"50",X"00",X"4B",X"00",X"47",X"00",X"43",X"00",X"3F",X"00",X"3C",X"00", + X"38",X"00",X"35",X"00",X"32",X"00",X"2F",X"00",X"2D",X"00",X"2A",X"00",X"28",X"00",X"26",X"00", + X"24",X"00",X"22",X"00",X"20",X"00",X"1E",X"00",X"1C",X"00",X"1B",X"00",X"00",X"FE",X"E8",X"FE", + X"B6",X"93",X"1F",X"0C",X"93",X"1F",X"06",X"98",X"9F",X"24",X"3C",X"11",X"80",X"FD",X"69",X"FD", + X"79",X"21",X"07",X"21",X"07",X"21",X"07",X"21",X"07",X"21",X"07",X"21",X"07",X"21",X"0E",X"99", + X"9F",X"24",X"0E",X"95",X"9B",X"20",X"0E",X"21",X"07",X"21",X"07",X"21",X"07",X"21",X"07",X"21", + X"07",X"21",X"07",X"9D",X"A3",X"28",X"0E",X"A0",X"A6",X"2B",X"0E",X"22",X"02",X"28",X"02",X"2D", + X"02",X"28",X"02",X"22",X"02",X"28",X"02",X"2D",X"02",X"28",X"02",X"22",X"02",X"28",X"02",X"2D", + X"02",X"28",X"02",X"2E",X"02",X"2D",X"28",X"21",X"80",X"EF",X"FF",X"FE",X"DC",X"BA",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"01",X"02",X"01",X"00",X"FF",X"FE", + X"FF",X"FD",X"C3",X"FE",X"B6",X"51",X"24",X"50",X"06",X"50",X"06",X"50",X"0C",X"50",X"06",X"50", + X"06",X"50",X"04",X"50",X"04",X"50",X"04",X"50",X"18",X"50",X"04",X"50",X"04",X"50",X"04",X"50", + X"0C",X"50",X"0C",X"50",X"24",X"50",X"06",X"50",X"06",X"50",X"0C",X"50",X"06",X"50",X"06",X"50", + X"04",X"50",X"04",X"50",X"04",X"50",X"18",X"50",X"04",X"50",X"04",X"50",X"04",X"50",X"0C",X"50", + X"18",X"26",X"80",X"FD",X"BA",X"98",X"76",X"55",X"44",X"33",X"22",X"11",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"FE",X"28",X"FD",X"79",X"98",X"1C",X"10",X"3F",X"08",X"98",X"1C",X"04",X"98", + X"1C",X"04",X"98",X"1C",X"10",X"3F",X"08",X"98",X"1C",X"04",X"98",X"1C",X"04",X"98",X"1C",X"08", + X"93",X"18",X"08",X"98",X"1C",X"08",X"9C",X"1F",X"08",X"98",X"1C",X"08",X"93",X"18",X"08",X"98", + X"1C",X"08",X"93",X"18",X"08",X"98",X"1C",X"08",X"9C",X"1F",X"08",X"98",X"1C",X"08",X"93",X"18", + X"08",X"98",X"1C",X"08",X"93",X"18",X"08",X"98",X"1C",X"08",X"9C",X"1F",X"08",X"98",X"1C",X"08", + X"93",X"18",X"08",X"9C",X"1F",X"30",X"1A",X"80",X"FF",X"FE",X"DC",X"BA",X"98",X"76",X"54",X"32", + X"10",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"FE",X"66",X"FE",X"B6",X"0C",X"18",X"11",X"18", + X"0C",X"18",X"11",X"18",X"0C",X"18",X"11",X"18",X"0C",X"12",X"0C",X"06",X"11",X"18",X"9D",X"21", + X"18",X"9F",X"23",X"18",X"A1",X"24",X"18",X"A3",X"26",X"18",X"9F",X"A4",X"28",X"18",X"07",X"12", + X"07",X"06",X"00",X"3C",X"18",X"80",X"DE",X"EF",X"FE",X"DC",X"BA",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"FE",X"B2",X"FE",X"B6",X"18",X"06",X"1A",X"06",X"1C",X"0C", + X"18",X"0C",X"1A",X"24",X"23",X"18",X"17",X"06",X"18",X"06",X"1A",X"0C",X"17",X"0C",X"18",X"24", + X"24",X"18",X"A4",X"28",X"0C",X"A3",X"26",X"0C",X"A1",X"24",X"0C",X"9F",X"23",X"0C",X"9D",X"21", + X"18",X"9A",X"1F",X"18",X"17",X"06",X"18",X"06",X"1A",X"0C",X"17",X"0C",X"18",X"24",X"24",X"24", + X"18",X"80",X"FF",X"EE",X"DD",X"CC",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"FE",X"E8",X"FE",X"B6",X"96",X"9A",X"1D",X"1E",X"91",X"95", + X"18",X"1E",X"94",X"98",X"1B",X"1E",X"8F",X"94",X"18",X"14",X"16",X"0A",X"8C",X"91",X"15",X"14", + X"16",X"0A",X"91",X"95",X"18",X"32",X"18",X"80",X"EE",X"FF",X"FF",X"EE",X"EE",X"DD",X"CC",X"BB", + X"AA",X"99",X"88",X"88",X"88",X"88",X"88",X"88",X"FF",X"16",X"FE",X"B6",X"1C",X"06",X"1F",X"06", + X"1C",X"06",X"18",X"06",X"1A",X"06",X"18",X"06",X"15",X"06",X"13",X"06",X"18",X"06",X"13",X"06", + X"17",X"06",X"18",X"1E",X"18",X"80",X"FF",X"FF",X"EE",X"EE",X"DD",X"DD",X"CC",X"CC",X"00",X"00", + X"00",X"00",X"00",X"00",X"00",X"00",X"FE",X"28",X"FE",X"B6",X"16",X"0F",X"16",X"05",X"16",X"05", + X"16",X"05",X"1A",X"0F",X"16",X"0F",X"1D",X"0F",X"1D",X"05",X"1D",X"05",X"1D",X"05",X"21",X"0F", + X"1D",X"32",X"1D",X"80",X"FE",X"28",X"FE",X"B6",X"16",X"06",X"16",X"02",X"16",X"02",X"16",X"02", + X"1A",X"06",X"16",X"06",X"1D",X"06",X"1D",X"02",X"1D",X"02",X"1D",X"02",X"21",X"06",X"1D",X"32", + X"11",X"80",X"FE",X"28",X"FE",X"B6",X"1B",X"0F",X"16",X"05",X"16",X"05",X"16",X"05",X"17",X"30", + X"16",X"05",X"16",X"05",X"16",X"05",X"17",X"30",X"16",X"80",X"FD",X"69",X"FE",X"B6",X"A0",X"23", + X"12",X"A0",X"23",X"0C",X"9C",X"20",X"06",X"9E",X"21",X"12",X"9C",X"20",X"32",X"13",X"80",X"FD", + X"C3",X"FE",X"B6",X"16",X"04",X"16",X"04",X"16",X"04",X"16",X"04",X"1A",X"08",X"1C",X"80",X"A6", + X"A0",X"20",X"08",X"BD",X"F3",X"BE",X"B6",X"C8",X"80",X"84",X"7F",X"B7",X"C8",X"80",X"7A",X"C8", + X"80",X"A6",X"A4",X"47",X"84",X"F8",X"E6",X"A0",X"58",X"58",X"58",X"58",X"57",X"C4",X"F8",X"7D", + X"C8",X"80",X"2B",X"DF",X"BD",X"F3",X"DF",X"B6",X"C8",X"80",X"85",X"0F",X"26",X"E0",X"85",X"20", + X"27",X"CD",X"39",X"4B",X"41",X"52",X"52",X"53",X"4F",X"46",X"54",X"38",X"32",X"4C",X"44",X"4D", + X"43",X"42",X"43",X"4A",X"54",X"38",X"32",X"4C",X"44",X"4D",X"43",X"42",X"43",X"4A",X"00",X"00", + X"00",X"00",X"CB",X"F2",X"CB",X"F2",X"CB",X"F5",X"CB",X"F8",X"CB",X"FB",X"CB",X"FB",X"F0",X"00"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/GCE - Vectrex_MiST/rtl/vectrex_mist.sv b/GCE - Vectrex_MiST/rtl/vectrex_mist.sv new file mode 100644 index 00000000..0c595d3e --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/vectrex_mist.sv @@ -0,0 +1,179 @@ +module vectrex_mist +( + output LED, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output AUDIO_L, + output AUDIO_R, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "Vectrex;BINVEC;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire [9:0] kbjoy; +wire [7:0] joystick_0; +wire [7:0] joystick_1; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [7:0] pot_x; +wire [7:0] pot_y; +wire [9:0] audio; +wire hs, vs, cs; +wire [3:0] r, g, b; +wire blankn; +wire cart_rd; +wire [14:0] cart_addr; +wire [7:0] cart_do; +wire ioctl_downl; +wire [7:0] ioctl_index; +wire ioctl_wr; +wire [14:0] ioctl_addr; +wire [7:0] ioctl_dout; + + +assign LED = !ioctl_downl; + +wire clk_25, clk_12p5, clk_6p25, cpu_clock; +wire pll_locked; + +always @(clk_6p25)begin + pot_x = 8'h00; + pot_y = 8'h00; + if (joystick_0[3] | joystick_1[3] | kbjoy[3]) pot_y = 8'h7F; + if (joystick_0[2] | joystick_1[2] | kbjoy[2]) pot_y = 8'h80; + if (joystick_0[1] | joystick_1[1] | kbjoy[1]) pot_x = 8'h80; + if (joystick_0[0] | joystick_1[0] | kbjoy[0]) pot_x = 8'h7F; +end + +pll pll ( + .inclk0 ( CLOCK_27 ), + .areset ( 0 ), + .c0 ( clk_25 ), + .c1 ( clk_12p5 ), + .c2 ( clk_6p25 ), + .locked ( pll_locked ) + ); + +card card ( + .clock ( cpu_clock ), + .address ( ioctl_downl ? ioctl_addr : cart_addr),//16kb only for now + .data ( ioctl_dout ), + .rden ( !ioctl_downl && cart_rd), + .wren ( ioctl_downl && ioctl_wr), + .q ( cart_do ) + ); + +vectrex vectrex ( + .clock_24 ( clk_25 ), + .clock_12 ( clk_12p5 ), + .cpu_clock_o ( cpu_clock ), + .reset ( status[0] | status[6] | buttons[1] | ioctl_downl), + .video_r ( r ), + .video_g ( g ), + .video_b ( b ), + .video_csync ( ), + .video_blankn ( blankn ), + .video_hs ( hs ), + .video_vs ( vs ), + .audio_out ( audio ), + .cart_addr ( cart_addr ), + .cart_do ( cart_do ), + .cart_rd ( cart_rd ), + .rt_1 ( joystick_0[4] | joystick_1[4] | kbjoy[4]),//1 + .lf_1 ( joystick_0[5] | joystick_1[5] | kbjoy[5]),//2 + .dn_1 ( kbjoy[6] ),//3 + .up_1 ( kbjoy[7] ),//4 + .pot_x_1 ( pot_x ), + .pot_y_1 ( pot_y ), + .rt_2 ( joystick_0[4] | joystick_1[4] | kbjoy[4]),//1 + .lf_2 ( joystick_0[5] | joystick_1[5 ] | kbjoy[5]),//2 + .dn_2 ( kbjoy[6] ),//3 + .up_2 ( kbjoy[7] ),//4 + .pot_x_2 ( pot_x ), + .pot_y_2 ( pot_y ), + .leds ( ), + .dbg_cpu_addr ( ) + ); + +dac dac ( + .clk_i ( clk_25 ), + .res_n_i ( 1 ), + .dac_i ( audio ), + .dac_o ( AUDIO_L ) + ); +assign AUDIO_R = AUDIO_L; + +video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(1)) video_mixer ( + .clk_sys ( clk_25 ), + .ce_pix ( clk_6p25 ), + .ce_pix_actual ( clk_6p25 ), + .SPI_SCK ( SPI_SCK ), + .SPI_SS3 ( SPI_SS3 ), + .SPI_DI ( SPI_DI ), + .R ( blankn ? r : "0000"), + .G ( blankn ? g : "0000"), + .B ( blankn ? b : "0000"), + .HSync ( hs ), + .VSync ( vs ), + .VGA_R ( VGA_R ), + .VGA_G ( VGA_G ), + .VGA_B ( VGA_B ), + .VGA_VS ( VGA_VS ), + .VGA_HS ( VGA_HS ), + .scandoubler_disable(1 ), + .ypbpr_full ( 1 ), + .line_start ( 0 ), + .mono ( 0 ) + ); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io ( + .clk_sys ( clk_25 ), + .conf_str ( CONF_STR ), + .SPI_SCK ( SPI_SCK ), + .CONF_DATA0 ( CONF_DATA0 ), + .SPI_SS2 ( SPI_SS2 ), + .SPI_DO ( SPI_DO ), + .SPI_DI ( SPI_DI ), + .buttons ( buttons ), + .switches ( switches ), + .ypbpr ( ypbpr ), + .ps2_kbd_clk ( ps2_kbd_clk ), + .ps2_kbd_data ( ps2_kbd_data ), + .joystick_0 ( joystick_0 ), + .joystick_1 ( joystick_1 ), + .status ( status ), + .ioctl_download( ioctl_downl ), + .ioctl_index ( ioctl_index ), + .ioctl_wr ( ioctl_wr ), + .ioctl_addr ( ioctl_addr ), + .ioctl_dout ( ioctl_dout ) + ); + +keyboard keyboard ( + .clk ( clk_25 ), + .reset ( ), + .ps2_kbd_clk ( ps2_kbd_clk ), + .ps2_kbd_data ( ps2_kbd_data ), + .joystick ( kbjoy ) + ); + + +endmodule \ No newline at end of file diff --git a/GCE - Vectrex_MiST/rtl/vectrex_scramble_prom.vhd b/GCE - Vectrex_MiST/rtl/vectrex_scramble_prom.vhd new file mode 100644 index 00000000..a903961a --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/vectrex_scramble_prom.vhd @@ -0,0 +1,278 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity vectrex_scramble_prom is +port ( + clk : in std_logic; + addr : in std_logic_vector(11 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of vectrex_scramble_prom is + type rom is array(0 to 4095) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"67",X"20",X"47",X"43",X"45",X"20",X"31",X"39",X"38",X"32",X"80",X"FD",X"D3",X"F8",X"50",X"20", + X"C8",X"53",X"43",X"52",X"41",X"4D",X"42",X"4C",X"45",X"80",X"00",X"BD",X"F1",X"8B",X"BD",X"F1", + X"AF",X"CC",X"02",X"03",X"BD",X"F7",X"A9",X"0A",X"79",X"0A",X"7A",X"0A",X"7A",X"86",X"01",X"0F", + X"21",X"0F",X"22",X"20",X"41",X"8E",X"C8",X"A6",X"C6",X"35",X"BD",X"F5",X"50",X"8E",X"C9",X"4D", + X"6F",X"80",X"EC",X"81",X"8C",X"C9",X"65",X"26",X"F7",X"CC",X"01",X"DF",X"DD",X"C9",X"86",X"10", + X"97",X"FD",X"CC",X"28",X"A0",X"DD",X"C4",X"8E",X"C8",X"80",X"CC",X"B6",X"00",X"ED",X"81",X"8C", + X"C8",X"A4",X"26",X"F9",X"96",X"A4",X"48",X"48",X"48",X"48",X"97",X"A3",X"BD",X"F5",X"17",X"84", + X"06",X"8B",X"0E",X"97",X"C3",X"39",X"86",X"05",X"97",X"FE",X"0D",X"79",X"26",X"02",X"86",X"FF", + X"97",X"FF",X"0F",X"E5",X"8E",X"C9",X"3A",X"BD",X"F8",X"4F",X"30",X"14",X"BD",X"F8",X"4F",X"30", + X"1C",X"CC",X"F8",X"30",X"ED",X"84",X"ED",X"0C",X"86",X"7F",X"ED",X"0E",X"C6",X"B0",X"ED",X"02", + X"6F",X"1F",X"6F",X"0B",X"CC",X"0F",X"01",X"DD",X"F9",X"86",X"02",X"97",X"F4",X"97",X"F5",X"D7", + X"F3",X"BD",X"0E",X"C7",X"0F",X"F6",X"D6",X"F3",X"5C",X"C4",X"01",X"0D",X"79",X"26",X"01",X"5F", + X"D7",X"F3",X"4F",X"1F",X"01",X"E6",X"89",X"C8",X"F4",X"D7",X"A4",X"5A",X"5A",X"1F",X"02",X"EC", + X"A9",X"0A",X"3A",X"DD",X"FB",X"EC",X"A9",X"0A",X"48",X"DD",X"EF",X"0F",X"C7",X"0F",X"E4",X"6A", + X"89",X"C8",X"FE",X"2A",X"0E",X"DC",X"FE",X"84",X"80",X"C4",X"80",X"10",X"83",X"80",X"80",X"26", + X"C0",X"20",X"83",X"BD",X"00",X"35",X"0C",X"6A",X"0D",X"F6",X"27",X"0E",X"BD",X"F6",X"87",X"0D", + X"56",X"26",X"0A",X"0F",X"F6",X"BD",X"0E",X"C7",X"20",X"03",X"BD",X"0E",X"E2",X"BD",X"02",X"87", + X"0D",X"DB",X"2B",X"0E",X"0D",X"E5",X"2B",X"0A",X"D6",X"11",X"C4",X"F0",X"C1",X"F0",X"26",X"02", + X"0A",X"E5",X"DC",X"1B",X"1E",X"89",X"DD",X"EA",X"0D",X"DB",X"2A",X"08",X"96",X"C7",X"80",X"02", + X"84",X"0E",X"97",X"C7",X"D6",X"F3",X"4F",X"1F",X"02",X"96",X"A3",X"44",X"44",X"44",X"44",X"84", + X"FE",X"97",X"A4",X"A7",X"A9",X"C8",X"F4",X"7E",X"03",X"04",X"DC",X"C4",X"9E",X"C9",X"27",X"06", + X"0D",X"EA",X"27",X"0C",X"2A",X"04",X"4A",X"4A",X"20",X"06",X"81",X"5E",X"2C",X"02",X"4C",X"4C", + X"0D",X"EB",X"27",X"0F",X"2A",X"08",X"C1",X"A0",X"2D",X"09",X"5A",X"5A",X"20",X"05",X"5D",X"2A", + X"02",X"5C",X"5C",X"DD",X"C4",X"1F",X"01",X"86",X"0D",X"BD",X"02",X"6F",X"10",X"8E",X"C8",X"CB", + X"EC",X"A1",X"C1",X"70",X"2E",X"1D",X"CB",X"04",X"ED",X"3E",X"1F",X"01",X"86",X"FF",X"97",X"A5", + X"BD",X"08",X"23",X"24",X"09",X"96",X"A5",X"2B",X"0A",X"BD",X"09",X"5A",X"20",X"05",X"BD",X"02", + X"F9",X"20",X"05",X"CC",X"80",X"80",X"ED",X"3E",X"10",X"8C",X"C8",X"D3",X"26",X"D2",X"D6",X"11", + X"C4",X"0A",X"27",X"1C",X"8E",X"C8",X"CC",X"E6",X"81",X"C1",X"80",X"26",X"0E",X"DC",X"C4",X"CB", + X"0E",X"ED",X"1D",X"96",X"67",X"8A",X"20",X"97",X"67",X"20",X"05",X"8C",X"C8",X"D4",X"26",X"E7", + X"10",X"8E",X"C8",X"D3",X"EC",X"A1",X"C1",X"90",X"2D",X"24",X"80",X"02",X"6D",X"22",X"27",X"09", + X"6A",X"22",X"E6",X"22",X"4C",X"54",X"54",X"EB",X"3F",X"ED",X"3E",X"1F",X"01",X"0F",X"A5",X"BD", + X"08",X"23",X"25",X"07",X"86",X"0B",X"BD",X"02",X"6F",X"20",X"08",X"BD",X"09",X"5A",X"CC",X"80", + X"80",X"ED",X"3E",X"10",X"8C",X"C8",X"D7",X"26",X"CB",X"D6",X"11",X"C4",X"05",X"27",X"20",X"8E", + X"C8",X"D3",X"EC",X"81",X"81",X"80",X"26",X"12",X"DC",X"C4",X"CB",X"08",X"ED",X"1E",X"86",X"08", + X"A7",X"02",X"96",X"67",X"8A",X"08",X"97",X"67",X"20",X"05",X"8C",X"C8",X"D7",X"26",X"E3",X"CE", + X"08",X"1D",X"DC",X"C4",X"0D",X"7A",X"2B",X"02",X"AB",X"43",X"EB",X"C4",X"1F",X"01",X"86",X"FF", + X"97",X"A5",X"BD",X"08",X"23",X"24",X"0B",X"96",X"A5",X"2B",X"03",X"BD",X"09",X"5A",X"BD",X"08", + X"0C",X"39",X"33",X"41",X"11",X"83",X"08",X"20",X"26",X"D8",X"39",X"8E",X"00",X"10",X"5F",X"AD", + X"9F",X"C8",X"EC",X"39",X"97",X"C6",X"D6",X"C7",X"DA",X"C8",X"1F",X"01",X"8D",X"54",X"39",X"8D", + X"51",X"34",X"36",X"10",X"8E",X"0D",X"6B",X"48",X"31",X"A6",X"AE",X"A4",X"8D",X"73",X"C6",X"1F", + X"D7",X"04",X"BD",X"F4",X"10",X"20",X"5C",X"BD",X"F1",X"92",X"8E",X"C8",X"00",X"CE",X"C8",X"3F", + X"86",X"0D",X"E6",X"C0",X"BD",X"F2",X"59",X"4A",X"2A",X"F8",X"BD",X"F1",X"F8",X"BD",X"F1",X"BA", + X"BD",X"F2",X"A5",X"BD",X"F1",X"AF",X"39",X"34",X"76",X"8E",X"C9",X"2E",X"0D",X"F3",X"27",X"02", + X"30",X"0C",X"BD",X"F8",X"7C",X"35",X"F6",X"34",X"36",X"8D",X"36",X"8D",X"2B",X"CC",X"F3",X"73", + X"20",X"18",X"34",X"36",X"8D",X"2B",X"8D",X"20",X"20",X"04",X"34",X"36",X"8D",X"23",X"CC",X"F3", + X"12",X"20",X"07",X"34",X"36",X"8D",X"1A",X"CC",X"F3",X"DF",X"FD",X"C8",X"E8",X"EC",X"62",X"AD", + X"9F",X"C8",X"E8",X"BD",X"F1",X"AF",X"35",X"B6",X"BD",X"F3",X"54",X"86",X"CE",X"B7",X"D0",X"0C", + X"39",X"BD",X"F1",X"AA",X"86",X"7F",X"97",X"04",X"39",X"34",X"36",X"8D",X"F4",X"8D",X"E9",X"CC", + X"F2",X"C3",X"20",X"D6",X"CC",X"02",X"D3",X"DD",X"EC",X"10",X"8E",X"C8",X"80",X"EC",X"A1",X"84", + X"F0",X"C4",X"0F",X"D7",X"B1",X"BD",X"02",X"64",X"9F",X"DE",X"10",X"8C",X"C8",X"82",X"26",X"06", + X"8E",X"00",X"F0",X"BD",X"02",X"CA",X"D6",X"B1",X"C1",X"04",X"27",X"14",X"A6",X"3F",X"2B",X"0B", + X"C6",X"08",X"A6",X"A4",X"84",X"F0",X"BD",X"09",X"B8",X"20",X"05",X"BD",X"02",X"5B",X"20",X"F2", + X"96",X"B1",X"27",X"1E",X"81",X"06",X"2A",X"1A",X"6D",X"3F",X"2A",X"13",X"9E",X"DE",X"BD",X"02", + X"C2",X"10",X"8C",X"C8",X"82",X"27",X"06",X"8E",X"00",X"10",X"BD",X"02",X"CA",X"96",X"B1",X"BD", + X"02",X"71",X"10",X"8C",X"C8",X"82",X"27",X"A5",X"96",X"C8",X"8B",X"10",X"97",X"C8",X"81",X"80", + X"26",X"9B",X"96",X"DB",X"2A",X"05",X"BD",X"01",X"4A",X"20",X"48",X"81",X"3E",X"2D",X"04",X"C6", + X"40",X"D7",X"67",X"44",X"25",X"02",X"0C",X"C5",X"CE",X"00",X"10",X"9E",X"C4",X"BD",X"02",X"C2", + X"86",X"3F",X"90",X"DB",X"48",X"B7",X"D0",X"04",X"BD",X"F1",X"AA",X"B6",X"C8",X"E7",X"31",X"C6", + X"EC",X"A9",X"0D",X"B5",X"BD",X"F3",X"12",X"BD",X"F1",X"AF",X"1F",X"30",X"1E",X"89",X"9B",X"E6", + X"81",X"15",X"2B",X"04",X"80",X"05",X"20",X"F8",X"BD",X"02",X"71",X"33",X"41",X"11",X"83",X"00", + X"15",X"26",X"C8",X"96",X"A4",X"85",X"04",X"26",X"3E",X"96",X"C7",X"81",X"08",X"26",X"38",X"10", + X"8E",X"C8",X"BF",X"EC",X"A1",X"10",X"83",X"80",X"80",X"27",X"08",X"10",X"8C",X"C8",X"C3",X"26", + X"F2",X"20",X"24",X"D6",X"C3",X"8E",X"C8",X"82",X"3A",X"EC",X"80",X"C4",X"0F",X"C1",X"02",X"26", + X"16",X"E6",X"84",X"CB",X"04",X"E7",X"84",X"84",X"F0",X"8B",X"08",X"D6",X"C3",X"58",X"58",X"58", + X"CB",X"90",X"ED",X"A3",X"BD",X"00",X"6C",X"10",X"8E",X"C8",X"BF",X"EC",X"A1",X"10",X"83",X"80", + X"80",X"27",X"2D",X"8B",X"02",X"81",X"70",X"27",X"22",X"0D",X"DB",X"2A",X"13",X"C0",X"02",X"0D", + X"7A",X"2B",X"09",X"85",X"03",X"26",X"05",X"D1",X"C5",X"2D",X"01",X"5A",X"C1",X"88",X"2D",X"0B", + X"ED",X"3E",X"1F",X"01",X"86",X"06",X"BD",X"02",X"6F",X"20",X"05",X"CC",X"80",X"80",X"ED",X"3E", + X"10",X"8C",X"C8",X"C3",X"26",X"C5",X"0D",X"DB",X"2A",X"1B",X"CE",X"C8",X"BF",X"CC",X"00",X"80", + X"DD",X"F7",X"EC",X"C1",X"BE",X"0D",X"A7",X"BD",X"04",X"DB",X"1F",X"12",X"BD",X"07",X"CA",X"11", + X"83",X"C8",X"C3",X"26",X"ED",X"96",X"A4",X"81",X"04",X"10",X"26",X"00",X"E3",X"10",X"8E",X"C8", + X"A6",X"4F",X"E6",X"28",X"1F",X"01",X"EC",X"A1",X"10",X"83",X"80",X"80",X"27",X"37",X"AB",X"89", + X"0D",X"7D",X"EB",X"89",X"04",X"9F",X"ED",X"3E",X"1F",X"01",X"86",X"0F",X"BD",X"02",X"6F",X"A6", + X"3E",X"E6",X"26",X"84",X"FE",X"2B",X"0C",X"81",X"28",X"25",X"0E",X"CA",X"02",X"20",X"0A",X"00", + X"FC",X"00",X"FC",X"81",X"E8",X"22",X"02",X"C4",X"FD",X"84",X"20",X"27",X"04",X"CA",X"01",X"20", + X"02",X"C4",X"FE",X"E7",X"26",X"10",X"8C",X"C8",X"AE",X"26",X"B6",X"0D",X"DB",X"2A",X"59",X"CE", + X"C8",X"A6",X"CC",X"01",X"00",X"DD",X"F7",X"EC",X"C1",X"BE",X"0D",X"A9",X"8D",X"0D",X"1F",X"12", + X"BD",X"07",X"CA",X"11",X"83",X"C8",X"AE",X"26",X"EE",X"20",X"3D",X"34",X"36",X"10",X"8E",X"C8", + X"CB",X"AE",X"A1",X"8C",X"80",X"80",X"27",X"17",X"10",X"8C",X"C8",X"D3",X"25",X"04",X"C1",X"20", + X"2E",X"0D",X"34",X"26",X"1F",X"02",X"EC",X"66",X"BD",X"F8",X"FF",X"35",X"26",X"25",X"08",X"10", + X"8C",X"C8",X"D7",X"26",X"DC",X"35",X"B6",X"BD",X"09",X"5A",X"CC",X"80",X"80",X"ED",X"A3",X"ED", + X"5E",X"DC",X"F7",X"BD",X"02",X"A7",X"35",X"B6",X"D6",X"A7",X"C4",X"FC",X"C1",X"80",X"26",X"05", + X"CC",X"80",X"80",X"DD",X"A6",X"0A",X"FD",X"26",X"27",X"86",X"20",X"97",X"FD",X"10",X"8E",X"C8", + X"A6",X"A6",X"2A",X"A7",X"28",X"EC",X"22",X"ED",X"A1",X"10",X"8C",X"C8",X"AC",X"26",X"F2",X"BD", + X"F5",X"17",X"84",X"0F",X"1F",X"89",X"CB",X"70",X"8B",X"10",X"DD",X"AC",X"86",X"01",X"97",X"B4", + X"96",X"A4",X"81",X"06",X"26",X"59",X"CE",X"C8",X"B7",X"EC",X"C1",X"C4",X"F8",X"C1",X"80",X"26", + X"07",X"CC",X"80",X"80",X"ED",X"5E",X"20",X"1A",X"EC",X"5E",X"C0",X"08",X"D0",X"7A",X"ED",X"5E", + X"0D",X"DB",X"2A",X"07",X"10",X"BE",X"0D",X"A9",X"BD",X"07",X"CA",X"AE",X"5E",X"86",X"0E",X"BD", + X"02",X"6F",X"11",X"83",X"C8",X"BF",X"26",X"D1",X"D6",X"BE",X"C1",X"40",X"2C",X"21",X"10",X"8E", + X"C8",X"B9",X"EC",X"A4",X"ED",X"A3",X"31",X"24",X"10",X"8C",X"C8",X"C3",X"26",X"F4",X"BD",X"F5", + X"17",X"84",X"F8",X"81",X"60",X"2E",X"F7",X"81",X"D8",X"2D",X"F3",X"C6",X"7F",X"DD",X"BD",X"BD", + X"09",X"86",X"96",X"80",X"48",X"48",X"48",X"48",X"BD",X"02",X"64",X"8E",X"00",X"F0",X"BD",X"02", + X"CA",X"10",X"8E",X"C8",X"82",X"A6",X"A0",X"48",X"48",X"48",X"48",X"97",X"B1",X"91",X"C6",X"26", + X"09",X"81",X"60",X"26",X"05",X"CC",X"02",X"CA",X"20",X"03",X"CC",X"02",X"D3",X"DD",X"EC",X"96", + X"B1",X"E6",X"A0",X"2A",X"07",X"BD",X"02",X"5B",X"96",X"B1",X"20",X"02",X"C6",X"08",X"BD",X"09", + X"B8",X"96",X"B1",X"97",X"C6",X"10",X"8C",X"C8",X"A4",X"26",X"CA",X"DC",X"D3",X"10",X"83",X"80", + X"80",X"26",X"0E",X"DC",X"D5",X"10",X"83",X"80",X"80",X"26",X"06",X"96",X"67",X"8A",X"10",X"97", + X"67",X"4F",X"D6",X"7A",X"CB",X"04",X"DD",X"DC",X"DC",X"C9",X"0D",X"DB",X"2A",X"0D",X"0D",X"C7", + X"26",X"09",X"93",X"DC",X"2A",X"03",X"CC",X"00",X"00",X"DD",X"C9",X"10",X"83",X"00",X"77",X"24", + X"06",X"96",X"6A",X"84",X"08",X"27",X"20",X"8E",X"98",X"B0",X"BD",X"02",X"C2",X"96",X"C9",X"27", + X"06",X"8E",X"00",X"50",X"BD",X"02",X"D3",X"D6",X"CA",X"54",X"54",X"D7",X"EE",X"54",X"54",X"DB", + X"EE",X"4F",X"1F",X"01",X"BD",X"02",X"D3",X"96",X"67",X"9E",X"C9",X"8C",X"00",X"77",X"22",X"04", + X"8A",X"02",X"20",X"02",X"8A",X"01",X"97",X"67",X"8E",X"C9",X"29",X"CE",X"C8",X"FE",X"6D",X"84", + X"26",X"19",X"A6",X"06",X"81",X"31",X"26",X"13",X"6C",X"84",X"6C",X"C4",X"34",X"40",X"BD",X"0E", + X"C7",X"CE",X"FF",X"8F",X"BD",X"F6",X"8D",X"0C",X"F6",X"35",X"40",X"30",X"0C",X"33",X"41",X"11", + X"83",X"C9",X"00",X"26",X"D9",X"CC",X"FC",X"38",X"DD",X"2A",X"0D",X"F3",X"27",X"07",X"8E",X"88", + X"44",X"D6",X"FF",X"20",X"05",X"8E",X"88",X"A0",X"D6",X"FE",X"2B",X"12",X"86",X"68",X"34",X"16", + X"BD",X"02",X"F1",X"BD",X"02",X"E8",X"35",X"16",X"BD",X"F3",X"93",X"BD",X"F1",X"AF",X"0D",X"DB", + X"10",X"2A",X"00",X"9E",X"96",X"C7",X"10",X"26",X"00",X"98",X"D6",X"F0",X"54",X"25",X"06",X"CC", + X"00",X"10",X"BD",X"02",X"A7",X"8E",X"C8",X"82",X"EC",X"84",X"ED",X"83",X"30",X"04",X"8C",X"C8", + X"A4",X"26",X"F5",X"DE",X"FB",X"9E",X"EF",X"30",X"01",X"A6",X"89",X"0B",X"63",X"85",X"10",X"26", + X"0E",X"33",X"41",X"11",X"83",X"00",X"FC",X"26",X"06",X"CE",X"00",X"ED",X"8E",X"01",X"EB",X"DF", + X"FB",X"9F",X"EF",X"E6",X"89",X"0B",X"63",X"A6",X"C9",X"0A",X"66",X"DD",X"A2",X"C4",X"E0",X"C1", + X"A0",X"26",X"11",X"0D",X"7A",X"27",X"02",X"2A",X"0B",X"1F",X"89",X"C4",X"0F",X"C1",X"05",X"24", + X"03",X"4C",X"97",X"A2",X"D6",X"A3",X"C5",X"08",X"27",X"20",X"C4",X"F7",X"D7",X"A3",X"96",X"E4", + X"4C",X"84",X"01",X"97",X"E4",X"27",X"13",X"D6",X"A4",X"5A",X"5A",X"4F",X"1F",X"01",X"EC",X"89", + X"0A",X"56",X"DD",X"FB",X"EC",X"89",X"0A",X"5E",X"DD",X"EF",X"CC",X"01",X"6F",X"10",X"93",X"EF", + X"26",X"10",X"0D",X"E4",X"27",X"0C",X"0F",X"E4",X"CC",X"00",X"D0",X"DD",X"FB",X"CC",X"01",X"78", + X"DD",X"EF",X"CE",X"C9",X"2A",X"BD",X"02",X"B7",X"0D",X"79",X"27",X"06",X"CE",X"C9",X"36",X"BD", + X"02",X"B7",X"0D",X"DB",X"2B",X"41",X"0A",X"DB",X"26",X"3D",X"DC",X"FE",X"4A",X"10",X"2A",X"F9", + X"30",X"5A",X"10",X"2A",X"F9",X"2B",X"8E",X"C9",X"2E",X"8D",X"10",X"8E",X"C9",X"3A",X"8D",X"0B", + X"9E",X"F9",X"30",X"1E",X"9F",X"F9",X"2A",X"09",X"7E",X"F0",X"00",X"CE",X"CB",X"EB",X"7E",X"F8", + X"D8",X"96",X"11",X"84",X"0F",X"10",X"26",X"F8",X"CD",X"0C",X"DB",X"CE",X"07",X"BA",X"0D",X"E5", + X"2A",X"02",X"33",X"48",X"BD",X"02",X"B7",X"7E",X"00",X"F6",X"FC",X"38",X"28",X"F8",X"45",X"4E", + X"44",X"80",X"FC",X"38",X"28",X"F8",X"50",X"41",X"4E",X"80",X"34",X"26",X"10",X"8E",X"08",X"1D", + X"10",X"9F",X"F1",X"DC",X"C4",X"EB",X"A4",X"0D",X"7A",X"2B",X"02",X"AB",X"23",X"1F",X"01",X"EC", + X"E4",X"C1",X"14",X"2C",X"2E",X"1F",X"02",X"EC",X"62",X"BD",X"F8",X"FF",X"24",X"22",X"D6",X"A4", + X"C1",X"06",X"27",X"08",X"CC",X"80",X"80",X"ED",X"5E",X"BD",X"09",X"5A",X"86",X"3F",X"97",X"DB", + X"BD",X"F5",X"17",X"84",X"0F",X"97",X"E7",X"44",X"97",X"E6",X"35",X"A6",X"34",X"26",X"20",X"EC", + X"10",X"9E",X"F1",X"31",X"21",X"10",X"8C",X"08",X"20",X"26",X"B5",X"35",X"A6",X"0C",X"F8",X"FE", + X"00",X"04",X"FC",X"34",X"70",X"1F",X"10",X"97",X"B6",X"1F",X"98",X"C4",X"F0",X"D7",X"B5",X"84", + X"0F",X"90",X"C7",X"2A",X"08",X"C0",X"10",X"96",X"B5",X"80",X"10",X"97",X"B5",X"CB",X"80",X"54", + X"54",X"54",X"4F",X"1F",X"02",X"DD",X"E0",X"EC",X"A9",X"C8",X"82",X"97",X"D8",X"D7",X"B1",X"84", + X"F0",X"D6",X"C7",X"DA",X"B5",X"DD",X"DE",X"DD",X"E2",X"A6",X"A9",X"C8",X"84",X"97",X"DA",X"0D", + X"B1",X"2B",X"1A",X"D6",X"DA",X"C4",X"F0",X"96",X"D8",X"84",X"F0",X"9A",X"C7",X"BD",X"09",X"E6", + X"D7",X"EE",X"1F",X"10",X"91",X"EE",X"2E",X"0B",X"1A",X"01",X"7E",X"09",X"4C",X"D6",X"D8",X"C4", + X"F0",X"20",X"ED",X"0D",X"A5",X"27",X"30",X"96",X"D8",X"48",X"48",X"48",X"48",X"97",X"D8",X"D6", + X"DA",X"58",X"58",X"58",X"58",X"D7",X"DA",X"10",X"83",X"60",X"60",X"27",X"1A",X"0D",X"B1",X"2B", + X"12",X"9A",X"C7",X"BD",X"09",X"E6",X"D7",X"EE",X"1F",X"10",X"91",X"EE",X"2D",X"09",X"1A",X"01", + X"7E",X"09",X"4C",X"D6",X"D8",X"20",X"EF",X"96",X"B1",X"84",X"0F",X"97",X"B1",X"27",X"04",X"81", + X"06",X"2B",X"05",X"1C",X"FE",X"7E",X"09",X"4C",X"D6",X"E2",X"CB",X"10",X"D1",X"B6",X"2D",X"F3", + X"CE",X"0D",X"95",X"48",X"33",X"C6",X"10",X"AE",X"C4",X"EC",X"22",X"1F",X"23",X"10",X"9E",X"E2", + X"BD",X"F8",X"E5",X"24",X"67",X"D6",X"B1",X"C1",X"05",X"26",X"2C",X"34",X"36",X"CE",X"FD",X"D3", + X"BD",X"F6",X"8D",X"86",X"01",X"97",X"F6",X"CE",X"00",X"02",X"DF",X"FB",X"DF",X"EF",X"CE",X"01", + X"DF",X"DF",X"C9",X"0C",X"7A",X"8E",X"C8",X"B7",X"C6",X"08",X"BD",X"F5",X"50",X"8E",X"C8",X"A6", + X"C6",X"08",X"BD",X"F5",X"50",X"35",X"36",X"58",X"4F",X"1F",X"02",X"EC",X"A9",X"09",X"4E",X"BD", + X"02",X"A7",X"96",X"B1",X"81",X"01",X"26",X"0F",X"9E",X"C9",X"C6",X"40",X"3A",X"8C",X"01",X"DF", + X"2D",X"03",X"8E",X"01",X"DF",X"9F",X"C9",X"81",X"04",X"27",X"0F",X"10",X"9E",X"E0",X"A6",X"A9", + X"C8",X"83",X"84",X"F0",X"A7",X"A9",X"C8",X"83",X"0F",X"A5",X"1A",X"01",X"35",X"F0",X"00",X"00", + X"01",X"50",X"00",X"50",X"02",X"00",X"00",X"00",X"08",X"00",X"34",X"26",X"0F",X"B5",X"10",X"8E", + X"C9",X"4D",X"A6",X"A4",X"27",X"12",X"91",X"B5",X"2A",X"03",X"10",X"9F",X"DE",X"31",X"23",X"10", + X"8C",X"C9",X"65",X"26",X"ED",X"10",X"9E",X"DE",X"86",X"0F",X"A7",X"A0",X"AF",X"A4",X"96",X"67", + X"8A",X"04",X"97",X"67",X"35",X"A6",X"34",X"36",X"10",X"8E",X"C9",X"4D",X"A6",X"A4",X"27",X"1E", + X"84",X"01",X"8B",X"07",X"AE",X"21",X"BD",X"02",X"6F",X"6A",X"A4",X"EC",X"21",X"0D",X"DB",X"2A", + X"0B",X"C0",X"02",X"C1",X"81",X"2E",X"05",X"6F",X"A4",X"CC",X"80",X"80",X"ED",X"21",X"31",X"23", + X"10",X"8C",X"C9",X"65",X"26",X"D6",X"35",X"B6",X"34",X"16",X"D6",X"C6",X"47",X"57",X"D7",X"C6", + X"90",X"C6",X"E6",X"61",X"10",X"83",X"00",X"00",X"27",X"1A",X"1F",X"01",X"84",X"C0",X"27",X"0A", + X"81",X"C0",X"27",X"06",X"AD",X"9F",X"C8",X"EC",X"20",X"06",X"1F",X"10",X"58",X"48",X"1F",X"01", + X"AD",X"9F",X"C8",X"EC",X"35",X"96",X"34",X"06",X"86",X"C9",X"1F",X"8B",X"35",X"06",X"DD",X"10", + X"84",X"0F",X"97",X"16",X"96",X"10",X"84",X"F0",X"97",X"10",X"91",X"11",X"27",X"34",X"8B",X"80", + X"CB",X"80",X"DD",X"12",X"91",X"13",X"25",X"04",X"1E",X"98",X"DD",X"12",X"D0",X"12",X"54",X"54", + X"54",X"54",X"D7",X"14",X"1F",X"10",X"C4",X"0F",X"D0",X"16",X"4F",X"C4",X"0F",X"20",X"03",X"9B", + X"14",X"5A",X"26",X"FB",X"97",X"15",X"D6",X"10",X"D1",X"11",X"2D",X"04",X"D0",X"15",X"20",X"02", + X"DB",X"15",X"86",X"C8",X"1F",X"8B",X"39",X"7E",X"00",X"F6",X"00",X"00",X"00",X"48",X"00",X"82", + X"00",X"9C",X"00",X"D1",X"00",X"ED",X"00",X"FC",X"00",X"00",X"00",X"A4",X"00",X"EA",X"01",X"20", + X"01",X"7B",X"01",X"EB",X"02",X"06",X"00",X"00",X"00",X"65",X"00",X"85",X"00",X"A2",X"00",X"00", + X"00",X"C1",X"00",X"EE",X"01",X"2A",X"D6",X"E6",X"F6",X"06",X"16",X"26",X"16",X"06",X"16",X"26", + X"16",X"06",X"F6",X"E6",X"D6",X"C6",X"B6",X"A6",X"B6",X"A6",X"B6",X"A6",X"B6",X"C6",X"D6",X"E6", + X"F6",X"06",X"16",X"06",X"F6",X"E6",X"C6",X"D6",X"E6",X"F6",X"16",X"26",X"16",X"06",X"F6",X"06", + X"16",X"F6",X"D6",X"C6",X"B6",X"C6",X"D6",X"C6",X"E6",X"D6",X"C6",X"D6",X"B6",X"A6",X"B6",X"A6", + X"B6",X"C6",X"B6",X"C6",X"D6",X"E6",X"D6",X"E6",X"C6",X"E6",X"F6",X"06",X"F6",X"E6",X"D6",X"C5", + X"A5",X"A4",X"A3",X"C4",X"D3",X"D5",X"E3",X"C3",X"D4",X"B4",X"B3",X"A4",X"A3",X"D4",X"B4",X"C5", + X"B4",X"B3",X"C4",X"C5",X"D4",X"D5",X"C4",X"D5",X"B4",X"C5",X"E6",X"E5",X"D4",X"B3",X"B4",X"B3", + X"A3",X"A4",X"B4",X"B5",X"C5",X"D5",X"D6",X"D5",X"C5",X"C4",X"B3",X"A3",X"A4",X"A5",X"B6",X"B5", + X"D4",X"C5",X"B5",X"A5",X"A4",X"B5",X"A5",X"C5",X"C6",X"A6",X"B6",X"C6",X"D6",X"C6",X"A6",X"B6", + X"A6",X"C6",X"B6",X"C6",X"D6",X"C6",X"B6",X"A6",X"C6",X"D6",X"B6",X"A6",X"B6",X"A6",X"B6",X"D6", + X"B6",X"A6",X"C6",X"46",X"36",X"46",X"26",X"46",X"56",X"46",X"56",X"46",X"36",X"26",X"16",X"06", + X"16",X"06",X"26",X"16",X"36",X"26",X"46",X"36",X"56",X"46",X"36",X"46",X"26",X"36",X"16",X"26", + X"06",X"16",X"06",X"16",X"26",X"36",X"46",X"56",X"46",X"56",X"36",X"46",X"56",X"36",X"56",X"36", + X"56",X"46",X"56",X"46",X"36",X"26",X"36",X"36",X"34",X"35",X"45",X"35",X"34",X"35",X"45",X"F5", + X"F0",X"B0",X"BC",X"B4",X"34",X"B4",X"BC",X"B2",X"12",X"14",X"34",X"24",X"23",X"B3",X"BC",X"B4", + X"34",X"24",X"C6",X"C6",X"F6",X"36",X"F6",X"C6",X"F6",X"C6",X"46",X"46",X"46",X"C6",X"F6",X"C6", + X"16",X"C6",X"C6",X"20",X"20",X"20",X"20",X"20",X"20",X"20",X"22",X"30",X"32",X"30",X"32",X"30", + X"32",X"32",X"32",X"30",X"33",X"30",X"30",X"20",X"20",X"20",X"20",X"20",X"20",X"20",X"20",X"20", + X"30",X"22",X"32",X"34",X"34",X"31",X"31",X"34",X"32",X"32",X"33",X"30",X"20",X"30",X"20",X"30", + X"32",X"30",X"32",X"30",X"32",X"33",X"31",X"30",X"20",X"22",X"30",X"30",X"22",X"30",X"22",X"34", + X"32",X"30",X"22",X"32",X"34",X"33",X"31",X"30",X"22",X"32",X"34",X"34",X"32",X"32",X"30",X"22", + X"32",X"30",X"20",X"20",X"20",X"20",X"20",X"22",X"32",X"30",X"24",X"32",X"30",X"24",X"32",X"30", + X"20",X"20",X"20",X"22",X"30",X"21",X"30",X"22",X"30",X"20",X"32",X"33",X"34",X"32",X"30",X"20", + X"20",X"20",X"20",X"22",X"34",X"31",X"31",X"30",X"22",X"30",X"20",X"20",X"20",X"20",X"22",X"30", + X"30",X"20",X"20",X"20",X"21",X"30",X"23",X"30",X"22",X"30",X"22",X"33",X"30",X"20",X"20",X"20", + X"24",X"32",X"32",X"33",X"31",X"30",X"20",X"32",X"32",X"32",X"30",X"21",X"32",X"33",X"30",X"21", + X"30",X"20",X"30",X"20",X"20",X"20",X"20",X"40",X"40",X"41",X"40",X"40",X"40",X"40",X"40",X"40", + X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40",X"40", + X"40",X"40",X"40",X"40",X"40",X"40",X"42",X"51",X"42",X"41",X"50",X"43",X"53",X"40",X"42",X"40", + X"42",X"50",X"40",X"40",X"40",X"43",X"42",X"50",X"43",X"50",X"42",X"41",X"40",X"40",X"48",X"40", + X"40",X"40",X"42",X"51",X"40",X"40",X"42",X"52",X"52",X"54",X"53",X"50",X"40",X"60",X"62",X"70", + X"60",X"60",X"60",X"60",X"60",X"72",X"71",X"72",X"70",X"60",X"60",X"60",X"61",X"70",X"60",X"60", + X"70",X"60",X"62",X"70",X"63",X"71",X"70",X"60",X"60",X"60",X"61",X"74",X"70",X"73",X"73",X"74", + X"71",X"72",X"72",X"70",X"60",X"70",X"63",X"73",X"70",X"71",X"70",X"70",X"60",X"68",X"60",X"70", + X"61",X"73",X"70",X"80",X"80",X"90",X"90",X"90",X"82",X"82",X"90",X"82",X"82",X"80",X"82",X"80", + X"82",X"92",X"82",X"91",X"82",X"92",X"82",X"90",X"80",X"90",X"83",X"90",X"90",X"90",X"82",X"80", + X"82",X"80",X"82",X"80",X"82",X"80",X"90",X"82",X"90",X"90",X"82",X"80",X"82",X"80",X"82",X"80", + X"82",X"80",X"82",X"90",X"90",X"93",X"91",X"93",X"92",X"92",X"80",X"80",X"93",X"80",X"90",X"80", + X"90",X"92",X"80",X"90",X"92",X"92",X"82",X"80",X"92",X"90",X"82",X"81",X"80",X"82",X"80",X"82", + X"80",X"82",X"80",X"82",X"80",X"91",X"90",X"91",X"90",X"91",X"8A",X"80",X"90",X"90",X"A0",X"A1", + X"B1",X"A0",X"B0",X"B0",X"A1",X"B0",X"A0",X"B0",X"B0",X"A0",X"B1",X"B1",X"B1",X"A1",X"B0",X"B0", + X"A0",X"B0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B1",X"B1",X"B1",X"A1",X"B1",X"B1",X"B0", + X"B0",X"B0",X"A0",X"B0",X"B0",X"A0",X"B1",X"B1",X"B1",X"B1",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0", + X"B0",X"A0",X"B0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0", + X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"A0",X"B0",X"A0",X"B0",X"B0", + X"A0",X"B0",X"A0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0", + X"B0",X"B0",X"B0",X"A0",X"B0",X"B0",X"B0",X"B0",X"B0",X"A0",X"A0",X"B0",X"B0",X"A0",X"C0",X"C0", + X"C0",X"C0",X"C0",X"D0",X"C0",X"D0",X"D0",X"C0",X"C0",X"C0",X"C0",X"C0",X"C0",X"D0",X"D0",X"C0", + X"D0",X"D5",X"D0",X"D0",X"D0",X"C0",X"D0",X"C0",X"D0",X"C0",X"D0",X"0D",X"BE",X"0D",X"B5",X"0D", + X"D1",X"0D",X"E7",X"0D",X"FD",X"0E",X"0B",X"0E",X"1B",X"0E",X"31",X"0E",X"44",X"03",X"03",X"FD", + X"FD",X"0E",X"57",X"0D",X"BE",X"0E",X"5E",X"0E",X"77",X"0E",X"87",X"0E",X"B0",X"0E",X"9A",X"0E", + X"C0",X"0E",X"AA",X"0E",X"B7",X"0D",X"BE",X"0D",X"AD",X"0D",X"A5",X"0D",X"A9",X"0E",X"07",X"0D", + X"A3",X"0D",X"A7",X"08",X"08",X"08",X"08",X"08",X"04",X"06",X"08",X"06",X"07",X"07",X"08",X"07", + X"05",X"0D",X"A9",X"0D",X"A9",X"00",X"00",X"D0",X"FF",X"18",X"08",X"FF",X"00",X"F0",X"FF",X"20", + X"00",X"FF",X"00",X"28",X"FF",X"E0",X"00",X"FF",X"00",X"E0",X"00",X"00",X"10",X"FF",X"E8",X"08", + X"01",X"00",X"00",X"EC",X"FF",X"40",X"F4",X"FF",X"C0",X"F4",X"FF",X"0C",X"F0",X"FF",X"0C",X"1C", + X"FF",X"F4",X"1C",X"FF",X"F4",X"F0",X"01",X"00",X"00",X"C8",X"FF",X"30",X"00",X"FF",X"00",X"30", + X"FF",X"D0",X"00",X"FF",X"30",X"D0",X"00",X"00",X"30",X"FF",X"D0",X"D0",X"01",X"FF",X"20",X"08", + X"FF",X"00",X"30",X"FF",X"E0",X"08",X"01",X"04",X"08",X"04",X"04",X"00",X"20",X"C0",X"FF",X"20", + X"20",X"FF",X"E0",X"20",X"FF",X"E0",X"E0",X"FF",X"20",X"E0",X"01",X"00",X"E0",X"0C",X"FF",X"40", + X"F4",X"FF",X"C0",X"F4",X"FF",X"0C",X"28",X"FF",X"0C",X"E4",X"FF",X"F4",X"E4",X"FF",X"F4",X"28", + X"01",X"00",X"28",X"F4",X"FF",X"B0",X"10",X"00",X"14",X"24",X"FF",X"34",X"B4",X"00",X"04",X"3C", + X"FF",X"BC",X"C0",X"01",X"00",X"28",X"E8",X"FF",X"B0",X"3C",X"00",X"04",X"D0",X"FF",X"4C",X"10", + X"00",X"D8",X"D4",X"FF",X"0C",X"50",X"01",X"FF",X"10",X"00",X"FF",X"00",X"FC",X"01",X"FF",X"E8", + X"F8",X"FF",X"00",X"F4",X"FF",X"24",X"F4",X"FF",X"F4",X"50",X"FF",X"F4",X"B0",X"FF",X"24",X"0C", + X"FF",X"00",X"0C",X"FF",X"E8",X"08",X"01",X"00",X"00",X"20",X"FF",X"10",X"0C",X"FF",X"F0",X"34", + X"FF",X"F0",X"CC",X"FF",X"10",X"F4",X"01",X"00",X"F4",X"F0",X"FF",X"14",X"F0",X"FF",X"08",X"20", + X"FF",X"F8",X"20",X"FF",X"EC",X"F0",X"FF",X"00",X"E0",X"01",X"FF",X"04",X"18",X"FF",X"08",X"E4", + X"FF",X"10",X"F8",X"FF",X"00",X"F4",X"FF",X"E8",X"14",X"01",X"FF",X"18",X"EC",X"FF",X"F4",X"F8", + X"FF",X"00",X"F8",X"FF",X"F4",X"20",X"01",X"FF",X"F4",X"E8",X"FF",X"00",X"F8",X"FF",X"0C",X"04", + X"FF",X"0C",X"FC",X"FF",X"F4",X"20",X"01",X"BD",X"F5",X"33",X"8E",X"C8",X"67",X"C6",X"0C",X"BD", + X"F5",X"3F",X"86",X"80",X"97",X"77",X"CC",X"0D",X"0D",X"DD",X"42",X"97",X"44",X"C6",X"38",X"D7", + X"45",X"39",X"BD",X"0E",X"D6",X"96",X"67",X"85",X"10",X"26",X"12",X"85",X"08",X"27",X"05",X"CC", + X"00",X"20",X"20",X"04",X"DC",X"6D",X"27",X"08",X"C3",X"00",X"02",X"20",X"03",X"CC",X"00",X"00", + X"DD",X"6D",X"DD",X"49",X"96",X"67",X"85",X"20",X"26",X"06",X"0D",X"71",X"27",X"20",X"20",X"02", + X"0F",X"71",X"D6",X"71",X"C1",X"10",X"27",X"16",X"C1",X"08",X"2C",X"09",X"CA",X"08",X"C5",X"02", + X"27",X"01",X"5F",X"C4",X"09",X"58",X"58",X"58",X"58",X"4F",X"0C",X"71",X"20",X"05",X"CC",X"00", + X"00",X"0F",X"71",X"DD",X"4B",X"96",X"67",X"84",X"44",X"27",X"0A",X"C6",X"FF",X"D7",X"77",X"84", + X"40",X"97",X"69",X"20",X"04",X"96",X"77",X"2B",X"5C",X"0C",X"77",X"96",X"77",X"D6",X"69",X"26", + X"17",X"81",X"12",X"22",X"17",X"D6",X"67",X"C5",X"02",X"26",X"4A",X"44",X"44",X"88",X"0F",X"97", + X"42",X"86",X"1C",X"97",X"45",X"7E",X"0F",X"F7",X"81",X"3F",X"23",X"07",X"C6",X"80",X"D7",X"77", + X"7E",X"0F",X"F7",X"81",X"10",X"23",X"02",X"86",X"10",X"8B",X"30",X"97",X"78",X"BD",X"F5",X"17", + X"84",X"7F",X"91",X"78",X"23",X"F7",X"5F",X"1C",X"FE",X"46",X"56",X"46",X"56",X"46",X"56",X"DD", + X"47",X"C3",X"00",X"05",X"DD",X"49",X"96",X"77",X"44",X"44",X"44",X"88",X"0F",X"97",X"43",X"97", + X"42",X"0F",X"44",X"20",X"52",X"96",X"67",X"85",X"01",X"26",X"38",X"98",X"68",X"84",X"03",X"27", + X"09",X"86",X"40",X"97",X"76",X"CC",X"05",X"00",X"20",X"39",X"0A",X"76",X"0A",X"76",X"2B",X"F1", + X"96",X"76",X"81",X"0A",X"23",X"08",X"C6",X"1A",X"3D",X"C3",X"00",X"94",X"20",X"25",X"CC",X"00", + X"00",X"20",X"20",X"00",X"2E",X"5C",X"8A",X"B8",X"B8",X"8A",X"5C",X"2E",X"00",X"00",X"00",X"2E", + X"5C",X"8A",X"B8",X"D6",X"6A",X"C4",X"0F",X"4F",X"1F",X"01",X"E6",X"89",X"0F",X"D3",X"59",X"49", + X"C3",X"01",X"6C",X"DD",X"74",X"DD",X"47",X"96",X"67",X"84",X"03",X"97",X"68",X"0F",X"67",X"39"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/GCE - Vectrex_MiST/rtl/video_mixer.sv b/GCE - Vectrex_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/GCE - Vectrex_MiST/rtl/video_mixer.sv @@ -0,0 +1,242 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 3 bits per component +// For half depth 6 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0, + + parameter OSD_COLOR = 3'd4, + parameter OSD_X_OFFSET = 10'd0, + parameter OSD_Y_OFFSET = 10'd0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + + // Some systems have multiple resolutions. + // ce_pix_actual should match ce_pix where every second or fourth pulse is enabled, + // thus half or qurter resolutions can be used without brake video sync while switching resolutions. + // For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix. + input ce_pix_actual, + + // OSD SPI interface + input SPI_SCK, + input SPI_SS3, + input SPI_DI, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // 0 = HVSync 31KHz, 1 = CSync 15KHz + input scandoubler_disable, + + // High quality 2x scaling + input hq2x, + + // YPbPr always uses composite sync + input ypbpr, + + // 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space) + input ypbpr_full, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // interlace sync. Positive pulses. + input HSync, + input VSync, + + // Falling of this signal means start of informative part of line. + // It can be horizontal blank signal. + // This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler + // If FPGA RAM is not an issue, then simply set it to 0 for whole line processing. + // Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts. + // Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel + // before first informative pixel. + input line_start, + + // MiST video output signals + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_VS, + output VGA_HS +); + +localparam DWIDTH = HALF_DEPTH ? 2 : 5; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .r_in(R), + .g_in(G), + .b_in(B), + + .hs_out(hs_sd), + .vs_out(vs_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd); +wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd); +wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd); + +generate + if(HALF_DEPTH) begin + wire [5:0] r = mono ? {gt,rt} : {rt,rt}; + wire [5:0] g = mono ? {gt,rt} : {gt,gt}; + wire [5:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [5:0] r = rt; + wire [5:0] g = gt; + wire [5:0] b = bt; + end +endgenerate + +wire hs = (scandoubler_disable ? HSync : hs_sd); +wire vs = (scandoubler_disable ? VSync : vs_sd); + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire [5:0] r_out, g_out, b_out; +always @(*) begin + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]}; + g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]}; + b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]}; + end + + 2: begin // reduce 50% = 1/2 + r_out = {1'b0, r[5:1]}; + g_out = {1'b0, g[5:1]}; + b_out = {1'b0, b[5:1]}; + end + + 3: begin // reduce 75% = 1/4 + r_out = {2'b00, r[5:2]}; + g_out = {2'b00, g[5:2]}; + b_out = {2'b00, b[5:2]}; + end + + default: begin + r_out = r; + g_out = g; + b_out = b; + end + endcase +end + +wire [5:0] red, green, blue; +osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd +( + .*, + + .R_in(r_out), + .G_in(g_out), + .B_in(b_out), + .HSync(hs), + .VSync(vs), + + .R_out(red), + .G_out(green), + .B_out(blue) +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red; +assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green; +assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue; +assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd; +assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd; + +endmodule diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/duplicate_byte b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/duplicate_byte new file mode 100644 index 00000000..f1dff2e9 Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/duplicate_byte differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/make_vhdl_prom b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/make_vhdl_prom new file mode 100644 index 00000000..a71da100 Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/linux32/make_vhdl_prom differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/duplicate_byte.exe b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/duplicate_byte.exe new file mode 100644 index 00000000..9e205c62 Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/duplicate_byte.exe differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/make_vhdl_prom.exe b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/make_vhdl_prom.exe new file mode 100644 index 00000000..7dd3525d Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win32/make_vhdl_prom.exe differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/duplicate_byte.exe b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/duplicate_byte.exe new file mode 100644 index 00000000..425e9082 Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/duplicate_byte.exe differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/make_vhdl_prom.exe b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/make_vhdl_prom.exe new file mode 100644 index 00000000..1e5618bf Binary files /dev/null and b/GCE - Vectrex_MiST/tools/tools_prom_src/binaries/win64/make_vhdl_prom.exe differ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/src/doc_compilation.txt b/GCE - Vectrex_MiST/tools/tools_prom_src/src/doc_compilation.txt new file mode 100644 index 00000000..d12ba3bf --- /dev/null +++ b/GCE - Vectrex_MiST/tools/tools_prom_src/src/doc_compilation.txt @@ -0,0 +1,28 @@ +------------------------------------------------------ +LINUX build command +------------------------------------------------------ +gcc duplicate_byte.c -lm +mv a.out duplicate_byte + +gcc make_vhdl_prom.c -lm +mv a.out make_vhdl_prom + +------------------------------------------------------ +Win32 build command (on linux system) +------------------------------------------------------ +i686-w64-mingw32-gcc duplicate_byte.c -lm -m32 +mv a.exe duplicate_byte.exe + +i686-w64-mingw32-gcc make_vhdl_prom.c -lm -m32 +mv a.exe make_vhdl_prom.exe + +------------------------------------------------------ +Win64 build command (on linux system) +------------------------------------------------------ +x86_64-w64-mingw32-gcc duplicate_byte.c -lm +mv a.exe duplicate_byte.exe + +x86_64-w64-mingw32-gcc make_vhdl_prom.c -lm +mv a.exe make_vhdl_prom.exe +------------------------------------------------------ +------------------------------------------------------ diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/src/duplicate_byte.c b/GCE - Vectrex_MiST/tools/tools_prom_src/src/duplicate_byte.c new file mode 100644 index 00000000..10bd7a02 --- /dev/null +++ b/GCE - Vectrex_MiST/tools/tools_prom_src/src/duplicate_byte.c @@ -0,0 +1,37 @@ +#include "stdio.h" +#include "stdlib.h" +main (int argc, char **argv) +{ +unsigned char byte; +FILE *fid_in,*fid_out; + +if (argc != 3) +{ + printf("Syntax : %s file_in file_out\n",argv[0]); + exit(0); +} + +fid_in = fopen(argv[1],"rb"); +if (fid_in == NULL) +{ + printf("can't open %s\n",argv[1]); + exit(0); +} + +fid_out = fopen(argv[2],"wb"); +if (fid_out == NULL) +{ + printf("can't open %s\n",argv[2]); + fclose(fid_in); + exit(0); +} + +while (fread(&byte,1,1,fid_in)==1) +{ + fwrite(&byte,1,1,fid_out); + fwrite(&byte,1,1,fid_out); +} + +fclose(fid_in); +fclose(fid_out); +} diff --git a/GCE - Vectrex_MiST/tools/tools_prom_src/src/make_vhdl_prom.c b/GCE - Vectrex_MiST/tools/tools_prom_src/src/make_vhdl_prom.c new file mode 100644 index 00000000..d6cb87cf --- /dev/null +++ b/GCE - Vectrex_MiST/tools/tools_prom_src/src/make_vhdl_prom.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +main (int argc, char **argv) +{ +unsigned char byte; +int data_len,nb_byte,first_byte; +char *end_file_name; +FILE *fid_in,*fid_out; + +if (argc != 3) +{ + printf("Syntax : %s file_in file_out\n",argv[0]); + exit(0); +} + +fid_in = fopen(argv[1],"rb"); +if (fid_in == NULL) +{ + printf("can't open %s\n",argv[1]); + exit(0); +} + +fid_out = fopen(argv[2],"wt"); +if (fid_out == NULL) +{ + printf("can't open %s\n",argv[2]); + fclose(fid_in); + exit(0); +} + +end_file_name = strstr(argv[2],".vhd"); +if (end_file_name!=NULL) *end_file_name='\0'; + +fseek(fid_in,0,SEEK_END); +data_len = ftell(fid_in); +fseek(fid_in,0,SEEK_SET); + +fprintf(fid_out,"library ieee;\n"); +fprintf(fid_out,"use ieee.std_logic_1164.all,ieee.numeric_std.all;\n\n"); +fprintf(fid_out,"entity %s is\n",argv[2]); +fprintf(fid_out,"port (\n"); +fprintf(fid_out,"\tclk : in std_logic;\n"); +fprintf(fid_out,"\taddr : in std_logic_vector(%d downto 0);\n",(int)ceil(log2((double)data_len))-1); +fprintf(fid_out,"\tdata : out std_logic_vector(7 downto 0)\n"); +fprintf(fid_out,");\n"); +fprintf(fid_out,"end entity;\n\n"); +fprintf(fid_out,"architecture prom of %s is\n",argv[2]); +fprintf(fid_out,"\ttype rom is array(0 to %d) of std_logic_vector(7 downto 0);\n",data_len-1); +fprintf(fid_out,"\tsignal rom_data: rom := ("); + +nb_byte = 0; +first_byte = 1; +while(fread(&byte,1,1,fid_in)==1) +{ + if (nb_byte==0) + { + if (first_byte==0) fprintf(fid_out,","); + fprintf(fid_out,"\n\t\t"); + } + else + { fprintf(fid_out,","); } + first_byte = 0; + + fprintf(fid_out,"X\"%02X\"",byte); + nb_byte++; + if (nb_byte==16) nb_byte=0; +} +fprintf(fid_out,");\n"); + +fprintf(fid_out,"begin\n"); +fprintf(fid_out,"process(clk)\n"); +fprintf(fid_out,"begin\n"); +fprintf(fid_out,"\tif rising_edge(clk) then\n"); +fprintf(fid_out,"\t\tdata <= rom_data(to_integer(unsigned(addr)));\n"); +fprintf(fid_out,"\tend if;\n"); +fprintf(fid_out,"end process;\n"); +fprintf(fid_out,"end architecture;\n"); + +fclose(fid_in); +fclose(fid_out); +} diff --git a/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vectrex_proms.bat b/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vectrex_proms.bat new file mode 100644 index 00000000..549c127c --- /dev/null +++ b/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vectrex_proms.bat @@ -0,0 +1,14 @@ + +make_vhdl_prom exec_rom.bin vectrex_exec_prom.vhd +make_vhdl_prom scramble.bin vectrex_scramble_prom.vhd +make_vhdl_prom berzerk.bin vectrex_berzerk_prom.vhd +make_vhdl_prom frogger.bin vectrex_frogger_prom.vhd +make_vhdl_prom spacewar.bin vectrex_spacewar_prom.vhd +make_vhdl_prom polepos.bin vectrex_polepos_prom.vhd +make_vhdl_prom ripoff.bin vectrex_ripoff_prom.vhd +make_vhdl_prom spike.bin vectrex_spike_prom.vhd +make_vhdl_prom startrek.bin vectrex_startrek_prom.vhd +make_vhdl_prom vecmania1.bin vectrex_vecmania1_prom.vhd +make_vhdl_prom webwars.bin vectrex_webwars_prom.vhd +make_vhdl_prom wotr.bin vectrex_wotr_prom.vhd +make_vhdl_prom AGT.bin vectrex_AGT_prom.vhd \ No newline at end of file diff --git a/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vhdl_prom.exe b/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vhdl_prom.exe new file mode 100644 index 00000000..1e5618bf Binary files /dev/null and b/GCE - Vectrex_MiST/tools/vectrex_unzip/make_vhdl_prom.exe differ diff --git a/GCE - Vectrex_MiST/vectrex_MiST.qpf b/GCE - Vectrex_MiST/vectrex_MiST.qpf new file mode 100644 index 00000000..05ae3715 --- /dev/null +++ b/GCE - Vectrex_MiST/vectrex_MiST.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2016 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.0 Build 196 10/24/2016 SJ Lite Edition +# Date created = 08:04:28 December 31, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "16.1" +DATE = "08:04:28 December 31, 2017" + +# Revisions + +PROJECT_REVISION = "vectrex_MiST" diff --git a/GCE - Vectrex_MiST/vectrex_MiST.qsf b/GCE - Vectrex_MiST/vectrex_MiST.qsf new file mode 100644 index 00000000..e409e86d --- /dev/null +++ b/GCE - Vectrex_MiST/vectrex_MiST.qsf @@ -0,0 +1,223 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Altera Program License +# Subscription Agreement, Altera MegaCore Function License +# Agreement, or other applicable license agreement, including, +# without limitation, that your use is for the sole purpose of +# programming logic devices manufactured by Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus II 64-Bit +# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition +# Date created = 06:03:35 February 11, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# vectrex_MiST_assignment_defaults.qdf +# If this file doesn't exist, see file: +# assignment_defaults.qdf +# +# 2) Altera recommends that you do not modify this file. This +# file is updated automatically by the Quartus II software +# and any changes you make may be lost or overwritten. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 15.1.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:45:13 JUNE 17,2016" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name VHDL_FILE rtl/YM2149_linmix_sep.vhd +set_global_assignment -name VHDL_FILE rtl/vectrex.vhd +set_global_assignment -name VHDL_FILE rtl/m6522a.vhd +set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd +set_global_assignment -name VHDL_FILE rtl/cpu09l_128a.vhd +set_global_assignment -name VHDL_FILE rtl/dac.vhd +set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv +set_global_assignment -name VERILOG_FILE rtl/keyboard.v +set_global_assignment -name VERILOG_FILE rtl/mist_io.v +set_global_assignment -name VERILOG_FILE rtl/osd.v +set_global_assignment -name QIP_FILE rtl/pll.qip +set_global_assignment -name VERILOG_FILE rtl/scandoubler.v +set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/vectrex_mist.sv +set_global_assignment -name VHDL_FILE rtl/vectrex_exec_prom.vhd +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" +set_global_assignment -name QIP_FILE rtl/card.qip + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +set_location_assignment PIN_144 -to VGA_R[5] +set_location_assignment PIN_143 -to VGA_R[4] +set_location_assignment PIN_142 -to VGA_R[3] +set_location_assignment PIN_141 -to VGA_R[2] +set_location_assignment PIN_137 -to VGA_R[1] +set_location_assignment PIN_135 -to VGA_R[0] +set_location_assignment PIN_133 -to VGA_B[5] +set_location_assignment PIN_132 -to VGA_B[4] +set_location_assignment PIN_125 -to VGA_B[3] +set_location_assignment PIN_121 -to VGA_B[2] +set_location_assignment PIN_120 -to VGA_B[1] +set_location_assignment PIN_115 -to VGA_B[0] +set_location_assignment PIN_114 -to VGA_G[5] +set_location_assignment PIN_113 -to VGA_G[4] +set_location_assignment PIN_112 -to VGA_G[3] +set_location_assignment PIN_111 -to VGA_G[2] +set_location_assignment PIN_110 -to VGA_G[1] +set_location_assignment PIN_106 -to VGA_G[0] +set_location_assignment PIN_136 -to VGA_VS +set_location_assignment PIN_119 -to VGA_HS +set_location_assignment PIN_65 -to AUDIO_L +set_location_assignment PIN_80 -to AUDIO_R +set_location_assignment PIN_105 -to SPI_DO +set_location_assignment PIN_88 -to SPI_DI +set_location_assignment PIN_126 -to SPI_SCK +set_location_assignment PIN_127 -to SPI_SS2 +set_location_assignment PIN_91 -to SPI_SS3 +set_location_assignment PIN_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 +set_global_assignment -name TOP_LEVEL_ENTITY vectrex_mist + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name ENABLE_NCE_PIN OFF +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON +set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# EDA Netlist Writer Assignments +# ============================== +set_global_assignment -name EDA_SIMULATION_TOOL "" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# Power Estimation Assignments +# ============================ +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" + +# Advanced I/O Timing Assignments +# =============================== +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall + +# start EDA_TOOL_SETTINGS(eda_simulation) +# --------------------------------------- + + # EDA Netlist Writer Assignments + # ============================== + set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation +set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation + +# end EDA_TOOL_SETTINGS(eda_simulation) +# ------------------------------------- + +# ------------------------------- +# start ENTITY(DE10_LITE_Default) + +# end ENTITY(DE10_LITE_Default) +# ----------------------------- + +# -------------------------- +# start ENTITY(vectrex_mist) + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top + set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top + set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(vectrex_mist) +# ------------------------ +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005 +set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF +set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT EXTRA +set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE AREA +set_global_assignment -name SYNTH_TIMING_DRIVEN_SYNTHESIS ON +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/GCE - Vectrex_MiST/vectrex_MiST.srf b/GCE - Vectrex_MiST/vectrex_MiST.srf new file mode 100644 index 00000000..1c9355aa --- /dev/null +++ b/GCE - Vectrex_MiST/vectrex_MiST.srf @@ -0,0 +1,13 @@ +{ "" "" "" "Verilog HDL or VHDL warning at vectrex.vhd(417): conditional expression evaluates to a constant" { } { } 0 10037 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "VHDL Signal Declaration warning at vectrex.vhd(126): used implicit default value for signal \"video_csync\" because signal was never assigned a value or an explicit default value. Use of implicit default value may introduce unintended design optimizations." { } { } 0 10541 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10235 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 14284 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10873 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10273 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10268 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10541 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 10492 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 13004 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 13024 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 15705 "" 0 0 "Quartus II" 0 -1 0 ""}