1
0
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:
gyurco
2018-09-04 22:05:18 +02:00
committed by GitHub
27 changed files with 1060 additions and 3430 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View File

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

View File

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

View File

@@ -167,7 +167,7 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# SignalTap II Assignments
# ========================
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/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

View File

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

View File

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

View File

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

View File

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