library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.conv_std_logic_vector; use ieee.std_logic_unsigned.conv_integer; entity decoder is generic (dsize : integer := 8); port ( set_clk : in std_logic; trig_clk : in std_logic; res_n : in std_logic; irq_n : in std_logic; nmi_n : in std_logic; rdy : in std_logic; instruction : in std_logic_vector (dsize - 1 downto 0); exec_cycle : in std_logic_vector (5 downto 0); next_cycle : out std_logic_vector (5 downto 0); status_reg : inout std_logic_vector (dsize - 1 downto 0); inst_we_n : out std_logic; ad_oe_n : out std_logic; dbuf_int_oe_n : out std_logic; dl_al_we_n : out std_logic; dl_ah_we_n : out std_logic; dl_al_oe_n : out std_logic; dl_ah_oe_n : out std_logic; dl_dh_oe_n : out std_logic; pcl_inc_n : out std_logic; pch_inc_n : out std_logic; pcl_cmd : out std_logic_vector(3 downto 0); pch_cmd : out std_logic_vector(3 downto 0); sp_cmd : out std_logic_vector(3 downto 0); sp_oe_n : out std_logic; sp_push_n : out std_logic; sp_pop_n : out std_logic; acc_cmd : out std_logic_vector(3 downto 0); x_cmd : out std_logic_vector(3 downto 0); y_cmd : out std_logic_vector(3 downto 0); abs_xy_n : out std_logic; ea_carry : in std_logic; pg_next_n : out std_logic; zp_n : out std_logic; zp_xy_n : out std_logic; rel_calc_n : out std_logic; indir_n : out std_logic; indir_x_n : out std_logic; indir_y_n : out std_logic; arith_en_n : out std_logic; stat_dec_oe_n : out std_logic; stat_bus_oe_n : out std_logic; stat_set_flg_n : out std_logic; stat_flg : out std_logic; stat_bus_all_n : out std_logic; stat_bus_nz_n : out std_logic; stat_alu_we_n : out std_logic; r_vec_oe_n : out std_logic; n_vec_oe_n : out std_logic; i_vec_oe_n : out std_logic; r_nw : out std_logic ;---for parameter check purpose!!! check_bit : out std_logic_vector(1 to 5) ); end decoder; architecture rtl of decoder is component d_flip_flop_bit port ( clk : in std_logic; res_n : in std_logic; set_n : in std_logic; we_n : in std_logic; d : in std_logic; q : out std_logic ); end component; procedure d_print(msg : string) is use std.textio.all; --use ieee.std_logic_textio.all; variable out_l : line; begin -- write(out_l, msg); -- writeline(output, out_l); end procedure; ---ival : 0x0000 - 0xffff function conv_hex8(ival : integer) return string is variable tmp1, tmp2 : integer; variable hex_chr: string (1 to 16) := "0123456789abcdef"; begin tmp2 := (ival mod 16 ** 2) / 16 ** 1; tmp1 := ival mod 16 ** 1; return hex_chr(tmp2 + 1) & hex_chr(tmp1 + 1); end; --cycle bit format -- bit 5 : pcl increment carry flag -- bit 4,3 : cycle type: 00 normal, 01 reset , 10 nmi, 11 irq -- bit 2-0 : cycle --00xxx : exec cycle : T0 > T1 > T2 > T3 > T4 > T5 > T6 > T0 constant T0 : std_logic_vector (5 downto 0) := "000000"; constant T1 : std_logic_vector (5 downto 0) := "000001"; constant T2 : std_logic_vector (5 downto 0) := "000010"; constant T3 : std_logic_vector (5 downto 0) := "000011"; constant T4 : std_logic_vector (5 downto 0) := "000100"; constant T5 : std_logic_vector (5 downto 0) := "000101"; constant T6 : std_logic_vector (5 downto 0) := "000110"; --01xxx : reset cycle : R0 > R1 > R2 > R3 > R4 > R5 > T0 constant R0 : std_logic_vector (5 downto 0) := "001000"; constant R1 : std_logic_vector (5 downto 0) := "001001"; constant R2 : std_logic_vector (5 downto 0) := "001010"; constant R3 : std_logic_vector (5 downto 0) := "001011"; constant R4 : std_logic_vector (5 downto 0) := "001100"; constant R5 : std_logic_vector (5 downto 0) := "001101"; --10xxx : nmi cycle : T0 > N1 > N2 > N3 > N4 > N5 > T0 constant N1 : std_logic_vector (5 downto 0) := "010001"; constant N2 : std_logic_vector (5 downto 0) := "010010"; constant N3 : std_logic_vector (5 downto 0) := "010011"; constant N4 : std_logic_vector (5 downto 0) := "010100"; constant N5 : std_logic_vector (5 downto 0) := "010101"; --11xxx : irq cycle : T0 > I1 > I2 > I3 > I4 > I5 > T0 constant I1 : std_logic_vector (5 downto 0) := "011001"; constant I2 : std_logic_vector (5 downto 0) := "011010"; constant I3 : std_logic_vector (5 downto 0) := "011011"; constant I4 : std_logic_vector (5 downto 0) := "011100"; constant I5 : std_logic_vector (5 downto 0) := "011101"; constant ERROR_CYCLE : std_logic_vector (5 downto 0) := "111111"; -- SR Flags (bit 7 to bit 0): -- 7 N .... Negative -- 6 V .... Overflow -- 5 - .... ignored -- 4 B .... Break -- 3 D .... Decimal (use BCD for arithmetics) -- 2 I .... Interrupt (IRQ disable) -- 1 Z .... Zero -- 0 C .... Carry constant st_N : integer := 7; constant st_V : integer := 6; constant st_B : integer := 4; constant st_D : integer := 3; constant st_I : integer := 2; constant st_Z : integer := 1; constant st_C : integer := 0; ---for pch_inc_n. signal pch_inc_input : std_logic; -- page boundary handling signal a2_abs_xy_next_cycle : std_logic_vector (5 downto 0); signal a2_indir_y_next_cycle : std_logic_vector (5 downto 0); signal a58_branch_next_cycle : std_logic_vector (5 downto 0); signal wait_a2_abs_xy_next : std_logic; signal wait_a2_indir_y_next : std_logic; signal wait_a58_branch_next : std_logic; begin ---pc page next is connected to top bit of exec_cycle pch_inc_input <= not exec_cycle(5); pch_inc_reg : d_flip_flop_bit port map(set_clk, '1', '1', '0', pch_inc_input, pch_inc_n); a2_abs_xy_next_cycle <= T4 when ea_carry = '1' else T0; a2_indir_y_next_cycle <= T5 when ea_carry = '1' else T0; a58_branch_next_cycle <= T3 when ea_carry = '1' else T0; main_p : process (set_clk, res_n, nmi_n, a2_abs_xy_next_cycle, a2_indir_y_next_cycle, a58_branch_next_cycle) ---for nmi handling variable nmi_handled_n : std_logic; ------------------------------------------------------------- ------------------------------------------------------------- ----------------------- comon routines ---------------------- ------------------------------------------------------------- ------------------------------------------------------------- ----------gate_cmd format ------3 : front port oe_n ------2 : front port we_n ------1 : back port oe_n ------0 : back port we_n procedure front_oe (signal cmd : out std_logic_vector(3 downto 0); val : in std_logic) is begin cmd(3) <= val; end; procedure front_we (signal cmd : out std_logic_vector(3 downto 0); val : in std_logic) is begin cmd(2) <= val; end; procedure back_oe (signal cmd : out std_logic_vector(3 downto 0); val : in std_logic) is begin cmd(1) <= val; end; procedure back_we (signal cmd : out std_logic_vector(3 downto 0); val : in std_logic) is begin cmd(0) <= val; end; procedure fetch_next is begin pcl_inc_n <= '0'; back_oe(pcl_cmd, '0'); back_oe(pch_cmd, '0'); back_we(pcl_cmd, '0'); back_we(pch_cmd, '1'); end procedure; procedure fetch_stop is begin pcl_inc_n <= '1'; back_oe(pcl_cmd, '1'); back_oe(pch_cmd, '1'); back_we(pcl_cmd, '1'); end procedure; procedure read_status is begin status_reg <= (others => 'Z'); stat_dec_oe_n <= '0'; end procedure; procedure disable_pins is begin --disable the last opration pins. dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; dl_ah_we_n <= '1'; dl_ah_oe_n <= '1'; dl_dh_oe_n <= '1'; sp_cmd <= "1111"; sp_oe_n <= '1'; sp_push_n <= '1'; sp_pop_n <= '1'; acc_cmd <= "1111"; x_cmd <= "1111"; y_cmd <= "1111"; abs_xy_n <= '1'; pg_next_n <= '1'; zp_n <= '1'; zp_xy_n <= '1'; rel_calc_n <= '1'; indir_n <= '1'; indir_x_n <= '1'; indir_y_n <= '1'; arith_en_n <= '1'; read_status; stat_bus_oe_n <= '1'; stat_set_flg_n <= '1'; stat_flg <= '1'; stat_bus_all_n <= '1'; stat_bus_nz_n <= '1'; stat_alu_we_n <= '1'; r_vec_oe_n <= '1'; n_vec_oe_n <= '1'; i_vec_oe_n <= '1'; wait_a2_abs_xy_next <= '0'; wait_a2_indir_y_next <= '0'; wait_a58_branch_next <= '0'; end procedure; procedure fetch_inst (inc_pcl : in std_logic) is begin if instruction = conv_std_logic_vector(16#4c#, dsize) then --if prior cycle is jump instruction, --fetch opcode from where the latch is pointing to. --latch > al. dl_al_oe_n <= '0'; pcl_cmd <= "1110"; else --fetch opcode and pcl increment. pcl_cmd <= "1100"; dl_al_oe_n <= '1'; end if; ad_oe_n <= '0'; pch_cmd <= "1101"; inst_we_n <= '0'; pcl_inc_n <= inc_pcl; r_nw <= '1'; d_print(string'("fetch 1")); end procedure; ---T0 cycle routine ---(along with the page boundary condition, the last ---cycle is bypassed and slided to T0.) procedure t0_cycle is begin disable_pins; if (nmi_n = '0' and nmi_handled_n = '1') then --start nmi handling... fetch_inst('1'); next_cycle <= N1; else fetch_inst('0'); next_cycle <= T1; end if; end procedure; ---common routine for single byte instruction. procedure single_inst is begin fetch_stop; next_cycle <= T0; end procedure; procedure fetch_imm is begin d_print("immediate"); fetch_next; --send data from data bus buffer. --receiver is instruction dependent. dbuf_int_oe_n <= '0'; next_cycle <= T0; end procedure; procedure set_nz_from_bus is begin --status register n/z bit update. stat_bus_nz_n <= '0'; end procedure; procedure set_zc_from_alu is begin --status register n/z bit update. stat_alu_we_n <= '0'; stat_dec_oe_n <= '1'; status_reg <= "00000011"; end procedure; procedure set_nz_from_alu is begin --status register n/z/c bit update. stat_alu_we_n <= '0'; stat_dec_oe_n <= '1'; status_reg <= "10000010"; end procedure; procedure set_nzc_from_alu is begin --status register n/z/c bit update. stat_alu_we_n <= '0'; stat_dec_oe_n <= '1'; status_reg <= "10000011"; end procedure; procedure set_nvz_from_alu is begin --status register n/z/v bit update. stat_alu_we_n <= '0'; stat_dec_oe_n <= '1'; status_reg <= "11000010"; end procedure; procedure set_nvzc_from_alu is begin stat_alu_we_n <= '0'; stat_dec_oe_n <= '1'; status_reg <= "11000011"; end procedure; --flag on/off instruction procedure set_flag (int_flg : in integer; val : in std_logic) is begin stat_dec_oe_n <= '1'; stat_set_flg_n <= '0'; --specify which to set. status_reg(7 downto int_flg + 1) <= (others =>'0'); status_reg(int_flg - 1 downto 0) <= (others =>'0'); status_reg(int_flg) <= '1'; stat_flg <= val; end procedure; --for sec/clc procedure set_flag0 (val : in std_logic) is begin stat_dec_oe_n <= '1'; stat_set_flg_n <= '0'; status_reg <= "00000001"; stat_flg <= val; end procedure; procedure fetch_low is begin d_print("fetch low 2"); --fetch next opcode (abs low). fetch_next; --latch abs low data. dbuf_int_oe_n <= '0'; dl_al_we_n <= '0'; next_cycle <= T2; end procedure; procedure abs_fetch_high is begin d_print("abs (xy) 3"); dl_al_we_n <= '1'; --latch abs hi data. fetch_next; dbuf_int_oe_n <= '0'; dl_ah_we_n <= '0'; next_cycle <= T3; end procedure; procedure abs_latch_out is begin --d_print("abs 4"); fetch_stop; dl_ah_we_n <= '1'; --latch > al/ah. dl_al_oe_n <= '0'; dl_ah_oe_n <= '0'; end procedure; procedure ea_x_out is begin -----calucurate and output effective addr back_oe(x_cmd, '0'); abs_xy_n <= '0'; end procedure; procedure ea_y_out is begin back_oe(y_cmd, '0'); abs_xy_n <= '0'; end procedure; --A.2. internal execution on memory data procedure a2_zp is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; dbuf_int_oe_n <= '0'; dl_al_we_n <= '1'; --calc zp. dl_al_oe_n <= '0'; zp_n <= '0'; next_cycle <= T0; end if; end procedure; procedure a2_abs is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then abs_latch_out; dbuf_int_oe_n <= '0'; next_cycle <= T0; end if; end procedure; procedure a2_page_next is begin --close open gate if page boundary crossed. back_we(acc_cmd, '1'); front_we(acc_cmd, '1'); front_we(x_cmd, '1'); front_we(y_cmd, '1'); stat_alu_we_n <= '1'; end procedure; procedure a2_abs_xy (is_x : in boolean) is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then --ea calc & lda pg_next_n <= '1'; abs_latch_out; if (is_x = true) then ea_x_out; else ea_y_out; end if; dbuf_int_oe_n <= '0'; wait_a2_abs_xy_next <= '1'; next_cycle <= a2_abs_xy_next_cycle; d_print("absx step 1"); elsif exec_cycle = T4 then --case page boundary crossed. --redo inst. d_print("absx 5 (page boudary crossed.)"); --next page. pg_next_n <= not ea_carry; next_cycle <= T0; end if; end procedure; procedure a2_zp_xy (is_x : in boolean) is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; --output BAL only dbuf_int_oe_n <= '0'; dl_al_we_n <= '1'; --calc zp. dl_al_oe_n <= '0'; zp_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then --t3 zp, xy zp_xy_n <= '0'; if (is_x = true) then back_oe(x_cmd, '0'); else back_oe(y_cmd, '0'); end if; next_cycle <= T0; end if; end procedure; procedure a2_indir_y is begin if exec_cycle = T1 then fetch_low; --get IAL dl_al_we_n <= '0'; elsif exec_cycle = T2 then fetch_stop; dl_al_we_n <= '1'; ---address is 00:IAL --output BAL @IAL indir_y_n <= '0'; dl_al_oe_n <= '0'; dbuf_int_oe_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then indir_y_n <= '0'; dl_al_oe_n <= '0'; --output BAH @IAL+1 dbuf_int_oe_n <= '0'; next_cycle <= T4; elsif exec_cycle = T4 then dl_al_oe_n <= '1'; dbuf_int_oe_n <= '1'; --add index y. pg_next_n <= '1'; back_oe(y_cmd, '0'); indir_y_n <= '0'; dbuf_int_oe_n <= '0'; wait_a2_indir_y_next <= '1'; next_cycle <= a2_indir_y_next_cycle; elsif exec_cycle = T5 then --case page boundary crossed. --redo inst. d_print("(indir), y (page boudary crossed.)"); --next page. pg_next_n <= not ea_carry; next_cycle <= T0; end if; end procedure; --A.3. store operation. procedure a3_zp is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; --calc zp. dl_al_oe_n <= '0'; zp_n <= '0'; r_nw <= '0'; next_cycle <= T0; end if; end procedure; procedure a3_zp_xy (is_x : in boolean) is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; --calc zp. dl_al_oe_n <= '0'; zp_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then --calc zp + index. dl_al_oe_n <= '0'; zp_n <= '0'; zp_xy_n <= '0'; if (is_x = true) then back_oe(x_cmd, '0'); else back_oe(y_cmd, '0'); end if; --write data r_nw <= '0'; next_cycle <= T0; end if; end procedure; procedure a3_abs is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then abs_latch_out; dbuf_int_oe_n <= '1'; r_nw <= '0'; next_cycle <= T0; end if; end procedure; procedure a3_abs_xy (is_x : in boolean) is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then --ea calc & lda pg_next_n <= '1'; abs_latch_out; dbuf_int_oe_n <= '1'; if (is_x = true) then ea_x_out; else ea_y_out; end if; next_cycle <= T4; elsif exec_cycle = T4 then pg_next_n <= not ea_carry; abs_latch_out; if (is_x = true) then ea_x_out; else ea_y_out; end if; r_nw <= '0'; next_cycle <= T0; end if; end procedure; procedure a3_indir_y is begin if exec_cycle = T1 then fetch_low; --get IAL dl_al_we_n <= '0'; elsif exec_cycle = T2 then fetch_stop; dl_al_we_n <= '1'; ---address is 00:IAL --output BAL @IAL indir_y_n <= '0'; dl_al_oe_n <= '0'; dbuf_int_oe_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then indir_y_n <= '0'; dl_al_oe_n <= '0'; --output BAH @IAL+1 dbuf_int_oe_n <= '0'; next_cycle <= T4; elsif exec_cycle = T4 then dl_al_oe_n <= '1'; dbuf_int_oe_n <= '1'; --add index y. pg_next_n <= '1'; back_oe(y_cmd, '0'); indir_y_n <= '0'; next_cycle <= T5; elsif exec_cycle = T5 then --page handling. back_oe(y_cmd, '1'); indir_y_n <= '0'; pg_next_n <= not ea_carry; r_nw <= '0'; next_cycle <= T0; end if; end procedure; ---A.4. read-modify-write operation procedure a4_zp is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; --t2 cycle only read dl_al_oe_n <= '0'; zp_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then dl_al_oe_n <= '0'; zp_n <= '0'; --keep data in the alu reg. arith_en_n <= '0'; dbuf_int_oe_n <= '0'; next_cycle <= T4; elsif exec_cycle = T4 then dbuf_int_oe_n <= '1'; --t5 cycle writes modified value. dl_al_oe_n <= '0'; zp_n <= '0'; r_nw <= '0'; arith_en_n <= '0'; next_cycle <= T0; end if; end procedure; procedure a4_zp_x is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then fetch_stop; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; --t2 cycle read bal only. dl_al_oe_n <= '0'; zp_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then --t3 cycle read bal + x dl_al_oe_n <= '0'; zp_n <= '0'; zp_xy_n <= '0'; back_oe(x_cmd, '0'); next_cycle <= T4; elsif exec_cycle = T4 then dl_al_oe_n <= '0'; zp_n <= '0'; zp_xy_n <= '0'; back_oe(x_cmd, '0'); --keep data in the alu reg. arith_en_n <= '0'; dbuf_int_oe_n <= '0'; next_cycle <= T5; elsif exec_cycle = T5 then dbuf_int_oe_n <= '1'; --t5 cycle writes modified value. dl_al_oe_n <= '0'; zp_n <= '0'; zp_xy_n <= '0'; back_oe(x_cmd, '0'); r_nw <= '0'; arith_en_n <= '0'; next_cycle <= T0; end if; end procedure; procedure a4_abs is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then --T3 cycle do nothing. abs_latch_out; next_cycle <= T4; elsif exec_cycle = T4 then abs_latch_out; --t4 cycle save data in the alu register only. --hardware maunual says write original data, --but this implementation doesn't write because bus shortage.... arith_en_n <= '0'; next_cycle <= T5; elsif exec_cycle = T5 then dbuf_int_oe_n <= '1'; --t5 cycle writes modified value. r_nw <= '0'; arith_en_n <= '0'; next_cycle <= T0; end if; end procedure; procedure a4_abs_x is begin if exec_cycle = T1 then fetch_low; elsif exec_cycle = T2 then abs_fetch_high; elsif exec_cycle = T3 then --T3 cycle discarded. pg_next_n <= '1'; abs_latch_out; ea_x_out; dbuf_int_oe_n <= '0'; next_cycle <= T4; elsif exec_cycle = T4 then --t4 cycle fetch only. abs_latch_out; ea_x_out; pg_next_n <= not ea_carry; next_cycle <= T5; elsif exec_cycle = T5 then --t4 cycle redo fetch and save data in the alu register only. arith_en_n <= '0'; next_cycle <= T6; elsif exec_cycle = T6 then --t5 cycle writes modified value. r_nw <= '0'; arith_en_n <= '0'; dbuf_int_oe_n <= '1'; next_cycle <= T0; end if; end procedure; -- A.5.1 push stack procedure a51_push is begin if exec_cycle = T1 then fetch_stop; next_cycle <= T2; elsif exec_cycle = T2 then back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_push_n <= '0'; sp_oe_n <= '0'; r_nw <= '0'; next_cycle <= T0; end if; end procedure; -- A.5.2 pull stack procedure a52_pull is begin if exec_cycle = T1 then fetch_stop; next_cycle <= T2; elsif exec_cycle = T2 then --stack decrement first. back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then sp_pop_n <= '1'; back_we(sp_cmd, '1'); ---pop data from stack. back_oe(sp_cmd, '0'); sp_oe_n <= '0'; dbuf_int_oe_n <= '0'; next_cycle <= T0; end if; end procedure; -- A.5.8 branch operations procedure a58_branch (int_flg : in integer; br_cond : in std_logic) is begin if exec_cycle = T1 then fetch_next; if status_reg(int_flg) = br_cond then d_print("get rel"); --latch rel value. dbuf_int_oe_n <= '0'; dl_ah_we_n <= '0'; next_cycle <= T2; else d_print("no branch"); next_cycle <= T0; end if; elsif exec_cycle = T2 then d_print("rel ea"); fetch_stop; dbuf_int_oe_n <= '1'; dl_ah_we_n <= '1'; --calc relative addr. rel_calc_n <= '0'; pg_next_n <= '1'; dl_dh_oe_n <= '0'; back_oe(pcl_cmd, '0'); back_oe(pch_cmd, '0'); back_we(pcl_cmd, '0'); wait_a58_branch_next <= '1'; next_cycle <= a58_branch_next_cycle; elsif exec_cycle = T3 then d_print("page crossed."); --page crossed. adh calc. back_we(pcl_cmd, '1'); back_oe(pcl_cmd, '0'); back_oe(pch_cmd, '0'); back_we(pch_cmd, '0'); dl_dh_oe_n <= '0'; rel_calc_n <= '0'; pg_next_n <= '0'; next_cycle <= T0; end if; end procedure; ------------------------------------------------------------- ------------------------------------------------------------- ---------------- main state machine start.... --------------- ------------------------------------------------------------- ------------------------------------------------------------- begin -- if (res_n = '0') then -- --pc l/h is reset vector. -- pcl_cmd <= "1110"; -- pch_cmd <= "1110"; -- next_cycle <= R0; -- elsif (res_n'event and res_n = '1') then -- pcl_cmd <= "1111"; -- pch_cmd <= "1111"; -- end if; -- -- if (nmi_n'event and nmi_n = '1') then -- --reset nmi handle status -- nmi_handled_n := '1'; -- end if; -- if (a2_abs_xy_next_cycle'event) then -- if (wait_a2_abs_xy_next = '1') then -- d_print("absx step 2"); -- next_cycle <= a2_abs_xy_next_cycle; -- if (ea_carry = '1') then -- a2_page_next; -- end if; -- end if; -- end if; -- -- if (a2_indir_y_next_cycle'event) then -- if (wait_a2_indir_y_next = '1') then -- d_print("indir step 2"); -- next_cycle <= a2_indir_y_next_cycle; -- if (ea_carry = '1') then -- a2_page_next; -- end if; -- end if; -- end if; -- -- if (a58_branch_next_cycle'event) then -- if (wait_a58_branch_next = '1') then -- d_print("branch step 2"); -- next_cycle <= a58_branch_next_cycle; -- if (ea_carry = '1') then -- a2_page_next; -- end if; -- end if; -- end if; --if (set_clk'event and set_clk = '1' and res_n = '1') then if (res_n = '0') then --pc l/h is reset vector. pcl_cmd <= "1110"; pch_cmd <= "1110"; next_cycle <= R0; elsif (rising_edge(set_clk)) then d_print(string'("-")); if exec_cycle = T0 then --cycle #1 t0_cycle; elsif exec_cycle = T1 or exec_cycle = T2 or exec_cycle = T3 or exec_cycle = T4 or exec_cycle = T5 or exec_cycle = T6 then --execute inst. ---asyncronous page change might happen. back_we(pch_cmd, '1'); if exec_cycle = T1 then d_print("decode and execute inst: " & conv_hex8(conv_integer(instruction))); --disable pin for jmp instruction dl_al_oe_n <= '1'; back_we(pcl_cmd, '1'); front_we(pch_cmd, '1'); --grab instruction register data. inst_we_n <= '1'; end if; --imelementation is wriiten in the order of hardware manual --appendix A. ---------------------------------------- --A.1. Single byte instruction. ---------------------------------------- if instruction = conv_std_logic_vector(16#0a#, dsize) then --asl acc mode. d_print("asl"); arith_en_n <= '0'; back_oe(acc_cmd, '0'); front_we(acc_cmd, '0'); set_nzc_from_alu; single_inst; elsif instruction = conv_std_logic_vector(16#18#, dsize) then d_print("clc"); set_flag0 ('0'); single_inst; elsif instruction = conv_std_logic_vector(16#d8#, dsize) then d_print("cld"); set_flag (st_D, '0'); single_inst; elsif instruction = conv_std_logic_vector(16#58#, dsize) then d_print("cli"); set_flag (st_I, '0'); single_inst; elsif instruction = conv_std_logic_vector(16#b8#, dsize) then d_print("clv"); set_flag (st_V, '0'); single_inst; elsif instruction = conv_std_logic_vector(16#ca#, dsize) then d_print("dex"); arith_en_n <= '0'; back_oe(x_cmd, '0'); front_we(x_cmd, '0'); --set nz bit. set_nz_from_bus; single_inst; elsif instruction = conv_std_logic_vector(16#88#, dsize) then d_print("dey"); arith_en_n <= '0'; back_oe(y_cmd, '0'); front_we(y_cmd, '0'); --set nz bit. set_nz_from_bus; single_inst; elsif instruction = conv_std_logic_vector(16#e8#, dsize) then d_print("inx"); arith_en_n <= '0'; back_oe(x_cmd, '0'); front_we(x_cmd, '0'); --set nz bit. set_nz_from_bus; single_inst; elsif instruction = conv_std_logic_vector(16#c8#, dsize) then d_print("iny"); arith_en_n <= '0'; back_oe(y_cmd, '0'); front_we(y_cmd, '0'); set_nz_from_bus; single_inst; elsif instruction = conv_std_logic_vector(16#4a#, dsize) then --lsr acc mode d_print("lsr"); arith_en_n <= '0'; back_oe(acc_cmd, '0'); front_we(acc_cmd, '0'); set_zc_from_alu; single_inst; elsif instruction = conv_std_logic_vector(16#ea#, dsize) then d_print("nop"); single_inst; elsif instruction = conv_std_logic_vector(16#2a#, dsize) then --rol acc d_print("rol"); arith_en_n <= '0'; back_oe(acc_cmd, '0'); front_we(acc_cmd, '0'); set_nzc_from_alu; single_inst; elsif instruction = conv_std_logic_vector(16#6a#, dsize) then --ror acc d_print("ror"); arith_en_n <= '0'; back_oe(acc_cmd, '0'); front_we(acc_cmd, '0'); set_nzc_from_alu; single_inst; elsif instruction = conv_std_logic_vector(16#38#, dsize) then d_print("sec"); set_flag0 ('1'); single_inst; elsif instruction = conv_std_logic_vector(16#f8#, dsize) then d_print("sed"); set_flag (st_D, '1'); single_inst; elsif instruction = conv_std_logic_vector(16#78#, dsize) then d_print("sei"); set_flag (st_I, '1'); single_inst; elsif instruction = conv_std_logic_vector(16#aa#, dsize) then d_print("tax"); set_nz_from_bus; single_inst; front_oe(acc_cmd, '0'); front_we(x_cmd, '0'); elsif instruction = conv_std_logic_vector(16#a8#, dsize) then d_print("tay"); set_nz_from_bus; single_inst; front_oe(acc_cmd, '0'); front_we(y_cmd, '0'); elsif instruction = conv_std_logic_vector(16#ba#, dsize) then d_print("tsx"); set_nz_from_bus; elsif instruction = conv_std_logic_vector(16#8a#, dsize) then d_print("txa"); set_nz_from_bus; single_inst; front_oe(x_cmd, '0'); front_we(acc_cmd, '0'); elsif instruction = conv_std_logic_vector(16#9a#, dsize) then d_print("txs"); set_nz_from_bus; single_inst; front_oe(x_cmd, '0'); front_we(sp_cmd, '0'); elsif instruction = conv_std_logic_vector(16#98#, dsize) then d_print("tya"); set_nz_from_bus; single_inst; front_oe(y_cmd, '0'); front_we(acc_cmd, '0'); ---------------------------------------- --A.2. internal execution on memory data ---------------------------------------- elsif instruction = conv_std_logic_vector(16#69#, dsize) then --imm d_print("adc"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; elsif instruction = conv_std_logic_vector(16#65#, dsize) then --zp d_print("adc"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#75#, dsize) then --zp, x d_print("adc"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#6d#, dsize) then --abs d_print("adc"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#7d#, dsize) then --abs, x d_print("adc"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#79#, dsize) then --abs, y d_print("adc"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#61#, dsize) then --(indir, x) d_print("adc"); elsif instruction = conv_std_logic_vector(16#71#, dsize) then --(indir), y d_print("adc"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#29#, dsize) then --imm d_print("and"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; elsif instruction = conv_std_logic_vector(16#25#, dsize) then --zp d_print("and"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#35#, dsize) then --zp, x d_print("and"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#2d#, dsize) then --abs d_print("and"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#3d#, dsize) then --abs, x d_print("and"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#39#, dsize) then --abs, y d_print("and"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#21#, dsize) then --(indir, x) d_print("and"); elsif instruction = conv_std_logic_vector(16#31#, dsize) then --(indir), y d_print("and"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#24#, dsize) then --zp d_print("bit"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nvz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#2c#, dsize) then --abs d_print("bit"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nvz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#c9#, dsize) then --imm d_print("cmp"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; elsif instruction = conv_std_logic_vector(16#c5#, dsize) then --zp d_print("cmp"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#d5#, dsize) then --zp, x d_print("cmp"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#cd#, dsize) then --abs d_print("cmp"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#dd#, dsize) then --abs, x d_print("cmp"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#d9#, dsize) then --abs, y d_print("cmp"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#c1#, dsize) then --(indir, x) d_print("cmp"); elsif instruction = conv_std_logic_vector(16#d1#, dsize) then --(indir), y d_print("cmp"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#e0#, dsize) then --imm d_print("cpx"); fetch_imm; arith_en_n <= '0'; back_oe(x_cmd, '0'); set_nzc_from_alu; elsif instruction = conv_std_logic_vector(16#e4#, dsize) then --zp d_print("cpx"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(x_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#ec#, dsize) then --abs d_print("cpx"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(x_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#c0#, dsize) then --imm d_print("cpy"); fetch_imm; arith_en_n <= '0'; back_oe(y_cmd, '0'); set_nzc_from_alu; elsif instruction = conv_std_logic_vector(16#c4#, dsize) then --zp d_print("cpy"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(y_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#cc#, dsize) then --abs d_print("cpy"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(y_cmd, '0'); set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#49#, dsize) then --imm d_print("eor"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; elsif instruction = conv_std_logic_vector(16#45#, dsize) then --zp d_print("eor"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#55#, dsize) then --zp, x d_print("eor"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#4d#, dsize) then --abs d_print("eor"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#5d#, dsize) then --abs, x d_print("eor"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#59#, dsize) then --abs, y d_print("eor"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#41#, dsize) then --(indir, x) d_print("eor"); elsif instruction = conv_std_logic_vector(16#51#, dsize) then --(indir), y d_print("eor"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#a9#, dsize) then --imm d_print("lda"); fetch_imm; front_we(acc_cmd, '0'); set_nz_from_bus; elsif instruction = conv_std_logic_vector(16#a5#, dsize) then --zp d_print("lda"); a2_zp; if exec_cycle = T2 then front_we(acc_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#b5#, dsize) then --zp, x d_print("lda"); a2_zp_xy(true); if exec_cycle = T3 then front_we(acc_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#ad#, dsize) then --abs d_print("lda"); a2_abs; if exec_cycle = T3 then set_nz_from_bus; front_we(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#bd#, dsize) then --abs, x d_print("lda"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then --lda. front_we(acc_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#b9#, dsize) then --abs, y d_print("lda"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then --lda. front_we(acc_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#a1#, dsize) then --(indir, x) d_print("lda"); elsif instruction = conv_std_logic_vector(16#b1#, dsize) then --(indir), y d_print("lda"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then --lda. front_we(acc_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#a2#, dsize) then --imm d_print("ldx"); fetch_imm; set_nz_from_bus; front_we(x_cmd, '0'); elsif instruction = conv_std_logic_vector(16#a6#, dsize) then --zp d_print("ldx"); a2_zp; if exec_cycle = T2 then front_we(x_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#b6#, dsize) then --zp, y d_print("ldx"); a2_zp_xy(false); if exec_cycle = T3 then front_we(x_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#ae#, dsize) then --abs d_print("ldx"); a2_abs; if exec_cycle = T3 then set_nz_from_bus; front_we(x_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#be#, dsize) then --abs, y d_print("ldx"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then front_we(x_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#a0#, dsize) then --imm d_print("ldy"); fetch_imm; set_nz_from_bus; front_we(y_cmd, '0'); elsif instruction = conv_std_logic_vector(16#a4#, dsize) then --zp d_print("ldy"); a2_zp; if exec_cycle = T2 then front_we(y_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#b4#, dsize) then --zp, x d_print("ldy"); a2_zp_xy(true); if exec_cycle = T3 then front_we(y_cmd, '0'); set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#ac#, dsize) then --abs d_print("ldy"); a2_abs; if exec_cycle = T3 then set_nz_from_bus; front_we(y_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#bc#, dsize) then --abs, x d_print("ldy"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then set_nz_from_bus; front_we(y_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#09#, dsize) then --imm d_print("ora"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; elsif instruction = conv_std_logic_vector(16#05#, dsize) then --zp d_print("ora"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#15#, dsize) then --zp, x d_print("ora"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#0d#, dsize) then --abs d_print("ora"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#1d#, dsize) then --abs, x d_print("ora"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#19#, dsize) then --abs, y d_print("ora"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#01#, dsize) then --(indir, x) d_print("ora"); elsif instruction = conv_std_logic_vector(16#11#, dsize) then --(indir), y d_print("ora"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nz_from_alu; end if; elsif instruction = conv_std_logic_vector(16#e9#, dsize) then --imm d_print("sbc"); fetch_imm; arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; elsif instruction = conv_std_logic_vector(16#e5#, dsize) then --zp d_print("sbc"); a2_zp; if exec_cycle = T2 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#f5#, dsize) then --zp, x d_print("sbc"); a2_zp_xy(true); if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#ed#, dsize) then --abs d_print("sbc"); a2_abs; if exec_cycle = T3 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#fd#, dsize) then --abs, x d_print("sbc"); a2_abs_xy(true); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#f9#, dsize) then --abs, y d_print("sbc"); a2_abs_xy(false); if exec_cycle = T3 or exec_cycle = T4 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#e1#, dsize) then --(indir, x) d_print("sbc"); elsif instruction = conv_std_logic_vector(16#f1#, dsize) then --(indir), y d_print("sbc"); a2_indir_y; if exec_cycle = T4 or exec_cycle = T5 then arith_en_n <= '0'; back_oe(acc_cmd, '0'); back_we(acc_cmd, '0'); set_nvzc_from_alu; end if; ---------------------------------------- ---A.3. store operation. ---------------------------------------- elsif instruction = conv_std_logic_vector(16#85#, dsize) then --zp d_print("sta"); a3_zp; if exec_cycle = T2 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#95#, dsize) then --zp, x d_print("sta"); a3_zp_xy(true); if exec_cycle = T2 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#8d#, dsize) then --abs d_print("sta"); a3_abs; if exec_cycle = T3 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#9d#, dsize) then --abs, x d_print("sta"); a3_abs_xy (true); if exec_cycle = T4 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#99#, dsize) then --abs, y d_print("sta"); a3_abs_xy (false); if exec_cycle = T4 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#81#, dsize) then --(indir, x) d_print("sta"); elsif instruction = conv_std_logic_vector(16#91#, dsize) then --(indir), y d_print("sta"); a3_indir_y; if exec_cycle = T5 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#86#, dsize) then --zp d_print("stx"); a3_zp; if exec_cycle = T2 then front_oe(x_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#96#, dsize) then --zp, y d_print("stx"); a3_zp_xy(false); if exec_cycle = T2 then front_oe(x_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#8e#, dsize) then --abs d_print("stx"); a3_abs; if exec_cycle = T3 then front_oe(x_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#84#, dsize) then --zp d_print("sty"); a3_zp; if exec_cycle = T2 then front_oe(y_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#94#, dsize) then --zp, x d_print("sty"); a3_zp_xy(true); if exec_cycle = T2 then front_oe(y_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#8c#, dsize) then --abs d_print("sty"); a3_abs; if exec_cycle = T3 then front_oe(y_cmd, '0'); end if; ---------------------------------------- ---A.4. read-modify-write operation ---------------------------------------- elsif instruction = conv_std_logic_vector(16#06#, dsize) then --zp d_print("asl"); a4_zp; if exec_cycle = T4 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#16#, dsize) then --zp, x d_print("asl"); a4_zp_x; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#0e#, dsize) then --abs d_print("asl"); a4_abs; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#1e#, dsize) then --abs, x d_print("asl"); a4_abs_x; if exec_cycle = T6 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#c6#, dsize) then --zp d_print("dec"); a4_zp; if exec_cycle = T4 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#d6#, dsize) then --zp, x d_print("dec"); a4_zp_x; if exec_cycle = T5 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#ce#, dsize) then --abs d_print("dec"); a4_abs; if exec_cycle = T5 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#de#, dsize) then --abs, x d_print("dec"); a4_abs_x; if exec_cycle = T6 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#e6#, dsize) then --zp d_print("inc"); a4_zp; if exec_cycle = T4 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#f6#, dsize) then --zp, x d_print("inc"); a4_zp_x; if exec_cycle = T5 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#ee#, dsize) then --abs d_print("inc"); a4_abs; if exec_cycle = T5 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#fe#, dsize) then --abs, x d_print("inc"); a4_abs_x; if exec_cycle = T6 then set_nz_from_bus; end if; elsif instruction = conv_std_logic_vector(16#46#, dsize) then --zp d_print("lsr"); a4_zp; if exec_cycle = T4 then set_zc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#56#, dsize) then --zp, x d_print("lsr"); a4_zp_x; if exec_cycle = T5 then set_zc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#4e#, dsize) then --abs d_print("lsr"); a4_abs; if exec_cycle = T5 then set_zc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#5e#, dsize) then --abs, x d_print("lsr"); a4_abs_x; if exec_cycle = T6 then set_zc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#26#, dsize) then --zp d_print("rol"); a4_zp; if exec_cycle = T4 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#36#, dsize) then --zp, x d_print("rol"); a4_zp_x; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#2e#, dsize) then --abs d_print("rol"); a4_abs; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#3e#, dsize) then --abs, x d_print("rol"); a4_abs_x; if exec_cycle = T6 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#66#, dsize) then --zp d_print("ror"); a4_zp; if exec_cycle = T4 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#76#, dsize) then --zp, x d_print("ror"); a4_zp_x; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#6e#, dsize) then --abs d_print("ror"); a4_abs; if exec_cycle = T5 then set_nzc_from_alu; end if; elsif instruction = conv_std_logic_vector(16#7e#, dsize) then --abs, x d_print("ror"); a4_abs_x; if exec_cycle = T6 then set_nzc_from_alu; end if; ---------------------------------------- --A.5. miscellaneous oprations. ---------------------------------------- -- A.5.1 push/pull elsif instruction = conv_std_logic_vector(16#08#, dsize) then d_print("php"); a51_push; if exec_cycle = T2 then stat_bus_oe_n <= '0'; end if; elsif instruction = conv_std_logic_vector(16#48#, dsize) then d_print("pha"); a51_push; if exec_cycle = T2 then front_oe(acc_cmd, '0'); end if; elsif instruction = conv_std_logic_vector(16#28#, dsize) then d_print("plp"); a52_pull; if exec_cycle = T3 then stat_dec_oe_n <= '1'; stat_bus_all_n <= '0'; end if; elsif instruction = conv_std_logic_vector(16#68#, dsize) then d_print("pla"); a52_pull; if exec_cycle = T3 then front_we(acc_cmd, '0'); set_nz_from_bus; end if; ---------------------------------------- -- A.5.3 jsr ---------------------------------------- elsif instruction = conv_std_logic_vector(16#20#, dsize) then if exec_cycle = T1 then d_print("jsr abs 2"); --fetch opcode. fetch_next; dbuf_int_oe_n <= '0'; --latch adl dl_al_we_n <= '0'; next_cycle <= T2; elsif exec_cycle = T2 then d_print("jsr 3"); fetch_stop; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; --push return addr high into stack. sp_push_n <= '0'; sp_oe_n <= '0'; front_oe(pch_cmd, '0'); back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); r_nw <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then d_print("jsr 4"); front_oe(pch_cmd, '1'); --push return addr low into stack. sp_push_n <= '0'; sp_oe_n <= '0'; front_oe(pcl_cmd, '0'); back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); r_nw <= '0'; next_cycle <= T4; elsif exec_cycle = T4 then d_print("jsr 5"); sp_push_n <= '1'; sp_oe_n <= '1'; front_oe(pcl_cmd, '1'); back_oe(sp_cmd, '1'); back_we(sp_cmd, '1'); r_nw <= '1'; --fetch last op. back_oe(pch_cmd, '0'); back_oe(pcl_cmd, '0'); dbuf_int_oe_n <= '0'; dl_ah_we_n <= '0'; next_cycle <= T5; elsif exec_cycle = T5 then d_print("jsr 6"); back_oe(pch_cmd, '1'); back_oe(pcl_cmd, '1'); dbuf_int_oe_n <= '1'; dl_ah_we_n <= '1'; --load/output pch ad_oe_n <= '1'; dl_dh_oe_n <= '0'; front_we(pch_cmd, '0'); --load pcl. dl_al_oe_n <= '0'; back_we(pcl_cmd, '0'); next_cycle <= T0; end if; --if exec_cycle = T1 then -- A.5.4 break elsif instruction = conv_std_logic_vector(16#00#, dsize) then ---------------------------------------- -- A.5.5 return from interrupt ---------------------------------------- elsif instruction = conv_std_logic_vector(16#40#, dsize) then if exec_cycle = T1 then d_print("rti 2"); fetch_stop; --pop stack (decrement only) back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; next_cycle <= T2; elsif exec_cycle = T2 then d_print("rti 3"); --pop p (status) back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; --load status reg stat_dec_oe_n <= '1'; dbuf_int_oe_n <= '0'; stat_bus_all_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then d_print("rti 4"); stat_bus_all_n <= '1'; --pop pcl back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; --load lo addr. dbuf_int_oe_n <= '0'; front_we(pcl_cmd, '0'); next_cycle <= T4; elsif exec_cycle = T4 then d_print("rti 5"); --stack decrement stop. back_we(sp_cmd, '1'); sp_pop_n <= '1'; front_we(pcl_cmd, '1'); --pop pch back_oe(sp_cmd, '0'); sp_oe_n <= '0'; --load hi addr. dbuf_int_oe_n <= '0'; front_we(pch_cmd, '0'); next_cycle <= T5; elsif exec_cycle = T5 then d_print("rti 6"); back_oe(sp_cmd, '1'); sp_oe_n <= '1'; --load hi addr. dbuf_int_oe_n <= '1'; front_we(pch_cmd, '1'); --increment pc. next_cycle <= T0; end if; --if exec_cycle = T1 then ---------------------------------------- -- A.5.6 jmp ---------------------------------------- elsif instruction = conv_std_logic_vector(16#4c#, dsize) then --abs if exec_cycle = T1 then d_print("jmp 2"); --fetch next opcode (abs low). fetch_next; --latch abs low data. dbuf_int_oe_n <= '0'; dl_al_we_n <= '0'; next_cycle <= T2; elsif exec_cycle = T2 then d_print("jmp 3"); dl_al_we_n <= '1'; --fetch abs hi fetch_next; --latch in dlh dbuf_int_oe_n <= '0'; dl_ah_we_n <= '0'; ---load pch. front_we(pch_cmd, '0'); next_cycle <= T0; end if; elsif instruction = conv_std_logic_vector(16#6c#, dsize) then --jmp (indir) if exec_cycle = T1 then d_print("jmp 2"); --fetch next opcode (abs low). fetch_next; --latch abs low data. dbuf_int_oe_n <= '0'; dl_al_we_n <= '0'; next_cycle <= T2; elsif exec_cycle = T2 then d_print("jmp 3"); dl_al_we_n <= '1'; --fetch abs hi fetch_next; --latch in dlh dbuf_int_oe_n <= '0'; dl_ah_we_n <= '0'; next_cycle <= T3; elsif exec_cycle = T3 then fetch_stop; dl_ah_we_n <= '1'; --IAH/IAL > ADL dl_ah_oe_n <= '0'; dl_al_oe_n <= '0'; front_we(pcl_cmd, '0'); next_cycle <= T4; elsif exec_cycle = T4 then dl_ah_oe_n <= '0'; dl_al_oe_n <= '0'; front_we(pcl_cmd, '1'); --IAH/IAL+1 > ADH front_we(pch_cmd, '0'); indir_n <= '0'; next_cycle <= T0; end if; ---------------------------------------- -- A.5.7 return from soubroutine ---------------------------------------- elsif instruction = conv_std_logic_vector(16#60#, dsize) then if exec_cycle = T1 then d_print("rts 2"); fetch_stop; --pop stack (decrement only) back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; next_cycle <= T2; elsif exec_cycle = T2 then d_print("rts 3"); --pop pcl back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); sp_pop_n <= '0'; sp_oe_n <= '0'; --load lo addr. dbuf_int_oe_n <= '0'; front_we(pcl_cmd, '0'); next_cycle <= T3; elsif exec_cycle = T3 then d_print("rts 4"); --stack decrement stop. back_we(sp_cmd, '1'); sp_pop_n <= '1'; front_we(pcl_cmd, '1'); --pop pch back_oe(sp_cmd, '0'); sp_oe_n <= '0'; --load hi addr. dbuf_int_oe_n <= '0'; front_we(pch_cmd, '0'); next_cycle <= T4; elsif exec_cycle = T4 then d_print("rts 5"); back_oe(sp_cmd, '1'); sp_oe_n <= '1'; --load hi addr. dbuf_int_oe_n <= '1'; front_we(pch_cmd, '1'); --empty cycle. --complying h/w manual... next_cycle <= T5; elsif exec_cycle = T5 then d_print("rts 6"); --increment pc. fetch_next; next_cycle <= T0; end if; --if exec_cycle = T1 then ---------------------------------------- -- A.5.8 branch operations ---------------------------------------- elsif instruction = conv_std_logic_vector(16#90#, dsize) then d_print("bcc"); a58_branch (st_C, '0'); elsif instruction = conv_std_logic_vector(16#b0#, dsize) then d_print("bcs"); a58_branch (st_C, '1'); elsif instruction = conv_std_logic_vector(16#f0#, dsize) then d_print("beq"); a58_branch (st_Z, '1'); elsif instruction = conv_std_logic_vector(16#30#, dsize) then d_print("bmi"); a58_branch (st_N, '1'); elsif instruction = conv_std_logic_vector(16#d0#, dsize) then d_print("bne"); a58_branch (st_Z, '0'); elsif instruction = conv_std_logic_vector(16#10#, dsize) then d_print("bpl"); a58_branch (st_N, '0'); elsif instruction = conv_std_logic_vector(16#50#, dsize) then d_print("bvc"); a58_branch (st_V, '0'); elsif instruction = conv_std_logic_vector(16#70#, dsize) then d_print("bvs"); a58_branch (st_V, '1'); else ---unknown instruction!!!! assert false report "======== unknow instruction " & conv_hex8(conv_integer(instruction)) severity failure; end if; --if instruction = conv_std_logic_vector(16#0a#, dsize) elsif exec_cycle = R0 then d_print(string'("reset")); front_we(pch_cmd, '1'); back_we(pcl_cmd, '1'); --initialize port... inst_we_n <= '1'; ad_oe_n <= '1'; dbuf_int_oe_n <= '1'; dl_al_we_n <= '1'; dl_ah_we_n <= '1'; dl_al_oe_n <= '1'; dl_ah_oe_n <= '1'; dl_dh_oe_n <= '1'; pcl_inc_n <= '1'; pcl_cmd <= "1111"; pch_cmd <= "1111"; sp_cmd <= "1111"; sp_oe_n <= '1'; sp_push_n <= '1'; sp_pop_n <= '1'; acc_cmd <= "1111"; x_cmd <= "1111"; y_cmd <= "1111"; abs_xy_n <= '1'; pg_next_n <= '1'; zp_n <= '1'; zp_xy_n <= '1'; rel_calc_n <= '1'; indir_n <= '1'; indir_x_n <= '1'; indir_y_n <= '1'; arith_en_n <= '1'; stat_dec_oe_n <= '1'; stat_bus_oe_n <= '1'; stat_set_flg_n <= '1'; stat_flg <= '1'; stat_bus_all_n <= '1'; stat_bus_nz_n <= '1'; stat_alu_we_n <= '1'; r_vec_oe_n <= '1'; n_vec_oe_n <= '1'; i_vec_oe_n <= '1'; nmi_handled_n := '1'; r_nw <= '1'; next_cycle <= R1; elsif exec_cycle = R1 or exec_cycle = N1 then pcl_cmd <= "1111"; pcl_inc_n <= '1'; inst_we_n <= '1'; dl_al_oe_n <= '1'; --push pch. d_print("R1"); ad_oe_n <= '0'; sp_push_n <= '0'; sp_oe_n <= '0'; pch_cmd <= "0111"; --front_oe(pch_cmd, '0'); back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); r_nw <= '0'; if exec_cycle = R1 then next_cycle <= R2; elsif exec_cycle = N1 then next_cycle <= N2; end if; elsif exec_cycle = R2 or exec_cycle = N2 then front_oe(pch_cmd, '1'); --push pcl. sp_push_n <= '0'; sp_oe_n <= '0'; front_oe(pcl_cmd, '0'); back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); r_nw <= '0'; if exec_cycle = R2 then next_cycle <= R3; elsif exec_cycle = N2 then next_cycle <= N3; end if; elsif exec_cycle = R3 or exec_cycle = N3 then front_oe(pcl_cmd, '1'); --push status. sp_push_n <= '0'; sp_oe_n <= '0'; stat_bus_oe_n <= '0'; back_oe(sp_cmd, '0'); back_we(sp_cmd, '0'); r_nw <= '0'; if exec_cycle = R3 then next_cycle <= R4; elsif exec_cycle = N3 then next_cycle <= N4; end if; elsif exec_cycle = R4 or exec_cycle = N4 then stat_bus_oe_n <= '1'; sp_push_n <= '1'; sp_oe_n <= '1'; front_oe(pcl_cmd, '1'); back_oe(sp_cmd, '1'); back_we(sp_cmd, '1'); --fetch reset vector low r_nw <= '1'; dbuf_int_oe_n <= '0'; front_we(pcl_cmd, '0'); if exec_cycle = R4 then r_vec_oe_n <= '0'; next_cycle <= R5; elsif exec_cycle = N4 then n_vec_oe_n <= '0'; next_cycle <= N5; end if; elsif exec_cycle = R5 or exec_cycle = N5 then front_we(pcl_cmd, '1'); --fetch reset vector hi front_we(pch_cmd, '0'); indir_n <= '0'; if exec_cycle = N5 then nmi_handled_n := '0'; end if; --start execute cycle. next_cycle <= T0; elsif exec_cycle(5) = '1' then ---pc increment and next page. d_print(string'("pch next page...")); --pcl stop increment pcl_inc_n <= '1'; back_we(pcl_cmd, '1'); --pch increment back_we(pch_cmd, '0'); back_oe(pch_cmd, '0'); if ('0' & exec_cycle(4 downto 0) = T0) then --do the t0 identical routine. disable_pins; inst_we_n <= '1'; r_nw <= '1'; elsif ('0' & exec_cycle(4 downto 0) = T1) then --if fetch cycle, preserve instrution register inst_we_n <= '1'; --TODO: must handle for jmp case??? elsif ('0' & exec_cycle(4 downto 0) = T2) then --disable previous we_n gate. --t1 cycle is fetch low oprand. dl_al_we_n <= '1'; elsif ('0' & exec_cycle(4 downto 0) = T3) then --t2 cycle is fetch high oprand. dl_ah_we_n <= '1'; end if; end if; --if exec_cycle = T0 then end if; --if (set_clk'event and set_clk = '1') end process; end rtl;