mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 15:44:40 +00:00
C16: replace the 1541 CPU (again)
- Use the CPU from 1541UltimateII project - Remove unnecessary hacks for the VIA chip from c1541_logic
This commit is contained in:
137
cores/c16/1541ultimate2cpu/alu.vhd
Normal file
137
cores/c16/1541ultimate2cpu/alu.vhd
Normal file
@@ -0,0 +1,137 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity alu is
|
||||
generic (
|
||||
support_bcd : boolean := true );
|
||||
port (
|
||||
operation : in std_logic_vector(2 downto 0);
|
||||
enable : in std_logic;
|
||||
|
||||
n_in : in std_logic;
|
||||
v_in : in std_logic;
|
||||
z_in : in std_logic;
|
||||
c_in : in std_logic;
|
||||
d_in : in std_logic;
|
||||
|
||||
data_a : in std_logic_vector(7 downto 0);
|
||||
data_b : in std_logic_vector(7 downto 0);
|
||||
|
||||
n_out : out std_logic;
|
||||
v_out : out std_logic;
|
||||
z_out : out std_logic;
|
||||
c_out : out std_logic;
|
||||
|
||||
data_out : out std_logic_vector(7 downto 0));
|
||||
|
||||
end alu;
|
||||
|
||||
architecture gideon of alu is
|
||||
signal data_out_i : std_logic_vector(7 downto 0) := X"FF";
|
||||
signal zero : std_logic;
|
||||
signal sum_c : std_logic;
|
||||
signal sum_n : std_logic;
|
||||
signal sum_z : std_logic;
|
||||
signal sum_v : std_logic;
|
||||
signal sum_result : std_logic_vector(7 downto 0) := X"FF";
|
||||
signal oper4 : std_logic_vector(3 downto 0);
|
||||
begin
|
||||
|
||||
-- ORA $nn AND $nn EOR $nn ADC $nn STA $nn LDA $nn CMP $nn SBC $nn
|
||||
|
||||
with oper4 select data_out_i <=
|
||||
data_a or data_b when "1000",
|
||||
data_a and data_b when "1001",
|
||||
data_a xor data_b when "1010",
|
||||
sum_result when "1011" | "1110" | "1111",
|
||||
data_b when others;
|
||||
|
||||
zero <= '1' when data_out_i = X"00" else '0';
|
||||
|
||||
sum: process(data_a, data_b, c_in, operation, d_in)
|
||||
variable b : std_logic_vector(7 downto 0);
|
||||
variable sum_l : std_logic_vector(4 downto 0);
|
||||
variable sum_h : std_logic_vector(4 downto 0);
|
||||
begin
|
||||
-- for subtraction invert second operand
|
||||
if operation(2)='1' then -- invert b
|
||||
b := not data_b;
|
||||
else
|
||||
b := data_b;
|
||||
end if;
|
||||
|
||||
-- sum_l(4) = carry of lower end, carry in is masked to '1' for CMP
|
||||
sum_l := ('0' & data_a(3 downto 0)) + ('0' & b(3 downto 0)) + (c_in or not operation(0));
|
||||
sum_h := ('0' & data_a(7 downto 4)) + ('0' & b(7 downto 4)) + sum_l(4);
|
||||
|
||||
if sum_l(3 downto 0)="0000" and sum_h(3 downto 0)="0000" then
|
||||
sum_z <= '1';
|
||||
else
|
||||
sum_z <= '0';
|
||||
end if;
|
||||
|
||||
sum_n <= sum_h(3);
|
||||
sum_c <= sum_h(4);
|
||||
sum_v <= (sum_h(3) xor data_a(7)) and (sum_h(3) xor data_b(7) xor operation(2));
|
||||
|
||||
-- fix up in decimal mode (not for CMP!)
|
||||
if d_in='1' and support_bcd then
|
||||
if operation(2)='0' then -- ADC
|
||||
sum_h := ('0' & data_a(7 downto 4)) + ('0' & b(7 downto 4));
|
||||
|
||||
if sum_l(4) = '1' or sum_l(3 downto 2)="11" or sum_l(3 downto 1)="101" then -- >9 (10-11, 12-15)
|
||||
sum_l := sum_l + ('0' & X"6");
|
||||
sum_l(4) := '1';
|
||||
end if;
|
||||
|
||||
-- negative when sum_h + sum_l(4) = 8
|
||||
sum_h := sum_h + sum_l(4);
|
||||
sum_n <= sum_h(3);
|
||||
|
||||
if sum_h(4) = '1' or sum_h(3 downto 2)="11" or sum_h(3 downto 1)="101" then --
|
||||
sum_h := sum_h + 6;
|
||||
sum_c <= '1';
|
||||
end if;
|
||||
|
||||
-- carry and overflow are output after fix
|
||||
-- sum_c <= sum_h(4);
|
||||
-- sum_v <= (sum_h(3) xor data_a(7)) and (sum_h(3) xor data_b(7) xor operation(2));
|
||||
|
||||
elsif operation(0)='1' then -- SBC
|
||||
-- flags are not adjusted in subtract mode
|
||||
if sum_l(4) = '0' then
|
||||
sum_l := sum_l - 6;
|
||||
end if;
|
||||
if sum_h(4) = '0' then
|
||||
sum_h := sum_h - 6;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
sum_result <= sum_h(3 downto 0) & sum_l(3 downto 0);
|
||||
end process;
|
||||
|
||||
oper4 <= enable & operation;
|
||||
|
||||
with oper4 select c_out <=
|
||||
sum_c when "1011" | "1111" | "1110",
|
||||
c_in when others;
|
||||
|
||||
with oper4 select z_out <=
|
||||
sum_z when "1011" | "1111" | "1110",
|
||||
zero when "1000" | "1001" | "1010" | "1101",
|
||||
z_in when others;
|
||||
|
||||
with oper4 select n_out <=
|
||||
sum_n when "1011" | "1111",
|
||||
data_out_i(7) when "1000" | "1001" | "1010" | "1101" | "1110",
|
||||
n_in when others;
|
||||
|
||||
with oper4 select v_out <=
|
||||
sum_v when "1011" | "1111",
|
||||
v_in when others;
|
||||
|
||||
data_out <= data_out_i;
|
||||
end gideon;
|
||||
66
cores/c16/1541ultimate2cpu/bit_cpx_cpy.vhd
Normal file
66
cores/c16/1541ultimate2cpu/bit_cpx_cpy.vhd
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity bit_cpx_cpy is
|
||||
port (
|
||||
operation : in std_logic_vector(2 downto 0);
|
||||
enable : in std_logic := '1'; -- instruction(1 downto 0)="00"
|
||||
|
||||
n_in : in std_logic;
|
||||
v_in : in std_logic;
|
||||
z_in : in std_logic;
|
||||
c_in : in std_logic;
|
||||
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
a_reg : in std_logic_vector(7 downto 0);
|
||||
x_reg : in std_logic_vector(7 downto 0);
|
||||
y_reg : in std_logic_vector(7 downto 0);
|
||||
|
||||
n_out : out std_logic;
|
||||
v_out : out std_logic;
|
||||
z_out : out std_logic;
|
||||
c_out : out std_logic );
|
||||
|
||||
end bit_cpx_cpy;
|
||||
|
||||
architecture gideon of bit_cpx_cpy is
|
||||
signal reg : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal diff : std_logic_vector(8 downto 0) := (others => '0');
|
||||
signal zero_cmp : std_logic;
|
||||
signal zero_ld : std_logic;
|
||||
signal zero_bit : std_logic;
|
||||
|
||||
signal oper4 : std_logic_vector(3 downto 0);
|
||||
begin
|
||||
-- *** BIT *** *** STY LDY CPY CPX
|
||||
reg <= x_reg when operation(0)='1' else y_reg;
|
||||
|
||||
diff <= ('1' & reg) - ('0' & data_in);
|
||||
zero_cmp <= '1' when diff(7 downto 0)=X"00" else '0';
|
||||
zero_ld <= '1' when data_in=X"00" else '0';
|
||||
zero_bit <= '1' when (data_in and a_reg)=X"00" else '0';
|
||||
|
||||
oper4 <= enable & operation;
|
||||
|
||||
with oper4 select c_out <=
|
||||
diff(8) when "1110" | "1111", -- CPX / CPY
|
||||
c_in when others;
|
||||
|
||||
with oper4 select z_out <=
|
||||
zero_cmp when "1110" | "1111", -- CPX / CPY
|
||||
zero_ld when "1101",
|
||||
zero_bit when "1001",
|
||||
z_in when others;
|
||||
|
||||
with oper4 select n_out <=
|
||||
diff(7) when "1110" | "1111", -- CPX / CPY
|
||||
data_in(7) when "1101" | "1001", -- LDY / BIT
|
||||
n_in when others;
|
||||
|
||||
with oper4 select v_out <=
|
||||
data_in(6) when "1001", -- BIT
|
||||
v_in when others;
|
||||
|
||||
end gideon;
|
||||
55
cores/c16/1541ultimate2cpu/cpu6502.vhd
Normal file
55
cores/c16/1541ultimate2cpu/cpu6502.vhd
Normal file
@@ -0,0 +1,55 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity cpu6502 is
|
||||
port (
|
||||
cpu_clk : in std_logic;
|
||||
cpu_reset : in std_logic;
|
||||
|
||||
cpu_ready : in std_logic;
|
||||
cpu_write : out std_logic;
|
||||
|
||||
cpu_wdata : out std_logic_vector(7 downto 0);
|
||||
cpu_rdata : in std_logic_vector(7 downto 0);
|
||||
cpu_addr : out std_logic_vector(16 downto 0);
|
||||
cpu_pc : out std_logic_vector(15 downto 0);
|
||||
|
||||
IRQn : in std_logic; -- IRQ interrupt (level sensitive)
|
||||
NMIn : in std_logic; -- NMI interrupt (edge sensitive)
|
||||
|
||||
SOn : in std_logic -- set Overflow flag
|
||||
);
|
||||
attribute optimize : string;
|
||||
attribute optimize of cpu6502 : entity is "SPEED";
|
||||
end cpu6502;
|
||||
|
||||
|
||||
|
||||
architecture cycle_exact of cpu6502 is
|
||||
|
||||
signal read_write_n : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
core: entity work.proc_core
|
||||
generic map (
|
||||
support_bcd => true )
|
||||
port map(
|
||||
clock => cpu_clk,
|
||||
clock_en => cpu_ready,
|
||||
reset => cpu_reset,
|
||||
|
||||
irq_n => IRQn,
|
||||
nmi_n => NMIn,
|
||||
so_n => SOn,
|
||||
|
||||
pc_out => cpu_pc,
|
||||
addr_out => cpu_addr,
|
||||
data_in => cpu_rdata,
|
||||
data_out => cpu_wdata,
|
||||
read_write_n => read_write_n );
|
||||
|
||||
cpu_write <= not read_write_n;
|
||||
|
||||
end cycle_exact;
|
||||
193
cores/c16/1541ultimate2cpu/data_oper.vhd
Normal file
193
cores/c16/1541ultimate2cpu/data_oper.vhd
Normal file
@@ -0,0 +1,193 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
library work;
|
||||
use work.pkg_6502_decode.all;
|
||||
|
||||
-- this module puts the alu, shifter and bit/compare unit together
|
||||
|
||||
entity data_oper is
|
||||
generic (
|
||||
support_bcd : boolean := true );
|
||||
port (
|
||||
inst : in std_logic_vector(7 downto 0);
|
||||
|
||||
n_in : in std_logic;
|
||||
v_in : in std_logic;
|
||||
z_in : in std_logic;
|
||||
c_in : in std_logic;
|
||||
d_in : in std_logic;
|
||||
i_in : in std_logic;
|
||||
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
a_reg : in std_logic_vector(7 downto 0);
|
||||
x_reg : in std_logic_vector(7 downto 0);
|
||||
y_reg : in std_logic_vector(7 downto 0);
|
||||
s_reg : in std_logic_vector(7 downto 0);
|
||||
|
||||
alu_out : out std_logic_vector(7 downto 0);
|
||||
mem_out : out std_logic_vector(7 downto 0);
|
||||
impl_out : out std_logic_vector(7 downto 0);
|
||||
|
||||
set_a : out std_logic;
|
||||
set_x : out std_logic;
|
||||
set_y : out std_logic;
|
||||
set_s : out std_logic;
|
||||
|
||||
n_out : out std_logic;
|
||||
v_out : out std_logic;
|
||||
z_out : out std_logic;
|
||||
c_out : out std_logic;
|
||||
d_out : out std_logic;
|
||||
i_out : out std_logic );
|
||||
end data_oper;
|
||||
|
||||
architecture gideon of data_oper is
|
||||
signal shift_sel : std_logic_vector(1 downto 0) := "00";
|
||||
signal shift_din : std_logic_vector(7 downto 0) := X"00";
|
||||
signal shift_dout: std_logic_vector(7 downto 0) := X"00";
|
||||
signal alu_data_a: std_logic_vector(7 downto 0) := X"00";
|
||||
signal row0_n : std_logic;
|
||||
signal row0_v : std_logic;
|
||||
signal row0_z : std_logic;
|
||||
signal row0_c : std_logic;
|
||||
|
||||
signal shft_n : std_logic;
|
||||
signal shft_z : std_logic;
|
||||
signal shft_c : std_logic;
|
||||
|
||||
signal alu_n : std_logic;
|
||||
signal alu_v : std_logic;
|
||||
signal alu_z : std_logic;
|
||||
signal alu_c : std_logic;
|
||||
|
||||
signal impl_n : std_logic;
|
||||
signal impl_z : std_logic;
|
||||
signal impl_c : std_logic;
|
||||
signal impl_v : std_logic;
|
||||
signal impl_i : std_logic;
|
||||
signal impl_d : std_logic;
|
||||
|
||||
signal shift_en : std_logic;
|
||||
signal alu_en : std_logic;
|
||||
signal impl_en : std_logic;
|
||||
signal impl_flags: boolean;
|
||||
begin
|
||||
shift_sel <= shifter_in_select(inst);
|
||||
with shift_sel select shift_din <=
|
||||
data_in when "01",
|
||||
a_reg when "10",
|
||||
data_in and a_reg when "11",
|
||||
X"FF" when others;
|
||||
|
||||
shift_en <= '1' when is_shift(inst) else '0';
|
||||
alu_en <= '1' when is_alu(inst) else '0';
|
||||
|
||||
row0: entity work.bit_cpx_cpy
|
||||
port map (
|
||||
operation => inst(7 downto 5),
|
||||
enable => '1',
|
||||
|
||||
n_in => n_in,
|
||||
v_in => v_in,
|
||||
z_in => z_in,
|
||||
c_in => c_in,
|
||||
|
||||
data_in => data_in,
|
||||
a_reg => a_reg,
|
||||
x_reg => x_reg,
|
||||
y_reg => y_reg,
|
||||
|
||||
n_out => row0_n,
|
||||
v_out => row0_v,
|
||||
z_out => row0_z,
|
||||
c_out => row0_c );
|
||||
|
||||
shft: entity work.shifter
|
||||
port map (
|
||||
operation => inst(7 downto 5),
|
||||
enable => shift_en,
|
||||
|
||||
c_in => c_in,
|
||||
n_in => n_in,
|
||||
z_in => z_in,
|
||||
|
||||
data_in => shift_din,
|
||||
|
||||
c_out => shft_c,
|
||||
n_out => shft_n,
|
||||
z_out => shft_z,
|
||||
|
||||
data_out => shift_dout );
|
||||
|
||||
alu_data_a <= a_reg and x_reg when x_to_alu(inst) else a_reg;
|
||||
|
||||
alu1: entity work.alu
|
||||
generic map (
|
||||
support_bcd => support_bcd )
|
||||
port map (
|
||||
operation => inst(7 downto 5),
|
||||
enable => alu_en,
|
||||
|
||||
n_in => shft_n,
|
||||
v_in => v_in,
|
||||
z_in => shft_z,
|
||||
c_in => shft_c,
|
||||
d_in => d_in,
|
||||
|
||||
data_a => alu_data_a,
|
||||
data_b => shift_dout,
|
||||
|
||||
n_out => alu_n,
|
||||
v_out => alu_v,
|
||||
z_out => alu_z,
|
||||
c_out => alu_c,
|
||||
|
||||
data_out => alu_out );
|
||||
|
||||
mem_out <= shift_dout;
|
||||
|
||||
impl_en <= '1' when is_implied(inst) else '0';
|
||||
impl_flags <= is_implied(inst) and (inst(4)='1' or inst(7)='1');
|
||||
|
||||
impl: entity work.implied
|
||||
port map (
|
||||
inst => inst,
|
||||
enable => impl_en,
|
||||
|
||||
c_in => c_in,
|
||||
i_in => i_in,
|
||||
n_in => n_in,
|
||||
z_in => z_in,
|
||||
d_in => d_in,
|
||||
v_in => v_in,
|
||||
|
||||
reg_a => a_reg,
|
||||
reg_x => x_reg,
|
||||
reg_y => y_reg,
|
||||
reg_s => s_reg,
|
||||
|
||||
i_out => impl_i,
|
||||
d_out => impl_d,
|
||||
c_out => impl_c,
|
||||
n_out => impl_n,
|
||||
z_out => impl_z,
|
||||
v_out => impl_v,
|
||||
|
||||
set_a => set_a,
|
||||
set_x => set_x,
|
||||
set_y => set_y,
|
||||
set_s => set_s,
|
||||
|
||||
data_out => impl_out );
|
||||
|
||||
n_out <= impl_n when impl_flags else row0_n when inst(1 downto 0)="00" else alu_n;
|
||||
v_out <= impl_v when impl_flags else row0_v when inst(1 downto 0)="00" else alu_v;
|
||||
z_out <= impl_z when impl_flags else row0_z when inst(1 downto 0)="00" else alu_z;
|
||||
c_out <= impl_c when impl_flags else row0_c when inst(1 downto 0)="00" else alu_c;
|
||||
i_out <= impl_i when impl_flags else i_in;
|
||||
d_out <= impl_d when impl_flags else d_in;
|
||||
|
||||
end gideon;
|
||||
114
cores/c16/1541ultimate2cpu/implied.vhd
Normal file
114
cores/c16/1541ultimate2cpu/implied.vhd
Normal file
@@ -0,0 +1,114 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity implied is
|
||||
port (
|
||||
inst : in std_logic_vector(7 downto 0);
|
||||
enable : in std_logic;
|
||||
|
||||
c_in : in std_logic;
|
||||
i_in : in std_logic;
|
||||
n_in : in std_logic;
|
||||
z_in : in std_logic;
|
||||
d_in : in std_logic;
|
||||
v_in : in std_logic;
|
||||
|
||||
reg_a : in std_logic_vector(7 downto 0);
|
||||
reg_x : in std_logic_vector(7 downto 0);
|
||||
reg_y : in std_logic_vector(7 downto 0);
|
||||
reg_s : in std_logic_vector(7 downto 0);
|
||||
|
||||
c_out : out std_logic;
|
||||
i_out : out std_logic;
|
||||
n_out : out std_logic;
|
||||
z_out : out std_logic;
|
||||
d_out : out std_logic;
|
||||
v_out : out std_logic;
|
||||
|
||||
set_a : out std_logic;
|
||||
set_x : out std_logic;
|
||||
set_y : out std_logic;
|
||||
set_s : out std_logic;
|
||||
|
||||
data_out : out std_logic_vector(7 downto 0));
|
||||
|
||||
end implied;
|
||||
|
||||
architecture gideon of implied is
|
||||
type t_int4_array is array(natural range <>) of integer range 0 to 3;
|
||||
-- ROMS for the upper (negative) implied instructions
|
||||
constant reg_sel_rom : t_int4_array(0 to 15) := ( 2,0,2,1,1,0,1,1,2,0,2,1,1,3,1,1 ); -- 0=A, 1=X, 2=Y, 3=S
|
||||
constant decr_rom : std_logic_vector(0 to 15) := "1000001000000000";
|
||||
constant incr_rom : std_logic_vector(0 to 15) := "0011000000000000";
|
||||
constant nz_flags : std_logic_vector(0 to 15) := "1111111010000100";
|
||||
constant v_flag : std_logic_vector(0 to 15) := "0000000001000000";
|
||||
constant d_flag : std_logic_vector(0 to 15) := "0000000000110000";
|
||||
constant set_a_rom : std_logic_vector(0 to 15) := "0000100010000000";
|
||||
constant set_x_rom : std_logic_vector(0 to 15) := "0001011000000100";
|
||||
constant set_y_rom : std_logic_vector(0 to 15) := "1110000000000000";
|
||||
constant set_s_rom : std_logic_vector(0 to 15) := "0000000000001000";
|
||||
|
||||
-- ROMS for the lower (positive) implied instructions
|
||||
constant shft_rom : std_logic_vector(0 to 15) := "0000111100000000";
|
||||
constant c_flag : std_logic_vector(0 to 15) := "0000000011000000";
|
||||
constant i_flag : std_logic_vector(0 to 15) := "0000000000110000";
|
||||
|
||||
signal selected_reg : std_logic_vector(7 downto 0) := X"00";
|
||||
signal operation : integer range 0 to 15;
|
||||
signal reg_sel : integer range 0 to 3;
|
||||
signal result : std_logic_vector(7 downto 0) := X"00";
|
||||
signal add : std_logic_vector(7 downto 0) := X"00";
|
||||
signal carry : std_logic := '0';
|
||||
signal zero : std_logic := '0';
|
||||
|
||||
signal n_hi : std_logic;
|
||||
signal z_hi : std_logic;
|
||||
signal v_hi : std_logic;
|
||||
signal d_hi : std_logic;
|
||||
|
||||
signal n_lo : std_logic;
|
||||
signal z_lo : std_logic;
|
||||
signal c_lo : std_logic;
|
||||
signal i_lo : std_logic;
|
||||
begin
|
||||
operation <= conv_integer(inst(4) & inst(1) & inst(6 downto 5));
|
||||
reg_sel <= reg_sel_rom(operation);
|
||||
with reg_sel select selected_reg <=
|
||||
reg_a when 0,
|
||||
reg_x when 1,
|
||||
reg_y when 2,
|
||||
reg_s when others;
|
||||
|
||||
add <= (others => decr_rom(operation));
|
||||
carry <= incr_rom(operation);
|
||||
|
||||
result <= selected_reg + add + carry;
|
||||
|
||||
zero <= '1' when result = X"00" else '0';
|
||||
|
||||
data_out <= result;
|
||||
|
||||
n_hi <= result(7) when nz_flags(operation)='1' else n_in;
|
||||
z_hi <= zero when nz_flags(operation)='1' else z_in;
|
||||
v_hi <= '0' when v_flag(operation)='1' else v_in;
|
||||
d_hi <= inst(5) when d_flag(operation)='1' else d_in;
|
||||
-- in high, C and I are never set
|
||||
|
||||
c_lo <= inst(5) when c_flag(operation)='1' else c_in;
|
||||
i_lo <= inst(5) when i_flag(operation)='1' else i_in;
|
||||
-- in low, V, N, Z and D are never set
|
||||
|
||||
set_a <= set_a_rom(operation) and inst(7) and enable;
|
||||
set_x <= set_x_rom(operation) and inst(7) and enable;
|
||||
set_y <= set_y_rom(operation) and inst(7) and enable;
|
||||
set_s <= set_s_rom(operation) and inst(7) and enable;
|
||||
|
||||
c_out <= c_in when inst(7)='1' else c_lo; -- C can only be set in lo
|
||||
i_out <= i_in when inst(7)='1' else i_lo; -- I can only be set in lo
|
||||
v_out <= v_hi when inst(7)='1' else v_in; -- V can only be set in hi
|
||||
d_out <= d_hi when inst(7)='1' else d_in; -- D can only be set in hi
|
||||
n_out <= n_hi when inst(7)='1' else n_in; -- N can only be set in hi
|
||||
z_out <= z_hi when inst(7)='1' else z_in; -- Z can only be set in hi
|
||||
|
||||
end gideon;
|
||||
248
cores/c16/1541ultimate2cpu/pkg_6502_decode.vhd
Normal file
248
cores/c16/1541ultimate2cpu/pkg_6502_decode.vhd
Normal file
@@ -0,0 +1,248 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
package pkg_6502_decode is
|
||||
|
||||
function is_absolute(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_abs_jump(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_immediate(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_implied(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_stack(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_push(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_zeropage(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_indirect(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_relative(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_load(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_store(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_shift(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_alu(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_rmw(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_jump(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_postindexed(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function is_illegal(inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
|
||||
function stack_idx(inst: std_logic_vector(7 downto 0)) return std_logic_vector;
|
||||
|
||||
constant c_stack_idx_brk : std_logic_vector(1 downto 0) := "00";
|
||||
constant c_stack_idx_jsr : std_logic_vector(1 downto 0) := "01";
|
||||
constant c_stack_idx_rti : std_logic_vector(1 downto 0) := "10";
|
||||
constant c_stack_idx_rts : std_logic_vector(1 downto 0) := "11";
|
||||
|
||||
function select_index_y (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function store_a_from_alu (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function load_a (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function load_x (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function load_y (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector;
|
||||
function x_to_alu (inst: std_logic_vector(7 downto 0)) return boolean;
|
||||
end;
|
||||
|
||||
package body pkg_6502_decode is
|
||||
|
||||
function is_absolute(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 4320 = X11X | 1101
|
||||
if inst(3 downto 2)="11" then
|
||||
return true;
|
||||
elsif inst(4 downto 2)="110" and inst(0)='1' then
|
||||
return true;
|
||||
end if;
|
||||
return false;
|
||||
end function;
|
||||
|
||||
function is_jump(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return inst(7 downto 6)="01" and inst(3 downto 0)=X"C";
|
||||
end function;
|
||||
|
||||
function is_immediate(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 76543210 = 1XX000X0
|
||||
if inst(7)='1' and inst(4 downto 2)="000" and inst(0)='0' then
|
||||
return true;
|
||||
-- 76543210 = XXX010X1
|
||||
elsif inst(4 downto 2)="010" and inst(0)='1' then
|
||||
return true;
|
||||
end if;
|
||||
return false;
|
||||
end function;
|
||||
|
||||
function is_implied(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 4320 = X100
|
||||
return inst(3 downto 2)="10" and inst(0)='0';
|
||||
end function;
|
||||
|
||||
function is_stack(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 76543210
|
||||
-- 0xx0x000
|
||||
return inst(7)='0' and inst(4)='0' and inst(2 downto 0)="000";
|
||||
end function;
|
||||
|
||||
function is_push(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- we already know it's a stack operation, so only the direction is important
|
||||
return inst(5)='0';
|
||||
end function;
|
||||
|
||||
function is_zeropage(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
if inst(3 downto 2)="01" then
|
||||
return true;
|
||||
elsif inst(3 downto 2)="00" and inst(0)='1' then
|
||||
return true;
|
||||
end if;
|
||||
return false;
|
||||
end function;
|
||||
|
||||
function is_indirect(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return (inst(3 downto 2)="00" and inst(0)='1');
|
||||
end function;
|
||||
|
||||
function is_relative(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return (inst(4 downto 0)="10000");
|
||||
end function;
|
||||
|
||||
function is_store(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return (inst(7 downto 5)="100");
|
||||
end function;
|
||||
|
||||
function is_shift(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
if inst(7)='1' and inst(4 downto 2)="010" then
|
||||
return false;
|
||||
end if;
|
||||
return (inst(1)='1');
|
||||
end function;
|
||||
|
||||
function is_alu(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
if inst(7)='0' and inst(4 downto 1)="0101" then
|
||||
return false;
|
||||
end if;
|
||||
return (inst(0)='1');
|
||||
end function;
|
||||
|
||||
function is_load(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return not is_store(inst) and not is_rmw(inst);
|
||||
end function;
|
||||
|
||||
function is_rmw(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return inst(1)='1' and inst(7 downto 6)/="10";
|
||||
end function;
|
||||
|
||||
function is_abs_jump(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return is_jump(inst) and inst(5)='0';
|
||||
end function;
|
||||
|
||||
function is_postindexed(inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return inst(4)='1';
|
||||
end function;
|
||||
|
||||
function stack_idx(inst: std_logic_vector(7 downto 0)) return std_logic_vector is
|
||||
begin
|
||||
return inst(6 downto 5);
|
||||
end function;
|
||||
|
||||
function select_index_y (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
if inst(4)='1' and inst(2)='0' and inst(0)='1' then -- XXX1X0X1
|
||||
return true;
|
||||
elsif inst(7 downto 6)="10" and inst(2 downto 1)="11" then -- 10XXX11X
|
||||
return true;
|
||||
end if;
|
||||
return false;
|
||||
end function;
|
||||
|
||||
-- function flags_bit_group (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
-- begin
|
||||
-- return inst(2 downto 0)="100";
|
||||
-- end function;
|
||||
--
|
||||
-- function flags_alu_group (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
-- begin
|
||||
-- return inst(1 downto 0)="01"; -- could also choose not to look at bit 1 (overlap)
|
||||
-- end function;
|
||||
--
|
||||
-- function flags_shift_group (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
-- begin
|
||||
-- return inst(1 downto 0)="10"; -- could also choose not to look at bit 0 (overlap)
|
||||
-- end function;
|
||||
|
||||
function load_a (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
return (inst = X"68");
|
||||
end function;
|
||||
|
||||
function store_a_from_alu (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 0XXXXXX1 or alu operations "lo"
|
||||
-- 1X100001 or alu operations "hi" (except store and cmp)
|
||||
-- 0XX01010 (implied)
|
||||
return (inst(7)='0' and inst(4 downto 0)="01010") or
|
||||
(inst(7)='0' and inst(0)='1') or
|
||||
(inst(7)='1' and inst(0)='1' and inst(5)='1');
|
||||
end function;
|
||||
|
||||
function load_x (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 101XXX1X or 1100101- (for SAX #)
|
||||
if inst(7 downto 1)="1100101" then
|
||||
return true;
|
||||
end if;
|
||||
return inst(7 downto 5)="101" and inst(1)='1' and not is_implied(inst);
|
||||
end function;
|
||||
|
||||
function load_y (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 101XXX00
|
||||
return inst(7 downto 5)="101" and inst(1 downto 0)="00" and not is_implied(inst);
|
||||
end function;
|
||||
|
||||
function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector is
|
||||
begin
|
||||
-- 00 = none, 01 = memory, 10 = A, 11 = A & M
|
||||
if inst(4 downto 2)="010" and inst(7)='0' then
|
||||
return inst(1 downto 0);
|
||||
end if;
|
||||
return "01";
|
||||
end function;
|
||||
|
||||
-- function shifter_in_select (inst: std_logic_vector(7 downto 0)) return std_logic_vector is
|
||||
-- begin
|
||||
-- -- 0=memory, 1=A
|
||||
-- if inst(4 downto 1)="0101" and inst(7)='0' then
|
||||
-- return "01";
|
||||
-- end if;
|
||||
-- return "10";
|
||||
-- end function;
|
||||
|
||||
function is_illegal (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
type t_my16bit_array is array(natural range <>) of std_logic_vector(15 downto 0);
|
||||
constant c_illegal_map : t_my16bit_array(0 to 15) := (
|
||||
X"989C", X"9C9C", X"888C", X"9C9C", X"889C", X"9C9C", X"889C", X"9C9C",
|
||||
X"8A8D", X"D88C", X"8888", X"888C", X"888C", X"9C9C", X"888C", X"9C9C" );
|
||||
variable row : std_logic_vector(15 downto 0);
|
||||
begin
|
||||
row := c_illegal_map(conv_integer(inst(7 downto 4)));
|
||||
return (row(conv_integer(inst(3 downto 0))) = '1');
|
||||
end function;
|
||||
|
||||
function x_to_alu (inst: std_logic_vector(7 downto 0)) return boolean is
|
||||
begin
|
||||
-- 1-00101- 8A,8B,CA,CB
|
||||
return inst(5 downto 1)="00101" and inst(7)='1';
|
||||
end function;
|
||||
|
||||
end;
|
||||
18
cores/c16/1541ultimate2cpu/pkg_6502_defs.vhd
Normal file
18
cores/c16/1541ultimate2cpu/pkg_6502_defs.vhd
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
package pkg_6502_defs is
|
||||
|
||||
subtype t_amux is integer range 0 to 3;
|
||||
constant c_amux_vector : t_amux := 0;
|
||||
constant c_amux_addr : t_amux := 1;
|
||||
constant c_amux_stack : t_amux := 2;
|
||||
constant c_amux_pc : t_amux := 3;
|
||||
|
||||
type t_pc_oper is (keep, increment, copy, from_alu);
|
||||
type t_adl_oper is (keep, increment, add_idx, load_bus, copy_dreg);
|
||||
type t_adh_oper is (keep, increment, clear, load_bus);
|
||||
type t_sp_oper is (keep, increment, decrement);
|
||||
type t_dout_mux is (reg_d, reg_accu, reg_axy, reg_flags, reg_pcl, reg_pch, shift_res);
|
||||
end;
|
||||
88
cores/c16/1541ultimate2cpu/pkg_6502_opcodes.vhd
Normal file
88
cores/c16/1541ultimate2cpu/pkg_6502_opcodes.vhd
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
package pkg_6502_opcodes is
|
||||
|
||||
type t_opcode_array is array(0 to 255) of string(1 to 13);
|
||||
|
||||
constant opcode_array : t_opcode_array := (
|
||||
|
||||
"BRK ", "ORA ($nn,X) ", "HLT* ", "ASO*($nn,X) ",
|
||||
"BOT*$nn ", "ORA $nn ", "ASL $nn ", "ASO*$nn ",
|
||||
"PHP ", "ORA # ", "ASL A ", "ORA*# ",
|
||||
"BOT*$nnnnn ", "ORA $nnnn ", "ASL $nnnn ", "ASO*$nnnn ",
|
||||
|
||||
"BPL rel ", "ORA ($nn),Y ", "HLT* ", "ASO*($nn),Y ",
|
||||
"BOT*$nn,X ", "ORA $nn,X ", "ASL $nn,X ", "ASO*$nn,X ",
|
||||
"CLC ", "ORA $nnnn,Y ", "NOP* ", "ASO*$nnnn,Y ",
|
||||
"BOT*$nnnn,X ", "ORA $nnnn,X ", "ASL $nnnn,X ", "ASO*$nnnn,X ",
|
||||
|
||||
"JSR $nnnn ", "AND ($nn,X) ", "HLT* ", "RLA*($nn,X) ",
|
||||
"BIT $nn ", "AND $nn ", "ROL $nn ", "RLA*$nn ",
|
||||
"PLP ", "AND # ", "ROL A ", "AND*# ",
|
||||
"BIT $nnnn ", "AND $nnnn ", "ROL $nnnn ", "RLA*$nnnn ",
|
||||
|
||||
"BMI rel ", "AND ($nn),Y ", "HLT* ", "RLA*($nn),Y ",
|
||||
"BIT*$nn,X ", "AND $nn,X ", "ROL $nn,X ", "RLA*$nn,X ",
|
||||
"SEC ", "AND $nnnn,Y ", "NOP* ", "RLA*$nnnn,Y ",
|
||||
"BIT*$nnnn,X ", "AND $nnnn,X ", "ROL $nnnn,X ", "RLA*$nnnn,X ",
|
||||
|
||||
"RTI ", "EOR ($nn,X) ", "HLT* ", "LSE*($nn,X) ",
|
||||
"RDM* ", "EOR $nn ", "LSR $nn ", "LSE*$nn ",
|
||||
"PHA ", "EOR # ", "LSR A ", "EOR*# ",
|
||||
"JMP $nnnn ", "EOR $nnnn ", "LSR $nnnn ", "LSE*$nnnn ",
|
||||
|
||||
"BVC rel ", "EOR ($nn),Y ", "HLT* ", "LSE*($nn),Y ",
|
||||
"RDM* ", "EOR $nn,X ", "LSR $nn,X ", "LSE*$nn,X ",
|
||||
"CLI ", "EOR $nnnn,Y ", "NOP* ", "LSE*$nnnn,Y ",
|
||||
"JMP*$nnnn ", "EOR $nnnn,X ", "LSR $nnnn,X ", "LSE*$nnnn,X ",
|
||||
|
||||
"RTS ", "ADC ($nn,X) ", "HLT* ", "RRA*($nn,X) ",
|
||||
"RDM* ", "ADC $nn ", "ROR $nn ", "RRA*$nn ",
|
||||
"PLA ", "ADC # ", "ROR A ", "ADC*# ",
|
||||
"JMP ($nnnn) ", "ADC $nnnn ", "ROR $nnnn ", "RRA*$nnnn ",
|
||||
|
||||
"BVS rel ", "ADC ($nn),Y ", "HLT* ", "RRA*($nn),Y ",
|
||||
"RDM* ", "ADC $nn,X ", "ROR $nn,X ", "RRA*$nn,X ",
|
||||
"SEI ", "ADC $nnnn,Y ", "NOP* ", "RRA*$nnnn,Y ",
|
||||
"JMP*($nnnn,X)", "ADC $nnnn,X ", "ROR $nnnn,X ", "RRA*$nnnn,X ",
|
||||
|
||||
"SKB* ", "STA ($nn,X) ", "SKB* ", "AXS*($nn,X) ",
|
||||
"STY $nn ", "STA $nn ", "STX $nn ", "AXS*$nn ",
|
||||
"DEY ", "SKB* ", "TXA ", "???* ",
|
||||
"STY $nnnn ", "STA $nnnn ", "STX $nnnn ", "AXS*$nnnn ",
|
||||
|
||||
"BCC ", "STA ($nn),Y ", "HLT* ", "AXS*($nn),Y ",
|
||||
"STY $nn,X ", "STA $nn,X ", "STX $nn,Y ", "AXS*$nn,Y ",
|
||||
"TYA ", "STA $nnnn,Y ", "TXS ", "AXS*$nnnn,Y ",
|
||||
"STY*$nnnn,X ", "STA $nnnn,X ", "STX*$nnnn,Y ", "AXS*$nnnn,Y ",
|
||||
|
||||
"LDY # ", "LDA ($nn,X) ", "LDX # ", "LAX*($nn,X) ",
|
||||
"LDY $nn ", "LDA $nn ", "LDX $nn ", "LAX*$nn ",
|
||||
"TAY ", "LDA # ", "TAX ", "LAX*# ",
|
||||
"LDY $nnnn ", "LDA $nnnn ", "LDX $nnnn ", "LAX*$nnnn ",
|
||||
|
||||
"BCS ", "LDA ($nn),Y ", "HLT* ", "LAX*($nn),Y ",
|
||||
"LDY $nn,X ", "LDA $nn,X ", "LDX $nn,Y ", "LAX*$nn,Y ",
|
||||
"CLV ", "LDA $nnnn,Y ", "TSX ", "LAX*$nnnn,Y ",
|
||||
"LDY $nnnn,X ", "LDA $nnnn,X ", "LDX $nnnn,Y ", "LAX*$nnnn,Y ",
|
||||
|
||||
"CPY # ", "CMP ($nn,X) ", "SKB* ", "DCM*($nn,X) ",
|
||||
"CPY $nn ", "CMP $nn ", "DEC $nn ", "DCM*$nn ",
|
||||
"INY ", "CMP # ", "DEX ", "SAX*# (used!)",
|
||||
"CPY $nnnn ", "CMP $nnnn ", "DEC $nnnn ", "DCM*$nnnn ",
|
||||
|
||||
"BNE ", "CMP ($nn),Y ", "HLT* ", "DCM*($nn),Y ",
|
||||
"RDM* ", "CMP $nn,X ", "DEC $nn,X ", "DCM*$nn,X ",
|
||||
"CLD ", "CMP $nnnn,Y ", "NOP* ", "DCM*$nnnn,Y ",
|
||||
"RDM*$nnnn,X ", "CMP $nnnn,X ", "DEC $nnnn,X ", "DCM*$nnnn,X ",
|
||||
|
||||
"CPX # ", "SBC ($nn,X) ", "SKB* ", "INS*($nn,X) ",
|
||||
"CPX $nn ", "SBC $nn ", "INC $nn ", "INS*$nn ",
|
||||
"INX ", "SBC # ", "NOP ", "SBC*# ",
|
||||
"CPX $nnnn ", "SBC $nnnn ", "INC $nnnn ", "INS*$nnnn ",
|
||||
|
||||
"BEQ ", "SBC ($nn),Y ", "HLT* ", "INS*($nn),Y ",
|
||||
"RDM* ", "SBC $nn,X ", "INC $nn,X ", "INS*$nn,X ",
|
||||
"SED ", "SBC $nnnn,Y ", "NOP* ", "INS*$nnnn,Y ",
|
||||
"RDM*$nnnn,X ", "SBC $nnnn,X ", "INC $nnnn,X ", "INS*$nnnn,X " );
|
||||
|
||||
end;
|
||||
472
cores/c16/1541ultimate2cpu/proc_control.vhd
Normal file
472
cores/c16/1541ultimate2cpu/proc_control.vhd
Normal file
@@ -0,0 +1,472 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
library work;
|
||||
use work.pkg_6502_defs.all;
|
||||
use work.pkg_6502_decode.all;
|
||||
|
||||
entity proc_control is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
clock_en : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
interrupt : in std_logic;
|
||||
i_reg : in std_logic_vector(7 downto 0);
|
||||
index_carry : in std_logic;
|
||||
pc_carry : in std_logic;
|
||||
branch_taken : in boolean;
|
||||
|
||||
sync : out std_logic;
|
||||
dummy_cycle : out std_logic;
|
||||
set_b : out std_logic;
|
||||
latch_dreg : out std_logic;
|
||||
copy_d2p : out std_logic;
|
||||
reg_update : out std_logic;
|
||||
rwn : out std_logic;
|
||||
vect_bit : out std_logic := '0';
|
||||
a16 : out std_logic;
|
||||
a_mux : out t_amux := c_amux_pc;
|
||||
dout_mux : out t_dout_mux;
|
||||
pc_oper : out t_pc_oper;
|
||||
s_oper : out t_sp_oper;
|
||||
adl_oper : out t_adl_oper;
|
||||
adh_oper : out t_adh_oper );
|
||||
|
||||
end proc_control;
|
||||
|
||||
|
||||
architecture gideon of proc_control is
|
||||
|
||||
type t_state is (fetch, decode, absolute, abs_hi, abs_fix, branch, branch_fix,
|
||||
indir1, indir2, jump_sub, jump, retrn, rmw1, rmw2, vector, startup,
|
||||
zp, zp_idx, zp_indir, push1, push2, push3, pull1, pull2, pull3 );
|
||||
|
||||
signal state : t_state;
|
||||
signal next_state : t_state;
|
||||
|
||||
signal next_cp_p : std_logic;
|
||||
signal next_rwn : std_logic;
|
||||
signal next_dreg : std_logic;
|
||||
signal next_amux : t_amux;
|
||||
signal next_dout : t_dout_mux;
|
||||
signal next_set_b : std_logic;
|
||||
signal next_dummy : std_logic;
|
||||
signal vectoring : std_logic;
|
||||
begin
|
||||
-- combinatroial process
|
||||
process(state, i_reg, index_carry, pc_carry, branch_taken, interrupt, vectoring)
|
||||
variable v_stack_idx : std_logic_vector(1 downto 0);
|
||||
begin
|
||||
-- defaults
|
||||
sync <= '0';
|
||||
pc_oper <= increment;
|
||||
next_amux <= c_amux_pc;
|
||||
next_rwn <= '1';
|
||||
next_state <= state;
|
||||
adl_oper <= keep;
|
||||
adh_oper <= keep;
|
||||
s_oper <= keep;
|
||||
next_dreg <= '1';
|
||||
next_cp_p <= '0';
|
||||
next_dout <= reg_d;
|
||||
next_set_b <= '0';
|
||||
next_dummy <= '0';
|
||||
|
||||
v_stack_idx := stack_idx(i_reg);
|
||||
|
||||
case state is
|
||||
when fetch =>
|
||||
sync <= '1';
|
||||
|
||||
if interrupt='1' then
|
||||
pc_oper <= keep;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_pch;
|
||||
next_state <= push1;
|
||||
next_amux <= c_amux_stack;
|
||||
else
|
||||
next_state <= decode;
|
||||
next_set_b <= '1';
|
||||
end if;
|
||||
|
||||
when decode =>
|
||||
adl_oper <= load_bus;
|
||||
adh_oper <= clear;
|
||||
|
||||
if is_absolute(i_reg) then
|
||||
if is_abs_jump(i_reg) then
|
||||
next_state <= jump;
|
||||
else
|
||||
next_state <= absolute;
|
||||
end if;
|
||||
elsif is_implied(i_reg) then
|
||||
pc_oper <= keep;
|
||||
if is_stack(i_reg) then -- PHP, PLP, PHA, PLA
|
||||
next_amux <= c_amux_stack;
|
||||
case v_stack_idx is
|
||||
when "00" => -- PHP
|
||||
next_state <= push3;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_flags;
|
||||
|
||||
when "10" => -- PHA
|
||||
next_state <= push3;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_accu;
|
||||
|
||||
when others =>
|
||||
next_state <= pull1;
|
||||
end case;
|
||||
else
|
||||
next_state <= fetch;
|
||||
end if;
|
||||
elsif is_zeropage(i_reg) then
|
||||
next_amux <= c_amux_addr;
|
||||
if is_indirect(i_reg) then
|
||||
if is_postindexed(i_reg) then
|
||||
next_state <= zp_indir;
|
||||
else
|
||||
next_state <= zp;
|
||||
next_dummy <= '1';
|
||||
end if;
|
||||
else
|
||||
next_state <= zp;
|
||||
if is_store(i_reg) and not is_postindexed(i_reg) then
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_axy;
|
||||
end if;
|
||||
end if;
|
||||
elsif is_relative(i_reg) then
|
||||
next_state <= branch;
|
||||
elsif is_stack(i_reg) then -- non-implied stack operations like BRK, JSR, RTI and RTS
|
||||
next_amux <= c_amux_stack;
|
||||
case v_stack_idx is
|
||||
when c_stack_idx_brk =>
|
||||
-- next_set_b <= '1';
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_pch;
|
||||
next_state <= push1;
|
||||
when c_stack_idx_jsr =>
|
||||
next_dreg <= '0';
|
||||
next_dout <= reg_pch;
|
||||
next_state <= jump_sub;
|
||||
when c_stack_idx_rti =>
|
||||
next_state <= pull1;
|
||||
when c_stack_idx_rts =>
|
||||
next_state <= pull2;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
elsif is_immediate(i_reg) then
|
||||
next_state <= fetch;
|
||||
end if;
|
||||
|
||||
when absolute =>
|
||||
next_state <= abs_hi;
|
||||
next_amux <= c_amux_addr;
|
||||
adh_oper <= load_bus;
|
||||
if is_postindexed(i_reg) then
|
||||
adl_oper <= add_idx;
|
||||
elsif not is_zeropage(i_reg) then
|
||||
if is_store(i_reg) then
|
||||
next_rwn <='0';
|
||||
next_dout <= reg_axy;
|
||||
end if;
|
||||
end if;
|
||||
if is_zeropage(i_reg) then
|
||||
pc_oper <= keep;
|
||||
else
|
||||
pc_oper <= increment;
|
||||
end if;
|
||||
|
||||
when abs_hi =>
|
||||
pc_oper <= keep;
|
||||
if is_postindexed(i_reg) then
|
||||
if is_load(i_reg) and index_carry='0' then
|
||||
next_amux <= c_amux_pc;
|
||||
next_state <= fetch;
|
||||
else
|
||||
next_amux <= c_amux_addr;
|
||||
next_state <= abs_fix;
|
||||
if index_carry='1' then
|
||||
adh_oper <= increment;
|
||||
end if;
|
||||
end if;
|
||||
if is_store(i_reg) then
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_axy;
|
||||
end if;
|
||||
else -- not post-indexed
|
||||
if is_jump(i_reg) then
|
||||
next_amux <= c_amux_addr;
|
||||
next_state <= jump;
|
||||
adl_oper <= increment;
|
||||
elsif is_rmw(i_reg) then
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_d;
|
||||
next_dummy <= '1';
|
||||
next_state <= rmw1;
|
||||
next_amux <= c_amux_addr;
|
||||
else
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when abs_fix =>
|
||||
pc_oper <= keep;
|
||||
|
||||
if is_rmw(i_reg) then
|
||||
next_state <= rmw1;
|
||||
next_amux <= c_amux_addr;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_d;
|
||||
next_dummy <= '1';
|
||||
else
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
end if;
|
||||
|
||||
when branch =>
|
||||
next_amux <= c_amux_pc;
|
||||
if branch_taken then
|
||||
pc_oper <= from_alu; -- add offset
|
||||
next_state <= branch_fix;
|
||||
else
|
||||
pc_oper <= increment;
|
||||
next_state <= decode;
|
||||
sync <= '1';
|
||||
end if;
|
||||
|
||||
when branch_fix =>
|
||||
next_amux <= c_amux_pc;
|
||||
|
||||
if pc_carry='1' then
|
||||
next_state <= fetch;
|
||||
pc_oper <= keep; -- this will fix the PCH, since the carry is set
|
||||
else
|
||||
sync <= '1';
|
||||
next_state <= decode;
|
||||
pc_oper <= increment;
|
||||
end if;
|
||||
|
||||
when indir1 =>
|
||||
pc_oper <= keep;
|
||||
next_state <= indir2;
|
||||
next_amux <= c_amux_addr;
|
||||
adl_oper <= copy_dreg;
|
||||
adh_oper <= load_bus;
|
||||
|
||||
if is_store(i_reg) then
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_axy;
|
||||
end if;
|
||||
|
||||
when indir2 =>
|
||||
pc_oper <= keep;
|
||||
if is_rmw(i_reg) then
|
||||
next_dummy <= '1';
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_d;
|
||||
next_state <= rmw1;
|
||||
next_amux <= c_amux_addr;
|
||||
else
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
end if;
|
||||
|
||||
when jump_sub =>
|
||||
next_state <= push1;
|
||||
pc_oper <= keep;
|
||||
next_dout <= reg_pch;
|
||||
next_rwn <= '0';
|
||||
next_dreg <= '0';
|
||||
next_amux <= c_amux_stack;
|
||||
|
||||
when jump =>
|
||||
pc_oper <= copy;
|
||||
next_amux <= c_amux_pc;
|
||||
if is_stack(i_reg) and v_stack_idx=c_stack_idx_rts and vectoring='0' then
|
||||
next_state <= retrn;
|
||||
else
|
||||
next_state <= fetch;
|
||||
end if;
|
||||
|
||||
when retrn =>
|
||||
pc_oper <= increment;
|
||||
next_state <= fetch;
|
||||
|
||||
when pull1 =>
|
||||
s_oper <= increment;
|
||||
next_state <= pull2;
|
||||
next_amux <= c_amux_stack;
|
||||
pc_oper <= keep;
|
||||
|
||||
when pull2 =>
|
||||
pc_oper <= keep;
|
||||
if is_implied(i_reg) then
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
next_cp_p <= not v_stack_idx(1); -- only for PLP
|
||||
else -- it was a stack operation, but not implied (RTS/RTI)
|
||||
s_oper <= increment;
|
||||
next_state <= pull3;
|
||||
next_amux <= c_amux_stack;
|
||||
next_cp_p <= not v_stack_idx(0); -- only for RTI
|
||||
end if;
|
||||
|
||||
when pull3 =>
|
||||
pc_oper <= keep;
|
||||
s_oper <= increment;
|
||||
next_state <= jump;
|
||||
next_amux <= c_amux_stack;
|
||||
|
||||
when push1 =>
|
||||
pc_oper <= keep;
|
||||
s_oper <= decrement;
|
||||
next_state <= push2;
|
||||
next_amux <= c_amux_stack;
|
||||
next_rwn <= '0';
|
||||
next_dreg <= '0';
|
||||
next_dout <= reg_pcl;
|
||||
|
||||
when push2 =>
|
||||
pc_oper <= keep;
|
||||
s_oper <= decrement;
|
||||
if (v_stack_idx=c_stack_idx_jsr) and vectoring='0' then
|
||||
next_state <= jump;
|
||||
next_amux <= c_amux_pc;
|
||||
else
|
||||
next_state <= push3;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_flags;
|
||||
next_amux <= c_amux_stack;
|
||||
end if;
|
||||
|
||||
when push3 =>
|
||||
pc_oper <= keep;
|
||||
s_oper <= decrement;
|
||||
if is_implied(i_reg) and vectoring='0' then -- PHP, PHA
|
||||
next_amux <= c_amux_pc;
|
||||
next_state <= fetch;
|
||||
else
|
||||
next_state <= vector;
|
||||
next_amux <= c_amux_vector;
|
||||
end if;
|
||||
|
||||
when rmw1 =>
|
||||
pc_oper <= keep;
|
||||
next_state <= rmw2;
|
||||
next_amux <= c_amux_addr;
|
||||
next_rwn <= '0';
|
||||
next_dout <= shift_res;
|
||||
|
||||
when rmw2 =>
|
||||
pc_oper <= keep;
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
|
||||
when vector =>
|
||||
next_state <= jump;
|
||||
pc_oper <= keep;
|
||||
next_amux <= c_amux_vector;
|
||||
|
||||
when startup =>
|
||||
next_state <= vector;
|
||||
pc_oper <= keep;
|
||||
next_amux <= c_amux_vector;
|
||||
|
||||
when zp =>
|
||||
pc_oper <= keep;
|
||||
if is_postindexed(i_reg) or is_indirect(i_reg) then
|
||||
adl_oper <= add_idx;
|
||||
next_state <= zp_idx;
|
||||
next_amux <= c_amux_addr;
|
||||
if is_postindexed(i_reg) and is_store(i_reg) then
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_axy;
|
||||
end if;
|
||||
elsif is_rmw(i_reg) then
|
||||
next_dummy <= '1';
|
||||
next_state <= rmw1;
|
||||
next_amux <= c_amux_addr;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_d;
|
||||
else
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
end if;
|
||||
|
||||
when zp_idx =>
|
||||
pc_oper <= keep;
|
||||
if is_indirect(i_reg) then
|
||||
next_state <= indir1;
|
||||
adl_oper <= increment;
|
||||
next_amux <= c_amux_addr;
|
||||
elsif is_rmw(i_reg) then
|
||||
next_state <= rmw1;
|
||||
next_amux <= c_amux_addr;
|
||||
next_rwn <= '0';
|
||||
next_dout <= reg_d;
|
||||
else
|
||||
next_state <= fetch;
|
||||
next_amux <= c_amux_pc;
|
||||
end if;
|
||||
|
||||
when zp_indir =>
|
||||
pc_oper <= keep;
|
||||
next_state <= absolute;
|
||||
next_amux <= c_amux_addr;
|
||||
adl_oper <= increment;
|
||||
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
reg_update <= '1' when (state = fetch) and vectoring='0' and
|
||||
not is_stack(i_reg) and not is_relative(i_reg) else '0';
|
||||
|
||||
vect_bit <= '0' when state = vector else '1';
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if clock_en='1' then
|
||||
state <= next_state;
|
||||
a_mux <= next_amux;
|
||||
dout_mux <= next_dout;
|
||||
rwn <= next_rwn;
|
||||
latch_dreg <= next_dreg and next_rwn; -- disable dreg latch for writes
|
||||
copy_d2p <= next_cp_p;
|
||||
set_b <= next_set_b;
|
||||
dummy_cycle <= next_dummy;
|
||||
|
||||
if next_amux = c_amux_vector or next_amux = c_amux_pc then
|
||||
a16 <= '1';
|
||||
else
|
||||
a16 <= '0';
|
||||
end if;
|
||||
|
||||
if state = fetch then
|
||||
vectoring <= interrupt;
|
||||
end if;
|
||||
end if;
|
||||
if reset='1' then
|
||||
a16 <= '1';
|
||||
state <= startup; --vector;
|
||||
a_mux <= c_amux_vector;
|
||||
rwn <= '1';
|
||||
latch_dreg <= '1';
|
||||
dout_mux <= reg_d;
|
||||
copy_d2p <= '0';
|
||||
set_b <= '0';
|
||||
vectoring <= '0';
|
||||
dummy_cycle <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end gideon;
|
||||
|
||||
233
cores/c16/1541ultimate2cpu/proc_core.vhd
Normal file
233
cores/c16/1541ultimate2cpu/proc_core.vhd
Normal file
@@ -0,0 +1,233 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
|
||||
library work;
|
||||
use work.pkg_6502_defs.all;
|
||||
|
||||
entity proc_core is
|
||||
generic (
|
||||
vector_page : std_logic_vector(15 downto 4) := X"FFF";
|
||||
support_bcd : boolean := true );
|
||||
port(
|
||||
clock : in std_logic;
|
||||
clock_en : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
irq_n : in std_logic := '1';
|
||||
nmi_n : in std_logic := '1';
|
||||
so_n : in std_logic := '1';
|
||||
|
||||
sync_out : out std_logic;
|
||||
pc_out : out std_logic_vector(15 downto 0);
|
||||
inst_out : out std_logic_vector(7 downto 0);
|
||||
addr_out : out std_logic_vector(16 downto 0);
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
read_write_n : out std_logic );
|
||||
|
||||
end proc_core;
|
||||
|
||||
architecture structural of proc_core is
|
||||
signal index_carry : std_logic;
|
||||
signal pc_carry : std_logic;
|
||||
signal branch_taken : boolean;
|
||||
signal i_reg : std_logic_vector(7 downto 0);
|
||||
signal d_reg : std_logic_vector(7 downto 0);
|
||||
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 s_reg : std_logic_vector(7 downto 0);
|
||||
signal p_reg : std_logic_vector(7 downto 0);
|
||||
|
||||
signal latch_dreg : std_logic;
|
||||
signal reg_update : std_logic;
|
||||
signal copy_d2p : std_logic;
|
||||
signal sync : std_logic;
|
||||
signal rwn : std_logic;
|
||||
signal vect_bit : std_logic;
|
||||
signal a_mux : t_amux;
|
||||
signal pc_oper : t_pc_oper;
|
||||
signal s_oper : t_sp_oper;
|
||||
signal adl_oper : t_adl_oper;
|
||||
signal adh_oper : t_adh_oper;
|
||||
signal dout_mux : t_dout_mux;
|
||||
|
||||
signal alu_out : std_logic_vector(7 downto 0);
|
||||
signal mem_out : std_logic_vector(7 downto 0);
|
||||
signal impl_out : std_logic_vector(7 downto 0);
|
||||
|
||||
signal set_a : std_logic;
|
||||
signal set_x : std_logic;
|
||||
signal set_y : std_logic;
|
||||
signal set_s : std_logic;
|
||||
|
||||
signal vect_addr : std_logic_vector(3 downto 0);
|
||||
signal interrupt : std_logic;
|
||||
|
||||
signal new_flags : std_logic_vector(7 downto 0);
|
||||
signal n_out : std_logic;
|
||||
signal v_out : std_logic;
|
||||
signal c_out : std_logic;
|
||||
signal z_out : std_logic;
|
||||
signal d_out : std_logic;
|
||||
signal i_out : std_logic;
|
||||
signal set_b : std_logic;
|
||||
signal clear_b : std_logic;
|
||||
signal a16 : std_logic;
|
||||
begin
|
||||
inst_out <= i_reg; -- for debug only
|
||||
|
||||
new_flags(7) <= n_out;
|
||||
new_flags(6) <= v_out;
|
||||
new_flags(5) <= '1';
|
||||
new_flags(4) <= p_reg(4);
|
||||
new_flags(3) <= d_out;
|
||||
new_flags(2) <= i_out;
|
||||
new_flags(1) <= z_out;
|
||||
new_flags(0) <= c_out;
|
||||
|
||||
ctrl: entity work.proc_control
|
||||
port map (
|
||||
clock => clock,
|
||||
clock_en => clock_en,
|
||||
reset => reset,
|
||||
|
||||
interrupt => interrupt,
|
||||
i_reg => i_reg,
|
||||
index_carry => index_carry,
|
||||
pc_carry => pc_carry,
|
||||
branch_taken => branch_taken,
|
||||
|
||||
sync => sync,
|
||||
latch_dreg => latch_dreg,
|
||||
reg_update => reg_update,
|
||||
set_b => set_b,
|
||||
copy_d2p => copy_d2p,
|
||||
vect_bit => vect_bit,
|
||||
a16 => a16,
|
||||
rwn => rwn,
|
||||
a_mux => a_mux,
|
||||
dout_mux => dout_mux,
|
||||
pc_oper => pc_oper,
|
||||
s_oper => s_oper,
|
||||
adl_oper => adl_oper,
|
||||
adh_oper => adh_oper );
|
||||
|
||||
oper: entity work.data_oper
|
||||
generic map (
|
||||
support_bcd => support_bcd )
|
||||
port map (
|
||||
inst => i_reg,
|
||||
|
||||
n_in => p_reg(7),
|
||||
v_in => p_reg(6),
|
||||
z_in => p_reg(1),
|
||||
c_in => p_reg(0),
|
||||
d_in => p_reg(3),
|
||||
i_in => p_reg(2),
|
||||
|
||||
data_in => d_reg,
|
||||
a_reg => a_reg,
|
||||
x_reg => x_reg,
|
||||
y_reg => y_reg,
|
||||
s_reg => s_reg,
|
||||
|
||||
alu_out => alu_out,
|
||||
mem_out => mem_out,
|
||||
impl_out => impl_out,
|
||||
|
||||
set_a => set_a,
|
||||
set_x => set_x,
|
||||
set_y => set_y,
|
||||
set_s => set_s,
|
||||
|
||||
n_out => n_out,
|
||||
v_out => v_out,
|
||||
z_out => z_out,
|
||||
c_out => c_out,
|
||||
d_out => d_out,
|
||||
i_out => i_out );
|
||||
|
||||
regs: entity work.proc_registers
|
||||
generic map (
|
||||
vector_page => vector_page )
|
||||
port map (
|
||||
clock => clock,
|
||||
clock_en => clock_en,
|
||||
reset => reset,
|
||||
|
||||
-- package pins
|
||||
data_in => data_in,
|
||||
data_out => data_out,
|
||||
so_n => so_n,
|
||||
|
||||
-- data from "data_oper"
|
||||
alu_data => alu_out,
|
||||
mem_data => mem_out,
|
||||
new_flags => new_flags,
|
||||
|
||||
-- from implied handler
|
||||
set_a => set_a,
|
||||
set_x => set_x,
|
||||
set_y => set_y,
|
||||
set_s => set_s,
|
||||
set_data => impl_out,
|
||||
|
||||
-- from interrupt controller
|
||||
vect_addr => vect_addr,
|
||||
interrupt => interrupt,
|
||||
set_b => set_b,
|
||||
clear_b => clear_b,
|
||||
|
||||
-- from processor state machine and decoder
|
||||
sync => sync,
|
||||
latch_dreg => latch_dreg,
|
||||
vect_bit => vect_bit,
|
||||
reg_update => reg_update,
|
||||
copy_d2p => copy_d2p,
|
||||
a_mux => a_mux,
|
||||
dout_mux => dout_mux,
|
||||
pc_oper => pc_oper,
|
||||
s_oper => s_oper,
|
||||
adl_oper => adl_oper,
|
||||
adh_oper => adh_oper,
|
||||
|
||||
-- outputs to processor state machine
|
||||
i_reg => i_reg,
|
||||
index_carry => index_carry,
|
||||
pc_carry => pc_carry,
|
||||
branch_taken => branch_taken,
|
||||
|
||||
-- register outputs
|
||||
addr_out => addr_out(15 downto 0),
|
||||
|
||||
d_reg => d_reg,
|
||||
a_reg => a_reg,
|
||||
x_reg => x_reg,
|
||||
y_reg => y_reg,
|
||||
s_reg => s_reg,
|
||||
p_reg => p_reg,
|
||||
pc_out => pc_out );
|
||||
|
||||
intr: entity work.proc_interrupt
|
||||
port map (
|
||||
clock => clock,
|
||||
clock_en => clock_en,
|
||||
reset => reset,
|
||||
|
||||
irq_n => irq_n,
|
||||
nmi_n => nmi_n,
|
||||
|
||||
i_flag => p_reg(2),
|
||||
clear_b => clear_b,
|
||||
|
||||
vect_bit => vect_bit,
|
||||
interrupt => interrupt,
|
||||
vect_addr => vect_addr );
|
||||
|
||||
read_write_n <= rwn;
|
||||
addr_out(16) <= a16;
|
||||
sync_out <= sync;
|
||||
end structural;
|
||||
83
cores/c16/1541ultimate2cpu/proc_interrupt.vhd
Normal file
83
cores/c16/1541ultimate2cpu/proc_interrupt.vhd
Normal file
@@ -0,0 +1,83 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
|
||||
entity proc_interrupt is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
clock_en : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
irq_n : in std_logic;
|
||||
nmi_n : in std_logic;
|
||||
|
||||
i_flag : in std_logic;
|
||||
clear_b : out std_logic;
|
||||
|
||||
vect_bit : in std_logic;
|
||||
interrupt : out std_logic;
|
||||
vect_addr : out std_logic_vector(3 downto 0) );
|
||||
|
||||
end proc_interrupt;
|
||||
|
||||
architecture gideon of proc_interrupt is
|
||||
signal irq_c : std_logic := '0';
|
||||
signal nmi_c : std_logic := '0';
|
||||
signal nmi_d : std_logic := '0';
|
||||
signal nmi_act : std_logic := '0';
|
||||
signal vect_h : std_logic_vector(1 downto 0) := "00";
|
||||
type state_t is (idle, do_irq, do_nmi);
|
||||
signal state : state_t;
|
||||
begin
|
||||
vect_addr <= '1' & vect_h & vect_bit;
|
||||
interrupt <= irq_c or nmi_act;
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
irq_c <= not (irq_n or i_flag);
|
||||
nmi_c <= not nmi_n;
|
||||
clear_b <= '0';
|
||||
|
||||
if clock_en='1' then
|
||||
nmi_d <= nmi_c;
|
||||
if nmi_d = '0' and nmi_c = '1' then -- edge
|
||||
nmi_act <= '1';
|
||||
end if;
|
||||
|
||||
case state is
|
||||
when idle =>
|
||||
vect_h <= "11"; -- FE/FF
|
||||
if nmi_act = '1' then
|
||||
vect_h <= "01"; -- FA/FB
|
||||
state <= do_nmi;
|
||||
elsif irq_c = '1' then
|
||||
state <= do_irq;
|
||||
clear_b <= '1';
|
||||
end if;
|
||||
|
||||
when do_irq =>
|
||||
if vect_bit='0' or irq_c='0' then
|
||||
state <= idle;
|
||||
end if;
|
||||
|
||||
when do_nmi =>
|
||||
if vect_bit='0' then
|
||||
nmi_act <= '0';
|
||||
state <= idle;
|
||||
end if;
|
||||
|
||||
when others =>
|
||||
state <= idle;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
vect_h <= "10"; -- FC/FD 1100
|
||||
state <= do_nmi;
|
||||
nmi_act <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end gideon;
|
||||
303
cores/c16/1541ultimate2cpu/proc_registers.vhd
Normal file
303
cores/c16/1541ultimate2cpu/proc_registers.vhd
Normal file
@@ -0,0 +1,303 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
|
||||
library work;
|
||||
use work.pkg_6502_defs.all;
|
||||
use work.pkg_6502_decode.all;
|
||||
|
||||
entity proc_registers is
|
||||
generic (
|
||||
vector_page : std_logic_vector(15 downto 4) := X"FFF" );
|
||||
port (
|
||||
clock : in std_logic;
|
||||
clock_en : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
-- package pins
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
|
||||
so_n : in std_logic := '1';
|
||||
|
||||
-- data from "data_oper"
|
||||
alu_data : in std_logic_vector(7 downto 0);
|
||||
mem_data : in std_logic_vector(7 downto 0);
|
||||
new_flags : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- from implied handler
|
||||
set_a : in std_logic;
|
||||
set_x : in std_logic;
|
||||
set_y : in std_logic;
|
||||
set_s : in std_logic;
|
||||
set_data : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- interrupt pins
|
||||
interrupt : in std_logic;
|
||||
vect_addr : in std_logic_vector(3 downto 0);
|
||||
set_b : in std_logic;
|
||||
clear_b : in std_logic;
|
||||
|
||||
-- from processor state machine and decoder
|
||||
sync : in std_logic; -- latch ireg
|
||||
latch_dreg : in std_logic;
|
||||
vect_bit : in std_logic;
|
||||
reg_update : in std_logic;
|
||||
copy_d2p : in std_logic;
|
||||
a_mux : in t_amux;
|
||||
dout_mux : in t_dout_mux;
|
||||
pc_oper : in t_pc_oper;
|
||||
s_oper : in t_sp_oper;
|
||||
adl_oper : in t_adl_oper;
|
||||
adh_oper : in t_adh_oper;
|
||||
|
||||
-- outputs to processor state machine
|
||||
i_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
index_carry : out std_logic;
|
||||
pc_carry : out std_logic;
|
||||
branch_taken : out boolean;
|
||||
|
||||
-- register outputs
|
||||
addr_out : out std_logic_vector(15 downto 0) := X"FFFF";
|
||||
|
||||
d_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
a_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
x_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
y_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
s_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
p_reg : out std_logic_vector(7 downto 0) := X"00";
|
||||
pc_out : out std_logic_vector(15 downto 0) );
|
||||
end proc_registers;
|
||||
|
||||
architecture gideon of proc_registers is
|
||||
-- signal a_reg : std_logic_vector(7 downto 0);
|
||||
signal dreg : std_logic_vector(7 downto 0) := X"00";
|
||||
signal a_reg_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal x_reg_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal y_reg_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal selected_idx : std_logic_vector(7 downto 0) := X"00";
|
||||
signal i_reg_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal s_reg_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal p_reg_i : std_logic_vector(7 downto 0) := X"30";
|
||||
signal pcl, pch : std_logic_vector(7 downto 0) := X"FF";
|
||||
signal adl, adh : std_logic_vector(7 downto 0) := X"00";
|
||||
signal pc_carry_i : std_logic;
|
||||
signal pc_carry_d : std_logic;
|
||||
signal branch_flag : std_logic;
|
||||
signal reg_out : std_logic_vector(7 downto 0);
|
||||
signal vect : std_logic_vector(3 downto 0) := "1111";
|
||||
signal dreg_zero : std_logic;
|
||||
|
||||
alias C_flag : std_logic is p_reg_i(0);
|
||||
alias Z_flag : std_logic is p_reg_i(1);
|
||||
alias I_flag : std_logic is p_reg_i(2);
|
||||
alias D_flag : std_logic is p_reg_i(3);
|
||||
alias B_flag : std_logic is p_reg_i(4);
|
||||
alias V_flag : std_logic is p_reg_i(6);
|
||||
alias N_flag : std_logic is p_reg_i(7);
|
||||
|
||||
begin
|
||||
dreg_zero <= '1' when dreg=X"00" else '0';
|
||||
|
||||
process(clock)
|
||||
variable pcl_t : std_logic_vector(8 downto 0);
|
||||
variable adl_t : std_logic_vector(8 downto 0);
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if clock_en='1' then
|
||||
-- Data Register
|
||||
if latch_dreg='1' then
|
||||
dreg <= data_in;
|
||||
end if;
|
||||
|
||||
-- Flags Register
|
||||
if copy_d2p = '1' then
|
||||
p_reg_i <= dreg;
|
||||
elsif reg_update='1' then
|
||||
p_reg_i <= new_flags;
|
||||
end if;
|
||||
|
||||
if vect_bit='0' then
|
||||
I_flag <= '1';
|
||||
end if;
|
||||
|
||||
if set_b='1' then
|
||||
B_flag <= '1';
|
||||
elsif clear_b='1' then
|
||||
B_flag <= '0';
|
||||
end if;
|
||||
|
||||
if so_n='0' then -- only 1 bit is affected, so no syncronization needed
|
||||
V_flag <= '1';
|
||||
end if;
|
||||
|
||||
-- Instruction Register
|
||||
if sync='1' then
|
||||
i_reg_i <= data_in;
|
||||
|
||||
-- Fix for PLA only :(
|
||||
if load_a(i_reg_i) then
|
||||
a_reg_i <= dreg;
|
||||
N_flag <= dreg(7);
|
||||
Z_flag <= dreg_zero;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Logic for the Program Counter
|
||||
pc_carry_i <= '0';
|
||||
case pc_oper is
|
||||
when increment =>
|
||||
if pcl = X"FF" then
|
||||
pch <= pch + 1;
|
||||
end if;
|
||||
pcl <= pcl + 1;
|
||||
|
||||
when copy =>
|
||||
pcl <= dreg;
|
||||
pch <= data_in;
|
||||
|
||||
when from_alu =>
|
||||
pcl_t := ('0' & pcl) + (dreg(7) & dreg); -- sign extended 1 bit
|
||||
pcl <= pcl_t(7 downto 0);
|
||||
pc_carry_i <= pcl_t(8);
|
||||
pc_carry_d <= dreg(7);
|
||||
|
||||
when others => -- keep (and fix)
|
||||
if pc_carry_i='1' then
|
||||
if pc_carry_d='1' then
|
||||
pch <= pch - 1;
|
||||
else
|
||||
pch <= pch + 1;
|
||||
end if;
|
||||
end if;
|
||||
end case;
|
||||
|
||||
-- Logic for the Address register
|
||||
case adl_oper is
|
||||
when increment =>
|
||||
adl <= adl + 1;
|
||||
|
||||
when add_idx =>
|
||||
adl_t := ('0' & dreg) + ('0' & selected_idx);
|
||||
adl <= adl_t(7 downto 0);
|
||||
index_carry <= adl_t(8);
|
||||
|
||||
when load_bus =>
|
||||
adl <= data_in;
|
||||
|
||||
when copy_dreg =>
|
||||
adl <= dreg;
|
||||
|
||||
when others =>
|
||||
null;
|
||||
|
||||
end case;
|
||||
|
||||
case adh_oper is
|
||||
when increment =>
|
||||
adh <= adh + 1;
|
||||
|
||||
when clear =>
|
||||
adh <= (others => '0');
|
||||
|
||||
when load_bus =>
|
||||
adh <= data_in;
|
||||
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
|
||||
-- Logic for ALU register
|
||||
if reg_update='1' then
|
||||
if set_a='1' then
|
||||
a_reg_i <= set_data;
|
||||
elsif store_a_from_alu(i_reg_i) then
|
||||
a_reg_i <= alu_data;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Logic for Index registers
|
||||
if reg_update='1' then
|
||||
if set_x='1' then
|
||||
x_reg_i <= set_data;
|
||||
elsif load_x(i_reg_i) then
|
||||
x_reg_i <= alu_data; --dreg; -- alu is okay, too (they should be the same)
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if reg_update='1' then
|
||||
if set_y='1' then
|
||||
y_reg_i <= set_data;
|
||||
elsif load_y(i_reg_i) then
|
||||
y_reg_i <= dreg;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Logic for the Stack Pointer
|
||||
if set_s='1' then
|
||||
s_reg_i <= set_data;
|
||||
else
|
||||
case s_oper is
|
||||
when increment =>
|
||||
s_reg_i <= s_reg_i + 1;
|
||||
|
||||
when decrement =>
|
||||
s_reg_i <= s_reg_i - 1;
|
||||
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
-- Reset
|
||||
if reset='1' then
|
||||
p_reg_i <= X"34"; -- I=1
|
||||
index_carry <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
with i_reg_i(7 downto 6) select branch_flag <=
|
||||
N_flag when "00",
|
||||
V_flag when "01",
|
||||
C_flag when "10",
|
||||
Z_flag when "11",
|
||||
'0' when others;
|
||||
|
||||
branch_taken <= (branch_flag xor not i_reg_i(5))='1';
|
||||
|
||||
with a_mux select addr_out <=
|
||||
vector_page & vect_addr when 0,
|
||||
adh & adl when 1,
|
||||
X"01" & s_reg_i when 2,
|
||||
pch & pcl when 3;
|
||||
|
||||
with i_reg_i(1 downto 0) select reg_out <=
|
||||
y_reg_i when "00",
|
||||
a_reg_i when "01",
|
||||
x_reg_i when "10",
|
||||
a_reg_i and x_reg_i when others;
|
||||
|
||||
with dout_mux select data_out <=
|
||||
dreg when reg_d,
|
||||
a_reg_i when reg_accu,
|
||||
reg_out when reg_axy,
|
||||
p_reg_i or X"20" when reg_flags,
|
||||
pcl when reg_pcl,
|
||||
pch when reg_pch,
|
||||
mem_data when shift_res,
|
||||
X"FF" when others;
|
||||
|
||||
selected_idx <= y_reg_i when select_index_y(i_reg_i) else x_reg_i;
|
||||
|
||||
pc_carry <= pc_carry_i;
|
||||
s_reg <= s_reg_i;
|
||||
p_reg <= p_reg_i;
|
||||
i_reg <= i_reg_i;
|
||||
a_reg <= a_reg_i;
|
||||
x_reg <= x_reg_i;
|
||||
y_reg <= y_reg_i;
|
||||
d_reg <= dreg;
|
||||
pc_out <= pch & pcl;
|
||||
end gideon;
|
||||
60
cores/c16/1541ultimate2cpu/shifter.vhd
Normal file
60
cores/c16/1541ultimate2cpu/shifter.vhd
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity shifter is
|
||||
port (
|
||||
operation : in std_logic_vector(2 downto 0);
|
||||
enable : in std_logic := '1'; -- instruction(1)
|
||||
|
||||
c_in : in std_logic;
|
||||
n_in : in std_logic;
|
||||
z_in : in std_logic;
|
||||
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
|
||||
c_out : out std_logic;
|
||||
n_out : out std_logic;
|
||||
z_out : out std_logic;
|
||||
|
||||
data_out : out std_logic_vector(7 downto 0) := X"00");
|
||||
|
||||
end shifter;
|
||||
|
||||
architecture gideon of shifter is
|
||||
signal data_out_i : std_logic_vector(7 downto 0) := X"00";
|
||||
signal zero : std_logic := '0';
|
||||
signal oper4 : std_logic_vector(3 downto 0) := X"0";
|
||||
begin
|
||||
-- ASL $nn ROL $nn LSR $nn ROR $nn STX $nn LDX $nn DEC $nn INC $nn
|
||||
|
||||
with operation select data_out_i <=
|
||||
data_in(6 downto 0) & '0' when "000",
|
||||
data_in(6 downto 0) & c_in when "001",
|
||||
'0' & data_in(7 downto 1) when "010",
|
||||
c_in & data_in(7 downto 1) when "011",
|
||||
data_in - 1 when "110",
|
||||
data_in + 1 when "111",
|
||||
data_in when others;
|
||||
|
||||
zero <= '1' when data_out_i = X"00" else '0';
|
||||
|
||||
oper4 <= enable & operation;
|
||||
|
||||
with oper4 select c_out <=
|
||||
data_in(7) when "1000" | "1001",
|
||||
data_in(0) when "1010" | "1011",
|
||||
c_in when others;
|
||||
|
||||
with oper4 select z_out <=
|
||||
zero when "1000" | "1001" | "1010" | "1011" | "1101" | "1110" | "1111",
|
||||
z_in when others;
|
||||
|
||||
with oper4 select n_out <=
|
||||
data_out_i(7) when "1000" | "1001" | "1010" | "1011" | "1101" | "1110" | "1111",
|
||||
n_in when others;
|
||||
|
||||
data_out <= data_out_i when enable='1' else data_in;
|
||||
|
||||
end gideon;
|
||||
@@ -112,8 +112,7 @@ begin
|
||||
reset_n <= not reset;
|
||||
|
||||
process (clk_32M, reset)
|
||||
variable count : std_logic_vector(8 downto 0) := (others => '0');
|
||||
alias hcnt : std_logic_vector(1 downto 0) is count(4 downto 3);
|
||||
variable count : std_logic_vector(4 downto 0) := (others => '0');
|
||||
begin
|
||||
if rising_edge(clk_32M) then
|
||||
-- generate 1MHz pulse
|
||||
@@ -122,17 +121,12 @@ begin
|
||||
if count(4 downto 0) = "01000" then
|
||||
clk_1M_pulse <= '1';
|
||||
end if;
|
||||
-- if count = "000100000" then -- DAR divide by 33 (otherwise real c64 miss EOI acknowledge)
|
||||
if count = "000011111" then -- TH - C16 MiST: zero after 31, restart from 1
|
||||
count := (0 => '1', others => '0');
|
||||
else -- DAR
|
||||
count := std_logic_vector(unsigned(count) + 1);
|
||||
end if; -- DAR
|
||||
count := std_logic_vector(unsigned(count) + 1);
|
||||
end if;
|
||||
p2_h <= not hcnt(1);
|
||||
p2_h <= not count(4);
|
||||
|
||||
-- for original m6522 design that requires a real clock
|
||||
-- clk_4M_en <= not count(2);
|
||||
-- clk_4M_en <= not count(2);
|
||||
|
||||
-- for version 002 with clock enable
|
||||
if count(2 downto 0) = "111" then
|
||||
@@ -159,10 +153,10 @@ begin
|
||||
-- hook up UC1 ports
|
||||
--
|
||||
|
||||
uc1_cs1 <= cpu_a(11);
|
||||
uc1_cs1 <= '1';
|
||||
--uc1_cs2_n: see decode logic above
|
||||
-- CA1
|
||||
--uc1_ca1_i <= not sb_atn_in; -- DAR comment : synched with clk_4M_en see below
|
||||
uc1_ca1_i <= not sb_atn_in;
|
||||
-- PA
|
||||
uc1_pa_i(0) <= tr00_sense_n;
|
||||
uc1_pa_i(7 downto 1) <= (others => '0'); -- NC
|
||||
@@ -187,7 +181,7 @@ begin
|
||||
-- hook up UC3 ports
|
||||
--
|
||||
|
||||
uc3_cs1 <= cpu_a(11);
|
||||
uc3_cs1 <= '1';
|
||||
--uc3_cs2_n: see decode logic above
|
||||
-- CA1
|
||||
uc3_ca1_i <= cpu_so_n; -- byte ready gated with soe
|
||||
@@ -223,54 +217,19 @@ begin
|
||||
-- external connections
|
||||
-- ATN never driven by the 1541
|
||||
sb_atn_oe <= '0';
|
||||
|
||||
|
||||
-- DAR
|
||||
process (clk_32M)
|
||||
begin
|
||||
if rising_edge(clk_32M) then
|
||||
if clk_4M_en = '1' then
|
||||
uc1_ca1_i <= not sb_atn_in; -- DAR sample external atn to ensure not missing edge within VIA
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clk_32M, cpu_sync)
|
||||
begin
|
||||
if rising_edge(clk_32M) then
|
||||
if cpu_sync = '1' then
|
||||
dbg_adr_fetch <= cpu_a(15 downto 0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
dbg_cpu_irq <= cpu_irq_n;
|
||||
-- DAR
|
||||
|
||||
cpu_inst : entity work.T65
|
||||
port map
|
||||
(
|
||||
Mode => "00", -- 6502
|
||||
Res_n => reset_n,
|
||||
Enable => clk_1M_pulse,
|
||||
Clk => clk_32M,
|
||||
Rdy => '1',
|
||||
Abort_n => '1',
|
||||
IRQ_n => cpu_irq_n,
|
||||
NMI_n => '1',
|
||||
SO_n => cpu_so_n,
|
||||
R_W_n => cpu_rw_n,
|
||||
Sync => cpu_sync, -- open -- DAR
|
||||
EF => open,
|
||||
MF => open,
|
||||
XF => open,
|
||||
ML_n => open,
|
||||
VP_n => open,
|
||||
VDA => open,
|
||||
VPA => open,
|
||||
A => cpu_a,
|
||||
DI => cpu_di,
|
||||
DO => cpu_do
|
||||
);
|
||||
cpu: work.proc_core
|
||||
port map(
|
||||
reset => reset,
|
||||
clock_en => clk_1M_pulse,
|
||||
clock => clk_32M,
|
||||
so_n => cpu_so_n,
|
||||
irq_n => cpu_irq_n,
|
||||
read_write_n => cpu_rw_n,
|
||||
addr_out => cpu_a(16 downto 0),
|
||||
data_in => cpu_di,
|
||||
data_out => cpu_do
|
||||
);
|
||||
|
||||
rom_inst : entity work.sprom
|
||||
generic map
|
||||
|
||||
@@ -167,7 +167,7 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
||||
# SignalTap II Assignments
|
||||
# ========================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp2.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
@@ -350,7 +350,21 @@ set_global_assignment -name VHDL_FILE c1541/sprom.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/c1541_sd.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/c1541_logic.vhd
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE c1541/mist_sd_card.sv
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/shifter.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/proc_registers.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/proc_interrupt.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/proc_core.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/proc_control.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/pkg_6502_opcodes.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/pkg_6502_defs.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/pkg_6502_decode.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/implied.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/data_oper.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/cpu6502.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/bit_cpx_cpy.vhd
|
||||
set_global_assignment -name VHDL_FILE 1541ultimate2cpu/alu.vhd
|
||||
set_global_assignment -name VHDL_FILE t65/T65_Pack.vhd
|
||||
set_global_assignment -name VHDL_FILE t65/T65_MCode.vhd
|
||||
set_global_assignment -name VHDL_FILE t65/T65_ALU.vhd
|
||||
set_global_assignment -name VHDL_FILE t65/T65.vhd
|
||||
set_global_assignment -name VHDL_FILE t65/T65.vhd
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/stp2.stp
|
||||
Reference in New Issue
Block a user