Professional Documents
Culture Documents
----------------------------------------------------------------------------
-- The Free IP Project
-- VHDL 6502 Core
-- (c) 1999, The Free IP Project and David Kessner
--
--
-- FREE IP GENERAL PUBLIC LICENSE
-- TERMS AND CONDITIONS FOR USE, COPYING, DISTRIBUTION, AND MODIFICATION
--
-- 1. You may copy and distribute verbatim copies of this core, as long
-- as this file, and the other associated files, remain intact and
-- unmodified. Modifications are outlined below. Also, see the
-- import/export warning above for further restrictions on
-- distribution.
-- 2. You may use this core in any way, be it academic, commercial, or
-- military. Modified or not.
-- 3. Distribution of this core must be free of charge. Charging is
-- allowed only for value added services. Value added services
-- would include copying fees, modifications, customizations, and
-- inclusion in other products.
-- 4. If a modified source code is distributed, the original unmodified
-- source code must also be included (or a link to the Free IP web
-- site). In the modified source code there must be clear
-- identification of the modified version.
-- 5. Visit the Free IP web site for additional information.
-- http://www.free-ip.com
--
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
package free_6502 is
component core_6502
port (clk :in std_logic;
reset :in std_logic;
irq_in :in std_logic;
nmi_in :in std_logic;
addr_pin :out std_logic_vector (15 downto 0);
din :in std_logic_vector (7 downto 0);
dout :out std_logic_vector (7 downto 0);
dout_oe :out std_logic;
we_pin :out std_logic;
rd_pin :out std_logic;
sync :out std_logic
);
end component;
component core_6502_debug
port (clk :in std_logic;
reset :in std_logic;
irq_in :in std_logic;
nmi_in :in std_logic;
addr_pin :out std_logic_vector (15 downto 0);
din :in std_logic_vector (7 downto 0);
dout :out std_logic_vector (7 downto 0);
dout_oe :out std_logic;
we_pin :out std_logic;
rd_pin :out std_logic;
sync :out std_logic;
stack_page :in std_logic_vector (7 downto 0);
reg_a_out :out std_logic_vector (7 downto 0);
reg_x_out :out std_logic_vector (7 downto 0);
reg_y_out :out std_logic_vector (7 downto 0);
reg_sr_out :out std_logic_vector (7 downto 0);
reg_sp_out :out std_logic_vector (7 downto 0);
reg_pc_out :out std_logic_vector (15 downto 0)
);
end component;
end free_6502;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.microcode.all;
use work.free_6502.all;
entity core_6502_debug is
port (clk :in std_logic;
reset :in std_logic;
irq_in :in std_logic;
nmi_in :in std_logic;
addr_pin :out std_logic_vector (15 downto 0);
din :in std_logic_vector (7 downto 0);
dout :out std_logic_vector (7 downto 0);
dout_oe :out std_logic;
we_pin :out std_logic;
rd_pin :out std_logic;
sync :out std_logic;
stack_page :in std_logic_vector (7 downto 0);
reg_a_out :out std_logic_vector (7 downto 0);
reg_x_out :out std_logic_vector (7 downto 0);
reg_y_out :out std_logic_vector (7 downto 0);
reg_sr_out :out std_logic_vector (7 downto 0);
reg_sp_out :out std_logic_vector (7 downto 0);
reg_pc_out :out std_logic_vector (15 downto 0)
);
end core_6502_debug;
-- registered inputs
signal nmi_reg1 :std_logic;
signal nmi_reg2 :std_logic;
signal irq_reg :std_logic;
signal data_in :std_logic_vector (7 downto 0);
-- Internal registers
signal a_reg :std_logic_vector (7 downto 0);
signal x_reg :std_logic_vector (7 downto 0);
signal y_reg :std_logic_vector (7 downto 0);
signal dint1 :std_logic_vector (7 downto 0);
signal dint2 :std_logic_vector (7 downto 0);
signal dint3 :std_logic_vector (7 downto 0);
signal opcode_reg :std_logic_vector (7 downto 0);
signal sp :std_logic_vector (7 downto 0);
signal pc :std_logic_vector (15 downto 0);
signal n_flag :std_logic;
signal v_flag :std_logic;
signal b_flag :std_logic;
signal d_flag :std_logic;
signal i_flag :std_logic;
signal z_flag :std_logic;
signal c_flag :std_logic;
-- Combinotorial signals
signal opcode :std_logic_vector (7 downto 0);
signal alu_in1 :std_logic_vector (8 downto 0);
signal alu_in2 :std_logic_vector (8 downto 0);
signal alu_out :std_logic_vector (8 downto 0);
-- Misc signals
signal first_run :std_logic;
signal fetch_d :std_logic;
signal data_out :std_logic_vector (7 downto 0);
signal data_oe :std_logic;
signal addr_out :std_logic_vector (15 downto 0);
signal we_out :std_logic;
signal nmi_event :std_logic;
begin
-- Debug outputs
reg_a_out <= a_reg;
reg_x_out <= x_reg;
reg_y_out <= y_reg;
reg_sr_out <= n_flag & v_flag & '1' & b_flag & d_flag
& i_flag & z_flag & c_flag;
reg_sp_out <= sp;
reg_pc_out <= pc;
-----------------------------------------------------------------------------
-- Revised address output block
-------------------------------
-- These revisons to the address output block are intended to improve
-- synthesis results for both area and speed. They intended to
-- accomplish the following:
-- - Make the use of a single adder very clear to the synthesis tool.
-- - Move all decoding and muxing in front of the adder. This allows
-- the synthesis more flexibility in optimizing an balancing propagation
-- paths.
-- Ed Beers (sreeb@beers.nu) 9/14/99
-----------------------------------------------------------------------------
if done=MC_DONE then
--addr_out <= pc;
addr_add_1 := pc;
elsif state=FETCH then
--addr_out <= pc + 1;
addr_add_1 := pc;
addr_add_cin := '1';
else
case addr_op is
when MC_NOP =>
--addr_out <= pc;
addr_add_1 := pc;
when MC_PC_P =>
--addr_out <= pc + 1;
addr_add_1 := pc;
addr_add_cin := '1';
when MC_SPLIT =>
--addr_out <= data_in & dint1;
addr_add_1 := data_in & dint1;
when MC_SPLIT_P =>
--addr_out <= (data_in & dint1) + 1;
addr_add_1 := data_in & dint1;
addr_add_cin := '1';
when MC_SPLIT_X =>
--addr_out <= (data_in & dint1) + x_reg;
addr_add_1 := data_in & dint1;
addr_add_2 := x_reg;
when MC_SPLIT_Y =>
--addr_out <= (data_in & dint1) + y_reg;
addr_add_1 := data_in & dint1;
addr_add_2 := y_reg;
when MC_DIN_Z =>
--addr_out <= ("00000000" & data_in);
addr_add_1 := "00000000" & data_in;
when MC_DIN_ZP =>
--addr_out <= ("00000000" & data_in) + 1;
addr_add_1 := "00000000" & data_in;
addr_add_cin := '1';
when MC_DIN_ZX =>
--addr_out <= ("00000000" & data_in) + x_reg;
addr_add_1 := "00000000" & data_in;
addr_add_2 := x_reg;
eight_bit_flag := '1';
when MC_DIN_ZXP =>
--addr_out <= ("00000000" & data_in) + x_reg + 1;
addr_add_1 := "00000000" & data_in;
addr_add_2 := x_reg;
addr_add_cin := '1';
eight_bit_flag := '1';
when MC_DIN_ZY =>
--addr_out <= ("00000000" & data_in) + y_reg;
addr_add_1 := "00000000" & data_in;
addr_add_2 := y_reg;
eight_bit_flag := '1';
when MC_DINT16 =>
--addr_out <= dint2 & dint1;
addr_add_1 := dint2 & dint1;
when MC_DINT16_X =>
--addr_out <= dint2 & dint1 + x_reg;
addr_add_1 := dint2 & dint1;
addr_add_2 := x_reg;
when MC_DINT1_Z =>
--addr_out_d <= ("00000000" & dint1);
addr_add_1 := ("00000000" & dint1);
when MC_DINT1_ZX =>
--addr_out <= ("00000000" & dint1) + x_reg;
addr_add_1 := "00000000" & dint1;
addr_add_2 := x_reg;
when MC_SP =>
--addr_out <= stack_page & sp;
addr_add_1 := stack_page & sp;
when MC_V_NMI1 =>
--addr_out <= vect_nmi1;
addr_add_1 := vect_nmi1;
when MC_V_NMI2 =>
--addr_out <= vect_nmi2;
addr_add_1 := vect_nmi2;
when MC_V_RESET1 =>
--addr_out <= vect_reset1;
addr_add_1 := vect_reset1;
when MC_V_RESET2 =>
--addr_out <= vect_reset2;
addr_add_1 := vect_reset2;
when MC_V_IRQ1 =>
--addr_out <= vect_irq1;
addr_add_1 := vect_irq1;
when MC_V_IRQ2 =>
--addr_out <= vect_irq2;
addr_add_1 := vect_irq2;
when others =>
--addr_out <= pc;
addr_add_1 := pc;
end case;
end if;
end if;
end process;
-- The registers
process (clk, reset)
begin
if reset='1' then
a_reg <= "00000000";
elsif clk'event and clk='1' then
if a_le=MC_LE then
a_reg <= alu_out (7 downto 0);
end if;
end if;
end process;
case alu_op is
when MC_PASS1 => alu_out <= alu_in1;
when MC_PASS2 => alu_out <= alu_in2;
when MC_ADD =>
--alu_out <= alu_in1 + alu_in2;
alu_add_in2 <= alu_in2;
alu_add_cin <= '0';
alu_out <= alu_add;
when MC_ADDC =>
--alu_out <= alu_in1 + alu_in2 + ("00000000" & c_flag);
alu_add_in2 <= alu_in2;
alu_add_cin <= c_flag;
alu_out <= alu_add;
when MC_SUB =>
--alu_out <= alu_in1 - alu_in2;
alu_add_in2 <= not alu_in2;
alu_add_cin <= '1';
alu_out <= (not alu_add(8)) & alu_add(7 downto 0);
when MC_SUBB =>
--alu_out <= alu_in1 - alu_in2 - ("00000000" & c_flag);
alu_add_in2 <= not alu_in2;
alu_add_cin <= c_flag;
alu_out <= (not alu_add(8)) & alu_add(7 downto 0);
when MC_BIT_AND => alu_out <= alu_in1 and alu_in2;
when MC_BIT_OR => alu_out <= alu_in1 or alu_in2;
when MC_BIT_XOR => alu_out <= alu_in1 xor alu_in2;
when MC_BIT_ASL => alu_out <= alu_in1(7 downto 0) & "0";
when MC_BIT_LSR => alu_out <= alu_in1(0) & "0" & alu_in1(7 downto 1);
when MC_BIT_ROL => alu_out <= alu_in1(7 downto 0) & c_flag;
when MC_BIT_ROR => alu_out <= alu_in1(0) & c_flag & alu_in1(7 downto
1);
when others => alu_out <= alu_in1;
end case;
end process;
end core_6502_arch_debug;
----------------------------------------------------------------------------
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
use work.microcode.all;
use work.free_6502.all;
entity core_6502 is
port (clk :in std_logic;
reset :in std_logic;
irq_in :in std_logic;
nmi_in :in std_logic;
addr_pin :out std_logic_vector (15 downto 0);
din :in std_logic_vector (7 downto 0);
dout :out std_logic_vector (7 downto 0);
dout_oe :out std_logic;
we_pin :out std_logic;
rd_pin :out std_logic;
sync :out std_logic
);
end core_6502;
end arch_core_6502;
----------------------------------------------------------------------------
----------------------------------------------------------------------------