diff --git a/cores/c16/1541ultimate2cpu/alu.vhd b/cores/c16/1541ultimate2cpu/alu.vhd deleted file mode 100644 index b5d35dc..0000000 --- a/cores/c16/1541ultimate2cpu/alu.vhd +++ /dev/null @@ -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; \ No newline at end of file diff --git a/cores/c16/1541ultimate2cpu/bit_cpx_cpy.vhd b/cores/c16/1541ultimate2cpu/bit_cpx_cpy.vhd deleted file mode 100644 index 36def28..0000000 --- a/cores/c16/1541ultimate2cpu/bit_cpx_cpy.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/cpu6502.vhd b/cores/c16/1541ultimate2cpu/cpu6502.vhd deleted file mode 100644 index 9ba5e39..0000000 --- a/cores/c16/1541ultimate2cpu/cpu6502.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/data_oper.vhd b/cores/c16/1541ultimate2cpu/data_oper.vhd deleted file mode 100644 index eca1911..0000000 --- a/cores/c16/1541ultimate2cpu/data_oper.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/implied.vhd b/cores/c16/1541ultimate2cpu/implied.vhd deleted file mode 100644 index bfdeaa4..0000000 --- a/cores/c16/1541ultimate2cpu/implied.vhd +++ /dev/null @@ -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; \ No newline at end of file diff --git a/cores/c16/1541ultimate2cpu/pkg_6502_decode.vhd b/cores/c16/1541ultimate2cpu/pkg_6502_decode.vhd deleted file mode 100644 index 2b7af5a..0000000 --- a/cores/c16/1541ultimate2cpu/pkg_6502_decode.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/pkg_6502_defs.vhd b/cores/c16/1541ultimate2cpu/pkg_6502_defs.vhd deleted file mode 100644 index 808429c..0000000 --- a/cores/c16/1541ultimate2cpu/pkg_6502_defs.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/pkg_6502_opcodes.vhd b/cores/c16/1541ultimate2cpu/pkg_6502_opcodes.vhd deleted file mode 100644 index 1e04749..0000000 --- a/cores/c16/1541ultimate2cpu/pkg_6502_opcodes.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/proc_control.vhd b/cores/c16/1541ultimate2cpu/proc_control.vhd deleted file mode 100644 index db56a2b..0000000 --- a/cores/c16/1541ultimate2cpu/proc_control.vhd +++ /dev/null @@ -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; - diff --git a/cores/c16/1541ultimate2cpu/proc_core.vhd b/cores/c16/1541ultimate2cpu/proc_core.vhd deleted file mode 100644 index 8b7c7c2..0000000 --- a/cores/c16/1541ultimate2cpu/proc_core.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/proc_interrupt.vhd b/cores/c16/1541ultimate2cpu/proc_interrupt.vhd deleted file mode 100644 index 5aa5ffb..0000000 --- a/cores/c16/1541ultimate2cpu/proc_interrupt.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/proc_registers.vhd b/cores/c16/1541ultimate2cpu/proc_registers.vhd deleted file mode 100644 index ff2cae5..0000000 --- a/cores/c16/1541ultimate2cpu/proc_registers.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/1541ultimate2cpu/shifter.vhd b/cores/c16/1541ultimate2cpu/shifter.vhd deleted file mode 100644 index 56bce45..0000000 --- a/cores/c16/1541ultimate2cpu/shifter.vhd +++ /dev/null @@ -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; \ No newline at end of file diff --git a/cores/c16/basic_rom.v b/cores/c16/basic_rom.v index f319ae9..f5825d5 100644 --- a/cores/c16/basic_rom.v +++ b/cores/c16/basic_rom.v @@ -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; diff --git a/cores/c16/c1541/c1541_logic.vhd b/cores/c16/c1541/c1541_logic.vhd index 3b52e50..78d00dc 100644 --- a/cores/c16/c1541/c1541_logic.vhd +++ b/cores/c16/c1541/c1541_logic.vhd @@ -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; diff --git a/cores/c16/c1541/c1541_sd.vhd b/cores/c16/c1541/c1541_sd.vhd index 676f499..86a954b 100644 --- a/cores/c16/c1541/c1541_sd.vhd +++ b/cores/c16/c1541/c1541_sd.vhd @@ -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 ); diff --git a/cores/c16/c1541/gcr_floppy.vhd b/cores/c16/c1541/gcr_floppy.vhd index 07621a3..9b125a2 100644 --- a/cores/c16/c1541/gcr_floppy.vhd +++ b/cores/c16/c1541/gcr_floppy.vhd @@ -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; diff --git a/cores/c16/c1541/gen_rom.vhd b/cores/c16/c1541/gen_rom.vhd new file mode 100644 index 0000000..b254f67 --- /dev/null +++ b/cores/c16/c1541/gen_rom.vhd @@ -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; diff --git a/cores/c16/c1541/m6522.vhd b/cores/c16/c1541/m6522.vhd deleted file mode 100644 index 87fee00..0000000 --- a/cores/c16/c1541/m6522.vhd +++ /dev/null @@ -1,1015 +0,0 @@ --- --- A simulation model of VIC20 hardware - VIA implementation --- Copyright (c) MikeJ - March 2003 --- --- All rights reserved --- --- Redistribution and use in source and synthezised forms, with or without --- modification, are permitted provided that the following conditions are met: --- --- Redistributions of source code must retain the above copyright notice, --- this list of conditions and the following disclaimer. --- --- Redistributions in synthesized form must reproduce the above copyright --- notice, this list of conditions and the following disclaimer in the --- documentation and/or other materials provided with the distribution. --- --- Neither the name of the author nor the names of other contributors may --- be used to endorse or promote products derived from this software without --- specific prior written permission. --- --- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" --- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, --- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR --- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE --- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR --- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF --- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS --- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN --- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) --- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE --- POSSIBILITY OF SUCH DAMAGE. --- --- You are responsible for any legal issues arising from your use of this code. --- --- The latest version of this file can be found at: www.fpgaarcade.com --- --- Email vic20@fpgaarcade.com --- --- --- Revision list --- --- dmb: ier bit 7 should read back as '1' --- dmb: Fixes to sr_do_shift change that broke MMFS on the Beeb (SR mode 0) --- version 005 Many fixes to all areas, VIA now passes all VICE tests --- version 004 fixes to PB7 T1 control and Mode 0 Shift Register operation --- version 003 fix reset of T1/T2 IFR flags if T1/T2 is reload via reg5/reg9 from wolfgang (WoS) --- Ported to numeric_std and simulation fix for signal initializations from arnim laeuger --- version 002 fix from Mark McDougall, untested --- version 001 initial release --- not very sure about the shift register, documentation is a bit light. - -library ieee ; - use ieee.std_logic_1164.all; - use ieee.numeric_std.all; - -entity M6522 is - port ( - I_RS : in std_logic_vector(3 downto 0); - I_DATA : in std_logic_vector(7 downto 0); - O_DATA : out std_logic_vector(7 downto 0); - O_DATA_OE_L : out std_logic; - - I_RW_L : in std_logic; - I_CS1 : in std_logic; - I_CS2_L : in std_logic; - - O_IRQ_L : out std_logic; -- note, not open drain - - -- port a - I_CA1 : in std_logic; - I_CA2 : in std_logic; - O_CA2 : out std_logic; - O_CA2_OE_L : out std_logic; - - I_PA : in std_logic_vector(7 downto 0); - O_PA : out std_logic_vector(7 downto 0); - O_PA_OE_L : out std_logic_vector(7 downto 0); - - -- port b - I_CB1 : in std_logic; - O_CB1 : out std_logic; - O_CB1_OE_L : out std_logic; - - I_CB2 : in std_logic; - O_CB2 : out std_logic; - O_CB2_OE_L : out std_logic; - - I_PB : in std_logic_vector(7 downto 0); - O_PB : out std_logic_vector(7 downto 0); - O_PB_OE_L : out std_logic_vector(7 downto 0); - - I_P2_H : in std_logic; -- high for phase 2 clock ____----__ - RESET_L : in std_logic; - ENA_4 : in std_logic; -- clk enable - CLK : in std_logic - ); -end; - -architecture RTL of M6522 is - - signal phase : std_logic_vector(1 downto 0):="00"; - signal p2_h_t1 : std_logic; - signal cs : std_logic; - - -- registers - signal r_ddra : std_logic_vector(7 downto 0); - signal r_ora : std_logic_vector(7 downto 0); - signal r_ira : std_logic_vector(7 downto 0); - - signal r_ddrb : std_logic_vector(7 downto 0); - signal r_orb : std_logic_vector(7 downto 0); - signal r_irb : std_logic_vector(7 downto 0); - - signal r_t1l_l : std_logic_vector(7 downto 0); - signal r_t1l_h : std_logic_vector(7 downto 0); - signal r_t2l_l : std_logic_vector(7 downto 0); - signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip - signal r_sr : std_logic_vector(7 downto 0); - signal r_acr : std_logic_vector(7 downto 0); - signal r_pcr : std_logic_vector(7 downto 0); - signal r_ifr : std_logic_vector(7 downto 0); - signal r_ier : std_logic_vector(6 downto 0); - - signal sr_write_ena : boolean; - signal sr_read_ena : boolean; - signal ifr_write_ena : boolean; - signal ier_write_ena : boolean; - signal clear_irq : std_logic_vector(7 downto 0); - signal load_data : std_logic_vector(7 downto 0); - - -- timer 1 - signal t1c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here... - signal t1c_active : boolean; - signal t1c_done : boolean; - signal t1_w_reset_int : boolean; - signal t1_r_reset_int : boolean; - signal t1_load_counter : boolean; - signal t1_reload_counter : boolean; - signal t1_int_enable : boolean := false; - signal t1_toggle : std_logic; - signal t1_irq : std_logic := '0'; - signal t1_pb7 : std_logic := '1'; - signal t1_pb7_en_c : std_logic; - signal t1_pb7_en_d : std_logic; - - -- timer 2 - signal t2c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here... - signal t2c_active : boolean; - signal t2c_done : boolean; - signal t2_pb6 : std_logic; - signal t2_pb6_t1 : std_logic; - signal t2_cnt_clk : std_logic := '1'; - signal t2_w_reset_int : boolean; - signal t2_r_reset_int : boolean; - signal t2_load_counter : boolean; - signal t2_reload_counter : boolean; - signal t2_int_enable : boolean := false; - signal t2_irq : std_logic := '0'; - signal t2_sr_ena : boolean; - - -- shift reg - signal sr_cnt : std_logic_vector(3 downto 0); - signal sr_cb1_oe_l : std_logic; - signal sr_cb1_out : std_logic; - signal sr_drive_cb2 : std_logic; - signal sr_strobe : std_logic; - signal sr_do_shift : boolean := false; - signal sr_strobe_t1 : std_logic; - signal sr_strobe_falling : boolean; - signal sr_strobe_rising : boolean; - signal sr_irq : std_logic; - signal sr_out : std_logic; - signal sr_active : boolean; - - -- io - signal w_orb_hs : std_logic; - signal w_ora_hs : std_logic; - signal r_irb_hs : std_logic; - signal r_ira_hs : std_logic; - - signal ca_hs_sr : std_logic; - signal ca_hs_pulse : std_logic; - signal cb_hs_sr : std_logic; - signal cb_hs_pulse : std_logic; - - signal cb1_in_mux : std_logic; - signal ca1_ip_reg_c : std_logic; - signal ca1_ip_reg_d : std_logic; - signal cb1_ip_reg_c : std_logic; - signal cb1_ip_reg_d : std_logic; - signal ca1_int : boolean; - signal cb1_int : boolean; - signal ca1_irq : std_logic; - signal cb1_irq : std_logic; - - signal ca2_ip_reg_c : std_logic; - signal ca2_ip_reg_d : std_logic; - signal cb2_ip_reg_c : std_logic; - signal cb2_ip_reg_d : std_logic; - signal ca2_int : boolean; - signal cb2_int : boolean; - signal ca2_irq : std_logic; - signal cb2_irq : std_logic; - - signal final_irq : std_logic; -begin - - p_phase : process - begin - -- internal clock phase - wait until rising_edge(CLK); - if (ENA_4 = '1') then - p2_h_t1 <= I_P2_H; - if (p2_h_t1 = '0') and (I_P2_H = '1') then - phase <= "11"; - else - phase <= std_logic_vector(unsigned(phase) + 1); - end if; - end if; - end process; - - p_cs : process(I_CS1, I_CS2_L, I_P2_H) - begin - cs <= '0'; - if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then - cs <= '1'; - end if; - end process; - - -- peripheral control reg (pcr) - -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge) - -- 3..1 ca2 operation - -- 000 input -ve edge - -- 001 independend interrupt input -ve edge - -- 010 input +ve edge - -- 011 independend interrupt input +ve edge - -- 100 handshake output - -- 101 pulse output - -- 110 low output - -- 111 high output - -- 7..4 as 3..0 for cb1,cb2 - - -- auxiliary control reg (acr) - -- 0 input latch PA (0 disable, 1 enable) - -- 1 input latch PB (0 disable, 1 enable) - -- 4..2 shift reg control - -- 000 disable - -- 001 shift in using t2 - -- 010 shift in using o2 - -- 011 shift in using ext clk - -- 100 shift out free running t2 rate - -- 101 shift out using t2 - -- 101 shift out using o2 - -- 101 shift out using ext clk - -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6) - -- 7..6 t1 timer control - -- 00 timed interrupt each time t1 is loaded pb7 disable - -- 01 continuous interrupts pb7 disable - -- 00 timed interrupt each time t1 is loaded pb7 one shot output - -- 01 continuous interrupts pb7 square wave output - -- - - p_write_reg_reset : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - r_ora <= x"00"; r_orb <= x"00"; - r_ddra <= x"00"; r_ddrb <= x"00"; - r_acr <= x"00"; r_pcr <= x"00"; - - w_orb_hs <= '0'; - w_ora_hs <= '0'; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - w_orb_hs <= '0'; - w_ora_hs <= '0'; - if (cs = '1') and (I_RW_L = '0') then - case I_RS is - when x"0" => r_orb <= I_DATA; w_orb_hs <= '1'; - when x"1" => r_ora <= I_DATA; w_ora_hs <= '1'; - when x"2" => r_ddrb <= I_DATA; - when x"3" => r_ddra <= I_DATA; - - when x"B" => r_acr <= I_DATA; - when x"C" => r_pcr <= I_DATA; - when x"F" => r_ora <= I_DATA; - - when others => null; - end case; - end if; - - -- Set timer PB7 state, only on rising edge of setting ACR(7) - if ((t1_pb7_en_d = '0') and (t1_pb7_en_c = '1')) then - t1_pb7 <= '1'; - end if; - - if t1_load_counter then - t1_pb7 <= '0'; -- Reset internal timer 1 PB7 state on every timer load - elsif t1_toggle = '1' then - t1_pb7 <= not t1_pb7; - end if; - end if; - end if; - end process; - - p_write_reg : process (RESET_L, CLK) is - begin - if (RESET_L = '0') then - -- The spec says, this is not reset. - -- Fact is that the 1541 VIA1 timer won't work, - -- as the firmware ONLY sets the r_t1l_h latch!!!! - r_t1l_l <= (others => '1'); -- All latches default to FFFF - r_t1l_h <= (others => '1'); - r_t2l_l <= (others => '1'); - r_t2l_h <= (others => '1'); - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - t1_w_reset_int <= false; - t1_load_counter <= false; - - t2_w_reset_int <= false; - t2_load_counter <= false; - - load_data <= x"00"; - sr_write_ena <= false; - ifr_write_ena <= false; - ier_write_ena <= false; - - if (cs = '1') and (I_RW_L = '0') then - load_data <= I_DATA; - case I_RS is - when x"4" => r_t1l_l <= I_DATA; - when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; - t1_load_counter <= true; - - when x"6" => r_t1l_l <= I_DATA; - when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true; - - when x"8" => r_t2l_l <= I_DATA; - when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true; - t2_load_counter <= true; - - when x"A" => sr_write_ena <= true; - when x"D" => ifr_write_ena <= true; - when x"E" => ier_write_ena <= true; - - when others => null; - end case; - end if; - end if; - end if; - end process; - - p_oe : process(cs, I_RW_L) - begin - O_DATA_OE_L <= '1'; - if (cs = '1') and (I_RW_L = '1') then - O_DATA_OE_L <= '0'; - end if; - end process; - - p_read : process(cs, I_RW_L, I_RS, r_irb, r_ira, r_ddrb, r_ddra, t1c, r_t1l_l, - r_t1l_h, t2c, r_sr, r_acr, r_pcr, r_ifr, r_ier, r_ora, r_orb, t1_pb7_en_d, t1_pb7) - variable orb : std_logic_vector(7 downto 0); - begin - t1_r_reset_int <= false; - t2_r_reset_int <= false; - sr_read_ena <= false; - r_irb_hs <= '0'; - r_ira_hs <= '0'; - O_DATA <= x"00"; -- default - orb := (r_irb and not r_ddrb) or (r_orb and r_ddrb); - - -- If PB7 under timer control, assign value from timer - if (t1_pb7_en_d = '1') then - orb(7) := t1_pb7; - end if; - - if (cs = '1') and (I_RW_L = '1') then - case I_RS is - when x"0" => O_DATA <= orb; r_irb_hs <= '1'; - when x"1" => O_DATA <= (r_ira and not r_ddra) or (r_ora and r_ddra); r_ira_hs <= '1'; - when x"2" => O_DATA <= r_ddrb; - when x"3" => O_DATA <= r_ddra; - when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true; - when x"5" => O_DATA <= t1c(15 downto 8); - when x"6" => O_DATA <= r_t1l_l; - when x"7" => O_DATA <= r_t1l_h; - when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true; - when x"9" => O_DATA <= t2c(15 downto 8); - when x"A" => O_DATA <= r_sr; sr_read_ena <= true; - when x"B" => O_DATA <= r_acr; - when x"C" => O_DATA <= r_pcr; - when x"D" => O_DATA <= r_ifr; - -- DMB: ier bit 7 should read back as '1' - when x"E" => O_DATA <= ('1' & r_ier); - when x"F" => O_DATA <= r_ira; - when others => null; - end case; - end if; - - end process; - - -- - -- IO - -- - - p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1) - begin - -- if the shift register is enabled, cb1 may be an output - -- in this case we should NOT listen to the input as - -- CB1 interrupts are not generated by the shift register - if (sr_cb1_oe_l = '1') then - cb1_in_mux <= I_CB1; - else - cb1_in_mux <= '1'; - end if; - end process; - - p_ca1_cb1_int : process(r_pcr, ca1_ip_reg_c, ca1_ip_reg_d, cb1_ip_reg_c, cb1_ip_reg_d) - begin - if (r_pcr(0) = '0') then -- ca1 control - -- negative edge - ca1_int <= (ca1_ip_reg_d = '1') and (ca1_ip_reg_c = '0'); - else - -- positive edge - ca1_int <= (ca1_ip_reg_d = '0') and (ca1_ip_reg_c = '1'); - end if; - - if (r_pcr(4) = '0') then -- cb1 control - -- negative edge - cb1_int <= (cb1_ip_reg_d = '1') and (cb1_ip_reg_c = '0'); - else - -- positive edge - cb1_int <= (cb1_ip_reg_d = '0') and (cb1_ip_reg_c = '1'); - end if; - end process; - - p_ca2_cb2_int : process(r_pcr, ca2_ip_reg_c, ca2_ip_reg_d, cb2_ip_reg_c, cb2_ip_reg_d) - begin - ca2_int <= false; - if (r_pcr(3) = '0') then -- ca2 input - if (r_pcr(2) = '0') then -- ca2 edge - -- negative edge - ca2_int <= (ca2_ip_reg_d = '1') and (ca2_ip_reg_c = '0'); - else - -- positive edge - ca2_int <= (ca2_ip_reg_d = '0') and (ca2_ip_reg_c = '1'); - end if; - end if; - - cb2_int <= false; - if (r_pcr(7) = '0') then -- cb2 input - if (r_pcr(6) = '0') then -- cb2 edge - -- negative edge - cb2_int <= (cb2_ip_reg_d = '1') and (cb2_ip_reg_c = '0'); - else - -- positive edge - cb2_int <= (cb2_ip_reg_d = '0') and (cb2_ip_reg_c = '1'); - end if; - end if; - end process; - - p_ca2_cb2 : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - O_CA2 <= '1'; -- Pullup is default - O_CA2_OE_L <= '1'; - O_CB2 <= '1'; -- Pullup is default - O_CB2_OE_L <= '1'; - - ca_hs_sr <= '0'; - ca_hs_pulse <= '0'; - cb_hs_sr <= '0'; - cb_hs_pulse <= '0'; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - -- ca - if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then - ca_hs_sr <= '1'; - elsif ca1_int then - ca_hs_sr <= '0'; - end if; - - if (phase = "00") then - ca_hs_pulse <= w_ora_hs or r_ira_hs; - end if; - - O_CA2_OE_L <= not r_pcr(3); -- ca2 output - case r_pcr(3 downto 1) is - when "000" => O_CA2 <= I_CA2; -- input, output follows input - when "001" => O_CA2 <= I_CA2; -- input, output follows input - when "010" => O_CA2 <= I_CA2; -- input, output follows input - when "011" => O_CA2 <= I_CA2; -- input, output follows input - when "100" => O_CA2 <= not (ca_hs_sr); -- handshake - when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse - when "110" => O_CA2 <= '0'; -- low - when "111" => O_CA2 <= '1'; -- high - when others => null; - end case; - - -- cb - if (phase = "00") and (w_orb_hs = '1') then - cb_hs_sr <= '1'; - elsif cb1_int then - cb_hs_sr <= '0'; - end if; - - if (phase = "00") then - cb_hs_pulse <= w_orb_hs; - end if; - - O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial - if (sr_drive_cb2 = '1') then -- serial output - O_CB2 <= sr_out; - else - case r_pcr(7 downto 5) is - when "000" => O_CB2 <= I_CB2; -- input, output follows input - when "001" => O_CB2 <= I_CB2; -- input, output follows input - when "010" => O_CB2 <= I_CB2; -- input, output follows input - when "011" => O_CB2 <= I_CB2; -- input, output follows input - when "100" => O_CB2 <= not (cb_hs_sr); -- handshake - when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse - when "110" => O_CB2 <= '0'; -- low - when "111" => O_CB2 <= '1'; -- high - when others => null; - end case; - end if; - end if; - end if; - end process; - - O_CB1 <= sr_cb1_out; - O_CB1_OE_L <= sr_cb1_oe_l; - - p_ca_cb_irq : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - ca1_irq <= '0'; - ca2_irq <= '0'; - cb1_irq <= '0'; - cb2_irq <= '0'; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - -- not pretty - if ca1_int then - ca1_irq <= '1'; - elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then - ca1_irq <= '0'; - end if; - - if ca2_int then - ca2_irq <= '1'; - else - if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or - (clear_irq(0) = '1') then - ca2_irq <= '0'; - end if; - end if; - - if cb1_int then - cb1_irq <= '1'; - elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then - cb1_irq <= '0'; - end if; - - if cb2_int then - cb2_irq <= '1'; - else - if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or - (clear_irq(3) = '1') then - cb2_irq <= '0'; - end if; - end if; - end if; - end if; - end process; - - p_input_reg : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - ca1_ip_reg_c <= '0'; - ca1_ip_reg_d <= '0'; - - cb1_ip_reg_c <= '0'; - cb1_ip_reg_d <= '0'; - - ca2_ip_reg_c <= '0'; - ca2_ip_reg_d <= '0'; - - cb2_ip_reg_c <= '0'; - cb2_ip_reg_d <= '0'; - - r_ira <= x"00"; - r_irb <= x"00"; - - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - -- we have a fast clock, so we can have input registers - ca1_ip_reg_c <= I_CA1; - ca1_ip_reg_d <= ca1_ip_reg_c; - - cb1_ip_reg_c <= cb1_in_mux; - cb1_ip_reg_d <= cb1_ip_reg_c; - - ca2_ip_reg_c <= I_CA2; - ca2_ip_reg_d <= ca2_ip_reg_c; - - cb2_ip_reg_c <= I_CB2; - cb2_ip_reg_d <= cb2_ip_reg_c; - - if (r_acr(0) = '0') then - r_ira <= I_PA; - else -- enable latching - if ca1_int then - r_ira <= I_PA; - end if; - end if; - - if (r_acr(1) = '0') then - r_irb <= I_PB; - else -- enable latching - if cb1_int then - r_irb <= I_PB; - end if; - end if; - end if; - end if; - end process; - - p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb, t1_pb7_en_d, t1_pb7) - begin - -- data direction reg (ddr) 0 = input, 1 = output - O_PA <= r_ora; - O_PA_OE_L <= not r_ddra; - - -- If PB7 is timer driven output set PB7 to the timer state, otherwise use value in ORB register - if (t1_pb7_en_d = '1') then - O_PB <= t1_pb7 & r_orb(6 downto 0); - else - O_PB <= r_orb; - end if; - - -- NOTE: r_ddrb(7) must be set to enable T1 output on PB7 - [various datasheets specify this] - O_PB_OE_L <= not r_ddrb; - end process; - - -- - -- Timer 1 - -- - - -- Detect change in r_acr(7), timer 1 mode for PB7 - p_pb7_enable : process - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - t1_pb7_en_c <= r_acr(7); - t1_pb7_en_d <= t1_pb7_en_c; - end if; - end process; - - p_timer1_done : process - variable done : boolean; - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - done := (t1c = x"0000"); - t1c_done <= done and (phase = "11"); - if (phase = "11") and not t1_load_counter then -- Don't set reload if T1L-H written - t1_reload_counter <= done; - elsif t1_load_counter then -- Cancel a reload when T1L-H written - t1_reload_counter <= false; - end if; - if t1_load_counter then -- done reset on load! - t1c_done <= false; - end if; - end if; - end process; - - p_timer1 : process - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - if t1_load_counter or (t1_reload_counter and phase = "11") then - t1c( 7 downto 0) <= r_t1l_l; - t1c(15 downto 8) <= r_t1l_h; - -- There is a need to write to Latch HI to enable interrupts for both continuous and one-shot modes - if t1_load_counter then - t1_int_enable <= true; - end if; - elsif (phase="11") then - t1c <= std_logic_vector(unsigned(t1c) - 1); - end if; - - if t1_load_counter or t1_reload_counter then - t1c_active <= true; - elsif t1c_done then - t1c_active <= false; - end if; - - t1_toggle <= '0'; - if t1c_active and t1c_done then - if t1_int_enable then -- Set interrupt only if T1L-H has been written - t1_toggle <= '1'; - t1_irq <= '1'; - if (r_acr(6) = '0') then -- Disable further interrupts if in one shot mode - t1_int_enable <= false; - end if; - end if; - elsif t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then - t1_irq <= '0'; - end if; - if t1_load_counter then -- irq reset on load! - t1_irq <= '0'; - end if; - end if; - end process; - - -- - -- Timer2 - -- - - p_timer2_pb6_input : process - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - if (phase = "01") then -- leading edge p2_h - t2_pb6 <= I_PB(6); - t2_pb6_t1 <= t2_pb6; - end if; - end if; - end process; - - -- Ensure we don't start counting until the P2 clock after r_acr is changed - p_timer2_ena : process - begin - wait until rising_edge(I_P2_H); - if r_acr(5) = '0' then - t2_cnt_clk <= '1'; - else - t2_cnt_clk <= '0'; - end if; - end process; - - p_timer2_done : process - variable done : boolean; - variable done_sr : boolean; - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - done := (t2c = x"0000"); -- Normal timer expires at 0000 - done_sr := (t2c(7 downto 0) = x"00"); -- Shift register expires on low byte = 00 - t2c_done <= done and (phase = "11"); - if (phase = "11") then - t2_reload_counter <= done_sr; -- Timer 2 is only reloaded when used for the shift register - end if; - if t2_load_counter then -- done reset on load! - t2c_done <= false; - end if; - end if; - end process; - - p_timer2 : process - variable ena : boolean; - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - if (t2_cnt_clk ='1') then - ena := true; - t2c_active <= true; - t2_int_enable <= true; - else - ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge - end if; - - -- Shift register reload is only active when shift register mode using T2 is enabled - if t2_reload_counter and (phase="11") and ((r_acr(4 downto 2) = "001") or (r_acr(4 downto 2) = "100") or (r_acr(4 downto 2) = "101")) then - t2c(7 downto 0) <= r_t2l_l; -- For shift register only low latch is loaded! - elsif t2_load_counter then - t2_int_enable <= true; - t2c( 7 downto 0) <= r_t2l_l; - t2c(15 downto 8) <= r_t2l_h; - else - if (phase="11") and ena then -- or count mode - t2c <= std_logic_vector(unsigned(t2c) - 1); - end if; - end if; - - -- Shift register strobe on T2 occurs one P2H clock after timer expires - -- so enable the strobe when we roll over to FF - t2_sr_ena <= (t2c(7 downto 0) = x"FF") and (phase = "11"); - - if t2_load_counter then - t2c_active <= true; - elsif t2c_done then - t2c_active <= false; - end if; - - if t2c_active and t2c_done and t2_int_enable then - t2_int_enable <= false; - t2_irq <= '1'; - elsif t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then - t2_irq <= '0'; - end if; - if t2_load_counter then -- irq reset on load! - t2_irq <= '0'; - end if; - end if; - end process; - - -- - -- Shift Register - -- - - p_sr : process(RESET_L, CLK) - variable dir_out : std_logic; - variable ena : std_logic; - variable cb1_op : std_logic; - variable cb1_ip : std_logic; - variable use_t2 : std_logic; - variable free_run : std_logic; - variable sr_count_ena : boolean; - begin - if (RESET_L = '0') then - r_sr <= x"00"; - sr_drive_cb2 <= '0'; - sr_cb1_oe_l <= '1'; - sr_cb1_out <= '0'; - sr_do_shift <= false; - sr_strobe <= '1'; - sr_cnt <= "0000"; - sr_irq <= '0'; - sr_out <= '0'; - sr_active <= false; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - -- decode mode - dir_out := r_acr(4); -- output on cb2 - cb1_op := '0'; - cb1_ip := '0'; - use_t2 := '0'; - free_run := '0'; - - -- DMB: SR still runs even in disabled mode (on rising edge of CB1). - -- It just doesn't generate any interrupts. - -- Ref BBC micro advanced user guide p409 - - case r_acr(4 downto 2) is - -- DMB: in disabled mode, configure cb1 as an input - when "000" => ena := '0'; cb1_ip := '1'; -- 0x00 Mode 0 SR disabled - when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1'; -- 0x04 Mode 1 Shift in under T2 control - when "010" => ena := '1'; cb1_op := '1'; -- 0x08 Mode 2 Shift in under P2 control - when "011" => ena := '1'; cb1_ip := '1'; -- 0x0C Mode 3 Shift in under control of ext clock - when "100" => ena := '1'; cb1_op := '1'; use_t2 := '1'; free_run := '1'; -- 0x10 Mode 4 Shift out free running under T2 control - when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1'; -- 0x14 Mode 5 Shift out under T2 control - when "110" => ena := '1'; cb1_op := '1'; -- 0x18 Mode 6 Shift out under P2 control - when "111" => ena := '1'; cb1_ip := '1'; -- 0x1C Mode 7 Shift out under control of ext clock - when others => null; - end case; - - -- clock select - -- DMB: in disabled mode, strobe from cb1 - if (cb1_ip = '1') then - sr_strobe <= I_CB1; - else - if (sr_cnt(3) = '0') and (free_run = '0') then - sr_strobe <= '1'; - else - if ((use_t2 = '1') and t2_sr_ena) or - ((use_t2 = '0') and (phase = "00")) then - sr_strobe <= not sr_strobe; - end if; - end if; - end if; - - -- latch on rising edge, shift on falling edge of P2 - if sr_write_ena then - r_sr <= load_data; - sr_out <= r_sr(7); - - else - -- DMB: allow shifting in all modes - if (dir_out = '0') then - -- input - if (sr_cnt(3) = '1') or (cb1_ip = '1') then - if sr_strobe_rising then - sr_do_shift <= true; - r_sr(0) <= I_CB2; - -- DMB: Added sr_stroble_falling to avoid premature shift - -- (fixes issue with MMFS on the Beeb in SR mode 0) - elsif sr_do_shift and sr_strobe_falling then - sr_do_shift <= false; - r_sr(7 downto 1) <= r_sr(6 downto 0); - end if; - end if; - else - -- output - if (sr_cnt(3) = '1') or (cb1_ip = '1') or (free_run = '1') then - if sr_strobe_falling then - sr_out <= r_sr(7); - sr_do_shift <= true; - -- DMB: Added sr_stroble_falling to avoid premature shift - -- (fixes issue with MMFS on the Beeb in SR mode 0) - elsif sr_do_shift and sr_strobe_rising then - sr_do_shift <= false; - r_sr <= r_sr(6 downto 0) & r_sr(7); - end if; - end if; - end if; - end if; - - -- Set shift enabled flag, note does not get set for free_run mode ! - if (ena = '1') and (sr_cnt(3) = '1') then - sr_active <= true; - elsif (ena = '1') and (sr_cnt(3) = '0') and (phase="11") then - sr_active <= false; - end if; - - sr_count_ena := sr_strobe_rising; - - -- DMB: reseting sr_count when not enabled cause the sr to - -- start running immediately it was enabled, which is incorrect - -- and broke the latest SmartSPI ROM on the BBC Micro - if (ena = '1') and (sr_write_ena or sr_read_ena) and (not sr_active) then - -- some documentation says sr bit in IFR must be set as well ? - sr_cnt <= "1000"; - elsif sr_count_ena and (sr_cnt(3) = '1') then - sr_cnt <= std_logic_vector(unsigned(sr_cnt) + 1); - end if; - - if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then - sr_irq <= '1'; - elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then - sr_irq <= '0'; - end if; - - -- assign ops - sr_drive_cb2 <= dir_out; - sr_cb1_oe_l <= not cb1_op; - sr_cb1_out <= sr_strobe; - end if; - end if; - end process; - - p_sr_strobe_rise_fall : process - begin - wait until rising_edge(CLK); - if (ENA_4 = '1') then - sr_strobe_t1 <= sr_strobe; - sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1'); - sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0'); - end if; - end process; - - -- - -- Interrupts - -- - - p_ier : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - r_ier <= "0000000"; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - if ier_write_ena then - if (load_data(7) = '1') then - -- set - r_ier <= r_ier or load_data(6 downto 0); - else - -- clear - r_ier <= r_ier and not load_data(6 downto 0); - end if; - end if; - end if; - end if; - end process; - - p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq, - cb1_irq, cb2_irq) - begin - r_ifr(7) <= final_irq; - r_ifr(6) <= t1_irq; - r_ifr(5) <= t2_irq; - r_ifr(4) <= cb1_irq; - r_ifr(3) <= cb2_irq; - r_ifr(2) <= sr_irq; - r_ifr(1) <= ca1_irq; - r_ifr(0) <= ca2_irq; - - O_IRQ_L <= not final_irq; - end process; - - p_irq : process(RESET_L, CLK) - begin - if (RESET_L = '0') then - final_irq <= '0'; - elsif rising_edge(CLK) then - if (ENA_4 = '1') then - if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then - final_irq <= '0'; -- no interrupts - else - final_irq <= '1'; - end if; - end if; - end if; - end process; - - p_clear_irq : process(ifr_write_ena, load_data) - begin - clear_irq <= x"00"; - if ifr_write_ena then - clear_irq <= load_data; - end if; - end process; - -end architecture RTL; diff --git a/cores/c16/c1541/sprom.vhd b/cores/c16/c1541/sprom.vhd deleted file mode 100644 index 2b1ae58..0000000 --- a/cores/c16/c1541/sprom.vhd +++ /dev/null @@ -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; diff --git a/cores/c16/c1541/via6522.vhd b/cores/c16/c1541/via6522.vhd new file mode 100644 index 0000000..7c982bc --- /dev/null +++ b/cores/c16/c1541/via6522.vhd @@ -0,0 +1,678 @@ +------------------------------------------------------------------------------- +-- +-- (C) COPYRIGHT 2007-2017, Gideon's Logic Architectures +-- +------------------------------------------------------------------------------- +-- Title : VIA 6522 +------------------------------------------------------------------------------- +-- Author : Gideon Zweijtzer +------------------------------------------------------------------------------- +-- 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; diff --git a/cores/c16/c16.v b/cores/c16/c16.v index 542d74e..7410dd6 100644 --- a/cores/c16/c16.v +++ b/cores/c16/c16.v @@ -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) ); diff --git a/cores/c16/c16_mist.qsf b/cores/c16/c16_mist.qsf index 2c29a9e..46aff41 100644 --- a/cores/c16/c16_mist.qsf +++ b/cores/c16/c16_mist.qsf @@ -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 \ No newline at end of file +set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/cores/c16/c16_mist.v b/cores/c16/c16_mist.v index d504a14..dead4c0 100644 --- a/cores/c16/c16_mist.v +++ b/cores/c16/c16_mist.v @@ -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 diff --git a/cores/c16/mos8501.v b/cores/c16/mos8501.v index 8739c08..3f862be 100644 --- a/cores/c16/mos8501.v +++ b/cores/c16/mos8501.v @@ -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) ); diff --git a/cores/c16/t65/T65.vhd b/cores/c16/t65/T65.vhd index b9fa335..d6aba9c 100755 --- a/cores/c16/t65/T65.vhd +++ b/cores/c16/t65/T65.vhd @@ -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; diff --git a/cores/c16/user_io.v b/cores/c16/user_io.v index c86a3fc..5505f93 100644 --- a/cores/c16/user_io.v +++ b/cores/c16/user_io.v @@ -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