From 3975fdfe4275347dab666e43dbfdaebe80c58ff8 Mon Sep 17 00:00:00 2001 From: Mike Stirling Date: Tue, 12 Jul 2011 20:52:34 +0100 Subject: Initial commit. Some modules imported from experimental 6502 platform. Project added for Quartus 9.1 --- T65/T65_ALU.vhd | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 T65/T65_ALU.vhd (limited to 'T65/T65_ALU.vhd') diff --git a/T65/T65_ALU.vhd b/T65/T65_ALU.vhd new file mode 100644 index 0000000..d9d25e1 --- /dev/null +++ b/T65/T65_ALU.vhd @@ -0,0 +1,260 @@ +-- **** +-- T65(b) core. In an effort to merge and maintain bug fixes .... +-- +-- +-- Ver 300 Bugfixes by ehenciak added +-- MikeJ March 2005 +-- Latest version from www.fpgaarcade.com (original www.opencores.org) +-- +-- **** +-- +-- 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; -- cgit v1.2.3