mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-05 15:44:40 +00:00
Merge pull request #63 from gyurco/c16
C16 - 1541, prg loader fixes, rom replacement support
This commit is contained in:
@@ -1,137 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,66 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,55 +0,0 @@
|
||||
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;
|
||||
@@ -1,193 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,114 +0,0 @@
|
||||
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;
|
||||
@@ -1,248 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,88 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -1,472 +0,0 @@
|
||||
|
||||
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;
|
||||
|
||||
@@ -1,233 +0,0 @@
|
||||
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;
|
||||
@@ -1,83 +0,0 @@
|
||||
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;
|
||||
@@ -1,303 +0,0 @@
|
||||
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;
|
||||
@@ -1,60 +0,0 @@
|
||||
|
||||
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;
|
||||
@@ -37,6 +37,8 @@ module basic_rom(
|
||||
input wire clk,
|
||||
input wire [13:0] address_in,
|
||||
output wire [7:0] data_out,
|
||||
input wire [7:0] data_in,
|
||||
input wire wr,
|
||||
input wire cs
|
||||
);
|
||||
|
||||
@@ -46,9 +48,13 @@ reg [7:0] data;
|
||||
reg cs_prev=1'b1;
|
||||
wire enable;
|
||||
|
||||
always@(posedge clk)
|
||||
always@(posedge clk) begin
|
||||
if (wr)
|
||||
basic[address_in] <= data_in;
|
||||
|
||||
if(enable)
|
||||
data<=basic[address_in];
|
||||
end
|
||||
|
||||
always@(posedge clk)
|
||||
cs_prev<=cs;
|
||||
|
||||
@@ -40,6 +40,11 @@ entity c1541_logic is
|
||||
wps_n : in std_logic; -- write-protect sense
|
||||
tr00_sense_n : in std_logic; -- track 0 sense (unused?)
|
||||
act : out std_logic; -- activity LED
|
||||
|
||||
c1541rom_clk : in std_logic;
|
||||
c1541rom_addr : in std_logic_vector(13 downto 0);
|
||||
c1541rom_data : in std_logic_vector(7 downto 0);
|
||||
c1541rom_wr : in std_logic;
|
||||
|
||||
dbg_adr_fetch : out std_logic_vector(15 downto 0); -- dbg DAR
|
||||
dbg_cpu_irq : out std_logic -- dbg DAR
|
||||
@@ -50,8 +55,8 @@ architecture SYN of c1541_logic is
|
||||
|
||||
-- clocks, reset
|
||||
signal reset_n : std_logic;
|
||||
signal clk_4M_en : std_logic;
|
||||
signal p2_h : std_logic;
|
||||
signal p2_h_r : std_logic;
|
||||
signal p2_h_f : std_logic;
|
||||
signal clk_1M_pulse : std_logic;
|
||||
|
||||
-- cpu signals
|
||||
@@ -107,6 +112,14 @@ architecture SYN of c1541_logic is
|
||||
signal atn : std_logic; -- attention
|
||||
signal soe : std_logic; -- set overflow enable
|
||||
|
||||
signal uc1_pb_oe : std_logic_vector(7 downto 0);
|
||||
signal uc1_irq : std_logic;
|
||||
signal uc3_irq : std_logic;
|
||||
signal uc3_ca2_oe : std_logic;
|
||||
signal uc3_cb2_oe : std_logic;
|
||||
signal uc3_pa_oe : std_logic_vector(7 downto 0);
|
||||
signal uc3_pb_oe : std_logic_vector(7 downto 0);
|
||||
|
||||
begin
|
||||
|
||||
reset_n <= not reset;
|
||||
@@ -115,25 +128,12 @@ begin
|
||||
variable count : std_logic_vector(4 downto 0) := (others => '0');
|
||||
begin
|
||||
if rising_edge(clk_32M) then
|
||||
-- generate 1MHz pulse
|
||||
clk_1M_pulse <= '0';
|
||||
--if count(4 downto 0) = "00111" then
|
||||
if count(4 downto 0) = "01000" then
|
||||
clk_1M_pulse <= '1';
|
||||
end if;
|
||||
count := std_logic_vector(unsigned(count) + 1);
|
||||
count := std_logic_vector(unsigned(count) + 1);
|
||||
end if;
|
||||
p2_h <= not count(4);
|
||||
|
||||
-- for original m6522 design that requires a real clock
|
||||
-- clk_4M_en <= not count(2);
|
||||
|
||||
-- for version 002 with clock enable
|
||||
if count(2 downto 0) = "111" then
|
||||
clk_4M_en <= '1';
|
||||
else
|
||||
clk_4M_en <= '0';
|
||||
end if;
|
||||
if count = "10000" then clk_1M_pulse <= '1'; else clk_1M_pulse <='0' ; end if;
|
||||
if count = "00000" then p2_h_r <= '1'; else p2_h_r <='0' ; end if;
|
||||
if count = "10000" then p2_h_f <= '1'; else p2_h_f <='0' ; end if;
|
||||
end process;
|
||||
|
||||
-- decode logic
|
||||
@@ -203,7 +203,8 @@ begin
|
||||
--
|
||||
-- CPU connections
|
||||
--
|
||||
cpu_di <= rom_do when rom_cs = '1' else
|
||||
cpu_di <= cpu_do when cpu_rw_n = '0' else
|
||||
rom_do when rom_cs = '1' else
|
||||
ram_do when ram_cs = '1' else
|
||||
uc1_do when (uc1_cs1 = '1' and uc1_cs2_n = '0') else
|
||||
uc3_do when (uc3_cs1 = '1' and uc3_cs2_n = '0') else
|
||||
@@ -218,37 +219,55 @@ begin
|
||||
-- ATN never driven by the 1541
|
||||
sb_atn_oe <= '0';
|
||||
|
||||
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
|
||||
);
|
||||
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
|
||||
);
|
||||
|
||||
rom_inst : entity work.sprom
|
||||
rom_inst : entity work.gen_rom
|
||||
generic map
|
||||
(
|
||||
-- init_file => "../roms/JiffyDOS_C1541.hex", -- DAR tested OK
|
||||
-- init_file => "../roms/25196802.hex",
|
||||
-- init_file => "../roms/25196801.hex",
|
||||
init_file => "../roms/325302-1_901229-03.hex",
|
||||
INIT_FILE => "../roms/325302-1_901229-03.hex",
|
||||
-- init_file => "../roms/1541_c000_01_and_e000_06aa.hex", -- DAR tested OK
|
||||
|
||||
|
||||
numwords_a => 16384,
|
||||
widthad_a => 14
|
||||
DATA_WIDTH => 8,
|
||||
ADDR_WIDTH => 14
|
||||
)
|
||||
port map
|
||||
(
|
||||
clock => clk_32M,
|
||||
address => cpu_a(13 downto 0),
|
||||
q => rom_do
|
||||
rdclock => clk_32M,
|
||||
rdaddress => cpu_a(13 downto 0),
|
||||
q => rom_do,
|
||||
|
||||
wrclock => c1541rom_clk,
|
||||
wraddress => c1541rom_addr,
|
||||
wren => c1541rom_wr,
|
||||
data => c1541rom_data
|
||||
);
|
||||
|
||||
ram_inst : entity work.spram
|
||||
@@ -266,90 +285,78 @@ begin
|
||||
q => ram_do
|
||||
);
|
||||
|
||||
uc1_via6522_inst : entity work.M6522
|
||||
uc1_pb_oe_n <= not uc1_pb_oe;
|
||||
uc1_irq_n <= not uc1_irq;
|
||||
|
||||
uc1_via6522_inst : entity work.via6522
|
||||
port map
|
||||
(
|
||||
I_RS => cpu_a(3 downto 0),
|
||||
I_DATA => cpu_do,
|
||||
O_DATA => uc1_do,
|
||||
O_DATA_OE_L => uc1_do_oe_n,
|
||||
clock => clk_32M,
|
||||
rising => p2_h_r,
|
||||
falling => p2_h_f,
|
||||
reset => not reset_n,
|
||||
|
||||
I_RW_L => cpu_rw_n,
|
||||
I_CS1 => uc1_cs1,
|
||||
I_CS2_L => uc1_cs2_n,
|
||||
addr => cpu_a(3 downto 0),
|
||||
wen => not cpu_rw_n and not uc1_cs2_n,
|
||||
ren => cpu_rw_n and not uc1_cs2_n,
|
||||
data_in => cpu_do,
|
||||
data_out => uc1_do,
|
||||
|
||||
O_IRQ_L => uc1_irq_n,
|
||||
port_a_i => uc1_pa_i,
|
||||
|
||||
-- port a
|
||||
I_CA1 => uc1_ca1_i,
|
||||
I_CA2 => '0',
|
||||
O_CA2 => open,
|
||||
O_CA2_OE_L => open,
|
||||
port_b_o => uc1_pb_o,
|
||||
port_b_t => uc1_pb_oe,
|
||||
port_b_i => uc1_pb_i,
|
||||
|
||||
I_PA => uc1_pa_i,
|
||||
O_PA => open,
|
||||
O_PA_OE_L => open,
|
||||
ca1_i => uc1_ca1_i,
|
||||
ca2_i => '0',
|
||||
|
||||
-- port b
|
||||
I_CB1 => '0',
|
||||
O_CB1 => open,
|
||||
O_CB1_OE_L => open,
|
||||
cb1_i => '0',
|
||||
cb2_i => '0',
|
||||
|
||||
I_CB2 => '0',
|
||||
O_CB2 => open,
|
||||
O_CB2_OE_L => open,
|
||||
|
||||
I_PB => uc1_pb_i,
|
||||
O_PB => uc1_pb_o,
|
||||
O_PB_OE_L => uc1_pb_oe_n,
|
||||
|
||||
RESET_L => reset_n,
|
||||
CLK => clk_32M,
|
||||
I_P2_H => p2_h, -- high for phase 2 clock ____----__
|
||||
ENA_4 => clk_4M_en -- 4x system clock (4HZ) _-_-_-_-_-
|
||||
irq => uc1_irq
|
||||
);
|
||||
|
||||
uc3_via6522_inst : entity work.M6522
|
||||
uc3_irq_n <= not uc3_irq;
|
||||
uc3_ca2_oe_n <= not uc3_ca2_oe;
|
||||
uc3_cb2_oe_n <= not uc3_cb2_oe;
|
||||
uc3_pa_oe_n <= not uc3_pa_oe;
|
||||
uc3_pb_oe_n <= not uc3_pb_oe;
|
||||
|
||||
uc3_via6522_inst : entity work.via6522
|
||||
port map
|
||||
(
|
||||
I_RS => cpu_a(3 downto 0),
|
||||
I_DATA => cpu_do,
|
||||
O_DATA => uc3_do,
|
||||
O_DATA_OE_L => uc3_do_oe_n,
|
||||
clock => clk_32M,
|
||||
rising => p2_h_r,
|
||||
falling => p2_h_f,
|
||||
reset => not reset_n,
|
||||
|
||||
I_RW_L => cpu_rw_n,
|
||||
I_CS1 => cpu_a(11),
|
||||
I_CS2_L => uc3_cs2_n,
|
||||
addr => cpu_a(3 downto 0),
|
||||
wen => not cpu_rw_n and not uc3_cs2_n,
|
||||
ren => cpu_rw_n and not uc3_cs2_n,
|
||||
data_in => cpu_do,
|
||||
data_out => uc3_do,
|
||||
|
||||
O_IRQ_L => uc3_irq_n,
|
||||
port_a_o => uc3_pa_o,
|
||||
port_a_t => uc3_pa_oe,
|
||||
port_a_i => uc3_pa_i,
|
||||
|
||||
-- port a
|
||||
I_CA1 => uc3_ca1_i,
|
||||
I_CA2 => '0',
|
||||
O_CA2 => uc3_ca2_o,
|
||||
O_CA2_OE_L => uc3_ca2_oe_n,
|
||||
port_b_o => uc3_pb_o,
|
||||
port_b_t => uc3_pb_oe,
|
||||
port_b_i => uc3_pb_i,
|
||||
|
||||
I_PA => uc3_pa_i,
|
||||
O_PA => uc3_pa_o,
|
||||
O_PA_OE_L => uc3_pa_oe_n,
|
||||
ca1_i => uc3_ca1_i,
|
||||
|
||||
-- port b
|
||||
I_CB1 => '0',
|
||||
O_CB1 => open,
|
||||
O_CB1_OE_L => open,
|
||||
ca2_o => uc3_ca2_o,
|
||||
ca2_i => '0',
|
||||
ca2_t => uc3_ca2_oe,
|
||||
|
||||
I_CB2 => '0',
|
||||
O_CB2 => uc3_cb2_o,
|
||||
O_CB2_OE_L => uc3_cb2_oe_n,
|
||||
cb1_i => '0',
|
||||
|
||||
I_PB => uc3_pb_i,
|
||||
O_PB => uc3_pb_o,
|
||||
O_PB_OE_L => uc3_pb_oe_n,
|
||||
cb2_o => uc3_cb2_o,
|
||||
cb2_i => '0',
|
||||
cb2_t => uc3_cb2_oe,
|
||||
|
||||
RESET_L => reset_n,
|
||||
CLK => clk_32M,
|
||||
I_P2_H => p2_h, -- high for phase 2 clock ____----__
|
||||
ENA_4 => clk_4M_en -- 4x system clock (4HZ) _-_-_-_-_-
|
||||
irq => uc3_irq
|
||||
);
|
||||
|
||||
end SYN;
|
||||
|
||||
@@ -56,6 +56,11 @@ port(
|
||||
|
||||
led : out std_logic;
|
||||
|
||||
c1541rom_clk : in std_logic;
|
||||
c1541rom_addr : in std_logic_vector(13 downto 0);
|
||||
c1541rom_data : in std_logic_vector(7 downto 0);
|
||||
c1541rom_wr : in std_logic;
|
||||
|
||||
dbg_track_num_dbl : out std_logic_vector(6 downto 0);
|
||||
dbg_sd_busy : out std_logic;
|
||||
dbg_sd_state : out std_logic_vector(7 downto 0);
|
||||
@@ -171,7 +176,12 @@ begin
|
||||
wps_n => '1', -- write-protect sense (0 = protected)
|
||||
tr00_sense_n => '1', -- track 0 sense (unused?)
|
||||
act => act, -- activity LED
|
||||
|
||||
|
||||
c1541rom_clk => c1541rom_clk,
|
||||
c1541rom_addr => c1541rom_addr,
|
||||
c1541rom_data => c1541rom_data,
|
||||
c1541rom_wr => c1541rom_wr,
|
||||
|
||||
dbg_adr_fetch => dbg_adr_fetch,
|
||||
dbg_cpu_irq => open
|
||||
);
|
||||
|
||||
@@ -66,6 +66,8 @@ signal gcr_byte : std_logic_vector(7 downto 0);
|
||||
signal mode_r1 : std_logic;
|
||||
signal mode_r2 : std_logic;
|
||||
|
||||
signal old_track : std_logic_vector(5 downto 0);
|
||||
|
||||
type gcr_array is array(0 to 15) of std_logic_vector(4 downto 0);
|
||||
|
||||
signal gcr_lut : gcr_array :=
|
||||
@@ -193,7 +195,13 @@ end process;
|
||||
|
||||
read_write_process : process (clk32, bit_clk_en)
|
||||
begin
|
||||
if rising_edge(clk32) and bit_clk_en = '1' then
|
||||
if rising_edge(clk32) then
|
||||
|
||||
old_track <= track_num;
|
||||
|
||||
if old_track /= track_num then
|
||||
sector <= (others => '0'); --reset sector number on track change
|
||||
else if bit_clk_en = '1' then
|
||||
|
||||
mode_r2 <= mode;
|
||||
if mode = '1' then autorise_write <= '0'; end if;
|
||||
@@ -312,7 +320,9 @@ begin
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end struct;
|
||||
|
||||
65
cores/c16/c1541/gen_rom.vhd
Normal file
65
cores/c16/c1541/gen_rom.vhd
Normal file
@@ -0,0 +1,65 @@
|
||||
-- altera message_off 10306
|
||||
|
||||
library ieee;
|
||||
use IEEE.std_logic_1164.all;
|
||||
use IEEE.std_logic_unsigned.ALL;
|
||||
use IEEE.numeric_std.all;
|
||||
|
||||
entity gen_rom is
|
||||
|
||||
generic
|
||||
(
|
||||
INIT_FILE : string := "";
|
||||
ADDR_WIDTH : natural := 14;
|
||||
DATA_WIDTH : natural := 8
|
||||
);
|
||||
|
||||
port
|
||||
(
|
||||
wrclock : in std_logic;
|
||||
wraddress : in std_logic_vector((ADDR_WIDTH - 1) downto 0) := (others => '0');
|
||||
data : in std_logic_vector((DATA_WIDTH - 1) downto 0) := (others => '0');
|
||||
wren : in std_logic := '0';
|
||||
|
||||
rdclock : in std_logic;
|
||||
rdaddress : in std_logic_vector((ADDR_WIDTH - 1) downto 0);
|
||||
q : out std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
cs : in std_logic := '1'
|
||||
);
|
||||
|
||||
end gen_rom;
|
||||
|
||||
architecture rtl of gen_rom is
|
||||
|
||||
subtype word_t is std_logic_vector((DATA_WIDTH-1) downto 0);
|
||||
type memory_t is array(2**ADDR_WIDTH-1 downto 0) of word_t;
|
||||
|
||||
shared variable ram : memory_t;
|
||||
|
||||
attribute ram_init_file : string;
|
||||
attribute ram_init_file of ram : variable is INIT_FILE;
|
||||
|
||||
signal q0 : std_logic_vector((DATA_WIDTH - 1) downto 0);
|
||||
|
||||
|
||||
begin
|
||||
|
||||
q<= q0 when cs = '1' else (others => '1');
|
||||
|
||||
-- WR Port
|
||||
process(wrclock) begin
|
||||
if(rising_edge(wrclock)) then
|
||||
if(wren = '1') then
|
||||
ram(to_integer(unsigned(wraddress))) := data;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- RD Port
|
||||
process(rdclock) begin
|
||||
if(rising_edge(rdclock)) then
|
||||
q0 <= ram(to_integer(unsigned(rdaddress)));
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end rtl;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,77 +0,0 @@
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.all;
|
||||
|
||||
LIBRARY altera_mf;
|
||||
USE altera_mf.all;
|
||||
|
||||
ENTITY sprom IS
|
||||
GENERIC
|
||||
(
|
||||
init_file : string := "";
|
||||
numwords_a : natural := 0; -- not used any more
|
||||
widthad_a : natural;
|
||||
width_a : natural := 8;
|
||||
outdata_reg_a : string := "UNREGISTERED"
|
||||
);
|
||||
PORT
|
||||
(
|
||||
address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
clock : IN STD_LOGIC ;
|
||||
q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END sprom;
|
||||
|
||||
|
||||
ARCHITECTURE SYN OF sprom IS
|
||||
|
||||
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
|
||||
|
||||
COMPONENT altsyncram
|
||||
GENERIC (
|
||||
clock_enable_input_a : STRING;
|
||||
clock_enable_output_a : STRING;
|
||||
init_file : STRING;
|
||||
intended_device_family : STRING;
|
||||
lpm_hint : STRING;
|
||||
lpm_type : STRING;
|
||||
numwords_a : NATURAL;
|
||||
operation_mode : STRING;
|
||||
outdata_aclr_a : STRING;
|
||||
outdata_reg_a : STRING;
|
||||
widthad_a : NATURAL;
|
||||
width_a : NATURAL;
|
||||
width_byteena_a : NATURAL
|
||||
);
|
||||
PORT (
|
||||
clock0 : IN STD_LOGIC ;
|
||||
address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
|
||||
q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
BEGIN
|
||||
q <= sub_wire0(width_a-1 DOWNTO 0);
|
||||
|
||||
altsyncram_component : altsyncram
|
||||
GENERIC MAP (
|
||||
clock_enable_input_a => "BYPASS",
|
||||
clock_enable_output_a => "BYPASS",
|
||||
init_file => init_file,
|
||||
intended_device_family => "Cyclone II",
|
||||
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
|
||||
lpm_type => "altsyncram",
|
||||
numwords_a => 2**widthad_a,
|
||||
operation_mode => "ROM",
|
||||
outdata_aclr_a => "NONE",
|
||||
outdata_reg_a => outdata_reg_a,
|
||||
widthad_a => widthad_a,
|
||||
width_a => width_a,
|
||||
width_byteena_a => 1
|
||||
)
|
||||
PORT MAP (
|
||||
clock0 => clock,
|
||||
address_a => address,
|
||||
q_a => sub_wire0
|
||||
);
|
||||
|
||||
END SYN;
|
||||
678
cores/c16/c1541/via6522.vhd
Normal file
678
cores/c16/c1541/via6522.vhd
Normal file
@@ -0,0 +1,678 @@
|
||||
-------------------------------------------------------------------------------
|
||||
--
|
||||
-- (C) COPYRIGHT 2007-2017, Gideon's Logic Architectures
|
||||
--
|
||||
-------------------------------------------------------------------------------
|
||||
-- Title : VIA 6522
|
||||
-------------------------------------------------------------------------------
|
||||
-- Author : Gideon Zweijtzer <gideon.zweijtzer@gmail.com>
|
||||
-------------------------------------------------------------------------------
|
||||
-- Description: This module implements the 6522 VIA chip.
|
||||
-- Please note: A LOT OF REVERSE ENGINEERING has been done to
|
||||
-- make this module as accurate as it is now. Please do not copy
|
||||
-- (use in your own projects) without written permission of the
|
||||
-- author.
|
||||
-------------------------------------------------------------------------------
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
entity via6522 is
|
||||
port (
|
||||
clock : in std_logic;
|
||||
rising : in std_logic;
|
||||
falling : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
addr : in std_logic_vector(3 downto 0);
|
||||
wen : in std_logic;
|
||||
ren : in std_logic;
|
||||
data_in : in std_logic_vector(7 downto 0);
|
||||
data_out : out std_logic_vector(7 downto 0);
|
||||
|
||||
phi2_ref : out std_logic;
|
||||
|
||||
-- pio --
|
||||
port_a_o : out std_logic_vector(7 downto 0);
|
||||
port_a_t : out std_logic_vector(7 downto 0);
|
||||
port_a_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
port_b_o : out std_logic_vector(7 downto 0);
|
||||
port_b_t : out std_logic_vector(7 downto 0);
|
||||
port_b_i : in std_logic_vector(7 downto 0);
|
||||
|
||||
-- handshake pins
|
||||
ca1_i : in std_logic;
|
||||
|
||||
ca2_o : out std_logic;
|
||||
ca2_i : in std_logic;
|
||||
ca2_t : out std_logic;
|
||||
|
||||
cb1_o : out std_logic;
|
||||
cb1_i : in std_logic;
|
||||
cb1_t : out std_logic;
|
||||
|
||||
cb2_o : out std_logic;
|
||||
cb2_i : in std_logic;
|
||||
cb2_t : out std_logic;
|
||||
|
||||
irq : out std_logic );
|
||||
|
||||
end via6522;
|
||||
|
||||
architecture Gideon of via6522 is
|
||||
|
||||
type pio_t is
|
||||
record
|
||||
pra : std_logic_vector(7 downto 0);
|
||||
ddra : std_logic_vector(7 downto 0);
|
||||
prb : std_logic_vector(7 downto 0);
|
||||
ddrb : std_logic_vector(7 downto 0);
|
||||
end record;
|
||||
|
||||
constant pio_default : pio_t := (others => (others => '0'));
|
||||
constant latch_reset_pattern : std_logic_vector(15 downto 0) := X"5550";
|
||||
|
||||
signal last_data : std_logic_vector(7 downto 0) := X"55";
|
||||
|
||||
signal pio_i : pio_t;
|
||||
signal port_a_c : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal port_b_c : std_logic_vector(7 downto 0) := (others => '0');
|
||||
|
||||
signal irq_mask : std_logic_vector(6 downto 0) := (others => '0');
|
||||
signal irq_flags : std_logic_vector(6 downto 0) := (others => '0');
|
||||
signal irq_events : std_logic_vector(6 downto 0) := (others => '0');
|
||||
signal irq_out : std_logic;
|
||||
|
||||
signal timer_a_latch : std_logic_vector(15 downto 0) := latch_reset_pattern;
|
||||
signal timer_b_latch : std_logic_vector(15 downto 0) := latch_reset_pattern;
|
||||
signal timer_a_count : std_logic_vector(15 downto 0) := latch_reset_pattern;
|
||||
signal timer_b_count : std_logic_vector(15 downto 0) := latch_reset_pattern;
|
||||
signal timer_a_out : std_logic;
|
||||
signal timer_b_tick : std_logic;
|
||||
|
||||
signal acr, pcr : std_logic_vector(7 downto 0) := X"00";
|
||||
signal shift_reg : std_logic_vector(7 downto 0) := X"00";
|
||||
signal serport_en : std_logic;
|
||||
signal ser_cb2_o : std_logic;
|
||||
signal hs_cb2_o : std_logic;
|
||||
signal trigger_serial: std_logic;
|
||||
|
||||
alias ca2_event : std_logic is irq_events(0);
|
||||
alias ca1_event : std_logic is irq_events(1);
|
||||
alias serial_event : std_logic is irq_events(2);
|
||||
alias cb2_event : std_logic is irq_events(3);
|
||||
alias cb1_event : std_logic is irq_events(4);
|
||||
alias timer_b_event : std_logic is irq_events(5);
|
||||
alias timer_a_event : std_logic is irq_events(6);
|
||||
|
||||
alias ca2_flag : std_logic is irq_flags(0);
|
||||
alias ca1_flag : std_logic is irq_flags(1);
|
||||
alias serial_flag : std_logic is irq_flags(2);
|
||||
alias cb2_flag : std_logic is irq_flags(3);
|
||||
alias cb1_flag : std_logic is irq_flags(4);
|
||||
alias timer_b_flag : std_logic is irq_flags(5);
|
||||
alias timer_a_flag : std_logic is irq_flags(6);
|
||||
|
||||
alias tmr_a_output_en : std_logic is acr(7);
|
||||
alias tmr_a_freerun : std_logic is acr(6);
|
||||
alias tmr_b_count_mode : std_logic is acr(5);
|
||||
alias shift_dir : std_logic is acr(4);
|
||||
alias shift_clk_sel : std_logic_vector(1 downto 0) is acr(3 downto 2);
|
||||
alias shift_mode_control : std_logic_vector(2 downto 0) is acr(4 downto 2);
|
||||
alias pb_latch_en : std_logic is acr(1);
|
||||
alias pa_latch_en : std_logic is acr(0);
|
||||
|
||||
alias cb2_is_output : std_logic is pcr(7);
|
||||
alias cb2_edge_select : std_logic is pcr(6); -- for when CB2 is input
|
||||
alias cb2_no_irq_clr : std_logic is pcr(5); -- for when CB2 is input
|
||||
alias cb2_out_mode : std_logic_vector(1 downto 0) is pcr(6 downto 5);
|
||||
alias cb1_edge_select : std_logic is pcr(4);
|
||||
|
||||
alias ca2_is_output : std_logic is pcr(3);
|
||||
alias ca2_edge_select : std_logic is pcr(2); -- for when CA2 is input
|
||||
alias ca2_no_irq_clr : std_logic is pcr(1); -- for when CA2 is input
|
||||
alias ca2_out_mode : std_logic_vector(1 downto 0) is pcr(2 downto 1);
|
||||
alias ca1_edge_select : std_logic is pcr(0);
|
||||
|
||||
signal ira, irb : std_logic_vector(7 downto 0) := (others => '0');
|
||||
|
||||
signal write_t1c_h : std_logic;
|
||||
signal write_t2c_h : std_logic;
|
||||
|
||||
signal ca1_c, ca2_c : std_logic;
|
||||
signal cb1_c, cb2_c : std_logic;
|
||||
signal ca1_d, ca2_d : std_logic;
|
||||
signal cb1_d, cb2_d : std_logic;
|
||||
|
||||
signal ca2_handshake_o : std_logic;
|
||||
signal ca2_pulse_o : std_logic;
|
||||
signal cb2_handshake_o : std_logic;
|
||||
signal cb2_pulse_o : std_logic;
|
||||
signal shift_active : std_logic;
|
||||
begin
|
||||
irq <= irq_out;
|
||||
|
||||
write_t1c_h <= '1' when addr = X"5" and wen='1' and falling = '1' else '0';
|
||||
write_t2c_h <= '1' when addr = X"9" and wen='1' and falling = '1' else '0';
|
||||
|
||||
ca1_event <= (ca1_c xor ca1_d) and (ca1_d xor ca1_edge_select);
|
||||
ca2_event <= (ca2_c xor ca2_d) and (ca2_d xor ca2_edge_select);
|
||||
cb1_event <= (cb1_c xor cb1_d) and (cb1_d xor cb1_edge_select);
|
||||
cb2_event <= (cb2_c xor cb2_d) and (cb2_d xor cb2_edge_select);
|
||||
|
||||
ca2_t <= ca2_is_output;
|
||||
cb2_t <= cb2_is_output when serport_en='0' else shift_dir;
|
||||
cb2_o <= hs_cb2_o when serport_en='0' else ser_cb2_o;
|
||||
|
||||
with ca2_out_mode select ca2_o <=
|
||||
ca2_handshake_o when "00",
|
||||
ca2_pulse_o when "01",
|
||||
'0' when "10",
|
||||
'1' when others;
|
||||
|
||||
with cb2_out_mode select hs_cb2_o <=
|
||||
cb2_handshake_o when "00",
|
||||
cb2_pulse_o when "01",
|
||||
'0' when "10",
|
||||
'1' when others;
|
||||
|
||||
process(irq_flags, irq_mask)
|
||||
begin
|
||||
if (irq_flags and irq_mask) = "0000000" then
|
||||
irq_out <= '0';
|
||||
else
|
||||
irq_out <= '1';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if rising = '1' then
|
||||
phi2_ref <= '1';
|
||||
elsif falling = '1' then
|
||||
phi2_ref <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
-- CA1/CA2/CB1/CB2 edge detect flipflops
|
||||
ca1_c <= To_X01(ca1_i);
|
||||
ca2_c <= To_X01(ca2_i);
|
||||
cb1_c <= To_X01(cb1_i);
|
||||
cb2_c <= To_X01(cb2_i);
|
||||
|
||||
ca1_d <= ca1_c;
|
||||
ca2_d <= ca2_c;
|
||||
cb1_d <= cb1_c;
|
||||
cb2_d <= cb2_c;
|
||||
|
||||
-- input registers
|
||||
port_a_c <= port_a_i;
|
||||
port_b_c <= port_b_i;
|
||||
|
||||
-- input latch emulation
|
||||
if pa_latch_en = '0' or ca1_event = '1' then
|
||||
ira <= port_a_c;
|
||||
end if;
|
||||
|
||||
if pb_latch_en = '0' or cb1_event = '1' then
|
||||
irb <= port_b_c;
|
||||
end if;
|
||||
|
||||
-- CA2 logic
|
||||
if ca1_event = '1' then
|
||||
ca2_handshake_o <= '1';
|
||||
elsif (ren = '1' or wen = '1') and addr = X"1" and falling = '1' then
|
||||
ca2_handshake_o <= '0';
|
||||
end if;
|
||||
|
||||
if falling = '1' then
|
||||
if (ren = '1' or wen = '1') and addr = X"1" then
|
||||
ca2_pulse_o <= '0';
|
||||
else
|
||||
ca2_pulse_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- CB2 logic
|
||||
if cb1_event = '1' then
|
||||
cb2_handshake_o <= '1';
|
||||
elsif (ren = '1' or wen = '1') and addr = X"0" and falling = '1' then
|
||||
cb2_handshake_o <= '0';
|
||||
end if;
|
||||
|
||||
if falling = '1' then
|
||||
if (ren = '1' or wen = '1') and addr = X"0" then
|
||||
cb2_pulse_o <= '0';
|
||||
else
|
||||
cb2_pulse_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- Interrupt logic
|
||||
irq_flags <= irq_flags or irq_events;
|
||||
|
||||
if falling = '1' then
|
||||
trigger_serial <= '0';
|
||||
end if;
|
||||
|
||||
-- Writes --
|
||||
if wen='1' and falling = '1' then
|
||||
last_data <= data_in;
|
||||
case addr is
|
||||
when X"0" => -- ORB
|
||||
pio_i.prb <= data_in;
|
||||
if cb2_no_irq_clr='0' then
|
||||
cb2_flag <= '0';
|
||||
end if;
|
||||
cb1_flag <= '0';
|
||||
|
||||
when X"1" => -- ORA
|
||||
pio_i.pra <= data_in;
|
||||
if ca2_no_irq_clr='0' then
|
||||
ca2_flag <= '0';
|
||||
end if;
|
||||
ca1_flag <= '0';
|
||||
|
||||
when X"2" => -- DDRB
|
||||
pio_i.ddrb <= data_in;
|
||||
|
||||
when X"3" => -- DDRA
|
||||
pio_i.ddra <= data_in;
|
||||
|
||||
when X"4" => -- TA LO counter (write=latch)
|
||||
timer_a_latch(7 downto 0) <= data_in;
|
||||
|
||||
when X"5" => -- TA HI counter
|
||||
timer_a_latch(15 downto 8) <= data_in;
|
||||
timer_a_flag <= '0';
|
||||
|
||||
when X"6" => -- TA LO latch
|
||||
timer_a_latch(7 downto 0) <= data_in;
|
||||
|
||||
when X"7" => -- TA HI latch
|
||||
timer_a_latch(15 downto 8) <= data_in;
|
||||
timer_a_flag <= '0';
|
||||
|
||||
when X"8" => -- TB LO latch
|
||||
timer_b_latch(7 downto 0) <= data_in;
|
||||
|
||||
when X"9" => -- TB HI counter
|
||||
timer_b_flag <= '0';
|
||||
|
||||
when X"A" => -- Serial port
|
||||
serial_flag <= '0';
|
||||
if shift_active = '0' then
|
||||
trigger_serial <= '1';
|
||||
end if;
|
||||
|
||||
when X"B" => -- ACR (Auxiliary Control Register)
|
||||
acr <= data_in;
|
||||
|
||||
when X"C" => -- PCR (Peripheral Control Register)
|
||||
pcr <= data_in;
|
||||
|
||||
when X"D" => -- IFR
|
||||
irq_flags <= irq_flags and not data_in(6 downto 0);
|
||||
|
||||
when X"E" => -- IER
|
||||
if data_in(7)='1' then -- set
|
||||
irq_mask <= irq_mask or data_in(6 downto 0);
|
||||
else -- clear
|
||||
irq_mask <= irq_mask and not data_in(6 downto 0);
|
||||
end if;
|
||||
|
||||
when X"F" => -- ORA no handshake
|
||||
pio_i.pra <= data_in;
|
||||
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- Reads - Output only --
|
||||
data_out <= X"00";
|
||||
case addr is
|
||||
when X"0" => -- ORB
|
||||
--Port B reads its own output register for pins set to output.
|
||||
data_out <= (pio_i.prb and pio_i.ddrb) or (irb and not pio_i.ddrb);
|
||||
when X"1" => -- ORA
|
||||
data_out <= ira;
|
||||
when X"2" => -- DDRB
|
||||
data_out <= pio_i.ddrb;
|
||||
when X"3" => -- DDRA
|
||||
data_out <= pio_i.ddra;
|
||||
when X"4" => -- TA LO counter
|
||||
data_out <= timer_a_count(7 downto 0);
|
||||
when X"5" => -- TA HI counter
|
||||
data_out <= timer_a_count(15 downto 8);
|
||||
when X"6" => -- TA LO latch
|
||||
data_out <= timer_a_latch(7 downto 0);
|
||||
when X"7" => -- TA HI latch
|
||||
data_out <= timer_a_latch(15 downto 8);
|
||||
when X"8" => -- TA LO counter
|
||||
data_out <= timer_b_count(7 downto 0);
|
||||
when X"9" => -- TA HI counter
|
||||
data_out <= timer_b_count(15 downto 8);
|
||||
when X"A" => -- SR
|
||||
data_out <= shift_reg;
|
||||
when X"B" => -- ACR
|
||||
data_out <= acr;
|
||||
when X"C" => -- PCR
|
||||
data_out <= pcr;
|
||||
when X"D" => -- IFR
|
||||
data_out <= irq_out & irq_flags;
|
||||
when X"E" => -- IER
|
||||
data_out <= '0' & irq_mask;
|
||||
when X"F" => -- ORA
|
||||
data_out <= ira;
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
|
||||
-- Read actions --
|
||||
if ren = '1' and falling = '1' then
|
||||
case addr is
|
||||
when X"0" => -- ORB
|
||||
if cb2_no_irq_clr='0' then
|
||||
cb2_flag <= '0';
|
||||
end if;
|
||||
cb1_flag <= '0';
|
||||
|
||||
when X"1" => -- ORA
|
||||
if ca2_no_irq_clr='0' then
|
||||
ca2_flag <= '0';
|
||||
end if;
|
||||
ca1_flag <= '0';
|
||||
|
||||
when X"4" => -- TA LO counter
|
||||
timer_a_flag <= '0';
|
||||
|
||||
when X"8" => -- TB LO counter
|
||||
timer_b_flag <= '0';
|
||||
|
||||
when X"A" => -- SR
|
||||
serial_flag <= '0';
|
||||
trigger_serial <= '1';
|
||||
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
pio_i <= pio_default;
|
||||
irq_mask <= (others => '0');
|
||||
irq_flags <= (others => '0');
|
||||
acr <= (others => '0');
|
||||
pcr <= (others => '0');
|
||||
ca2_handshake_o <= '1';
|
||||
ca2_pulse_o <= '1';
|
||||
cb2_handshake_o <= '1';
|
||||
cb2_pulse_o <= '1';
|
||||
timer_a_latch <= latch_reset_pattern;
|
||||
timer_b_latch <= latch_reset_pattern;
|
||||
trigger_serial <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- PIO Out select --
|
||||
port_a_o <= pio_i.pra;
|
||||
port_b_o(6 downto 0) <= pio_i.prb(6 downto 0);
|
||||
port_b_o(7) <= pio_i.prb(7) when tmr_a_output_en='0' else timer_a_out;
|
||||
|
||||
port_a_t <= pio_i.ddra;
|
||||
port_b_t(6 downto 0) <= pio_i.ddrb(6 downto 0);
|
||||
port_b_t(7) <= pio_i.ddrb(7) or tmr_a_output_en;
|
||||
|
||||
|
||||
-- Timer A
|
||||
tmr_a: block
|
||||
signal timer_a_reload : std_logic;
|
||||
signal timer_a_oneshot_trig : std_logic;
|
||||
signal timer_a_toggle : std_logic;
|
||||
begin
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if falling = '1' then
|
||||
-- always count, or load
|
||||
|
||||
if timer_a_reload = '1' then
|
||||
timer_a_count <= timer_a_latch;
|
||||
timer_a_reload <= '0';
|
||||
timer_a_oneshot_trig <= '0';
|
||||
else
|
||||
if timer_a_count = X"0000" then
|
||||
-- generate an event if we were triggered
|
||||
timer_a_reload <= '1';
|
||||
end if;
|
||||
--Timer coutinues to count in both free run and one shot.
|
||||
timer_a_count <= timer_a_count - X"0001";
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if rising = '1' then
|
||||
if timer_a_event = '1' then
|
||||
timer_a_toggle <= not timer_a_toggle;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if write_t1c_h = '1' then
|
||||
timer_a_toggle <= '0';
|
||||
timer_a_count <= data_in & timer_a_latch(7 downto 0);
|
||||
timer_a_reload <= '0';
|
||||
timer_a_oneshot_trig <= '1';
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
timer_a_toggle <= '1';
|
||||
timer_a_count <= latch_reset_pattern;
|
||||
timer_a_reload <= '0';
|
||||
timer_a_oneshot_trig <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
timer_a_out <= timer_a_toggle;
|
||||
timer_a_event <= rising and timer_a_reload and (tmr_a_freerun or timer_a_oneshot_trig);
|
||||
|
||||
end block tmr_a;
|
||||
|
||||
-- Timer B
|
||||
tmr_b: block
|
||||
signal timer_b_reload_lo : std_logic;
|
||||
signal timer_b_oneshot_trig : std_logic;
|
||||
signal timer_b_timeout : std_logic;
|
||||
signal pb6_c, pb6_d : std_logic;
|
||||
begin
|
||||
process(clock)
|
||||
variable timer_b_decrement : std_logic;
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
timer_b_decrement := '0';
|
||||
|
||||
if rising = '1' then
|
||||
pb6_c <= To_X01(port_b_i(6));
|
||||
pb6_d <= pb6_c;
|
||||
end if;
|
||||
|
||||
if falling = '1' then
|
||||
timer_b_timeout <= '0';
|
||||
timer_b_tick <= '0';
|
||||
|
||||
if tmr_b_count_mode = '1' then
|
||||
if (pb6_d='1' and pb6_c='0') then
|
||||
timer_b_decrement := '1';
|
||||
end if;
|
||||
else -- one shot or used for shift register
|
||||
timer_b_decrement := '1';
|
||||
end if;
|
||||
|
||||
if timer_b_decrement = '1' then
|
||||
if timer_b_count = X"0000" then
|
||||
if timer_b_oneshot_trig = '1' then
|
||||
timer_b_oneshot_trig <= '0';
|
||||
timer_b_timeout <= '1';
|
||||
end if;
|
||||
end if;
|
||||
if timer_b_count(7 downto 0) = X"00" then
|
||||
case shift_mode_control is
|
||||
when "001" | "101" | "100" =>
|
||||
timer_b_reload_lo <= '1';
|
||||
timer_b_tick <= '1';
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
end if;
|
||||
timer_b_count <= timer_b_count - X"0001";
|
||||
end if;
|
||||
if timer_b_reload_lo = '1' then
|
||||
timer_b_count(7 downto 0) <= timer_b_latch(7 downto 0);
|
||||
timer_b_reload_lo <= '0';
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if write_t2c_h = '1' then
|
||||
timer_b_count <= data_in & timer_b_latch(7 downto 0);
|
||||
timer_b_oneshot_trig <= '1';
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
timer_b_count <= latch_reset_pattern;
|
||||
timer_b_reload_lo <= '0';
|
||||
timer_b_oneshot_trig <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
timer_b_event <= rising and timer_b_timeout;
|
||||
|
||||
end block tmr_b;
|
||||
|
||||
ser: block
|
||||
signal shift_clock_d : std_logic;
|
||||
signal shift_clock : std_logic;
|
||||
signal shift_tick_r : std_logic;
|
||||
signal shift_tick_f : std_logic;
|
||||
signal cb2_c : std_logic := '0';
|
||||
signal bit_cnt : integer range 0 to 7;
|
||||
signal shift_pulse : std_logic;
|
||||
begin
|
||||
process(shift_active, timer_b_tick, shift_clk_sel, shift_clock, shift_clock_d)
|
||||
begin
|
||||
case shift_clk_sel is
|
||||
when "10" =>
|
||||
shift_pulse <= '1';
|
||||
|
||||
when "00"|"01" =>
|
||||
shift_pulse <= timer_b_tick;
|
||||
|
||||
when others =>
|
||||
shift_pulse <= shift_clock and not shift_clock_d;
|
||||
|
||||
end case;
|
||||
|
||||
if shift_active = '0' then
|
||||
shift_pulse <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if rising = '1' then
|
||||
cb2_c <= To_X01(cb2_i);
|
||||
|
||||
if shift_active='0' then
|
||||
shift_clock <= '1';
|
||||
elsif shift_clk_sel = "11" then
|
||||
shift_clock <= To_X01(cb1_i);
|
||||
elsif shift_pulse = '1' then
|
||||
shift_clock <= not shift_clock;
|
||||
end if;
|
||||
|
||||
shift_clock_d <= shift_clock;
|
||||
|
||||
if shift_tick_f = '1' then
|
||||
ser_cb2_o <= shift_reg(7);
|
||||
end if;
|
||||
end if;
|
||||
if reset = '1' then
|
||||
shift_clock <= '1';
|
||||
shift_clock_d <= '1';
|
||||
ser_cb2_o <= '1';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
cb1_t <= '0' when shift_clk_sel="11" else serport_en;
|
||||
cb1_o <= shift_clock_d;
|
||||
|
||||
serport_en <= shift_dir or shift_clk_sel(1) or shift_clk_sel(0);
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if reset = '1' then
|
||||
shift_reg <= X"FF";
|
||||
shift_tick_r <= '0';
|
||||
shift_tick_f <= '0';
|
||||
elsif falling = '1' then
|
||||
shift_tick_r <= not shift_clock_d and shift_clock;
|
||||
shift_tick_f <= shift_clock_d and not shift_clock;
|
||||
|
||||
if wen = '1' and addr = X"A" then
|
||||
shift_reg <= data_in;
|
||||
elsif shift_tick_r = '1' then
|
||||
if shift_dir='1' then -- output
|
||||
shift_reg <= shift_reg(6 downto 0) & shift_reg(7);
|
||||
else
|
||||
shift_reg <= shift_reg(6 downto 0) & cb2_c;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-- tell people that we're ready!
|
||||
serial_event <= shift_tick_r and not shift_active and rising;
|
||||
|
||||
process(clock)
|
||||
begin
|
||||
if rising_edge(clock) then
|
||||
if falling = '1' then
|
||||
if shift_active = '0' then
|
||||
if trigger_serial = '1' then
|
||||
bit_cnt <= 7;
|
||||
shift_active <= '1';
|
||||
end if;
|
||||
else -- we're active
|
||||
if shift_clk_sel = "00" then
|
||||
shift_active <= shift_dir; -- when '1' we're active, but for mode 000 we go inactive.
|
||||
elsif shift_pulse = '1' and shift_clock = '1' then
|
||||
if bit_cnt = 0 then
|
||||
shift_active <= '0';
|
||||
else
|
||||
bit_cnt <= bit_cnt - 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
if reset='1' then
|
||||
shift_active <= '0';
|
||||
bit_cnt <= 0;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end block ser;
|
||||
end Gideon;
|
||||
@@ -65,10 +65,11 @@ module C16 #(parameter MODE_PAL = 1)(
|
||||
|
||||
output AUDIO_L,
|
||||
output AUDIO_R,
|
||||
|
||||
input [13:0] kernal_dl_addr,
|
||||
input [7:0] kernal_dl_data,
|
||||
|
||||
input [13:0] dl_addr,
|
||||
input [7:0] dl_data,
|
||||
input kernal_dl_write,
|
||||
input basic_dl_write,
|
||||
|
||||
output PAL,
|
||||
|
||||
@@ -152,9 +153,9 @@ ted mos8360(
|
||||
|
||||
kernal_rom #(.MODE_PAL(MODE_PAL)) kernal(
|
||||
.clk(CLK28),
|
||||
.address_in(sreset?kernal_dl_addr:c16_addr[13:0]),
|
||||
.address_in(kernal_dl_write?dl_addr:c16_addr[13:0]),
|
||||
.data_out(kernal_data),
|
||||
.data_in(kernal_dl_data),
|
||||
.data_in(dl_data),
|
||||
.wr(kernal_dl_write),
|
||||
.cs(cs1)
|
||||
);
|
||||
@@ -163,8 +164,10 @@ ted mos8360(
|
||||
|
||||
basic_rom basic(
|
||||
.clk(CLK28),
|
||||
.address_in(c16_addr[13:0]),
|
||||
.address_in(basic_dl_write?dl_addr:c16_addr[13:0]),
|
||||
.data_out(basic_data),
|
||||
.data_in(dl_data),
|
||||
.wr(basic_dl_write),
|
||||
.cs(cs0)
|
||||
);
|
||||
|
||||
|
||||
@@ -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/stp2.stp
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
# ============================
|
||||
@@ -323,7 +323,6 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to SPI_DO
|
||||
set_instance_assignment -name CURRENT_STRENGTH_NEW 4MA -to CONF_DATA0
|
||||
set_global_assignment -name VERILOG_INPUT_VERSION VERILOG_2001
|
||||
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
set_global_assignment -name VHDL_FILE gen_ram.vhd
|
||||
set_global_assignment -name QIP_FILE pll_ntsc.qip
|
||||
set_global_assignment -name QIP_FILE pll_pal.qip
|
||||
@@ -341,30 +340,16 @@ set_global_assignment -name VERILOG_FILE c16_mist.v
|
||||
set_global_assignment -name VERILOG_FILE c16_keymatrix.v
|
||||
set_global_assignment -name VERILOG_FILE c16.v
|
||||
set_global_assignment -name VERILOG_FILE basic_rom.v
|
||||
set_global_assignment -name SIGNALTAP_FILE stp1.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
|
||||
set_global_assignment -name VHDL_FILE c1541/m6522.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/gcr_floppy.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/spram.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/sprom.vhd
|
||||
set_global_assignment -name VHDL_FILE c1541/gen_rom.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 VHDL_FILE c1541/via6522.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 SIGNALTAP_FILE output_files/stp2.stp
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
@@ -310,7 +310,7 @@ data_io data_io (
|
||||
reg [15:0] reg_2d;
|
||||
reg [15:0] reg_2f;
|
||||
reg [15:0] reg_31;
|
||||
reg [15:0] reg_ae;
|
||||
reg [15:0] reg_9d;
|
||||
|
||||
wire zp_2d_sel = c16_sdram_addr == 16'h002d;
|
||||
wire zp_2e_sel = c16_sdram_addr == 16'h002e;
|
||||
@@ -318,12 +318,12 @@ wire zp_2f_sel = c16_sdram_addr == 16'h002f;
|
||||
wire zp_30_sel = c16_sdram_addr == 16'h0030;
|
||||
wire zp_31_sel = c16_sdram_addr == 16'h0031;
|
||||
wire zp_32_sel = c16_sdram_addr == 16'h0032;
|
||||
wire zp_ae_sel = c16_sdram_addr == 16'h00ae;
|
||||
wire zp_af_sel = c16_sdram_addr == 16'h00af;
|
||||
wire zp_9d_sel = c16_sdram_addr == 16'h009d;
|
||||
wire zp_9e_sel = c16_sdram_addr == 16'h009e;
|
||||
|
||||
wire zp_overwrite =
|
||||
zp_2d_sel || zp_2e_sel || zp_2f_sel || zp_30_sel ||
|
||||
zp_31_sel || zp_32_sel || zp_ae_sel || zp_af_sel;
|
||||
zp_31_sel || zp_32_sel || zp_9d_sel || zp_9e_sel;
|
||||
|
||||
reg zp_cas_delay, zp_sel;
|
||||
reg zp_dl_delay, zp_dl;
|
||||
@@ -343,7 +343,7 @@ always @(posedge clk28) begin
|
||||
reg_2d <= ioctl_sdram_addr + 16'd1;
|
||||
reg_2f <= ioctl_sdram_addr + 16'd1;
|
||||
reg_31 <= ioctl_sdram_addr + 16'd1;
|
||||
reg_ae <= ioctl_sdram_addr + 16'd1;
|
||||
reg_9d <= ioctl_sdram_addr + 16'd1;
|
||||
end else if(zp_sel && !c16_rw) begin
|
||||
// cpu writes registers
|
||||
if(zp_2d_sel) reg_2d[ 7:0] <= c16_dout;
|
||||
@@ -352,8 +352,8 @@ always @(posedge clk28) begin
|
||||
if(zp_30_sel) reg_2f[15:8] <= c16_dout;
|
||||
if(zp_31_sel) reg_31[ 7:0] <= c16_dout;
|
||||
if(zp_32_sel) reg_31[15:8] <= c16_dout;
|
||||
if(zp_ae_sel) reg_ae[ 7:0] <= c16_dout;
|
||||
if(zp_af_sel) reg_ae[15:8] <= c16_dout;
|
||||
if(zp_9d_sel) reg_9d[ 7:0] <= c16_dout;
|
||||
if(zp_9e_sel) reg_9d[15:8] <= c16_dout;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -361,7 +361,7 @@ wire [7:0] zp_ovl_dout =
|
||||
zp_2d_sel?reg_2d[7:0]:zp_2e_sel?reg_2d[15:8]:
|
||||
zp_2f_sel?reg_2f[7:0]:zp_30_sel?reg_2f[15:8]:
|
||||
zp_31_sel?reg_31[7:0]:zp_32_sel?reg_31[15:8]:
|
||||
zp_ae_sel?reg_ae[7:0]:zp_af_sel?reg_ae[15:8]:
|
||||
zp_9d_sel?reg_9d[7:0]:zp_9e_sel?reg_9d[15:8]:
|
||||
8'hff;
|
||||
|
||||
// the address taken from the first to bytes of a prg file tell
|
||||
@@ -487,21 +487,23 @@ wire c16_rw;
|
||||
wire [7:0] c16_a;
|
||||
wire [7:0] c16_dout;
|
||||
|
||||
reg kernal_dl_wr;
|
||||
reg [7:0] kernal_dl_data;
|
||||
reg [13:0] kernal_dl_addr;
|
||||
reg kernal_dl_wr, basic_dl_wr, c1541_dl_wr;
|
||||
reg [7:0] rom_dl_data;
|
||||
reg [13:0] rom_dl_addr;
|
||||
|
||||
wire ioctl_kernal_wr = rom_download && ioctl_wr;
|
||||
wire ioctl_rom_wr = rom_download && ioctl_wr;
|
||||
|
||||
reg last_ioctl_wr;
|
||||
always @(negedge clk28) begin
|
||||
last_ioctl_wr <= ioctl_kernal_wr;
|
||||
if(ioctl_kernal_wr && !last_ioctl_wr) begin
|
||||
kernal_dl_data <= ioctl_data;
|
||||
kernal_dl_addr <= ioctl_addr[13:0];
|
||||
kernal_dl_wr <= 1'b1;
|
||||
reg last_ioctl_rom_wr;
|
||||
last_ioctl_rom_wr <= ioctl_rom_wr;
|
||||
if(ioctl_rom_wr && !last_ioctl_rom_wr) begin
|
||||
rom_dl_data <= ioctl_data;
|
||||
rom_dl_addr <= ioctl_addr[13:0];
|
||||
c1541_dl_wr <= !ioctl_addr[15:14];
|
||||
kernal_dl_wr <= ioctl_addr[15:14] == 2'd1;
|
||||
basic_dl_wr <= ioctl_addr[15:14] == 2'd2;
|
||||
end else
|
||||
kernal_dl_wr <= 1'b0;
|
||||
{ kernal_dl_wr, basic_dl_wr, c1541_dl_wr } <= 0;
|
||||
end
|
||||
|
||||
// include the c16 itself
|
||||
@@ -529,9 +531,10 @@ C16 #(.MODE_PAL(MODE_PAL)) c16 (
|
||||
.PS2DAT ( ps2_kbd_data ),
|
||||
.PS2CLK ( ps2_kbd_clk ),
|
||||
|
||||
.kernal_dl_addr ( kernal_dl_addr ),
|
||||
.kernal_dl_data ( kernal_dl_data ),
|
||||
.kernal_dl_write ( kernal_dl_wr),
|
||||
.dl_addr ( rom_dl_addr ),
|
||||
.dl_data ( rom_dl_data ),
|
||||
.kernal_dl_write ( kernal_dl_wr ),
|
||||
.basic_dl_write ( basic_dl_wr ),
|
||||
|
||||
.IEC_DATAOUT ( c16_iec_data_o ),
|
||||
.IEC_DATAIN ( !c16_iec_data_i ),
|
||||
@@ -635,8 +638,12 @@ c1541_sd c1541_sd (
|
||||
.sd_buff_dout ( sd_dout ),
|
||||
.sd_buff_wr ( sd_dout_strobe ),
|
||||
.sd_buff_addr ( sd_buff_addr ),
|
||||
.led ( led_disk ),
|
||||
|
||||
.led ( led_disk )
|
||||
.c1541rom_clk ( clk28 ),
|
||||
.c1541rom_addr ( rom_dl_addr ),
|
||||
.c1541rom_data ( rom_dl_data ),
|
||||
.c1541rom_wr ( c1541_dl_wr )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -59,6 +59,7 @@ reg [7:0] port_data=8'b0;
|
||||
reg rw_reg,aec_reg;
|
||||
|
||||
// 6502 CPU core
|
||||
|
||||
wire we_n;
|
||||
assign we = ~we_n;
|
||||
|
||||
@@ -75,7 +76,7 @@ T65 cpu_core(
|
||||
.SO_n(1),
|
||||
.R_w_n(we_n),
|
||||
.A(core_address),
|
||||
.DI(core_data_in),
|
||||
.DI(we_n ? core_data_in : core_data_out),
|
||||
.DO(core_data_out)
|
||||
);
|
||||
|
||||
|
||||
@@ -463,9 +463,6 @@ begin
|
||||
--This should happen after P has been pushed to stack
|
||||
tmpP(Flag_I) := '1';
|
||||
end if;
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
tmpP(Flag_V) := '1';
|
||||
end if;
|
||||
if RstCycle = '1' then
|
||||
tmpP(Flag_I) := '1';
|
||||
tmpP(Flag_D) := '0';
|
||||
@@ -474,7 +471,6 @@ begin
|
||||
|
||||
P<=tmpP;--new way
|
||||
|
||||
SO_n_o <= SO_n;
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510), not best way yet, though - but works...
|
||||
IRQ_n_o <= IRQ_n;
|
||||
end if;
|
||||
@@ -484,6 +480,13 @@ begin
|
||||
NMI_n_o <= NMI_n;
|
||||
end if;
|
||||
end if;
|
||||
-- act immediately on SO pin change
|
||||
-- The signal is sampled on the trailing edge of phi1 and must be externally synchronized (from datasheet)
|
||||
SO_n_o <= SO_n;
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
P(Flag_V) <= '1';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
@@ -33,15 +33,15 @@ module user_io #(parameter STRLEN=0) (
|
||||
output reg SPI_MISO,
|
||||
input SPI_MOSI,
|
||||
|
||||
output reg [7:0] joystick_0,
|
||||
output reg [7:0] joystick_1,
|
||||
output reg [15:0] joystick_analog_0,
|
||||
output reg [15:0] joystick_analog_1,
|
||||
output [1:0] buttons,
|
||||
output [1:0] switches,
|
||||
output reg [7:0] joystick_0,
|
||||
output reg [7:0] joystick_1,
|
||||
output reg [15:0] joystick_analog_0,
|
||||
output reg [15:0] joystick_analog_1,
|
||||
output [1:0] buttons,
|
||||
output [1:0] switches,
|
||||
output scandoubler_disable,
|
||||
|
||||
output reg [7:0] status,
|
||||
output ypbpr,
|
||||
output reg [31:0] status,
|
||||
|
||||
// connection to sd card emulation
|
||||
input [31:0] sd_lba,
|
||||
@@ -58,6 +58,7 @@ module user_io #(parameter STRLEN=0) (
|
||||
output reg [8:0] sd_buff_addr,
|
||||
|
||||
output reg img_mounted, //rising edge if a new image is mounted
|
||||
output reg [31:0] img_size, // size of image in bytes
|
||||
|
||||
// ps2 keyboard emulation
|
||||
input ps2_clk, // 12-16khz provided by core
|
||||
@@ -77,12 +78,13 @@ reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
|
||||
reg [7:0] byte_cnt; // counts bytes
|
||||
reg [5:0] joystick0;
|
||||
reg [5:0] joystick1;
|
||||
reg [4:0] but_sw;
|
||||
reg [7:0] but_sw;
|
||||
reg [2:0] stick_idx;
|
||||
|
||||
assign buttons = but_sw[1:0];
|
||||
assign switches = but_sw[3:2];
|
||||
assign scandoubler_disable = but_sw[4];
|
||||
assign ypbpr = but_sw[5];
|
||||
|
||||
// this variant of user_io is for 8 bit cores (type == a4) only
|
||||
wire [7:0] core_type = 8'ha4;
|
||||
@@ -112,56 +114,60 @@ assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0);
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_kbd_r_inc;
|
||||
always@(posedge ps2_clk) begin
|
||||
ps2_kbd_r_inc <= 1'b0;
|
||||
|
||||
if(ps2_kbd_r_inc)
|
||||
ps2_kbd_rptr <= ps2_kbd_rptr + 1;
|
||||
always@(posedge clk_sys) begin
|
||||
reg ps2_clkD;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_kbd_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
|
||||
ps2_kbd_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_kbd_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_kbd_tx_state <= 4'd1;
|
||||
ps2_clkD <= ps2_clk;
|
||||
if (~ps2_clkD & ps2_clk) begin
|
||||
ps2_kbd_r_inc <= 1'b0;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_kbd_data <= 1'b0; // start bit is 0
|
||||
if(ps2_kbd_r_inc)
|
||||
ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_kbd_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
|
||||
ps2_kbd_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_kbd_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_kbd_tx_state <= 4'd1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_kbd_data <= 1'b0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
|
||||
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
|
||||
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
|
||||
if(ps2_kbd_tx_byte[0])
|
||||
ps2_kbd_parity <= !ps2_kbd_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_kbd_tx_state == 9)
|
||||
ps2_kbd_data <= ps2_kbd_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_kbd_tx_state == 10)
|
||||
ps2_kbd_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_kbd_tx_state < 11)
|
||||
ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1;
|
||||
else
|
||||
ps2_kbd_tx_state <= 4'd0;
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
|
||||
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
|
||||
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
|
||||
if(ps2_kbd_tx_byte[0])
|
||||
ps2_kbd_parity <= !ps2_kbd_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_kbd_tx_state == 9)
|
||||
ps2_kbd_data <= ps2_kbd_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_kbd_tx_state == 10)
|
||||
ps2_kbd_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_kbd_tx_state < 11)
|
||||
ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1;
|
||||
else
|
||||
ps2_kbd_tx_state <= 4'd0;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// mouse
|
||||
reg [7:0] ps2_mouse_fifo [(2**PS2_FIFO_BITS)-1:0];
|
||||
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
|
||||
@@ -177,53 +183,57 @@ assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0);
|
||||
// ps2 transmitter
|
||||
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
|
||||
reg ps2_mouse_r_inc;
|
||||
always@(posedge ps2_clk) begin
|
||||
ps2_mouse_r_inc <= 1'b0;
|
||||
|
||||
if(ps2_mouse_r_inc)
|
||||
ps2_mouse_rptr <= ps2_mouse_rptr + 1;
|
||||
always@(posedge clk_sys) begin
|
||||
reg ps2_clkD;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_mouse_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
|
||||
ps2_mouse_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_mouse_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_mouse_tx_state <= 4'd1;
|
||||
ps2_clkD <= ps2_clk;
|
||||
if (~ps2_clkD & ps2_clk) begin
|
||||
ps2_mouse_r_inc <= 1'b0;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_mouse_data <= 1'b0; // start bit is 0
|
||||
if(ps2_mouse_r_inc)
|
||||
ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;
|
||||
|
||||
// transmitter is idle?
|
||||
if(ps2_mouse_tx_state == 0) begin
|
||||
// data in fifo present?
|
||||
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
|
||||
// load tx register from fifo
|
||||
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
|
||||
ps2_mouse_r_inc <= 1'b1;
|
||||
|
||||
// reset parity
|
||||
ps2_mouse_parity <= 1'b1;
|
||||
|
||||
// start transmitter
|
||||
ps2_mouse_tx_state <= 4'd1;
|
||||
|
||||
// put start bit on data line
|
||||
ps2_mouse_data <= 1'b0; // start bit is 0
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
|
||||
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
|
||||
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
|
||||
if(ps2_mouse_tx_byte[0])
|
||||
ps2_mouse_parity <= !ps2_mouse_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_mouse_tx_state == 9)
|
||||
ps2_mouse_data <= ps2_mouse_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_mouse_tx_state == 10)
|
||||
ps2_mouse_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_mouse_tx_state < 11)
|
||||
ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1;
|
||||
else
|
||||
ps2_mouse_tx_state <= 4'd0;
|
||||
end
|
||||
end else begin
|
||||
|
||||
// transmission of 8 data bits
|
||||
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
|
||||
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
|
||||
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
|
||||
if(ps2_mouse_tx_byte[0])
|
||||
ps2_mouse_parity <= !ps2_mouse_parity;
|
||||
end
|
||||
|
||||
// transmission of parity
|
||||
if(ps2_mouse_tx_state == 9)
|
||||
ps2_mouse_data <= ps2_mouse_parity;
|
||||
|
||||
// transmission of stop bit
|
||||
if(ps2_mouse_tx_state == 10)
|
||||
ps2_mouse_data <= 1'b1; // stop bit is 1
|
||||
|
||||
// advance state machine
|
||||
if(ps2_mouse_tx_state < 11)
|
||||
ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1;
|
||||
else
|
||||
ps2_mouse_tx_state <= 4'd0;
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -246,7 +256,7 @@ always @(posedge serial_strobe or posedge status[0]) begin
|
||||
serial_out_wptr <= 0;
|
||||
end else begin
|
||||
serial_out_fifo[serial_out_wptr] <= serial_data;
|
||||
serial_out_wptr <= serial_out_wptr + 1;
|
||||
serial_out_wptr <= serial_out_wptr + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -257,7 +267,7 @@ always@(negedge spi_sck or posedge status[0]) begin
|
||||
if((byte_cnt != 0) && (cmd == 8'h1b)) begin
|
||||
// read last bit -> advance read pointer
|
||||
if((bit_cnt == 7) && !byte_cnt[0] && serial_out_data_available)
|
||||
serial_out_rptr <= serial_out_rptr + 1;
|
||||
serial_out_rptr <= serial_out_rptr + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -385,16 +395,14 @@ always @(posedge clk_sys) begin
|
||||
8'h04: begin
|
||||
// store incoming ps2 mouse bytes
|
||||
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_byte_in;
|
||||
ps2_mouse_wptr <= ps2_mouse_wptr + 1;
|
||||
ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
|
||||
end
|
||||
8'h05: begin
|
||||
// store incoming ps2 keyboard bytes
|
||||
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_byte_in;
|
||||
ps2_kbd_wptr <= ps2_kbd_wptr + 1;
|
||||
ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
|
||||
end
|
||||
|
||||
8'h15: status <= spi_byte_in;
|
||||
|
||||
// joystick analog
|
||||
8'h1a: begin
|
||||
// first byte is joystick indes
|
||||
@@ -414,7 +422,13 @@ always @(posedge clk_sys) begin
|
||||
joystick_analog_1[7:0] <= spi_byte_in;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
8'h15: status <= spi_byte_in;
|
||||
|
||||
// status, 32bit version
|
||||
8'h1e: if(abyte_cnt<6) status[(abyte_cnt-2)<<3 +:8] <= spi_byte_in;
|
||||
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -493,8 +507,11 @@ always @(posedge clk_sd) begin
|
||||
sd_ack_conf <= 1'b1;
|
||||
sd_dout <= spi_byte_in;
|
||||
end
|
||||
|
||||
8'h1c: img_mounted <= 1;
|
||||
|
||||
8'h1c: img_mounted <= 1;
|
||||
|
||||
// send image info
|
||||
8'h1d: if(abyte_cnt<6) img_size[(byte_cnt-2)<<3 +:8] <= spi_byte_in;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user