-- -- GM HC11 CPU Core -- Copyright (C) Green Mountain Computing Systems, 2000 -- All rights reserved. -- -- This file may not be freely distributed. This file has been provided -- under the terms of the GM Core License Agreement in license.txt. -- -- hc11rtl.vhd - This is the synthesizable model of the CPU Core. The testmode generic -- is used for the purpose of testing, and should be set to false for synthesis. -- -- 8/15/00 Created - Scott Thibault -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity hc11cpu is generic (testmode : boolean := false); port (E, ph1 : in std_logic; reset : in std_logic; ino : in std_logic_vector (3 downto 0); iavail : in std_logic; iaccept, CCR_X, CCR_I : out std_logic; rw : out std_logic; address : out std_logic_vector (15 downto 0); data : in std_logic_vector (7 downto 0); write_data : out std_logic_vector (7 downto 0); debug_cycle : out std_logic_vector (5 downto 0); debug_A, debug_B, debug_CCR : out std_logic_vector (7 downto 0); debug_X, debug_Y, debug_SP : out std_logic_vector (15 downto 0); debug_micro : out unsigned (5 downto 0)); -- updated by JCS constant PREFIX_Y : std_logic_vector (7 downto 0) := "00011000"; -- 18 constant PREFIX_D : std_logic_vector (7 downto 0) := "00011010"; -- 1A constant PREFIX_D_Y : std_logic_vector (7 downto 0) := "11001101"; -- CD constant ABA : std_logic_vector (7 downto 0) := "00011011"; -- 1B constant ABI : std_logic_vector (7 downto 0) := "00111010"; -- 3A constant ADCA : std_logic_vector (7 downto 0) := "10001001"; -- 89 constant ADCB : std_logic_vector (7 downto 0) := "11001001"; -- C9 constant ADDA : std_logic_vector (7 downto 0) := "10001011"; -- 8B constant ADDB : std_logic_vector (7 downto 0) := "11001011"; -- CB constant ADDD : std_logic_vector (7 downto 0) := "11000011"; -- C3 constant ANDA : std_logic_vector (7 downto 0) := "10000100"; -- 84 constant ANDB : std_logic_vector (7 downto 0) := "11000100"; -- C4 constant ASLA : std_logic_vector (7 downto 0) := "01001000"; -- 48 constant ASLB : std_logic_vector (7 downto 0) := "01011000"; -- 58 constant ASL : std_logic_vector (7 downto 0) := "01001000"; -- 48 constant ASLD : std_logic_vector (7 downto 0) := "00000101"; -- 05 constant ASRA : std_logic_vector (7 downto 0) := "01000111"; -- 47 constant ASRB : std_logic_vector (7 downto 0) := "01010111"; -- 57 constant ASR : std_logic_vector (7 downto 0) := "01000111"; -- 47 constant BCC : std_logic_vector (7 downto 0) := "00100100"; -- 24 constant BCLR_DIR : std_logic_vector (7 downto 0) := "00010101"; -- 15 constant BCLR_IND : std_logic_vector (7 downto 0) := "00011101"; -- 1D constant BCS : std_logic_vector (7 downto 0) := "00100101"; -- 25 constant BEQ : std_logic_vector (7 downto 0) := "00100111"; -- 27 constant BGE : std_logic_vector (7 downto 0) := "00101100"; -- 2C constant BGT : std_logic_vector (7 downto 0) := "00101110"; -- 2E constant BHI : std_logic_vector (7 downto 0) := "00100010"; -- 22 constant BITA : std_logic_vector (7 downto 0) := "10000101"; -- 85 constant BITB : std_logic_vector (7 downto 0) := "11000101"; -- C5 constant BLE : std_logic_vector (7 downto 0) := "00101111"; -- 2F constant BLS : std_logic_vector (7 downto 0) := "00100011"; -- 23 constant BLT : std_logic_vector (7 downto 0) := "00101101"; -- 2D constant BMI : std_logic_vector (7 downto 0) := "00101011"; -- 2B constant BNE : std_logic_vector (7 downto 0) := "00100110"; -- 26 constant BPL : std_logic_vector (7 downto 0) := "00101010"; -- 2A constant BRA : std_logic_vector (7 downto 0) := "00100000"; -- 20 constant BRCLR_DIR : std_logic_vector (7 downto 0) := "00010011"; -- 13 constant BRCLR_IND : std_logic_vector (7 downto 0) := "00011111"; -- 1F constant BRN : std_logic_vector (7 downto 0) := "00100001"; -- 21 constant BRSET_DIR : std_logic_vector (7 downto 0) := "00010010"; -- 12 constant BRSET_IND : std_logic_vector (7 downto 0) := "00011110"; -- 1E constant BSET_DIR : std_logic_vector (7 downto 0) := "00010100"; -- 14 constant BSET_IND : std_logic_vector (7 downto 0) := "00011100"; -- 1C constant BSR : std_logic_vector (7 downto 0) := "10001101"; -- 8D constant BVC : std_logic_vector (7 downto 0) := "00101000"; -- 28 constant BVS : std_logic_vector (7 downto 0) := "00101001"; -- 29 constant CBA : std_logic_vector (7 downto 0) := "00010001"; -- 11 constant CLC : std_logic_vector (7 downto 0) := "00001100"; -- 0C constant CLI : std_logic_vector (7 downto 0) := "00001110"; -- 0E constant CLV : std_logic_vector (7 downto 0) := "00001010"; -- 0A constant CLRA : std_logic_vector (7 downto 0) := "01001111"; -- 4F constant CLRB : std_logic_vector (7 downto 0) := "01011111"; -- 5F constant CLR : std_logic_vector (7 downto 0) := "01001111"; -- 4F constant CMPA : std_logic_vector (7 downto 0) := "10000001"; -- 81 constant CMPB : std_logic_vector (7 downto 0) := "11000001"; -- C1 constant COMA : std_logic_vector (7 downto 0) := "01000011"; -- 43 constant COMB : std_logic_vector (7 downto 0) := "01010011"; -- 53 constant COM : std_logic_vector (7 downto 0) := "01000011"; -- 43 constant CPI : std_logic_vector (7 downto 0) := "10001100"; -- 8C constant DAA : std_logic_vector (7 downto 0) := "00011001"; -- 19 constant DECA : std_logic_vector (7 downto 0) := "01001010"; -- 4A constant DECB : std_logic_vector (7 downto 0) := "01011010"; -- 5A constant DEC : std_logic_vector (7 downto 0) := "01001010"; -- 4A constant DES : std_logic_vector (7 downto 0) := "00110100"; -- 34 constant DEI : std_logic_vector (7 downto 0) := "00001001"; -- 09 constant EORA : std_logic_vector (7 downto 0) := "10001000"; -- 88 constant EORB : std_logic_vector (7 downto 0) := "11001000"; -- C8 constant IDIV : std_logic_vector (7 downto 0) := "00000010"; -- 02 -- added by JCS constant FDIV : std_logic_vector (7 downto 0) := "00000011"; -- 03 -- added by JCS constant INCA : std_logic_vector (7 downto 0) := "01001100"; -- 4C constant INCB : std_logic_vector (7 downto 0) := "01011100"; -- 5C constant INC : std_logic_vector (7 downto 0) := "01001100"; -- 4C constant INS : std_logic_vector (7 downto 0) := "00110001"; -- 31 constant INI : std_logic_vector (7 downto 0) := "00001000"; -- 08 constant JMP : std_logic_vector (7 downto 0) := "01001110"; -- 4E constant JSR : std_logic_vector (7 downto 0) := "10001101"; -- 8D constant LDAA : std_logic_vector (7 downto 0) := "10000110"; -- 86 constant LDAB : std_logic_vector (7 downto 0) := "11000110"; -- C6 constant LDD : std_logic_vector (7 downto 0) := "11001100"; -- CC constant LDS : std_logic_vector (7 downto 0) := "10001110"; -- 8E constant LDI : std_logic_vector (7 downto 0) := "11001110"; -- CE constant LSRA : std_logic_vector (7 downto 0) := "01000100"; -- 44 constant LSRB : std_logic_vector (7 downto 0) := "01010100"; -- 54 constant LSR : std_logic_vector (7 downto 0) := "01000100"; -- 44 constant LSRD : std_logic_vector (7 downto 0) := "00000100"; -- 04 constant MUL : std_logic_vector (7 downto 0) := "00111101"; -- 3D constant NEGA : std_logic_vector (7 downto 0) := "01000000"; -- 40 constant NEGB : std_logic_vector (7 downto 0) := "01010000"; -- 50 constant NEG : std_logic_vector (7 downto 0) := "01000000"; -- 40 constant NOP : std_logic_vector (7 downto 0) := "00000001"; -- 01 constant ORA : std_logic_vector (7 downto 0) := "10001010"; -- 8A constant ORB : std_logic_vector (7 downto 0) := "11001010"; -- CA constant PSHA : std_logic_vector (7 downto 0) := "00110110"; -- 36 constant PSHB : std_logic_vector (7 downto 0) := "00110111"; -- 37 constant PSHI : std_logic_vector (7 downto 0) := "00111100"; -- 3C constant PULA : std_logic_vector (7 downto 0) := "00110010"; -- 32 constant PULB : std_logic_vector (7 downto 0) := "00110011"; -- 33 constant PULI : std_logic_vector (7 downto 0) := "00111000"; -- 38 constant ROLA : std_logic_vector (7 downto 0) := "01001001"; -- 49 constant ROLB : std_logic_vector (7 downto 0) := "01011001"; -- 59 constant ROLc : std_logic_vector (7 downto 0) := "01001001"; -- 49 constant RORA : std_logic_vector (7 downto 0) := "01000110"; -- 46 constant RORB : std_logic_vector (7 downto 0) := "01010110"; -- 56 constant RORc : std_logic_vector (7 downto 0) := "01000110"; -- 46 constant RTI : std_logic_vector (7 downto 0) := "00111011"; -- 3B constant RTS : std_logic_vector (7 downto 0) := "00111001"; -- 39 constant SBA : std_logic_vector (7 downto 0) := "00010000"; -- 10 constant SBCA : std_logic_vector (7 downto 0) := "10000010"; -- 82 constant SBCB : std_logic_vector (7 downto 0) := "11000010"; -- C2 constant SEC : std_logic_vector (7 downto 0) := "00001101"; -- 0D constant SEI : std_logic_vector (7 downto 0) := "00001111"; -- 0F constant SEV : std_logic_vector (7 downto 0) := "00001011"; -- 0B constant STAA : std_logic_vector (7 downto 0) := "10000111"; -- 87 constant STAB : std_logic_vector (7 downto 0) := "11000111"; -- C7 constant STD : std_logic_vector (7 downto 0) := "11001101"; -- CD constant STS : std_logic_vector (7 downto 0) := "10001111"; -- 8F constant STI : std_logic_vector (7 downto 0) := "11001111"; -- CF constant SUBA : std_logic_vector (7 downto 0) := "10000000"; -- 80 constant SUBB : std_logic_vector (7 downto 0) := "11000000"; -- C0 constant SUBD : std_logic_vector (7 downto 0) := "10000011"; -- 83 constant SWI : std_logic_vector (7 downto 0) := "00111111"; -- 3F constant TAB : std_logic_vector (7 downto 0) := "00010110"; -- 16 constant TAP : std_logic_vector (7 downto 0) := "00000110"; -- 06 constant TBA : std_logic_vector (7 downto 0) := "00010111"; -- 17 constant TPA : std_logic_vector (7 downto 0) := "00000111"; -- 07 constant TSTA : std_logic_vector (7 downto 0) := "01001101"; -- 4D constant TSTB : std_logic_vector (7 downto 0) := "01011101"; -- 5D constant TST : std_logic_vector (7 downto 0) := "01001101"; -- 4D constant TSI : std_logic_vector (7 downto 0) := "00110000"; -- 30 constant TIS : std_logic_vector (7 downto 0) := "00110101"; -- 35 constant WAI : std_logic_vector (7 downto 0) := "00111110"; -- 3E constant XGDI : std_logic_vector (7 downto 0) := "10001111"; -- 8F constant IMM : std_logic_vector (1 downto 0) := "00"; constant DIR : std_logic_vector (1 downto 0) := "01"; constant EXT : std_logic_vector (1 downto 0) := "11"; constant IND : std_logic_vector (1 downto 0) := "10"; constant SBIT : integer := 7; constant XBIT : integer := 6; constant HBIT : integer := 5; constant IBIT : integer := 4; constant NBIT : integer := 3; constant ZBIT : integer := 2; constant VBIT : integer := 1; constant CBIT : integer := 0; end; architecture rtl of hc11cpu is type cpu_states is (INIT, FETCH1, FETCH2, FETCH_AGAIN, FETCH3, FETCH4, LOAD1, LOAD2, IGNORE, IGNORE2, CALCADDR, WRITE, WRITE2, WAIT_INT, INT1, INT2); type alu_ops is (ALU_PASS, ALU_ADD, ALU_ADDC, ALU_AND, ALU_LSL, ALU_LSR, ALU_ASR, ALU_CLR, ALU_OR, ALU_SUB, ALU_PASS2, ALU_XOR, ALU_MUL, ALU_LSL16, ALU_SADD16, ALU_SUBC, ALU_LSR16, ALU_ROL, ALU_ROR); type alu_loc is (ZERO, ALU_REG, ACCA, ACCB, ACCD, IX, IY, SPC, IMM8, IMM16, ANT_IMM8, SSP, ONE, BIT1, BIT4, BIT6_4, NEGONE, DEC_ADJ, MULOP, IXH, IYH, BUS_DATA, SCCR, ACCB_DIV, DIVBYZERO); -- these items added by JCS type cond_ops is (COND_PASS, COND_ADD8, COND_ADD16, COND_LOGIC8, COND_SHIFTL8, COND_SHIFTR8, COND_SHIFTL16, COND_SHIFTR16, COND_SUB8, COND_SUB16, COND_CLR, COND_SET, COND_NEG, COND_DA, COND_NZV, COND_Z16, COND_MUL, COND_LOAD16, COND_ADDLO, COND_RESTORE, COND_DIV, COND_DIVSUB, COND_DIVADD, COND_DIVSPC1, COND_DIVSPC2); -- these items added by JCS type sp_ops is (PASS_SP, SET_SP, INC_SP, DEC_SP); signal rw_i : std_logic; signal address_i, naddress, load_addr : std_logic_vector (15 downto 0); signal state,nstate : cpu_states; signal micro_cnt : unsigned (5 downto 0); -- updated by JCS signal micro_rst : std_logic; signal prev_data, datain : std_logic_vector (7 downto 0); signal PC,nPC,SP, svc_vec, ind_addr : unsigned (15 downto 0); signal branch, write_byte : std_logic; signal is_prefix_1, is_prefix_2, is_prefix_3, prefixed : std_logic; signal y_prefix, d_prefix : std_logic; signal opcode, next_opcode : std_logic_vector (7 downto 0); signal interrupt : std_logic; alias mode : std_logic_vector (1 downto 0) is opcode(5 downto 4); signal A,B,CCR : std_logic_vector (7 downto 0); signal X,Y : std_logic_vector (15 downto 0); signal sp_op : sp_ops; signal alu_op : alu_ops; signal alu_in1, alu_in2, alu_res : alu_loc; signal cond_op : cond_ops; signal shift_b : std_logic; signal shift_alu_div : std_logic; signal shift_accd_div : std_logic; signal alucond : std_logic_vector (7 downto 0); signal aluout, alureg : unsigned (15 downto 0); signal alu_int : std_logic_vector (8 downto 0); begin process (E) begin if (E'event and E='0') then prev_data <= datain; datain <= data; end if; end process; iaccept <= '0' when (state = INT1) and (interrupt = '1') else '1'; next_opcode <= data when interrupt /= '1' else WAI; process (E) begin if (E'event and E='0') then if (state = FETCH1 or (state = FETCH2 and prefixed = '1')) then opcode <= next_opcode; end if; end if; end process; process (reset,E) begin if (reset = '1') then PC <= "0000000000000000"; if (testmode) then state <= FETCH1; address_i <= "0000000000000000"; else state <= INIT; address_i <= "1111111111111110"; end if; interrupt <= '0'; else if (E'event and E='0') then PC <= nPC; state <= nstate; if (nstate /= INT1 or state = INIT) then address_i <= naddress; else address_i <= std_logic_vector(svc_vec); end if; if (CCR(IBIT) /= '1') then -- added by JCS interrupt <= iavail; else -- added by JCS interrupt <= '0'; -- added by JCS end if; -- added by JCS end if; end if; end process; process (E) begin if (E'event and E='0') then if (state = LOAD1) then load_addr <= address_i; end if; end if; end process; process (E) begin if (E'event and E='0') then if (micro_rst = '1') then micro_cnt <= (others => '0'); else micro_cnt <= micro_cnt + 1; end if; end if; end process; prefix : process (data) begin if (data = PREFIX_Y) then is_prefix_1 <= '1'; is_prefix_2 <= '0'; is_prefix_3 <= '0'; elsif (data = PREFIX_D) then is_prefix_1 <= '0'; is_prefix_2 <= '1'; is_prefix_3 <= '0'; elsif (data = PREFIX_D_Y) then is_prefix_1 <= '0'; is_prefix_2 <= '0'; is_prefix_3 <= '1'; else is_prefix_1 <= '0'; is_prefix_2 <= '0'; is_prefix_3 <= '0'; end if; end process; process (E) begin if (E'event and E='0') then if (state = FETCH1) then y_prefix <= is_prefix_1 or is_prefix_3; d_prefix <= is_prefix_2 or is_prefix_3; end if; end if; end process; prefixed <= y_prefix or d_prefix; svc_vec <= "1111111111010110" + ("00000000000" & unsigned(ino) & "0"); address_gen : process (state,y_prefix,PC,X,Y,datain) variable src : unsigned (15 downto 0); variable lo : unsigned (8 downto 0); variable hi : unsigned (7 downto 0); variable sign : boolean; begin if (state = CALCADDR) then if (y_prefix = '0') then src := unsigned(X); else src := unsigned(Y); end if; sign := false; else src := PC; sign := datain(7) = '1'; end if; lo := ("0" & src(7 downto 0)) + ("0" & unsigned(datain)); if (sign) then if (lo(8) = '0') then hi := src(15 downto 8) - 1; else hi := src(15 downto 8); end if; else if (lo(8) = '1') then hi := src(15 downto 8) + 1; else hi := src(15 downto 8); end if; end if; ind_addr <= hi & lo(7 downto 0); end process; control : process (PC,state,opcode,datain,ind_addr,data,load_addr,SP, micro_cnt,svc_vec,address_i,branch,interrupt, prefixed) variable next_PC : unsigned (15 downto 0); variable next_addr : std_logic_vector (15 downto 0); variable next_state : cpu_states; variable start : boolean; variable opclass : std_logic_vector (7 downto 0); variable even : std_logic; procedure inc_pc is begin next_PC := PC + 1; next_addr := std_logic_vector(next_PC); end; begin start := ((state = FETCH2) and (prefixed = '0')) or (state = FETCH_AGAIN); next_PC := PC; next_addr := std_logic_vector(next_PC); if (start) then micro_rst <= '1'; else micro_rst <= '0'; end if; next_state := state; if (state = FETCH1) then if (interrupt /= '1') then inc_pc; end if; next_state := FETCH2; elsif (state = INIT) then next_addr := "1111111111111110"; next_state := INT1; elsif (state = INT1) then --next_addr := std_logic_vector(unsigned(address_i)+1); next_addr := std_logic_vector(unsigned(address_i(15 downto 1)&'1')); -- updated by JCS next_state := INT2; elsif (state = INT2) then next_addr := datain & data; next_PC := unsigned(next_addr); next_state := FETCH1; else case opcode is when PREFIX_Y | PREFIX_D | PREFIX_D_Y => next_state := FETCH_AGAIN; inc_pc; when ABA | ASLA | ASLB | ASRA | ASRB | CBA | CLC | CLI | CLV | CLRA | CLRB | COMA | COMB | DAA | DECA | DECB | INCA | INCB | LSRA | LSRB | NEGA | NEGB | NOP | ROLA | ROLB | RORA | RORB | SBA | SEC | SEI | SEV | TAB | TAP | TBA | TPA | TSTA | TSTB => next_state := FETCH1; when ABI | ASLD | DEI | INI | LSRD | XGDI => if (start) then next_addr := "1111111111111111"; next_state := IGNORE; else next_state := FETCH1; end if; when BCC | BCS | BEQ | BGE | BGT | BHI | BLE | BLS | BLT | BMI | BNE | BPL | BRA | BRN | BVC | BVS => if (state = FETCH2) then next_PC := PC + 1; next_addr := "1111111111111111"; next_state := IGNORE; else if (branch = '1') then next_PC := ind_addr; else next_PC := PC; end if; next_addr := std_logic_vector(next_PC); next_state := FETCH1; end if; when BSR => if (state = FETCH2) then next_PC := next_PC + 1; next_addr := (others => '1'); next_state := IGNORE; elsif (state = IGNORE) then -- next_PC := ind_addr; -- commented out by JCS 09/18/2006 next_addr := std_logic_vector(ind_addr); next_state := FETCH3; elsif (state = FETCH3) then next_PC := unsigned(address_i); -- added by JCS 09/18/2006 next_addr := std_logic_vector(SP); next_state := WRITE; elsif (state = WRITE) then if (micro_cnt(0) = '0') then next_addr := std_logic_vector(SP); next_state := WRITE; else next_addr := std_logic_vector(next_PC); next_state := FETCH1; end if; end if; when BCLR_DIR | BSET_DIR => if (state = FETCH2) then next_addr := "00000000" & data; next_state := LOAD1; elsif (state = LOAD1) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := "1111111111111111"; next_state := IGNORE; elsif (state = IGNORE) then next_addr := load_addr; next_state := WRITE; else inc_pc; next_state := FETCH1; end if; when BCLR_IND | BSET_IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := LOAD1; elsif (state = LOAD1) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := "1111111111111111"; next_state := IGNORE; elsif (state = IGNORE) then next_addr := load_addr; next_state := WRITE; else inc_pc; next_state := FETCH1; end if; when BRCLR_DIR | BRSET_DIR => if (state = FETCH2) then next_addr := "00000000" & data; next_state := LOAD1; elsif (state = LOAD1) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then inc_pc; next_state := FETCH4; elsif (state = FETCH4) then next_PC := PC + 1; next_addr := "1111111111111111"; next_state := IGNORE; else if (branch = '1') then next_PC := ind_addr; else next_PC := PC; end if; next_addr := std_logic_vector(next_PC); next_state := FETCH1; end if; when BRCLR_IND | BRSET_IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := LOAD1; elsif (state = LOAD1) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then inc_pc; next_state := FETCH4; elsif (state = FETCH4) then next_PC := PC + 1; next_addr := "1111111111111111"; next_state := IGNORE; else if (branch = '1') then next_PC := ind_addr; else next_PC := PC; end if; next_addr := std_logic_vector(next_PC); next_state := FETCH1; end if; when DES | INS => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := IGNORE; else next_state := FETCH1; end if; when MUL => if (state = FETCH2) then next_addr := "1111111111111111"; next_state := IGNORE; else if (micro_cnt(3 downto 0) /= "0111") then next_addr := "1111111111111111"; -- moved to here by JCS next_state := IGNORE; else next_state := FETCH1; end if; end if; -- added by JCS when IDIV | FDIV => if (micro_cnt = "100110") then next_state := FETCH1; else next_addr := "1111111111111111"; next_state := IGNORE; end if; -- when PSHA | PSHB => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := WRITE; else next_state := FETCH1; end if; when PSHI => if (start) then next_addr := std_logic_vector(SP); next_state := WRITE; else if (micro_cnt(0) = '0') then next_addr := std_logic_vector(SP); next_state := WRITE; else next_state := FETCH1; end if; end if; when PULA | PULB => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := IGNORE; elsif (state = IGNORE) then next_addr := std_logic_vector(SP); next_state := LOAD1; else next_state := FETCH1; end if; when PULI => if (start) then next_addr := std_logic_vector(SP); next_state := IGNORE; elsif (state = IGNORE) then next_addr := std_logic_vector(SP); next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(SP); next_state := LOAD2; else next_state := FETCH1; end if; when RTI => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := IGNORE; else if (state = IGNORE or state = LOAD1) then if (micro_cnt(3 downto 0) /= "0111") then next_addr := std_logic_vector(SP); next_state := LOAD1; else next_addr := std_logic_vector(SP); next_state := FETCH3; end if; elsif (state = FETCH3) then next_addr := std_logic_vector(SP); next_state := FETCH4; else next_addr := datain & data; next_PC := unsigned(next_addr); next_state := FETCH1; end if; end if; when RTS => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := IGNORE; elsif (state = IGNORE) then next_addr := std_logic_vector(SP); next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(SP); next_state := LOAD2; else next_addr := datain & data; next_PC := unsigned(next_addr); next_state := FETCH1; end if; when SWI | WAI => if (state = FETCH2) then next_addr := std_logic_vector(SP); next_state := WRITE; elsif (state = WRITE) then if (micro_cnt(3 downto 0) /= "0111") then -- updated by JCS next_addr := std_logic_vector(SP); next_state := WRITE; else next_addr := std_logic_vector(SP); next_state := WRITE2; end if; elsif (state = WRITE2) then -- commented by JCS -- if (micro_cnt(0) = '1') then -- next_addr := std_logic_vector(SP); -- next_state := WRITE2; -- else next_addr := std_logic_vector(address_i); -- updated by JCS if (opcode = SWI) then next_state := IGNORE; else next_state := WAIT_INT; end if; -- end if; elsif (state = IGNORE) then next_addr := "1111111111110110"; next_state := LOAD1; elsif (state = LOAD1) then --next_addr := std_logic_vector(unsigned(address_i)+1); next_addr := std_logic_vector(unsigned(address_i(15 downto 1))&'1'); -- OR with 1 instead of addition, vectors must start on even numbered addresses next_state := LOAD2; elsif (state = WAIT_INT) then next_addr := std_logic_vector(address_i); -- updated by JCS if (interrupt = '1') then next_state := INT1; else next_state := WAIT_INT; end if; else next_addr := datain & data; next_PC := unsigned(next_addr); next_state := FETCH1; end if; when TSI => if (start) then next_addr := std_logic_vector(SP); next_state := IGNORE; else next_state := FETCH1; end if; when TIS => if (start) then next_addr := "1111111111111111"; next_state := IGNORE; else next_state := FETCH1; end if; when others => opclass := (opcode and "11001111"); case opclass is when ASL | ASR | CLR | COM | DEC | INC | LSR | NEG | ROLc | RORc | TST => case mode is when EXT => if (state = FETCH2) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := datain & data; next_state := LOAD1; elsif (state = LOAD1) then next_addr := "1111111111111111"; next_state := IGNORE; elsif (state = IGNORE) then if (opclass /= TST) then next_addr := load_addr; next_state := WRITE; else next_addr := "1111111111111111"; next_state := IGNORE2; end if; else inc_pc; next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := LOAD1; elsif (state = LOAD1) then next_addr := "1111111111111111"; next_state := IGNORE; elsif (state = IGNORE) then if (opclass /= TST) then next_addr := load_addr; next_state := WRITE; else next_addr := "1111111111111111"; next_state := IGNORE2; end if; else inc_pc; next_state := FETCH1; end if; when others => null; end case; when ADCA | ADCB | ADDA | ADDB | ANDA | ANDB | BITA | BITB | CMPA | CMPB | EORA | EORB | LDAA | LDAB | ORA | ORB | SBCA | SBCB | STAA | STAB | SUBA | SUBB => case mode is when IMM => inc_pc; next_state := FETCH1; when DIR => if (state = FETCH2) then next_addr := "00000000" & data; if (opclass = STAA or opclass = STAB) then next_state := WRITE; else next_state := LOAD1; end if; else inc_pc; next_state := FETCH1; end if; when EXT => if (state = FETCH2) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := datain & data; if (opclass = STAA or opclass = STAB) then next_state := WRITE; else next_state := LOAD1; end if; else inc_pc; next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); if (opclass = STAA or opclass = STAB) then next_state := WRITE; else next_state := LOAD1; end if; else inc_pc; next_state := FETCH1; end if; when others => null; end case; when ADDD | SUBD | CPI => case mode is when IMM => if (start) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := "1111111111111111"; next_state := IGNORE; else inc_pc; next_state := FETCH1; end if; when DIR => if (start) then next_addr := "00000000" & data; next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; elsif (state = LOAD2) then next_addr := "1111111111111111"; next_state := IGNORE; else inc_pc; next_state := FETCH1; end if; when EXT => if (start) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := datain & data; next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; elsif (state = LOAD2) then next_addr := "1111111111111111"; next_state := IGNORE; else inc_pc; next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; elsif (state = LOAD2) then next_addr := "1111111111111111"; next_state := IGNORE; else inc_pc; next_state := FETCH1; end if; when others => null; end case; when LDD | LDS | LDI => case mode is when IMM => if (start) then inc_pc; next_state := FETCH3; else inc_pc; next_state := FETCH1; end if; when DIR => if (start) then next_addr := "00000000" & data; next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; else inc_pc; next_state := FETCH1; end if; when EXT => if (start) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := datain & data; next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; else inc_pc; next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := LOAD1; elsif (state = LOAD1) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := LOAD2; else inc_pc; next_state := FETCH1; end if; when others => null; end case; when STD | STS | STI => case mode is when DIR => if (start) then next_addr := "00000000" & data; next_state := WRITE; elsif (state = WRITE) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := WRITE2; else inc_pc; next_state := FETCH1; end if; when EXT => if (start) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_addr := datain & data; next_state := WRITE; elsif (state = WRITE) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := WRITE2; else inc_pc; next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_addr := std_logic_vector(ind_addr); next_state := WRITE; elsif (state = WRITE) then next_addr := std_logic_vector(unsigned(address_i)+1); next_state := WRITE2; else inc_pc; next_state := FETCH1; end if; when others => null; end case; when JMP => case mode is when EXT => if (state = FETCH2) then inc_pc; next_state := FETCH3; else next_addr := datain & data; next_PC := unsigned(next_addr); next_state := FETCH1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; else next_PC := ind_addr; next_addr := std_logic_vector(ind_addr); next_state := FETCH1; end if; when others => null; end case; when JSR => case mode is when DIR => if (state = FETCH2) then next_PC := PC + 1; next_addr := "00000000" & data; next_state := LOAD1; end if; when EXT => if (state = FETCH2) then inc_pc; next_state := FETCH3; elsif (state = FETCH3) then next_PC := PC + 1; next_addr := datain & data; next_state := LOAD1; end if; when IND => if (start) then next_addr := "1111111111111111"; next_state := CALCADDR; elsif (state = CALCADDR) then next_PC := PC + 1; next_addr := std_logic_vector(ind_addr); next_state := LOAD1; end if; when others => null; end case; if (state = LOAD1) then next_addr := std_logic_vector(SP); next_state := WRITE; elsif (state = WRITE) then next_PC := unsigned(load_addr); if (mode = DIR) then even := '1'; else even := '0'; end if; if (micro_cnt(0) = even) then next_addr := std_logic_vector(SP); next_state := WRITE; else next_addr := std_logic_vector(next_PC); next_state := FETCH1; end if; end if; when others => null; end case; end case; end if; nPC <= next_PC; nstate <= next_state; naddress <= next_addr; end process; decode : process (opcode, state, micro_cnt, micro_rst, y_prefix, d_prefix, alureg, CCR) variable spop_out : sp_ops; variable aluop_out : alu_ops; variable condop_out : cond_ops; variable aluin1_out, aluin2_out, alures_out : alu_loc; variable writebyte_out : std_logic; variable opclass : std_logic_vector (7 downto 0); variable even : std_logic; variable start : boolean; procedure decode_single(op : alu_ops; cond : cond_ops; src1, src2, res : alu_loc) is begin if (state = FETCH2) then aluop_out := op; condop_out := cond; aluin1_out := src1; aluin2_out := src2; alures_out := res; end if; end; procedure decode_mode8(op1 : alu_ops; op2 : cond_ops; src, res : alu_loc) is begin if (state = FETCH1) then aluin1_out := src; aluin2_out := IMM8; aluop_out := op1; condop_out := op2; alures_out := res; end if; end; procedure decode_mode16(op1,op2 : alu_ops; cop1,cop2 : cond_ops; src1, src2, res1, res2 : alu_loc) is begin if (state = FETCH3 or state = LOAD2) then aluop_out := ALU_PASS; aluin1_out := IMM8; alures_out := ALU_REG; elsif (state = IGNORE) then aluin1_out := src1; aluin2_out := IMM8; aluop_out := op1; condop_out := cop1; alures_out := res1; elsif (state = FETCH1) then aluin1_out := src2; aluin2_out := ALU_REG; aluop_out := op2; condop_out := cop2; alures_out := res2; end if; end; procedure decode_load16(res : alu_loc) is begin if (state = FETCH1) then aluin1_out := IMM16; aluop_out := ALU_PASS; condop_out := COND_LOAD16; alures_out := res; end if; end; procedure decode_store16(src : alu_loc) is begin if (state = WRITE) then writebyte_out := '1'; aluin1_out := src; aluop_out := ALU_PASS; alures_out := BUS_DATA; elsif (state = WRITE2) then aluin1_out := src; aluop_out := ALU_PASS; alures_out := BUS_DATA; condop_out := COND_LOAD16; end if; end; procedure decode_rw8(op1 : alu_ops; op2 : cond_ops; src1, src2 : alu_loc) is begin if (state = IGNORE) then aluin1_out := src1; aluin2_out := src2; aluop_out := op1; condop_out := op2; alures_out := ALU_REG; end if; end; begin spop_out := PASS_SP; aluop_out := ALU_PASS; condop_out := COND_PASS; aluin1_out := ACCA; aluin2_out := ACCB; alures_out := ZERO; writebyte_out := '0'; start := micro_rst = '1'; shift_b <= '0'; shift_alu_div <= '0'; shift_accd_div <= '0'; case opcode is when ABA => decode_single(ALU_ADD,COND_ADD8,ACCA,ACCB,ACCA); when CBA => decode_single(ALU_SUB,COND_SUB8,ACCA,ACCB,ZERO); when ASLA => decode_single(ALU_LSL,COND_SHIFTL8,ACCA,ZERO,ACCA); when ASLB => decode_single(ALU_LSL,COND_SHIFTL8,ACCB,ZERO,ACCB); when ASRA => decode_single(ALU_ASR,COND_SHIFTR8,ACCA,ZERO,ACCA); when ASRB => decode_single(ALU_ASR,COND_SHIFTR8,ACCB,ZERO,ACCB); when ABI => if (state = IGNORE) then aluop_out := ALU_ADD; if (y_prefix = '0') then aluin1_out := IX; alures_out := IX; else aluin1_out := IY; alures_out := IY; end if; aluin2_out := ACCB; end if; when ASLD => if (state = IGNORE) then aluop_out := ALU_LSL; condop_out := COND_SHIFTL8; aluin1_out := ACCB; alures_out := ACCB; elsif (state = FETCH1) then aluop_out := ALU_LSL16; condop_out := COND_SHIFTL16; aluin1_out := ACCA; alures_out := ACCA; end if; when BCC | BCS | BEQ | BGE | BGT | BHI | BLE | BLS | BLT | BMI | BNE | BPL | BRA | BRN | BVC | BVS => if (state = IGNORE) then aluop_out := ALU_SADD16; aluin1_out := SPC; aluin2_out := IMM8; alures_out := ALU_REG; end if; when BSR => if (state = IGNORE) then aluop_out := ALU_SADD16; aluin1_out := SPC; aluin2_out := IMM8; alures_out := ALU_REG; elsif (state = FETCH3) then spop_out := DEC_SP; aluop_out := ALU_PASS; aluin1_out := SPC; alures_out := ALU_REG; elsif (state = WRITE) then if (micro_cnt(0) = '0') then spop_out := DEC_SP; writebyte_out := '0'; else writebyte_out := '1'; end if; end if; when BCLR_DIR | BCLR_IND => decode_rw8(ALU_CLR,COND_LOGIC8,ANT_IMM8,IMM8); when BSET_DIR | BSET_IND => decode_rw8(ALU_OR,COND_LOGIC8,ANT_IMM8,IMM8); when BRCLR_DIR | BRCLR_IND | BRSET_DIR | BRSET_IND => if (state = FETCH4) then if (opcode = BRCLR_DIR or opcode = BRCLR_IND) then aluop_out := ALU_AND; else aluop_out := ALU_CLR; end if; alures_out := ALU_REG; aluin1_out := IMM8; aluin2_out := ANT_IMM8; elsif (state = IGNORE) then aluop_out := ALU_SADD16; aluin1_out := SPC; aluin2_out := IMM8; alures_out := ALU_REG; end if; when CLC => condop_out := COND_CLR; aluin1_out := ONE; when CLI => condop_out := COND_CLR; aluin1_out := BIT4; when CLV => condop_out := COND_CLR; aluin1_out := BIT1; when SEC => condop_out := COND_SET; aluin1_out := ONE; when SEI => condop_out := COND_SET; aluin1_out := BIT4; when SEV => condop_out := COND_SET; aluin1_out := BIT1; when CLRA => decode_single(ALU_PASS,COND_SHIFTL8,ZERO,ZERO,ACCA); when CLRB => decode_single(ALU_PASS,COND_SHIFTL8,ZERO,ZERO,ACCB); when COMA => decode_single(ALU_SUB,COND_NEG,NEGONE,ACCA,ACCA); when COMB => decode_single(ALU_SUB,COND_NEG,NEGONE,ACCB,ACCB); when DECA => decode_single(ALU_SUB,COND_NZV,ACCA,ONE,ACCA); when DECB => decode_single(ALU_SUB,COND_NZV,ACCB,ONE,ACCB); when DES => if (state = FETCH2) then spop_out := DEC_SP; end if; when INCA => decode_single(ALU_ADD,COND_NZV,ACCA,ONE,ACCA); when INCB => decode_single(ALU_ADD,COND_NZV,ACCB,ONE,ACCB); when INS => if (state = FETCH2) then spop_out := INC_SP; end if; when DAA => decode_single(ALU_ADD,COND_DA,ACCA,DEC_ADJ,ACCA); when DEI => if (state = IGNORE) then aluop_out := ALU_SUB; condop_out := COND_Z16; if (y_prefix = '0') then aluin1_out := IX; alures_out := IX; else aluin1_out := IY; alures_out := IY; end if; aluin2_out := ONE; end if; when INI => if (state = IGNORE) then aluop_out := ALU_ADD; condop_out := COND_Z16; if (y_prefix = '0') then aluin1_out := IX; alures_out := IX; else aluin1_out := IY; alures_out := IY; end if; aluin2_out := ONE; end if; when LSRA => decode_single(ALU_LSR,COND_SHIFTR8,ACCA,ZERO,ACCA); when LSRB => decode_single(ALU_LSR,COND_SHIFTR8,ACCB,ZERO,ACCB); when LSRD => if (state = IGNORE) then aluop_out := ALU_LSR; condop_out := COND_SHIFTR8; aluin1_out := ACCA; alures_out := ACCA; elsif (state = FETCH1) then aluop_out := ALU_LSR16; condop_out := COND_SHIFTR16; aluin1_out := ACCB; alures_out := ACCB; end if; when MUL => if (state = FETCH2) then aluop_out := ALU_PASS; aluin1_out := ZERO; alures_out := ALU_REG; elsif (state = IGNORE) then aluop_out := ALU_MUL; condop_out := COND_MUL; aluin1_out := ALU_REG; aluin2_out := MULOP; alures_out := ALU_REG; shift_b <= '1'; else aluop_out := ALU_PASS; aluin1_out := ALU_REG; alures_out := ACCA; end if; -- added by JCS when IDIV | FDIV => if (state = FETCH2) then aluop_out := ALU_SUB; condop_out := COND_DIVSPC1; aluin1_out := ACCB; aluin2_out := IX; elsif (micro_cnt = "000000") then aluop_out := ALU_SUBC; condop_out := COND_DIVSPC2; aluin1_out := ACCA; aluin2_out := IXH; elsif (micro_cnt = "000001") then aluop_out := ALU_PASS; alures_out := ALU_REG; if (opcode = IDIV) then aluin1_out := ACCD; else aluin1_out := ZERO; condop_out := COND_DIVSPC1; end if; elsif (micro_cnt = "000010") then aluop_out := ALU_PASS; aluin1_out := ZERO; if (opcode = IDIV) then alures_out := ACCD; end if; elsif (micro_cnt = "100011") then if (alureg(0) = '0') then aluop_out := ALU_ADD; condop_out := COND_DIVADD; aluin1_out := ACCB; aluin2_out := IX; alures_out := ACCB; end if; elsif (micro_cnt = "100100") then if (alureg(0) = '0') then aluop_out := ALU_ADDC; aluin1_out := ACCA; aluin2_out := IXH; alures_out := ACCA; end if; elsif (micro_cnt = "100101") then aluop_out := ALU_PASS; aluin1_out := IX; condop_out := COND_DIV; elsif (micro_cnt = "100110") then if (CCR(CBIT) = '1') or (CCR(VBIT) = '1') then aluop_out := ALU_PASS; aluin1_out := DIVBYZERO; alures_out := ALU_REG; end if; elsif (micro_cnt = "100111") then aluop_out := ALU_PASS; aluin1_out := ALU_REG; alures_out := IX; condop_out := COND_Z16; else if (micro_cnt(0) = '1') then shift_accd_div <= '1'; if (alureg(0) = '0') and (micro_cnt /= "000011") then aluop_out := ALU_ADD; condop_out := COND_DIVADD; else aluop_out := ALU_SUB; condop_out := COND_DIVSUB; end if; aluin1_out := ACCB_DIV; aluin2_out := IX; alures_out := ACCB; else shift_alu_div <= '1'; if (alureg(0) = '0') and (micro_cnt /= "000100") then aluop_out := ALU_ADDC; condop_out := COND_DIVADD; else aluop_out := ALU_SUBC; condop_out := COND_DIVSUB; end if; aluin1_out := ACCA; aluin2_out := IXH; alures_out := ACCA; end if; end if; -- when NEGA => decode_single(ALU_SUB,COND_SUB8,ZERO,ACCA,ACCA); when NEGB => decode_single(ALU_SUB,COND_SUB8,ZERO,ACCB,ACCB); when PSHA | PSHB => if (state = FETCH2) then aluop_out := ALU_PASS; if (opcode(0) = '0') then aluin1_out := ACCA; else aluin1_out := ACCB; end if; alures_out := ALU_REG; elsif (state = WRITE) then spop_out := DEC_SP; end if; when PSHI => if (start) then spop_out := DEC_SP; aluop_out := ALU_PASS; if (y_prefix = '0') then aluin1_out := IX; else aluin1_out := IY; end if; alures_out := ALU_REG; elsif (state = WRITE) then if (micro_cnt(0) = '0') then spop_out := DEC_SP; writebyte_out := '0'; else writebyte_out := '1'; end if; end if; when PULA | PULB => if (state = FETCH2) then spop_out := INC_SP; elsif (state = FETCH1) then aluop_out := ALU_PASS; aluin1_out := IMM8; if (opcode(0) = '0') then alures_out := ACCA; else alures_out := ACCB; end if; end if; when PULI => if (start or (state = IGNORE)) then spop_out := INC_SP; elsif (state = FETCH1) then aluop_out := ALU_PASS; aluin1_out := IMM16; if (y_prefix = '0') then alures_out := IX; else alures_out := IY; end if; end if; when ROLA => decode_single(ALU_ROL,COND_SHIFTL8,ACCA,ZERO,ACCA); when ROLB => decode_single(ALU_ROL,COND_SHIFTL8,ACCB,ZERO,ACCB); when RORA => decode_single(ALU_ROR,COND_SHIFTR8,ACCA,ZERO,ACCA); when RORB => decode_single(ALU_ROR,COND_SHIFTR8,ACCB,ZERO,ACCB); when RTI => if (state = FETCH2 or state = IGNORE or state = LOAD1) then spop_out := INC_SP; end if; if (state = LOAD1) then case micro_cnt(3 downto 0) is when "0010" => condop_out := COND_RESTORE; aluin1_out := IMM8; when "0011" => aluop_out := ALU_PASS; aluin1_out := IMM8; alures_out := ACCB; when "0100" => aluop_out := ALU_PASS; aluin1_out := IMM8; alures_out := ACCA; when "0110" => aluop_out := ALU_PASS; aluin1_out := IMM16; alures_out := IX; when others => null; end case; elsif (state = FETCH3) then aluop_out := ALU_PASS; aluin1_out := IMM16; alures_out := IY; end if; when RTS => if (state = FETCH2 or state = IGNORE) then spop_out := INC_SP; end if; when SBA => decode_single(ALU_SUB,COND_SUB8,ACCA,ACCB,ACCA); when SWI | WAI => if (state = FETCH2 OR state = WRITE) then spop_out := DEC_SP; end if; if (state = WRITE or state = WRITE2) then case micro_cnt(3 downto 0) is when "0000" => aluop_out := ALU_PASS; aluin1_out := SPC; alures_out := BUS_DATA; when "0001" => writebyte_out := '1'; aluop_out := ALU_PASS; aluin1_out := SPC; alures_out := BUS_DATA; when "0010" => aluop_out := ALU_PASS; aluin1_out := IY; alures_out := BUS_DATA; when "0011" => writebyte_out := '1'; aluop_out := ALU_PASS; aluin1_out := IY; alures_out := BUS_DATA; when "0100" => aluop_out := ALU_PASS; aluin1_out := IX; alures_out := BUS_DATA; when "0101" => writebyte_out := '1'; aluop_out := ALU_PASS; aluin1_out := IX; alures_out := BUS_DATA; when "0110" => aluop_out := ALU_PASS; aluin1_out := ACCA; alures_out := BUS_DATA; when "0111" => aluop_out := ALU_PASS; aluin1_out := ACCB; alures_out := BUS_DATA; when "1000" => aluop_out := ALU_PASS; aluin1_out := SCCR; alures_out := BUS_DATA; when others => null; end case; -- elsif (state = FETCH1) then elsif (state = INT1) then condop_out := COND_SET; aluin1_out := BIT4; elsif (state = LOAD1) then condop_out := COND_SET; aluin1_out := BIT6_4; end if; when TAB => decode_single(ALU_PASS,COND_LOGIC8,ACCA,ZERO,ACCB); when TAP => decode_single(ALU_PASS,COND_RESTORE,ACCA,ZERO,ZERO); when TPA => decode_single(ALU_PASS,COND_PASS,SCCR,ZERO,ACCA); when TBA => decode_single(ALU_PASS,COND_LOGIC8,ACCB,ZERO,ACCA); when TSTA => decode_single(ALU_SUB,COND_SUB8,ACCA,ZERO,ZERO); when TSTB => decode_single(ALU_SUB,COND_SUB8,ACCB,ZERO,ZERO); when TSI => if (state = IGNORE) then -- aluop_out := ALU_PASS; -- commented out by JCS 09/19/2006 aluop_out := ALU_SADD16; -- added by JCS 09/19/2006 aluin1_out := SSP; aluin2_out := ONE; -- added by JCS 09/19/2006 if (y_prefix = '0') then alures_out := IX; else alures_out := IY; end if; end if; when TIS => if (state = IGNORE) then -- aluop_out := ALU_PASS; -- commented out by JCS 09/19/2006 aluop_out := ALU_SUB; aluin2_out := ONE; -- added by JCS 09/19/2006 if (y_prefix = '0') then aluin1_out := IX; else aluin1_out := IY; end if; spop_out := SET_SP; end if; when XGDI => if (start) then aluop_out := ALU_PASS; if (y_prefix = '0') then aluin1_out := IX; else aluin1_out := IY; end if; alures_out := ALU_REG; elsif (state = IGNORE) then aluop_out := ALU_PASS; aluin1_out := ACCD; if (y_prefix = '0') then alures_out := IX; else alures_out := IY; end if; elsif (state = FETCH1) then aluop_out := ALU_PASS; aluin1_out := ALU_REG; alures_out := ACCD; end if; when others => opclass := (opcode and "11001111"); case opclass is when ADCA => decode_mode8(ALU_ADDC,COND_ADD8,ACCA,ACCA); when ADCB => decode_mode8(ALU_ADDC,COND_ADD8,ACCB,ACCB); when ADDA => decode_mode8(ALU_ADD,COND_ADD8,ACCA,ACCA); when ADDB => decode_mode8(ALU_ADD,COND_ADD8,ACCB,ACCB); when ADDD => decode_mode16(ALU_ADD,ALU_ADDC,COND_ADDLO,COND_ADD16,ACCB,ACCA,ACCB,ACCA); when ANDA => decode_mode8(ALU_AND,COND_LOGIC8,ACCA,ACCA); when ANDB => decode_mode8(ALU_AND,COND_LOGIC8,ACCB,ACCB); when ASL => decode_rw8(ALU_LSL,COND_SHIFTL8,IMM8,ACCB); when ASR => decode_rw8(ALU_ASR,COND_SHIFTR8,IMM8,ACCB); when BITA => decode_mode8(ALU_AND,COND_LOGIC8,ACCA,ZERO); when BITB => decode_mode8(ALU_AND,COND_LOGIC8,ACCB,ZERO); when CLR => decode_rw8(ALU_PASS,COND_SHIFTL8,ZERO,IMM8); when CMPA => decode_mode8(ALU_SUB,COND_SUB8,ACCA,ZERO); when CMPB => decode_mode8(ALU_SUB,COND_SUB8,ACCB,ZERO); when COM => decode_rw8(ALU_SUB,COND_NEG,NEGONE,IMM8); when SUBD => if (d_prefix = '0') then decode_mode16(ALU_SUB,ALU_SUBC,COND_SUB8,COND_SUB16,ACCB,ACCA,ACCB,ACCA); else decode_mode16(ALU_SUB,ALU_SUBC,COND_SUB8,COND_SUB16,ACCB,ACCA,ZERO,ZERO); end if; when CPI => if (y_prefix = d_prefix) then decode_mode16(ALU_SUB,ALU_SUBC,COND_SUB8,COND_SUB16,IX,IXH,ZERO,ZERO); else decode_mode16(ALU_SUB,ALU_SUBC,COND_SUB8,COND_SUB16,IY,IYH,ZERO,ZERO); end if; when DEC => decode_rw8(ALU_SUB,COND_NZV,IMM8,ONE); when EORA => decode_mode8(ALU_XOR,COND_LOGIC8,ACCA,ACCA); when EORB => decode_mode8(ALU_XOR,COND_LOGIC8,ACCB,ACCB); when INC => decode_rw8(ALU_ADD,COND_NZV,IMM8,ONE); when JMP => decode_mode8(ALU_PASS,COND_PASS,ACCA,ZERO); when JSR => if (state = LOAD1) then spop_out := DEC_SP; aluop_out := ALU_PASS; aluin1_out := SPC; alures_out := ALU_REG; elsif (state = WRITE) then if (mode = DIR) then even := '1'; else even := '0'; end if; if (micro_cnt(0) = even) then spop_out := DEC_SP; writebyte_out := '0'; else writebyte_out := '1'; end if; end if; when LDAA => decode_mode8(ALU_PASS2,COND_LOGIC8,ACCA,ACCA); when LDAB => decode_mode8(ALU_PASS2,COND_LOGIC8,ACCA,ACCB); when LDD => decode_load16(ACCD); when LDS => if (state = FETCH1) then spop_out := SET_SP; aluin1_out := IMM16; aluop_out := ALU_PASS; condop_out := COND_LOAD16; end if; when LDI => if (y_prefix = d_prefix) then decode_load16(IX); else decode_load16(IY); end if; when LSR => decode_rw8(ALU_LSR,COND_SHIFTR8,IMM8,ACCB); when NEG => decode_rw8(ALU_SUB,COND_SUB8,ZERO,IMM8); when ORA => decode_mode8(ALU_OR,COND_LOGIC8,ACCA,ACCA); when ORB => decode_mode8(ALU_OR,COND_LOGIC8,ACCB,ACCB); when ROLc => decode_rw8(ALU_ROL,COND_SHIFTL8,IMM8,ACCB); when RORc => decode_rw8(ALU_ROR,COND_SHIFTR8,IMM8,ACCB); when SBCA => decode_mode8(ALU_SUBC,COND_SUB8,ACCA,ACCA); when SBCB => decode_mode8(ALU_SUBC,COND_SUB8,ACCB,ACCB); when STAA => if (state = WRITE) then aluin1_out := ACCA; aluop_out := ALU_PASS; alures_out := BUS_DATA; condop_out := COND_LOGIC8; end if; when STAB => if (state = WRITE) then aluin1_out := ACCB; aluop_out := ALU_PASS; alures_out := BUS_DATA; condop_out := COND_LOGIC8; end if; when STD => decode_store16(ACCD); when STS => decode_store16(SSP); when STI => if (y_prefix = d_prefix) then decode_store16(IX); else decode_store16(IY); end if; when SUBA => decode_mode8(ALU_SUB,COND_SUB8,ACCA,ACCA); when SUBB => decode_mode8(ALU_SUB,COND_SUB8,ACCB,ACCB); when TST => decode_rw8(ALU_SUB,COND_SUB8,IMM8,ZERO); when others => null; end case; end case; sp_op <= spop_out; alu_op <= aluop_out; cond_op <= condop_out; alu_res <= alures_out; alu_in1 <= aluin1_out; alu_in2 <= aluin2_out; write_byte <= writebyte_out; end process; alu : process (alu_op, cond_op, alu_in1, alu_in2, A, B, X, Y, PC, SP, CCR, prev_data, datain, alureg) variable in1,in1hi,in2 : unsigned (8 downto 0); variable alu_out, alu_hi_out, alu_int_out : unsigned (8 downto 0); variable cond_out : std_logic_vector (7 downto 0); variable carry_in : unsigned (0 downto 0); variable carry_out : std_logic; procedure calc_dec_adj(a : in unsigned (7 downto 0); ret : out unsigned (7 downto 0); carry : out std_logic) is variable valid_lo, valid_hi, half_carry : boolean; begin valid_lo := a(3 downto 0) <= 9; valid_hi := a(7 downto 4) <= 9; half_carry := CCR(HBIT) = '1'; if (CCR(CBIT) = '1') then if (half_carry or not valid_lo) then ret := "01100110"; else ret := "01100000"; end if; carry := '1'; else if (valid_lo and valid_hi and not half_carry) then ret := "00000000"; carry := '0'; elsif (valid_hi and half_carry) then ret := "00000110"; carry := '0'; elsif (not valid_lo and not half_carry) then if (not valid_hi or a(7 downto 4) = 9) then ret := "01100110"; carry := '1'; else ret := "00000110"; carry := '0'; end if; elsif (half_carry) then ret := "01100110"; carry := '1'; else ret := "01100000"; carry := '1'; end if; end if; end; begin in1hi := "000000000"; case alu_in1 is when ZERO => in1 := "000000000"; when ONE => in1 := "000000001"; when NEGONE => in1 := "111111111"; when BIT1 => in1 := "000000010"; when BIT4 => in1 := "000010000"; when BIT6_4 => in1 := "001010000"; when ACCA => in1 := "0" & unsigned(A); when ACCB => in1 := "0" & unsigned(B); -- added by JCS when ACCB_DIV => in1 := "0" & unsigned(B(6 downto 0) & alureg(15)); when DIVBYZERO => in1hi := "111111111"; in1 := "111111111"; -- when ACCD => in1hi := "0" & unsigned(A); in1 := "0" & unsigned(B); when IX => in1hi := "0" & unsigned(X(15 downto 8)); in1 := "0" & unsigned(X(7 downto 0)); when IY => in1hi := "0" & unsigned(Y(15 downto 8)); in1 := "0" & unsigned(Y(7 downto 0)); when IXH => in1 := "0" & unsigned(X(15 downto 8)); when IYH => in1 := "0" & unsigned(Y(15 downto 8)); when SPC => in1 := "0" & PC(7 downto 0); in1hi := "0" & PC(15 downto 8); when SSP => in1 := "0" & SP(7 downto 0); in1hi := "0" & SP(15 downto 8); when SCCR => in1 := "0" & unsigned(CCR); when IMM8 => in1 := "0" & unsigned(datain); when ANT_IMM8 => in1 := "0" & unsigned(prev_data); when IMM16 => in1 := "0" & unsigned(datain); in1hi := "0" & unsigned(prev_data); when ALU_REG => in1 := "0" & alureg(7 downto 0); in1hi := "0" & alureg(15 downto 8); when others => in1 := "000000000"; end case; carry_out := '0'; case alu_in2 is when ZERO => in2 := "000000000"; when ONE => in2 := "000000001"; when ACCA => in2 := "0" & unsigned(A); when ACCB => in2 := "0" & unsigned(B); when IMM8 => in2 := "0" & unsigned(datain); when ANT_IMM8 => in2 := "0" & unsigned(prev_data); when ALU_REG => in2 := "0" & alureg(7 downto 0); -- -- when DEC_ADJ => -- in2(8) := '0'; -- calc_dec_adj(in1(7 downto 0),in2(7 downto 0),carry_out); -- when MULOP => if (B(0) = '1') then in2 := "0" & unsigned(A); else in2 := "000000000"; end if; -- added by JCS when IX => in2 := "0" & unsigned(X(7 downto 0)); when IXH => in2 := "0" & unsigned(X(15 downto 8)); -- when others => in2 := "000000000"; end case; case alu_op is when ALU_ADDC | ALU_SUBC | ALU_LSL16 | ALU_LSR16 | ALU_ROL | ALU_ROR => carry_in := unsigned(CCR(CBIT downto CBIT)); when others => carry_in := "0"; end case; case alu_op is when ALU_PASS | ALU_LSR | ALU_LSR16 | ALU_ROR => alu_out := in1; when ALU_PASS2 => alu_out := in2; when ALU_ADD | ALU_MUL | ALU_ADDC | ALU_SADD16 => alu_out := in1 + in2 + carry_in; when ALU_SUB | ALU_SUBC => alu_out := in1 - in2 - carry_in; when ALU_AND => alu_out := in1 and in2; when ALU_OR => alu_out := in1 or in2; when ALU_XOR => alu_out := in1 xor in2; when ALU_LSL | ALU_LSL16 | ALU_ROL => alu_out := in1(7 downto 0) & carry_in; when ALU_ASR => alu_out := carry_in & in1(7) & in1(7 downto 1); when ALU_CLR => alu_out := in1 and not in2; end case; if (alu_out(8) = '1') then case alu_op is when ALU_SADD16 => if (in2(7) = '0') then alu_hi_out := in1hi + 1; else alu_hi_out := in1hi; end if; when ALU_ADD | ALU_MUL | ALU_ADDC => alu_hi_out := in1hi + 1; when ALU_SUB => alu_hi_out := in1hi - 1; when others => alu_hi_out := in1hi; end case; else if (alu_op = ALU_SADD16 and in2(7) = '1') then alu_hi_out := in1hi - 1; else alu_hi_out := in1hi; end if; end if; alu_int_out := alu_out; if (alu_op = ALU_LSR or alu_op = ALU_LSR16 or alu_op = ALU_ROR) then -- updated by JCS alu_out := "0" & carry_in & alu_out(7 downto 1); end if; -- added by JCS if (alu_op = ALU_MUL) then alu_out := "0" & alu_out(8 downto 1); end if; -- cond_out := CCR; -- the cond_op section was updated by JCS to seperate the bits for logic simplification if (cond_op = COND_ADD8) then cond_out(HBIT) := (in1(3) and in2(3)) or (in2(3) and not alu_out(3)) or (not alu_out(3) and in1(3)); end if; case cond_op is when COND_ADD8 | COND_LOGIC8 | COND_SHIFTL8 | COND_SHIFTR8 | COND_SUB8 | COND_NEG | COND_DA | COND_NZV | COND_ADDLO | COND_ADD16 | COND_SUB16 | COND_SHIFTL16 => cond_out(NBIT) := alu_out(7); when COND_SHIFTR16 => cond_out(NBIT) := '0'; when COND_LOAD16 => cond_out(NBIT) := alu_hi_out(7); when others => null; end case; case cond_op is when COND_ADD8 | COND_LOGIC8 | COND_SHIFTL8 | COND_SHIFTR8 | COND_SUB8 | COND_NEG | COND_DA | COND_NZV | COND_ADDLO | COND_DIVSPC1 => if (alu_out(7 downto 0) = "00000000") then cond_out(ZBIT) := '1'; else cond_out(ZBIT) := '0'; end if; when COND_DIVSUB | COND_DIVADD => cond_out(ZBIT) := A(7); when COND_ADD16 | COND_SUB16 | COND_SHIFTL16 | COND_SHIFTR16 | COND_DIVSPC2 => if (CCR(ZBIT) = '1' and alu_out(7 downto 0) = "00000000") then cond_out(ZBIT) := '1'; else cond_out(ZBIT) := '0'; end if; when COND_Z16 | COND_LOAD16 => if (alu_out(7 downto 0) = "000000000" and alu_hi_out(7 downto 0) = "00000000") then cond_out(ZBIT) := '1'; else cond_out(ZBIT) := '0'; end if; when others => null; end case; case cond_op is when COND_ADD8 | COND_DIVADD | COND_ADD16 | COND_ADDLO => cond_out(CBIT) := (in1(7) and in2(7)) or (in2(7) and not alu_out(7)) or (not alu_out(7) and in1(7)); when COND_SUB8 | COND_SUB16 | COND_DIVSUB | COND_DIVSPC1 | COND_DIVSPC2 => cond_out(CBIT) := (not in1(7) and in2(7)) or (in2(7) and alu_out(7)) or (alu_out(7) and not in1(7)); when COND_SHIFTL8 | COND_SHIFTL16 => cond_out(CBIT) := in1(7); when COND_SHIFTR8 | COND_SHIFTR16 => cond_out(CBIT) := in1(0); when COND_NEG => cond_out(CBIT):='1'; when COND_DA => cond_out(CBIT) := carry_out; when COND_MUL => cond_out(CBIT) := alu_int_out(0); -- added by JCS when COND_DIV => if (alu_out(7 downto 0) = "000000000" and alu_hi_out(7 downto 0) = "00000000") then cond_out(CBIT) := '1'; else cond_out(CBIT) := '0'; end if; -- when COND_CLR => cond_out := CCR and not std_logic_vector(in1(7 downto 0)); when COND_SET => cond_out := CCR or std_logic_vector(in1(7 downto 0)); when COND_RESTORE => cond_out(SBIT) := in1(SBIT); cond_out(XBIT) := cond_out(XBIT) and in1(XBIT); cond_out(HBIT) := in1(HBIT); cond_out(IBIT) := in1(IBIT); cond_out(NBIT) := in1(NBIT); cond_out(ZBIT) := in1(ZBIT); cond_out(VBIT) := in1(VBIT); cond_out(CBIT) := in1(CBIT); when others => null; end case; case cond_op is when COND_ADD8 | COND_ADD16 | COND_ADDLO => cond_out(VBIT) := (in1(7) and in2(7) and not alu_out(7)) or (not in1(7) and not in2(7) and alu_out(7)); -- added by JCS when COND_DIVSPC1 => if (CCR(ZBIT) = '1' or CCR(CBIT) = '0') then cond_out(VBIT) := '1'; else cond_out(VBIT) := '0'; end if; when COND_DIVSPC2 => cond_out(VBIT) := '0'; -- when COND_SUB8 | COND_SUB16 | COND_NZV => cond_out(VBIT) := (in1(7) and not in2(7) and not alu_out(7)) or (not in1(7) and in2(7) and alu_out(7)); when COND_LOGIC8 | COND_NEG | COND_LOAD16 => -- updated by JCS cond_out(VBIT) := '0'; when COND_SHIFTL8 | COND_SHIFTL16 | COND_SHIFTR8 | COND_SHIFTR16 => cond_out(VBIT) := cond_out(NBIT) xor cond_out(CBIT); when others => null; end case; alucond <= cond_out; aluout <= alu_hi_out(7 downto 0) & alu_out(7 downto 0); alu_int <= std_logic_vector(alu_int_out); end process; decode_branch : process (opcode, CCR, alureg) begin case opcode is when BCC => branch <= not CCR(CBIT); when BCS => branch <= CCR(CBIT); when BEQ => branch <= CCR(ZBIT); when BGE => branch <= not (CCR(NBIT) xor CCR(VBIT)); when BGT => branch <= not (CCR(ZBIT) or (CCR(NBIT) xor CCR(VBIT))); when BHI => branch <= not (CCR(CBIT) or CCR(ZBIT)); when BLE => branch <= CCR(ZBIT) or (CCR(NBIT) xor CCR(VBIT)); when BLS => branch <= CCR(CBIT) or CCR(ZBIT); when BLT => branch <= CCR(NBIT) xor CCR(VBIT); when BMI => branch <= CCR(NBIT); when BNE => branch <= not CCR(ZBIT); when BPL => branch <= not CCR(NBIT); when BRA => branch <= '1'; when BVC => branch <= not CCR(VBIT); when BVS => branch <= CCR(VBIT); when BRCLR_DIR | BRCLR_IND | BRSET_DIR | BRSET_IND => if (alureg(7 downto 0) = "00000000") then branch <= '1'; else branch <= '0'; end if; when BRN => branch <= '0'; when others => branch <= '0'; end case; end process; process (reset, E) begin if (reset='1') then A<="00000001"; else if (E'event and E='0') then if (alu_res = ACCA) then A<=std_logic_vector(aluout(7 downto 0)); elsif (alu_res = ACCD) then A<=std_logic_vector(aluout(15 downto 8)); elsif (shift_accd_div = '1') then -- added by JCS A<=A(6 downto 0)&B(7); -- added by JCS end if; end if; end if; end process; process (reset, E) begin if (reset='1') then B<="00000010"; else if (E'event and E='0') then if (alu_res = ACCB or alu_res = ACCD) then B<=std_logic_vector(aluout(7 downto 0)); elsif (shift_b = '1') then B<=alu_int(0) & B(7 downto 1); end if; end if; end if; end process; process (reset, E) begin if (reset='1') then X<="0000000000000011"; else if (E'event and E='0') then if (alu_res = IX) then X<=std_logic_vector(aluout); end if; end if; end if; end process; process (reset, E) begin if (reset='1') then Y<="0000000000000100"; else if (E'event and E='0') then if (alu_res = IY) then Y<=std_logic_vector(aluout); end if; end if; end if; end process; process (reset, E) begin if (reset='1') then alureg<="0000000000000100"; else if (E'event and E='0') then if (alu_res = ALU_REG) then alureg<=aluout; elsif (shift_alu_div = '1') then -- added by JCS alureg<=alureg(14 downto 0)& not (alucond(CBIT) xor CCR(ZBIT)) ; -- added by JCS end if; end if; end if; end process; process (reset, E) begin if (reset='1') then CCR<="11010000"; else if (E'event and E='0') then CCR<=alucond; end if; end if; end process; process (reset, E) begin if (reset='1') then SP<="0000000011111111"; else if (E'event and E='0') then case sp_op is when PASS_SP => null; when SET_SP => SP <= aluout; when INC_SP => SP <= SP + 1; when DEC_SP => SP <= SP - 1; end case; end if; end if; end process; process (ph1, state) begin if (ph1 = '0' and (state = WRITE or state = WRITE2)) then rw_i <= '1'; else rw_i <= '0'; end if; end process; rw <= not rw_i; process (alu_res, write_byte, alureg, aluout) begin if (alu_res = BUS_DATA) then if (write_byte = '0') then write_data <= std_logic_vector(aluout(7 downto 0)); else write_data <= std_logic_vector(aluout(15 downto 8)); end if; else if (write_byte = '0') then write_data <= std_logic_vector(alureg(7 downto 0)); else write_data <= std_logic_vector(alureg(15 downto 8)); end if; end if; end process; address <= address_i; CCR_X <= CCR(XBIT); CCR_I <= CCR(IBIT); -- debug_cycle <= std_logic_vector(to_unsigned(cpu_states'pos(state),6)); debug_micro <= micro_cnt; debug_A <= A; debug_B <= B; debug_X <= X; debug_Y <= Y; debug_CCR <= CCR; debug_SP <= std_logic_vector(SP); end;