mirror of
https://github.com/hoglet67/AtomBusMon.git
synced 2024-06-18 02:29:28 +00:00
1053 lines
43 KiB
VHDL
Executable File
1053 lines
43 KiB
VHDL
Executable File
-- ****
|
|
-- T65(b) core. In an effort to merge and maintain bug fixes ....
|
|
--
|
|
--
|
|
-- Ver 302 minor timing fixes
|
|
-- Ver 301 Jump timing fixed
|
|
-- Ver 300 Bugfixes by ehenciak added
|
|
-- MikeJ March 2005
|
|
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
|
|
--
|
|
-- ****
|
|
--
|
|
-- 65xx compatible microprocessor core
|
|
--
|
|
-- Version : 0246 + fix
|
|
--
|
|
-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
|
|
--
|
|
-- 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 SOFTWARE 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.
|
|
--
|
|
-- Please report bugs to the author, but before you do so, please
|
|
-- make sure that this is not a derivative work and that
|
|
-- you have the latest version of this file.
|
|
--
|
|
-- The latest version of this file can be found at:
|
|
-- http://www.opencores.org/cvsweb.shtml/t65/
|
|
--
|
|
-- Limitations :
|
|
--
|
|
-- 65C02
|
|
-- supported : inc, dec, phx, plx, phy, ply
|
|
-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
|
|
--
|
|
-- File history :
|
|
--
|
|
-- 0246 : First release
|
|
--
|
|
|
|
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.numeric_std.all;
|
|
use work.T65_Pack.all;
|
|
|
|
entity T65_MCode is
|
|
port(
|
|
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
|
|
IR : in std_logic_vector(7 downto 0);
|
|
MCycle : in std_logic_vector(2 downto 0);
|
|
P : in std_logic_vector(7 downto 0);
|
|
LCycle : out std_logic_vector(2 downto 0);
|
|
ALU_Op : out std_logic_vector(3 downto 0);
|
|
Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
|
|
Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
|
|
Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
|
|
Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
|
|
BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
|
|
BreakAtNA : out std_logic;
|
|
ADAdd : out std_logic;
|
|
AddY : out std_logic;
|
|
PCAdd : out std_logic;
|
|
Inc_S : out std_logic;
|
|
Dec_S : out std_logic;
|
|
LDA : out std_logic;
|
|
LDP : out std_logic;
|
|
LDX : out std_logic;
|
|
LDY : out std_logic;
|
|
LDS : out std_logic;
|
|
LDDI : out std_logic;
|
|
LDALU : out std_logic;
|
|
LDAD : out std_logic;
|
|
LDBAL : out std_logic;
|
|
LDBAH : out std_logic;
|
|
SaveP : out std_logic;
|
|
Write : out std_logic
|
|
);
|
|
end T65_MCode;
|
|
|
|
architecture rtl of T65_MCode is
|
|
|
|
signal Branch : std_logic;
|
|
|
|
begin
|
|
|
|
with IR(7 downto 5) select
|
|
Branch <= not P(Flag_N) when "000",
|
|
P(Flag_N) when "001",
|
|
not P(Flag_V) when "010",
|
|
P(Flag_V) when "011",
|
|
not P(Flag_C) when "100",
|
|
P(Flag_C) when "101",
|
|
not P(Flag_Z) when "110",
|
|
P(Flag_Z) when others;
|
|
|
|
process (IR, MCycle, P, Branch, Mode)
|
|
begin
|
|
LCycle <= "001";
|
|
Set_BusA_To <= "001"; -- A
|
|
Set_Addr_To <= (others => '0');
|
|
Write_Data <= (others => '0');
|
|
Jump <= (others => '0');
|
|
BAAdd <= "00";
|
|
BreakAtNA <= '0';
|
|
ADAdd <= '0';
|
|
PCAdd <= '0';
|
|
Inc_S <= '0';
|
|
Dec_S <= '0';
|
|
LDA <= '0';
|
|
LDP <= '0';
|
|
LDX <= '0';
|
|
LDY <= '0';
|
|
LDS <= '0';
|
|
LDDI <= '0';
|
|
LDALU <= '0';
|
|
LDAD <= '0';
|
|
LDBAL <= '0';
|
|
LDBAH <= '0';
|
|
SaveP <= '0';
|
|
Write <= '0';
|
|
AddY <= '0';
|
|
|
|
case IR(7 downto 5) is
|
|
when "100" =>
|
|
--{{{
|
|
case IR(1 downto 0) is
|
|
when "00" =>
|
|
Set_BusA_To <= "011"; -- Y
|
|
Write_Data <= "011"; -- Y
|
|
when "10" =>
|
|
Set_BusA_To <= "010"; -- X
|
|
Write_Data <= "010"; -- X
|
|
when others =>
|
|
Write_Data <= "001"; -- A
|
|
end case;
|
|
--}}}
|
|
when "101" =>
|
|
--{{{
|
|
case IR(1 downto 0) is
|
|
when "00" =>
|
|
if IR(4) /= '1' or IR(2) /= '0' then
|
|
LDY <= '1';
|
|
end if;
|
|
when "10" =>
|
|
LDX <= '1';
|
|
when others =>
|
|
LDA <= '1';
|
|
end case;
|
|
Set_BusA_To <= "000"; -- DI
|
|
--}}}
|
|
when "110" =>
|
|
--{{{
|
|
case IR(1 downto 0) is
|
|
when "00" =>
|
|
if IR(4) = '0' then
|
|
LDY <= '1';
|
|
end if;
|
|
Set_BusA_To <= "011"; -- Y
|
|
when others =>
|
|
Set_BusA_To <= "001"; -- A
|
|
end case;
|
|
--}}}
|
|
when "111" =>
|
|
--{{{
|
|
case IR(1 downto 0) is
|
|
when "00" =>
|
|
if IR(4) = '0' then
|
|
LDX <= '1';
|
|
end if;
|
|
Set_BusA_To <= "010"; -- X
|
|
when others =>
|
|
Set_BusA_To <= "001"; -- A
|
|
end case;
|
|
--}}}
|
|
when others =>
|
|
end case;
|
|
|
|
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
|
|
Set_BusA_To <= "000"; -- DI
|
|
end if;
|
|
|
|
case IR(4 downto 0) is
|
|
when "00000" | "01000" | "01010" | "11000" | "11010" =>
|
|
--{{{
|
|
-- Implied
|
|
case IR is
|
|
when "00000000" =>
|
|
-- BRK
|
|
LCycle <= "110";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Set_Addr_To <= "01"; -- S
|
|
Write_Data <= "111"; -- PCH
|
|
Write <= '1';
|
|
when 2 =>
|
|
Dec_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
Write_Data <= "110"; -- PCL
|
|
Write <= '1';
|
|
when 3 =>
|
|
Dec_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
Write_Data <= "101"; -- P
|
|
Write <= '1';
|
|
when 4 =>
|
|
Dec_S <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 5 =>
|
|
LDDI <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 6 =>
|
|
Jump <= "10"; -- DIDL
|
|
when others =>
|
|
end case;
|
|
when "00100000" =>
|
|
-- JSR
|
|
LCycle <= "101";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDDI <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 2 =>
|
|
Set_Addr_To <= "01"; -- S
|
|
Write_Data <= "111"; -- PCH
|
|
Write <= '1';
|
|
when 3 =>
|
|
Dec_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
Write_Data <= "110"; -- PCL
|
|
Write <= '1';
|
|
when 4 =>
|
|
Dec_S <= '1';
|
|
when 5 =>
|
|
Jump <= "10"; -- DIDL
|
|
when others =>
|
|
end case;
|
|
when "01000000" =>
|
|
-- RTI
|
|
LCycle <= "101";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Set_Addr_To <= "01"; -- S
|
|
when 2 =>
|
|
Inc_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 3 =>
|
|
Inc_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
Set_BusA_To <= "000"; -- DI
|
|
when 4 =>
|
|
LDP <= '1';
|
|
Inc_S <= '1';
|
|
LDDI <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 5 =>
|
|
Jump <= "10"; -- DIDL
|
|
when others =>
|
|
end case;
|
|
when "01100000" =>
|
|
-- RTS
|
|
LCycle <= "101";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Set_Addr_To <= "01"; -- S
|
|
when 2 =>
|
|
Inc_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 3 =>
|
|
Inc_S <= '1';
|
|
LDDI <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 4 =>
|
|
Jump <= "10"; -- DIDL
|
|
when 5 =>
|
|
Jump <= "01";
|
|
when others =>
|
|
end case;
|
|
when "00001000" | "01001000" | "01011010" | "11011010" =>
|
|
-- PHP, PHA, PHY*, PHX*
|
|
LCycle <= "010";
|
|
if Mode = "00" and IR(1) = '1' then
|
|
LCycle <= "001";
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
case IR(7 downto 4) is
|
|
when "0000" =>
|
|
Write_Data <= "101"; -- P
|
|
when "0100" =>
|
|
Write_Data <= "001"; -- A
|
|
when "0101" =>
|
|
Write_Data <= "011"; -- Y
|
|
when "1101" =>
|
|
Write_Data <= "010"; -- X
|
|
when others =>
|
|
end case;
|
|
Write <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 2 =>
|
|
Dec_S <= '1';
|
|
when others =>
|
|
end case;
|
|
when "00101000" | "01101000" | "01111010" | "11111010" =>
|
|
-- PLP, PLA, PLY*, PLX*
|
|
LCycle <= "011";
|
|
if Mode = "00" and IR(1) = '1' then
|
|
LCycle <= "001";
|
|
end if;
|
|
case IR(7 downto 4) is
|
|
when "0010" =>
|
|
LDP <= '1';
|
|
when "0110" =>
|
|
LDA <= '1';
|
|
when "0111" =>
|
|
if Mode /= "00" then
|
|
LDY <= '1';
|
|
end if;
|
|
when "1111" =>
|
|
if Mode /= "00" then
|
|
LDX <= '1';
|
|
end if;
|
|
when others =>
|
|
end case;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
SaveP <= '1';
|
|
when 1 =>
|
|
Set_Addr_To <= "01"; -- S
|
|
when 2 =>
|
|
Inc_S <= '1';
|
|
Set_Addr_To <= "01"; -- S
|
|
when 3 =>
|
|
Set_BusA_To <= "000"; -- DI
|
|
when others =>
|
|
end case;
|
|
when "10100000" | "11000000" | "11100000" =>
|
|
-- LDY, CPY, CPX
|
|
-- Immediate
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
when others =>
|
|
end case;
|
|
when "10001000" =>
|
|
-- DEY
|
|
LDY <= '1';
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Set_BusA_To <= "011"; -- Y
|
|
when others =>
|
|
end case;
|
|
when "11001010" =>
|
|
-- DEX
|
|
LDX <= '1';
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Set_BusA_To <= "010"; -- X
|
|
when others =>
|
|
end case;
|
|
when "00011010" | "00111010" =>
|
|
-- INC*, DEC*
|
|
if Mode /= "00" then
|
|
LDA <= '1'; -- A
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Set_BusA_To <= "100"; -- S
|
|
when others =>
|
|
end case;
|
|
when "00001010" | "00101010" | "01001010" | "01101010" =>
|
|
-- ASL, ROL, LSR, ROR
|
|
LDA <= '1'; -- A
|
|
Set_BusA_To <= "001"; -- A
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
when others =>
|
|
end case;
|
|
when "10001010" | "10011000" =>
|
|
-- TYA, TXA
|
|
LDA <= '1'; -- A
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
when others =>
|
|
end case;
|
|
when "10101010" | "10101000" =>
|
|
-- TAX, TAY
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Set_BusA_To <= "001"; -- A
|
|
when others =>
|
|
end case;
|
|
when "10011010" =>
|
|
-- TXS
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
LDS <= '1';
|
|
when 1 =>
|
|
when others =>
|
|
end case;
|
|
when "10111010" =>
|
|
-- TSX
|
|
LDX <= '1';
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Set_BusA_To <= "100"; -- S
|
|
when others =>
|
|
end case;
|
|
|
|
-- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
|
|
-- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
|
|
-- case to_integer(unsigned(MCycle)) is
|
|
-- when 1 =>
|
|
-- when others =>
|
|
-- end case;
|
|
when others =>
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when others =>
|
|
end case;
|
|
end case;
|
|
--}}}
|
|
|
|
when "00001" | "00011" =>
|
|
--{{{
|
|
-- Zero Page Indexed Indirect (d,x)
|
|
LCycle <= "101";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
ADAdd <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 3 =>
|
|
BAAdd <= "01"; -- DB Inc
|
|
LDBAL <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 4 =>
|
|
LDBAH <= '1';
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 5 =>
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
|
|
when "01001" | "01011" =>
|
|
--{{{
|
|
-- Immediate
|
|
LDA <= '1';
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
when others =>
|
|
end case;
|
|
|
|
--}}}
|
|
|
|
when "00010" | "10010" =>
|
|
--{{{
|
|
-- Immediate, KIL
|
|
LDX <= '1';
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
if IR = "10100010" then
|
|
-- LDX
|
|
Jump <= "01";
|
|
else
|
|
-- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
end if;
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
|
|
when "00100" =>
|
|
--{{{
|
|
-- Zero Page
|
|
LCycle <= "010";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
if IR(7 downto 5) = "001" then
|
|
SaveP <= '1';
|
|
end if;
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
|
|
when "00101" | "00110" | "00111" =>
|
|
--{{{
|
|
-- Zero Page
|
|
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
|
|
-- Read-Modify-Write
|
|
LCycle <= "100";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
LDDI <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 3 =>
|
|
LDALU <= '1';
|
|
SaveP <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 4 =>
|
|
when others =>
|
|
end case;
|
|
else
|
|
LCycle <= "010";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
--}}}
|
|
|
|
when "01100" =>
|
|
--{{{
|
|
-- Absolute
|
|
if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
|
|
-- JMP
|
|
if IR(5) = '0' then
|
|
--LCycle <= "011";
|
|
LCycle <= "010";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDDI <= '1';
|
|
when 2 =>
|
|
Jump <= "10"; -- DIDL
|
|
when others =>
|
|
end case;
|
|
else
|
|
--LCycle <= "101";
|
|
LCycle <= "100"; -- mikej
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDDI <= '1';
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
LDBAH <= '1';
|
|
if Mode /= "00" then
|
|
Jump <= "10"; -- DIDL
|
|
end if;
|
|
if Mode = "00" then
|
|
Set_Addr_To <= "11"; -- BA
|
|
end if;
|
|
when 3 =>
|
|
LDDI <= '1';
|
|
if Mode = "00" then
|
|
Set_Addr_To <= "11"; -- BA
|
|
BAAdd <= "01"; -- DB Inc
|
|
else
|
|
Jump <= "01";
|
|
end if;
|
|
when 4 =>
|
|
Jump <= "10"; -- DIDL
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
else
|
|
LCycle <= "011";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
if IR(7 downto 5) = "001" then
|
|
SaveP <= '1';
|
|
end if;
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
LDBAH <= '1';
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
--}}}
|
|
|
|
when "01101" | "01110" | "01111" =>
|
|
--{{{
|
|
-- Absolute
|
|
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
|
|
-- Read-Modify-Write
|
|
LCycle <= "101";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
LDBAH <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
LDDI <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 4 =>
|
|
Write <= '1';
|
|
LDALU <= '1';
|
|
SaveP <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 5 =>
|
|
SaveP <= '0'; -- MIKEJ was 1
|
|
when others =>
|
|
end case;
|
|
else
|
|
LCycle <= "011";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
LDBAH <= '1';
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
--}}}
|
|
|
|
when "10000" =>
|
|
--{{{
|
|
-- Relative
|
|
|
|
-- This circuit dictates when the last
|
|
-- microcycle occurs for the branch depending on
|
|
-- whether or not the branch is taken and if a page
|
|
-- is crossed...
|
|
if (Branch = '1') then
|
|
|
|
LCycle <= "011"; -- We're done @ T3 if branching...upper
|
|
-- level logic will stop at T2 if no page cross
|
|
-- (See the Break signal)
|
|
else
|
|
|
|
LCycle <= "001";
|
|
|
|
end if;
|
|
|
|
-- This decodes the current microcycle and takes the
|
|
-- proper course of action...
|
|
case to_integer(unsigned(MCycle)) is
|
|
|
|
-- On the T1 microcycle, increment the program counter
|
|
-- and instruct the upper level logic to fetch the offset
|
|
-- from the Din bus and store it in the data latches. This
|
|
-- will be the last microcycle if the branch isn't taken.
|
|
when 1 =>
|
|
|
|
Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
|
|
-- from microcycle T0.
|
|
|
|
LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
|
|
-- the Din bus to the memory data latch (DL)
|
|
-- so that the branch offset is fetched.
|
|
|
|
-- In microcycle T2, tell the logic in the top level to
|
|
-- add the offset. If the most significant byte of the
|
|
-- program counter (i.e. the current "page") does not need
|
|
-- updating, we are done here...the Break signal at the
|
|
-- T65.vhd level takes care of that...
|
|
when 2 =>
|
|
|
|
Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
|
|
|
|
PCAdd <= '1'; -- This tells the PC adder to update itself with
|
|
-- the current offset recently fetched from
|
|
-- memory.
|
|
|
|
-- The following is microcycle T3 :
|
|
-- The program counter should be completely updated
|
|
-- on this cycle after the page cross is detected.
|
|
-- We don't need to do anything here...
|
|
when 3 =>
|
|
|
|
|
|
when others => null; -- Do nothing.
|
|
|
|
end case;
|
|
--}}}
|
|
|
|
when "10001" | "10011" =>
|
|
--{{{
|
|
-- Zero Page Indirect Indexed (d),y
|
|
LCycle <= "101";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
LDBAL <= '1';
|
|
BAAdd <= "01"; -- DB Inc
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 3 =>
|
|
Set_BusA_To <= "011"; -- Y
|
|
BAAdd <= "10"; -- BA Add
|
|
LDBAH <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 4 =>
|
|
BAAdd <= "11"; -- BA Adj
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
else
|
|
BreakAtNA <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 5 =>
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
|
|
when "10100" | "10101" | "10110" | "10111" =>
|
|
--{{{
|
|
-- Zero Page, X
|
|
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
|
|
-- Read-Modify-Write
|
|
LCycle <= "101";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
ADAdd <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 3 =>
|
|
LDDI <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 4 =>
|
|
LDALU <= '1';
|
|
SaveP <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 5 =>
|
|
when others =>
|
|
end case;
|
|
else
|
|
LCycle <= "011";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDAD <= '1';
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 2 =>
|
|
ADAdd <= '1';
|
|
-- Added this check for Y reg. use...
|
|
if (IR(3 downto 0) = "0110") then
|
|
AddY <= '1';
|
|
end if;
|
|
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
end if;
|
|
Set_Addr_To <= "10"; -- AD
|
|
when 3 => null;
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
--}}}
|
|
|
|
when "11001" | "11011" =>
|
|
--{{{
|
|
-- Absolute Y
|
|
LCycle <= "100";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
Set_BusA_To <= "011"; -- Y
|
|
BAAdd <= "10"; -- BA Add
|
|
LDBAH <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
BAAdd <= "11"; -- BA adj
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
else
|
|
BreakAtNA <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 4 =>
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
|
|
when "11100" | "11101" | "11110" | "11111" =>
|
|
--{{{
|
|
-- Absolute X
|
|
|
|
if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
|
|
-- Read-Modify-Write
|
|
LCycle <= "110";
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
Set_BusA_To <= "010"; -- X
|
|
BAAdd <= "10"; -- BA Add
|
|
LDBAH <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
BAAdd <= "11"; -- BA adj
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 4 =>
|
|
LDDI <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 5 =>
|
|
LDALU <= '1';
|
|
SaveP <= '1';
|
|
Write <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 6 =>
|
|
when others =>
|
|
end case;
|
|
else
|
|
LCycle <= "100";
|
|
if IR(7 downto 6) /= "10" then
|
|
LDA <= '1';
|
|
end if;
|
|
case to_integer(unsigned(MCycle)) is
|
|
when 0 =>
|
|
when 1 =>
|
|
Jump <= "01";
|
|
LDBAL <= '1';
|
|
when 2 =>
|
|
Jump <= "01";
|
|
-- mikej
|
|
-- special case 0xBE which uses Y reg as index!!
|
|
if (IR = "10111110") then
|
|
Set_BusA_To <= "011"; -- Y
|
|
else
|
|
Set_BusA_To <= "010"; -- X
|
|
end if;
|
|
BAAdd <= "10"; -- BA Add
|
|
LDBAH <= '1';
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 3 =>
|
|
BAAdd <= "11"; -- BA adj
|
|
if IR(7 downto 5) = "100" then
|
|
Write <= '1';
|
|
else
|
|
BreakAtNA <= '1';
|
|
end if;
|
|
Set_Addr_To <= "11"; -- BA
|
|
when 4 =>
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
--}}}
|
|
when others =>
|
|
end case;
|
|
end process;
|
|
|
|
process (IR, MCycle)
|
|
begin
|
|
-- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
|
|
-- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
|
|
case IR(1 downto 0) is
|
|
when "00" =>
|
|
--{{{
|
|
case IR(4 downto 2) is
|
|
when "000" | "001" | "011" =>
|
|
case IR(7 downto 5) is
|
|
when "110" | "111" =>
|
|
-- CP
|
|
ALU_Op <= "0110";
|
|
when "101" =>
|
|
-- LD
|
|
ALU_Op <= "0101";
|
|
when "001" =>
|
|
-- BIT
|
|
ALU_Op <= "1100";
|
|
when others =>
|
|
-- NOP/ST
|
|
ALU_Op <= "0100";
|
|
end case;
|
|
when "010" =>
|
|
case IR(7 downto 5) is
|
|
when "111" | "110" =>
|
|
-- IN
|
|
ALU_Op <= "1111";
|
|
when "100" =>
|
|
-- DEY
|
|
ALU_Op <= "1110";
|
|
when others =>
|
|
-- LD
|
|
ALU_Op <= "1101";
|
|
end case;
|
|
when "110" =>
|
|
case IR(7 downto 5) is
|
|
when "100" =>
|
|
-- TYA
|
|
ALU_Op <= "1101";
|
|
when others =>
|
|
ALU_Op <= "----";
|
|
end case;
|
|
when others =>
|
|
case IR(7 downto 5) is
|
|
when "101" =>
|
|
-- LD
|
|
ALU_Op <= "1101";
|
|
when others =>
|
|
ALU_Op <= "0100";
|
|
end case;
|
|
end case;
|
|
--}}}
|
|
when "01" => -- OR
|
|
--{{{
|
|
ALU_Op(3) <= '0';
|
|
ALU_Op(2 downto 0) <= IR(7 downto 5);
|
|
--}}}
|
|
when "10" =>
|
|
--{{{
|
|
ALU_Op(3) <= '1';
|
|
ALU_Op(2 downto 0) <= IR(7 downto 5);
|
|
case IR(7 downto 5) is
|
|
when "000" =>
|
|
if IR(4 downto 2) = "110" then
|
|
-- INC
|
|
ALU_Op <= "1111";
|
|
end if;
|
|
when "001" =>
|
|
if IR(4 downto 2) = "110" then
|
|
-- DEC
|
|
ALU_Op <= "1110";
|
|
end if;
|
|
when "100" =>
|
|
if IR(4 downto 2) = "010" then
|
|
-- TXA
|
|
ALU_Op <= "0101";
|
|
else
|
|
ALU_Op <= "0100";
|
|
end if;
|
|
when others =>
|
|
end case;
|
|
--}}}
|
|
when others =>
|
|
--{{{
|
|
case IR(7 downto 5) is
|
|
when "100" =>
|
|
ALU_Op <= "0100";
|
|
when others =>
|
|
if MCycle = "000" then
|
|
ALU_Op(3) <= '0';
|
|
ALU_Op(2 downto 0) <= IR(7 downto 5);
|
|
else
|
|
ALU_Op(3) <= '1';
|
|
ALU_Op(2 downto 0) <= IR(7 downto 5);
|
|
end if;
|
|
end case;
|
|
--}}}
|
|
end case;
|
|
end process;
|
|
|
|
end;
|