URL
https://opencores.org/ocsvn/t65/t65/trunk
Subversion Repositories t65
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/trunk/rtl/vhdl/T65_ALU.vhd
0,0 → 1,251
-- |
-- 6502 compatible microprocessor core |
-- |
-- Version : 0245 |
-- |
-- 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 : |
-- |
-- File history : |
-- |
-- 0245 : First version |
-- |
|
library IEEE; |
use IEEE.std_logic_1164.all; |
use IEEE.numeric_std.all; |
use work.T65_Pack.all; |
|
entity T65_ALU is |
port( |
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 |
Op : in std_logic_vector(3 downto 0); |
BusA : in std_logic_vector(7 downto 0); |
BusB : in std_logic_vector(7 downto 0); |
P_In : in std_logic_vector(7 downto 0); |
P_Out : out std_logic_vector(7 downto 0); |
Q : out std_logic_vector(7 downto 0) |
); |
end T65_ALU; |
|
architecture rtl of T65_ALU is |
|
-- AddSub variables (temporary signals) |
signal ADC_Z : std_logic; |
signal ADC_C : std_logic; |
signal ADC_V : std_logic; |
signal ADC_N : std_logic; |
signal ADC_Q : std_logic_vector(7 downto 0); |
signal SBC_Z : std_logic; |
signal SBC_C : std_logic; |
signal SBC_V : std_logic; |
signal SBC_N : std_logic; |
signal SBC_Q : std_logic_vector(7 downto 0); |
|
begin |
|
process (P_In, BusA, BusB) |
variable AL : unsigned(6 downto 0); |
variable AH : unsigned(6 downto 0); |
variable C : std_logic; |
begin |
AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7); |
AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); |
|
-- pragma translate_off |
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; |
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; |
-- pragma translate_on |
|
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then |
ADC_Z <= '1'; |
else |
ADC_Z <= '0'; |
end if; |
|
if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then |
AL(6 downto 1) := AL(6 downto 1) + 6; |
end if; |
|
C := AL(6) or AL(5); |
AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7); |
|
ADC_N <= AH(4); |
ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7)); |
|
-- pragma translate_off |
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if; |
-- pragma translate_on |
|
if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then |
AH(6 downto 1) := AH(6 downto 1) + 6; |
end if; |
|
ADC_C <= AH(6) or AH(5); |
|
ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); |
end process; |
|
process (Op, P_In, BusA, BusB) |
variable AL : unsigned(6 downto 0); |
variable AH : unsigned(5 downto 0); |
variable C : std_logic; |
begin |
C := P_In(Flag_C) or not Op(0); |
AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6); |
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6); |
|
-- pragma translate_off |
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if; |
if is_x(std_logic_vector(AH)) then AH := "000000"; end if; |
-- pragma translate_on |
|
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then |
SBC_Z <= '1'; |
else |
SBC_Z <= '0'; |
end if; |
|
SBC_C <= not AH(5); |
SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7)); |
SBC_N <= AH(4); |
|
if P_In(Flag_D) = '1' then |
if AL(5) = '1' then |
AL(5 downto 1) := AL(5 downto 1) - 6; |
end if; |
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6); |
if AH(5) = '1' then |
AH(5 downto 1) := AH(5 downto 1) - 6; |
end if; |
end if; |
|
SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1)); |
end process; |
|
process (Op, P_In, BusA, BusB, |
ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q, |
SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q) |
variable Q_t : std_logic_vector(7 downto 0); |
begin |
-- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC |
-- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC |
P_Out <= P_In; |
Q_t := BusA; |
case Op(3 downto 0) is |
when "0000" => |
-- ORA |
Q_t := BusA or BusB; |
when "0001" => |
-- AND |
Q_t := BusA and BusB; |
when "0010" => |
-- EOR |
Q_t := BusA xor BusB; |
when "0011" => |
-- ADC |
P_Out(Flag_V) <= ADC_V; |
P_Out(Flag_C) <= ADC_C; |
Q_t := ADC_Q; |
when "0101" | "1101" => |
-- LDA |
when "0110" => |
-- CMP |
P_Out(Flag_C) <= SBC_C; |
when "0111" => |
-- SBC |
P_Out(Flag_V) <= SBC_V; |
P_Out(Flag_C) <= SBC_C; |
Q_t := SBC_Q; |
when "1000" => |
-- ASL |
Q_t := BusA(6 downto 0) & "0"; |
P_Out(Flag_C) <= BusA(7); |
when "1001" => |
-- ROL |
Q_t := BusA(6 downto 0) & P_In(Flag_C); |
P_Out(Flag_C) <= BusA(7); |
when "1010" => |
-- LSR |
Q_t := "0" & BusA(7 downto 1); |
P_Out(Flag_C) <= BusA(0); |
when "1011" => |
-- ROR |
Q_t := P_In(Flag_C) & BusA(7 downto 1); |
P_Out(Flag_C) <= BusA(0); |
when "1100" => |
-- BIT |
P_Out(Flag_V) <= BusB(6); |
when "1110" => |
-- DEC |
Q_t := std_logic_vector(unsigned(BusA) - 1); |
when "1111" => |
-- INC |
Q_t := std_logic_vector(unsigned(BusA) + 1); |
when others => |
end case; |
|
case Op(3 downto 0) is |
when "0011" => |
P_Out(Flag_N) <= ADC_N; |
P_Out(Flag_Z) <= ADC_Z; |
when "0110" | "0111" => |
P_Out(Flag_N) <= SBC_N; |
P_Out(Flag_Z) <= SBC_Z; |
when "0100" => |
when "1100" => |
P_Out(Flag_N) <= BusB(7); |
if (BusA and BusB) = "00000000" then |
P_Out(Flag_Z) <= '1'; |
else |
P_Out(Flag_Z) <= '0'; |
end if; |
when others => |
P_Out(Flag_N) <= Q_t(7); |
if Q_t = "00000000" then |
P_Out(Flag_Z) <= '1'; |
else |
P_Out(Flag_Z) <= '0'; |
end if; |
end case; |
|
Q <= Q_t; |
end process; |
|
end; |
/trunk/rtl/vhdl/DebugSystemXR.vhd
0,0 → 1,174
-- 6502, Monitor ROM, external SRAM interface and two 16450 UARTs |
-- that can be synthesized and used with |
-- the NoICE debugger that can be found at |
-- http://www.noicedebugger.com/ |
|
library IEEE; |
use IEEE.std_logic_1164.all; |
|
entity DebugSystemXR is |
port( |
Reset_n : in std_logic; |
Clk : in std_logic; |
NMI_n : in std_logic; |
OE_n : out std_logic; |
WE_n : out std_logic; |
RAMCS_n : out std_logic; |
ROMCS_n : out std_logic; |
PGM_n : out std_logic; |
A : out std_logic_vector(16 downto 0); |
D : inout std_logic_vector(7 downto 0); |
RXD0 : in std_logic; |
CTS0 : in std_logic; |
DSR0 : in std_logic; |
RI0 : in std_logic; |
DCD0 : in std_logic; |
RXD1 : in std_logic; |
CTS1 : in std_logic; |
DSR1 : in std_logic; |
RI1 : in std_logic; |
DCD1 : in std_logic; |
TXD0 : out std_logic; |
RTS0 : out std_logic; |
DTR0 : out std_logic; |
TXD1 : out std_logic; |
RTS1 : out std_logic; |
DTR1 : out std_logic |
); |
end entity DebugSystemXR; |
|
architecture struct of DebugSystemXR is |
|
signal Res_n_s : std_logic; |
signal Rd_n : std_logic; |
signal Wr_n : std_logic; |
signal R_W_n : std_logic; |
signal A_i : std_logic_vector(23 downto 0); |
signal D_i : std_logic_vector(7 downto 0); |
signal ROM_D : std_logic_vector(7 downto 0); |
signal UART0_D : std_logic_vector(7 downto 0); |
signal UART1_D : std_logic_vector(7 downto 0); |
signal CPU_D : std_logic_vector(7 downto 0); |
|
signal Rdy : std_logic; |
|
signal IOWR_n : std_logic; |
signal RAMCS_n_i : std_logic; |
signal UART0CS_n : std_logic; |
signal UART1CS_n : std_logic; |
|
signal BaudOut0 : std_logic; |
signal BaudOut1 : std_logic; |
|
begin |
|
Rd_n <= not R_W_n or not Rdy; |
Wr_n <= R_W_n or not Rdy; |
OE_n <= not R_W_n; |
WE_n <= Wr_n; |
RAMCS_n <= RAMCS_n_i; |
ROMCS_n <= '1'; |
PGM_n <= '1'; |
A(14 downto 0) <= A_i(14 downto 0); |
A(16 downto 15) <= "00"; |
D <= D_i when R_W_n = '0' else "ZZZZZZZZ"; |
|
process (Reset_n, Clk) |
begin |
if Reset_n = '0' then |
Res_n_s <= '0'; |
Rdy <= '0'; |
elsif Clk'event and Clk = '1' then |
Res_n_s <= '1'; |
Rdy <= not Rdy; |
end if; |
end process; |
|
RAMCS_n_i <= A_i(15); |
UART0CS_n <= '0' when A_i(15 downto 3) = "1000000000000" else '1'; |
UART1CS_n <= '0' when A_i(15 downto 3) = "1000000010000" else '1'; |
|
CPU_D <= |
D when RAMCS_n_i = '0' else |
UART0_D when UART0CS_n = '0' else |
UART1_D when UART1CS_n = '0' else |
ROM_D; |
|
u0 : entity work.T65 |
port map( |
Mode => "00", |
Res_n => Res_n_s, |
Clk => Clk, |
Rdy => Rdy, |
Abort_n => '1', |
IRQ_n => '1', |
NMI_n => NMI_n, |
SO_n => '1', |
R_W_n => R_W_n, |
Sync => open, |
EF => open, |
MF => open, |
XF => open, |
ML_n => open, |
VP_n => open, |
VDA => open, |
VPA => open, |
A => A_i, |
DI => CPU_D, |
DO => D_i); |
|
u1 : entity work.Mon65XR |
port map( |
Clk => Clk, |
A => A_i(9 downto 0), |
D => ROM_D); |
|
u3 : entity work.T16450 |
port map( |
MR_n => Res_n_s, |
XIn => Clk, |
RClk => BaudOut0, |
CS_n => UART0CS_n, |
Rd_n => Rd_n, |
Wr_n => Wr_n, |
A => A_i(2 downto 0), |
D_In => D_i, |
D_Out => UART0_D, |
SIn => RXD0, |
CTS_n => CTS0, |
DSR_n => DSR0, |
RI_n => RI0, |
DCD_n => DCD0, |
SOut => TXD0, |
RTS_n => RTS0, |
DTR_n => DTR0, |
OUT1_n => open, |
OUT2_n => open, |
BaudOut => BaudOut0, |
Intr => open); |
|
u4 : entity work.T16450 |
port map( |
MR_n => Res_n_s, |
XIn => Clk, |
RClk => BaudOut1, |
CS_n => UART1CS_n, |
Rd_n => Rd_n, |
Wr_n => Wr_n, |
A => A_i(2 downto 0), |
D_In => D_i, |
D_Out => UART1_D, |
SIn => RXD1, |
CTS_n => CTS1, |
DSR_n => DSR1, |
RI_n => RI1, |
DCD_n => DCD1, |
SOut => TXD1, |
RTS_n => RTS1, |
DTR_n => DTR1, |
OUT1_n => open, |
OUT2_n => open, |
BaudOut => BaudOut1, |
Intr => open); |
|
end; |
/trunk/rtl/vhdl/T65_MCode.vhd
0,0 → 1,941
-- |
-- 65xx compatible microprocessor core |
-- |
-- Version : 0246 |
-- |
-- 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; |
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'; |
|
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"; |
case to_integer(unsigned(MCycle)) is |
when 2 => |
Jump <= "01"; |
LDDI <= '1'; |
when 3 => |
Jump <= "10"; -- DIDL |
when others => |
end case; |
else |
LCycle <= "101"; |
case to_integer(unsigned(MCycle)) is |
when 2 => |
Jump <= "01"; |
LDDI <= '1'; |
LDBAL <= '1'; |
when 3 => |
LDBAH <= '1'; |
if Mode /= "00" then |
Jump <= "10"; -- DIDL |
end if; |
if Mode = "00" then |
Set_Addr_To <= "11"; -- BA |
end if; |
when 4 => |
LDDI <= '1'; |
if Mode = "00" then |
Set_Addr_To <= "11"; -- BA |
BAAdd <= "01"; -- DB Inc |
else |
Jump <= "01"; |
end if; |
when 5 => |
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 <= '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 |
if Branch = '1' then |
LCycle <= "100"; |
else |
LCycle <= "010"; |
end if; |
case to_integer(unsigned(MCycle)) is |
when 2 => |
Jump <= "01"; |
LDDI <= '1'; |
when 3 => |
Jump <= "11"; -- Rel |
PCAdd <= '1'; |
when 4 => |
when others => |
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'; |
if IR(7 downto 5) = "100" then |
Write <= '1'; |
end if; |
Set_Addr_To <= "10"; -- AD |
when 3 => |
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"; |
Set_BusA_To <= "010"; -- X |
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" => |
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; |
/trunk/rtl/vhdl/T65_Pack.vhd
0,0 → 1,132
-- |
-- 65xx compatible microprocessor core |
-- |
-- Version : 0246 |
-- |
-- 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 : |
-- |
-- File history : |
-- |
|
library IEEE; |
use IEEE.std_logic_1164.all; |
|
package T65_Pack is |
|
constant Flag_C : integer := 0; |
constant Flag_Z : integer := 1; |
constant Flag_I : integer := 2; |
constant Flag_D : integer := 3; |
constant Flag_B : integer := 4; |
constant Flag_1 : integer := 5; |
constant Flag_V : integer := 6; |
constant Flag_N : integer := 7; |
|
component T65 |
port( |
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816 |
Res_n : in std_logic; |
Clk : in std_logic; |
Rdy : in std_logic; |
Abort_n : in std_logic; |
IRQ_n : in std_logic; |
NMI_n : in std_logic; |
SO_n : in std_logic; |
R_W_n : out std_logic; |
Sync : out std_logic; |
EF : out std_logic; |
MF : out std_logic; |
XF : out std_logic; |
ML_n : out std_logic; |
VP_n : out std_logic; |
VDA : out std_logic; |
VPA : out std_logic; |
A : out std_logic_vector(23 downto 0); |
DI : in std_logic_vector(7 downto 0); |
DO : out std_logic_vector(7 downto 0) |
); |
end component; |
|
component T65_MCode |
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; |
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 component; |
|
component T65_ALU |
port( |
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 |
Op : in std_logic_vector(3 downto 0); |
BusA : in std_logic_vector(7 downto 0); |
BusB : in std_logic_vector(7 downto 0); |
P_In : in std_logic_vector(7 downto 0); |
P_Out : out std_logic_vector(7 downto 0); |
Q : out std_logic_vector(7 downto 0) |
); |
end component; |
|
end; |
/trunk/rtl/vhdl/T65.vhd
0,0 → 1,507
-- |
-- 65xx compatible microprocessor core |
-- |
-- Version : 0246 |
-- |
-- 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 and 65C816 modes are incomplete |
-- Undocumented instructions are not supported |
-- Some interface signals behaves incorrect |
-- |
-- 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 is |
port( |
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816 |
Res_n : in std_logic; |
Clk : in std_logic; |
Rdy : in std_logic; |
Abort_n : in std_logic; |
IRQ_n : in std_logic; |
NMI_n : in std_logic; |
SO_n : in std_logic; |
R_W_n : out std_logic; |
Sync : out std_logic; |
EF : out std_logic; |
MF : out std_logic; |
XF : out std_logic; |
ML_n : out std_logic; |
VP_n : out std_logic; |
VDA : out std_logic; |
VPA : out std_logic; |
A : out std_logic_vector(23 downto 0); |
DI : in std_logic_vector(7 downto 0); |
DO : out std_logic_vector(7 downto 0) |
); |
end T65; |
|
architecture rtl of T65 is |
|
-- Registers |
signal ABC, X, Y, D : std_logic_vector(15 downto 0); |
signal P, AD, DL : std_logic_vector(7 downto 0); |
signal BAH : std_logic_vector(7 downto 0); |
signal BAL : std_logic_vector(8 downto 0); |
signal PBR : std_logic_vector(7 downto 0); |
signal DBR : std_logic_vector(7 downto 0); |
signal PC : unsigned(15 downto 0); |
signal S : unsigned(15 downto 0); |
signal EF_i : std_logic; |
signal MF_i : std_logic; |
signal XF_i : std_logic; |
|
signal IR : std_logic_vector(7 downto 0); |
|
signal MCycle : std_logic_vector(2 downto 0); |
|
signal Mode_r : std_logic_vector(1 downto 0); |
signal ALU_Op_r : std_logic_vector(3 downto 0); |
signal Write_Data_r : std_logic_vector(2 downto 0); |
signal Set_Addr_To_r : std_logic_vector(1 downto 0); |
|
signal PCAdder : unsigned(8 downto 0); |
|
signal RstCycle : std_logic; |
signal IRQCycle : std_logic; |
signal NMICycle : std_logic; |
|
signal B_o : std_logic; |
signal SO_n_o : std_logic; |
signal IRQ_n_o : std_logic; |
signal NMI_n_o : std_logic; |
signal NMIAct : std_logic; |
|
signal Break : std_logic; |
|
-- ALU signals |
signal BusA : std_logic_vector(7 downto 0); |
signal BusA_r : std_logic_vector(7 downto 0); |
signal BusB : std_logic_vector(7 downto 0); |
signal ALU_Q : std_logic_vector(7 downto 0); |
signal P_Out : std_logic_vector(7 downto 0); |
|
-- Micro code outputs |
signal LCycle : std_logic_vector(2 downto 0); |
signal ALU_Op : std_logic_vector(3 downto 0); |
signal Set_BusA_To : std_logic_vector(2 downto 0); |
signal Set_Addr_To : std_logic_vector(1 downto 0); |
signal Write_Data : std_logic_vector(2 downto 0); |
signal Jump : std_logic_vector(1 downto 0); |
signal BAAdd : std_logic_vector(1 downto 0); |
signal BreakAtNA : std_logic; |
signal ADAdd : std_logic; |
signal PCAdd : std_logic; |
signal Inc_S : std_logic; |
signal Dec_S : std_logic; |
signal LDA : std_logic; |
signal LDP : std_logic; |
signal LDX : std_logic; |
signal LDY : std_logic; |
signal LDS : std_logic; |
signal LDDI : std_logic; |
signal LDALU : std_logic; |
signal LDAD : std_logic; |
signal LDBAL : std_logic; |
signal LDBAH : std_logic; |
signal SaveP : std_logic; |
signal Write : std_logic; |
|
begin |
|
Sync <= '1' when MCycle = "000" else '0'; |
EF <= EF_i; |
MF <= MF_i; |
XF <= XF_i; |
ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1'; |
VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1'; |
VDA <= '1' when Set_Addr_To_r /= "000" else '0'; -- Incorrect !!!!!!!!!!!! |
VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!! |
|
mcode : T65_MCode |
port map( |
Mode => Mode_r, |
IR => IR, |
MCycle => MCycle, |
P => P, |
LCycle => LCycle, |
ALU_Op => ALU_Op, |
Set_BusA_To => Set_BusA_To, |
Set_Addr_To => Set_Addr_To, |
Write_Data => Write_Data, |
Jump => Jump, |
BAAdd => BAAdd, |
BreakAtNA => BreakAtNA, |
ADAdd => ADAdd, |
PCAdd => PCAdd, |
Inc_S => Inc_S, |
Dec_S => Dec_S, |
LDA => LDA, |
LDP => LDP, |
LDX => LDX, |
LDY => LDY, |
LDS => LDS, |
LDDI => LDDI, |
LDALU => LDALU, |
LDAD => LDAD, |
LDBAL => LDBAL, |
LDBAH => LDBAH, |
SaveP => SaveP, |
Write => Write); |
|
alu : T65_ALU |
port map( |
Mode => Mode_r, |
Op => ALU_Op_r, |
BusA => BusA_r, |
BusB => BusB, |
P_In => P, |
P_Out => P_Out, |
Q => ALU_Q); |
|
process (Res_n, Clk) |
begin |
if Res_n = '0' then |
PC <= (others => '0'); -- Program Counter |
IR <= "00000000"; |
|
S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!! |
|
D <= (others => '0'); |
PBR <= (others => '0'); |
DBR <= (others => '0'); |
|
Mode_r <= (others => '0'); |
ALU_Op_r <= "1100"; |
Write_Data_r <= "000"; |
Set_Addr_To_r <= "00"; |
|
R_W_n <= '1'; |
EF_i <= '1'; |
MF_i <= '1'; |
XF_i <= '1'; |
|
elsif Clk'event and Clk = '1' then |
if Rdy = '1' then |
R_W_n <= not Write or RstCycle; |
|
D <= (others => '1'); -- Dummy |
PBR <= (others => '1'); -- Dummy |
DBR <= (others => '1'); -- Dummy |
EF_i <= '0'; -- Dummy |
MF_i <= '0'; -- Dummy |
XF_i <= '0'; -- Dummy |
|
if MCycle = "000" then |
Mode_r <= Mode; |
|
if IRQCycle = '0' and NMICycle = '0' then |
PC <= PC + 1; |
end if; |
|
if IRQCycle = '1' or NMICycle = '1' then |
IR <= "00000000"; |
else |
IR <= DI; |
end if; |
end if; |
|
ALU_Op_r <= ALU_Op; |
Write_Data_r <= Write_Data; |
if Break = '1' then |
Set_Addr_To_r <= "00"; |
else |
Set_Addr_To_r <= Set_Addr_To; |
end if; |
|
if Inc_S = '1' then |
S <= S + 1; |
end if; |
if Dec_S = '1' and RstCycle = '0' then |
S <= S - 1; |
end if; |
if LDS = '1' then |
S(7 downto 0) <= unsigned(ALU_Q); |
end if; |
|
if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then |
PC <= PC + 1; |
end if; |
case Jump is |
when "01" => |
PC <= PC + 1; |
when "10" => |
PC <= unsigned(DI & DL); |
when "11" => |
if PCAdder(8) = '1' then |
if DL(7) = '0' then |
PC(15 downto 8) <= PC(15 downto 8) + 1; |
else |
PC(15 downto 8) <= PC(15 downto 8) - 1; |
end if; |
end if; |
PC(7 downto 0) <= PCAdder(7 downto 0); |
when others => |
end case; |
end if; |
end if; |
end process; |
|
process (Clk) |
begin |
if Clk'event and Clk = '1' then |
if Rdy = '1' then |
if MCycle = "000" then |
if LDA = '1' then |
ABC(7 downto 0) <= ALU_Q; |
end if; |
if LDX = '1' then |
X(7 downto 0) <= ALU_Q; |
end if; |
if LDY = '1' then |
Y(7 downto 0) <= ALU_Q; |
end if; |
if (LDA or LDX or LDY) = '1' then |
P <= P_Out; |
end if; |
end if; |
if SaveP = '1' then |
P <= P_Out; |
end if; |
if LDP = '1' then |
P <= ALU_Q; |
end if; |
if IR(4 downto 0) = "11000" then |
case IR(7 downto 5) is |
when "000" => |
P(Flag_C) <= '0'; |
when "001" => |
P(Flag_C) <= '1'; |
when "010" => |
P(Flag_I) <= '0'; |
when "011" => |
P(Flag_I) <= '1'; |
when "101" => |
P(Flag_V) <= '0'; |
when "110" => |
P(Flag_D) <= '0'; |
when "111" => |
P(Flag_D) <= '1'; |
when others => |
end case; |
end if; |
if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' then |
P(Flag_B) <= '1'; |
end if; |
if IR = "00000000" and MCycle = "100" and RstCycle = '0' and NMICycle = '0' then |
P(Flag_I) <= '1'; |
P(Flag_B) <= B_o; |
end if; |
if SO_n_o = '1' and SO_n = '0' then |
P(Flag_V) <= '1'; |
end if; |
if RstCycle = '1' and Mode_r /= "00" then |
P(Flag_1) <= '1'; |
P(Flag_D) <= '0'; |
P(Flag_I) <= '1'; |
end if; |
P(Flag_1) <= '1'; |
|
B_o <= P(Flag_B); |
SO_n_o <= SO_n; |
IRQ_n_o <= IRQ_n; |
NMI_n_o <= NMI_n; |
end if; |
end if; |
end process; |
|
--------------------------------------------------------------------------- |
-- |
-- Buses |
-- |
--------------------------------------------------------------------------- |
|
process (Res_n, Clk) |
begin |
if Res_n = '0' then |
BusA_r <= (others => '0'); |
BusB <= (others => '0'); |
AD <= (others => '0'); |
BAL <= (others => '0'); |
BAH <= (others => '0'); |
DL <= (others => '0'); |
elsif Clk'event and Clk = '1' then |
if Rdy = '1' then |
BusA_r <= BusA; |
BusB <= DI; |
|
case BAAdd is |
when "01" => |
-- BA Inc |
AD <= std_logic_vector(unsigned(AD) + 1); |
BAL <= std_logic_vector(unsigned(BAL) + 1); |
when "10" => |
-- BA Add |
BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9)); |
when "11" => |
-- BA Adj |
if BAL(8) = '1' then |
BAH <= std_logic_vector(unsigned(BAH) + 1); |
end if; |
when others => |
end case; |
|
if ADAdd = '1' then |
AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0))); |
end if; |
|
if IR = "00000000" then |
BAL <= (others => '1'); |
BAH <= (others => '1'); |
if RstCycle = '1' then |
BAL(2 downto 0) <= "100"; |
elsif NMICycle = '1' then |
BAL(2 downto 0) <= "010"; |
else |
BAL(2 downto 0) <= "110"; |
end if; |
if Set_addr_To_r = "11" then |
BAL(0) <= '1'; |
end if; |
end if; |
|
|
if LDDI = '1' then |
DL <= DI; |
end if; |
if LDALU = '1' then |
DL <= ALU_Q; |
end if; |
if LDAD = '1' then |
AD <= DI; |
end if; |
if LDBAL = '1' then |
BAL(7 downto 0) <= DI; |
end if; |
if LDBAH = '1' then |
BAH <= DI; |
end if; |
end if; |
end if; |
end process; |
|
Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8)); |
|
PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1' else "0" & PC(7 downto 0); |
|
with Set_BusA_To select |
BusA <= DI when "000", |
ABC(7 downto 0) when "001", |
X(7 downto 0) when "010", |
Y(7 downto 0) when "011", |
std_logic_vector(S(7 downto 0)) when "100", |
P when "101", |
(others => '-') when others; |
|
with Set_Addr_To_r select |
A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01", |
DBR & "00000000" & AD when "10", |
"00000000" & BAH & BAL(7 downto 0) when "11", |
PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others; |
|
with Write_Data_r select |
DO <= DL when "000", |
ABC(7 downto 0) when "001", |
X(7 downto 0) when "010", |
Y(7 downto 0) when "011", |
std_logic_vector(S(7 downto 0)) when "100", |
P when "101", |
std_logic_vector(PC(7 downto 0)) when "110", |
std_logic_vector(PC(15 downto 8)) when others; |
|
------------------------------------------------------------------------- |
-- |
-- Main state machine |
-- |
------------------------------------------------------------------------- |
|
process (Res_n, Clk) |
begin |
if Res_n = '0' then |
MCycle <= "001"; |
RstCycle <= '1'; |
IRQCycle <= '0'; |
NMICycle <= '0'; |
NMIAct <= '0'; |
elsif Clk'event and Clk = '1' then |
if Rdy = '1' then |
if MCycle = LCycle or Break = '1' then |
MCycle <= "000"; |
RstCycle <= '0'; |
IRQCycle <= '0'; |
NMICycle <= '0'; |
if NMIAct = '1' then |
NMICycle <= '1'; |
elsif IRQ_n_o = '0' and P(Flag_I) = '0' then |
IRQCycle <= '1'; |
end if; |
else |
MCycle <= std_logic_vector(unsigned(MCycle) + 1); |
end if; |
|
if NMICycle = '1' then |
NMIAct <= '0'; |
end if; |
if NMI_n_o = '1' and NMI_n = '0' then |
NMIAct <= '1'; |
end if; |
end if; |
end if; |
end process; |
|
end; |