1
0
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:
Gyorgy Szombathelyi
2018-08-31 23:51:06 +02:00
parent 190f592876
commit 215dad9602
15 changed files with 2105 additions and 62 deletions

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View 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;

View File

@@ -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

View File

@@ -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