diff options
Diffstat (limited to 'rtl/vhdl/T51_ALU.vhd')
-rw-r--r-- | rtl/vhdl/T51_ALU.vhd | 744 |
1 files changed, 744 insertions, 0 deletions
diff --git a/rtl/vhdl/T51_ALU.vhd b/rtl/vhdl/T51_ALU.vhd new file mode 100644 index 0000000..715ee53 --- /dev/null +++ b/rtl/vhdl/T51_ALU.vhd @@ -0,0 +1,744 @@ +-- +-- 8051 compatible microcontroller core +-- +-- Version : 0300 +-- +-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) +-- (c) 2004-2005 Andreas Voggeneder (andreas.voggeneder@fh-hagenberg.at) +-- +-- All rights reserved +-- +-- Redistribution and use in source and synthezised forms, with or without +-- modification, are permitted provided that the following conditions are met: +-- +-- Redistributions of source code must retain the above copyright notice, +-- this list of conditions and the following disclaimer. +-- +-- Redistributions in synthesized form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- Neither the name of the author nor the names of other contributors may +-- be used to endorse or promote products derived from this software without +-- specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. +-- +-- Please report bugs to the author, but before you do so, please +-- make sure that this is not a derivative work and that +-- you have the latest version of this file. +-- +-- The latest version of this file can be found at: +-- http://www.opencores.org/cvsweb.shtml/t51/ +-- +-- Limitations : +-- +-- File history : +-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use WORK.T51_Pack.all; + +entity T51_ALU is + generic( + tristate : integer := 0 + ); + port( + Clk : in std_logic; + Last : in std_logic; + OpCode : in std_logic_vector(7 downto 0); + ACC : in std_logic_vector(7 downto 0); + B : in std_logic_vector(7 downto 0); + IA : in std_logic_vector(7 downto 0); + IB : in std_logic_vector(7 downto 0); + Bit_Pattern : in std_logic_vector(7 downto 0); + CY_In : in std_logic; + AC_In : in std_logic; + ACC_Q : out std_logic_vector(7 downto 0); + B_Q : out std_logic_vector(7 downto 0); + IDCPBL_Q : out std_logic_vector(7 downto 0); + Div_Rdy : out std_logic; + CJNE : out std_logic; + DJNZ : out std_logic; + CY_Out : out std_logic; + AC_Out : out std_logic; + OV_Out : out std_logic; + CY_Wr : out std_logic; + AC_Wr : out std_logic; + OV_Wr : out std_logic + ); +end T51_ALU; + +architecture rtl of T51_ALU is + + signal Do_A_Imm : std_logic; + signal Do_A_Carry : std_logic; + signal Do_A_RR : std_logic; + signal Do_A_INC : std_logic; + signal Do_A_RRC : std_logic; + signal Do_A_DEC : std_logic; + signal Do_A_RL : std_logic; + signal Do_A_ADD : std_logic; + signal Do_A_RLC : std_logic; + signal Do_A_ORL : std_logic; + signal Do_A_ANL : std_logic; + signal Do_A_XRL : std_logic; + signal Do_A_MOV : std_logic; + signal Do_A_DIV : std_logic; + signal Do_A_SUBB : std_logic; + signal Do_A_MUL : std_logic; + signal Do_A_CJNE : std_logic; + signal Do_A_SWAP : std_logic; + signal Do_A_XCH : std_logic; + signal Do_A_DA : std_logic; + signal Do_A_XCHD : std_logic; + signal Do_A_CLR : std_logic; + signal Do_A_CPL : std_logic; + + -- Accumulator ALU input mux + signal AOP2 : std_logic_vector(7 downto 0); + + -- AD intermediate signal + signal ADA : std_logic_vector(8 downto 0); + + -- AddSub intermediate signals + signal AS_Carry7 : std_logic; + signal AS_AC : std_logic; + signal AS_CY : std_logic; + signal AS_Q : std_logic_vector(7 downto 0); + + signal Do_I_Imm : std_logic; + signal Do_I_INC : std_logic; + signal Do_I_DEC : std_logic; + signal Do_I_ORL : std_logic; + signal Do_I_ANL : std_logic; + signal Do_I_XRL : std_logic; + signal Do_I_MOV : std_logic; + signal Do_I_MOVD : std_logic; + signal Do_I_CJNE : std_logic; + + -- Auxiliary ALU input mux + signal IOP : std_logic_vector(7 downto 0); + + -- Auxiliary ALU delayed input + signal IA_d : std_logic_vector(7 downto 0); + + -- AddSub intermediate signals + signal CJNE_CY_n : std_logic; + signal CJNE_Q : std_logic_vector(7 downto 0); + signal CJNE_Q_ZERO : std_logic; + signal CJNE_CY : std_logic; + + -- MOV intermediate signals + signal MOV_Op : std_logic_vector(3 downto 0); + signal MOV_Q : std_logic_vector(7 downto 0); + + signal Do_B_Inv : std_logic; + signal Do_B_C_BA : std_logic; + signal Do_B_C_Dir : std_logic; + signal Do_B_BA_Dir : std_logic; + signal Do_B_MOV : std_logic; + signal Do_B_JBC : std_logic; + signal Do_B_Op : std_logic_vector(1 downto 0); + + -- Bit intermediate signals + signal Bit_Op1 : std_logic_vector(7 downto 0); + signal Bit_Op2 : std_logic_vector(7 downto 0); + signal Bit_IsOne : std_logic; + signal Bit_Result : std_logic_vector(7 downto 0); + + signal Last_r : std_logic; + + -- MulDiv intermediate signals + signal Mul_Q : std_logic_vector(15 downto 0); + signal Mul_OV : std_logic; + signal Div_Q : std_logic_vector(15 downto 0); + signal Div_OV : std_logic; + +begin + + -- Simplify some of the conditions, not all must be exclusive !!!! + + process (Clk) + begin + if Clk'event and Clk = '1' then + + -- ACC Operations + + Do_A_Imm <= '0'; + Do_A_Carry <= '0'; + Do_A_RR <= '0'; + Do_A_INC <= '0'; + Do_A_RRC <= '0'; + Do_A_DEC <= '0'; + Do_A_RL <= '0'; + Do_A_ADD <= '0'; + Do_A_RLC <= '0'; + Do_A_ORL <= '0'; + Do_A_ANL <= '0'; + Do_A_XRL <= '0'; + Do_A_MOV <= '0'; + Do_A_DIV <= '0'; + Do_A_SUBB <= '0'; + Do_A_MUL <= '0'; + Do_A_CJNE <= '0'; + Do_A_SWAP <= '0'; + Do_A_XCH <= '0'; + Do_A_DA <= '0'; + Do_A_XCHD <= '0'; + Do_A_CLR <= '0'; + Do_A_CPL <= '0'; + Do_A_Imm <= '0'; + if OpCode(3 downto 0) = "0100" then + Do_A_Imm <= '1'; + end if; + if OpCode = "00000011" then + -- 00000011 1 RR A + Do_A_RR <= '1'; + end if; + if OpCode = "00000100" then + -- 00000100 1 INC A + Do_A_INC <= '1'; + end if; + if OpCode = "00010011" then + -- 00010011 1 RRC A + Do_A_RRC <= '1'; + end if; + if OpCode = "00010100" then + -- 00010100 1 DEC A + Do_A_DEC <= '1'; + end if; + if OpCode = "00100011" then + -- 00100011 1 RL A + Do_A_RL <= '1'; + end if; + if OpCode = "00100100" or + OpCode = "00100101" or + OpCode(7 downto 1) = "0010011" or + OpCode(7 downto 3) = "00101" then + -- 00100100 2 ADD A,#data + -- 00100101 2 ADD A,data addr + -- 0010011i 1 ADD A,@Ri + -- 00101rrr 1 ADD A,Rn + Do_A_ADD <= '1'; + end if; + if OpCode = "00110011" then + -- 00110011 1 RLC A + Do_A_RLC <= '1'; + end if; + if OpCode = "00110100" or + OpCode = "00110101" or + OpCode(7 downto 1) = "0011011" or + OpCode(7 downto 3) = "00111" then + -- 00110100 2 ADDC A,#data + -- 00110101 2 ADDC A,data addr + -- 0011011i 1 ADDC A,@Ri + -- 00111rrr 1 ADDC A,Rn + Do_A_ADD <= '1'; + Do_A_Carry <= '1'; + end if; + if OpCode = "01000100" or + OpCode = "01000101" or + OpCode(7 downto 1) = "0100011" or + OpCode(7 downto 3) = "01001" then + -- 01000100 2 ORL A,#data + -- 01000101 2 ORL A,data addr + -- 0100011i 1 ORL A,@Ri + -- 01001rrr 1 ORL A,Rn + Do_A_ORL <= '1'; + end if; + if OpCode = "01010100" or + OpCode = "01010101" or + OpCode(7 downto 1) = "0101011" or + OpCode(7 downto 3) = "01011" then + -- 01010100 2 ANL A,#data + -- 01010101 2 ANL A,data addr + -- 0101011i 1 ANL A,@Ri + -- 01011rrr 1 ANL A,Rn + Do_A_ANL <= '1'; + end if; + if OpCode = "01100100" or + OpCode = "01100101" or + OpCode(7 downto 1) = "0110011" or + OpCode(7 downto 3) = "01101" then + -- 01100100 2 XRL A,#data + -- 01100101 2 XRL A,data addr + -- 0110011i 1 XRL A,@Ri + -- 01101rrr 1 XRL A,Rn + Do_A_XRL <= '1'; + end if; + if OpCode = "01110100" or + OpCode = "11100101" or + OpCode(7 downto 1) = "1110011" or + OpCode(7 downto 3) = "11101" then + -- 01110100 2 MOV A,#data + -- 10000011 1 MOVC A,@A+PC -- Not handled here + -- 10010011 1 MOVC A,@A+DPTR -- Not handled here + -- 11100000 1 MOVX A,@DPTR + -- 1110001i 1 MOVX A,@Ri + -- 11100101 2 MOV A,data addr + -- 1110011i 1 MOV A,@Ri + -- 11101rrr 1 MOV A,Rn + Do_A_MOV <= '1'; + end if; + if OpCode = "10000100" then + -- 10000100 1 DIV AB + Do_A_DIV <= '1'; + end if; + if OpCode = "10010100" or + OpCode = "10010101" or + OpCode(7 downto 1) = "1001011" or + OpCode(7 downto 3) = "10011" then + -- 10010100 2 SUBB A,#data + -- 10010101 2 SUBB A,data addr + -- 1001011i 1 SUBB A,@Ri + -- 10011rrr 1 SUBB A,Rn + Do_A_SUBB <= '1'; + Do_A_Carry <= '1'; + end if; + if OpCode = "10100100" then + -- 10100100 1 MUL AB + Do_A_MUL <= '1'; + end if; + if OpCode(7 downto 1) = "1011010" then + -- 10110100 3 CJNE A,#data,code addr + -- 10110101 3 CJNE A,data addr,code addr + Do_A_SUBB <= '1'; + Do_A_CJNE <= '1'; + end if; + if OpCode = "11000100" then + -- 11000100 1 SWAP A + Do_A_SWAP <= '1'; + end if; + if OpCode = "11000101" or + OpCode(7 downto 1) = "1100011" or + OpCode(7 downto 3) = "11001" then + -- 11000101 2 XCH A,data addr + -- 1100011i 1 XCH A,@Ri + -- 11001rrr 1 XCH A,Rn + Do_A_XCH <= '1'; + end if; + if OpCode = "11010100" then + -- 11010100 1 DA A + Do_A_DA <= '1'; + end if; + if OpCode(7 downto 1) = "1101011" then + -- 1101011i 1 XCHD A,@Ri + Do_A_XCHD <= '1'; + end if; + if OpCode = "11100100" then + -- 11100100 1 CLR A + Do_A_CLR <= '1'; + end if; + if OpCode = "11110100" then + -- 11110100 1 CPL A + Do_A_CPL <= '1'; + end if; + + -- IDCPBL Operations + + Do_I_Imm <= '0'; + Do_I_INC <= '0'; + Do_I_DEC <= '0'; + Do_I_ORL <= '0'; + Do_I_ANL <= '0'; + Do_I_XRL <= '0'; + Do_I_MOV <= '0'; + Do_I_MOVD <= '0'; + Do_I_CJNE <= '0'; + IA_d <= IA; + MOV_Op <= OpCode(7 downto 4); + if OpCode(3 downto 0) = "0011" then + Do_I_Imm <= '1'; + end if; + if OpCode = "00000101" or + OpCode(7 downto 1) = "0000011" or + OpCode(7 downto 3) = "00001" then + -- 00000101 2 INC data addr + -- 0000011i 1 INC @Ri + -- 00001rrr 1 INC Rn + Do_I_INC <= '1'; + end if; + if OpCode = "00010101" or + OpCode(7 downto 1) = "0001011" or + OpCode(7 downto 3) = "00011" or + OpCode(7 downto 3) = "11011" or + OpCode = "11010101" then + -- 00010101 2 DEC data addr + -- 0001011i 1 DEC @Ri + -- 00011rrr 1 DEC Rn + -- 11011rrr 2 DJNZ Rn,code addr + -- 11010101 3 DJNZ data addr, code addr + Do_I_DEC <= '1'; + end if; + if OpCode(7 downto 1) = "0100001" then + -- 01000010 2 ORL data addr,A + -- 01000011 3 ORL data addr,#data + Do_I_ORL <= '1'; + end if; + if OpCode(7 downto 1) = "0101001" then + -- 01010010 2 ANL data addr,A + -- 01010011 3 ANL data addr,#data + Do_I_ANL <= '1'; + end if; + if OpCode(7 downto 1) = "0110001" then + -- 01100010 2 XRL data addr,A + -- 01100011 3 XRL data addr,#data + Do_I_XRL <= '1'; + end if; + if OpCode = "01110101" or + OpCode(7 downto 1) = "0111011" or + OpCode(7 downto 3) = "01111" or + OpCode(7 downto 1) = "1000011" or + OpCode(7 downto 3) = "10001" or + OpCode = "10010000" or + OpCode(7 downto 1) = "1010011" or + OpCode(7 downto 3) = "10101" or + OpCode = "11110000" or + OpCode(7 downto 1) = "1111001" or + OpCode = "11110101" or + OpCode(7 downto 1) = "1111011" or + OpCode(7 downto 3) = "11111" or + (OpCode(7 downto 5) = "110" and OpCode(3 downto 0) = "0000") then + -- 01110101 3 MOV data addr,#data + -- 0111011i 2 MOV @Ri,#data + -- 01111rrr 2 MOV Rn,#data + -- 1000011i 2 MOV data addr,@Ri + -- 10001rrr 2 MOV data addr,Rn + -- 10010000 3 MOV DPTR,#data -- Not handled here + -- 1010011i 2 MOV @Ri,data addr + -- 10101rrr 2 MOV Rn,data addr + -- 11110000 1 MOVX @DPTR,A + -- 1111001i 1 MOVX @Ri,A + -- 11110101 2 MOV data addr,A + -- 1111011i 1 MOV @Ri,A + -- 11111rrr 1 MOV Rn,A + -- 11000000 2 PUSH data addr INC SP: MOV "@SP",<src> + -- 11010000 2 POP data addr MOV <dest>,"@SP": DEC SP + Do_I_MOV <= '1'; + end if; + if OpCode = "10000101" then + -- 10000101 3 MOV data addr,data addr + Do_I_MOVD <= '1'; + end if; + if OpCode(7 downto 1) = "1011011" or + OpCode(7 downto 3) = "10111" then + -- 1011011i 3 CJNE @Ri,#data,code addr + -- 10111rrr 3 CJNE Rn,#data,code addr + Do_I_CJNE <= '1'; + end if; + + -- Bit Operations + + Do_B_Inv <= '0'; + Do_B_C_BA <= '0'; + Do_B_C_Dir <= '0'; + Do_B_BA_Dir <= '0'; + Do_B_MOV <= '0'; + Do_B_JBC <= '0'; + Do_B_Op <= OpCode(5 downto 4); + if OpCode(1 downto 0) = "00" then + Do_B_Inv <= '1'; + end if; + if OpCode = "01110010" or + OpCode = "10000010" or + OpCode = "10100000" or + OpCode = "10100010" or + OpCode = "10110000" then + -- 01110010 2 ORL C, bit addr + -- 10000010 2 ANL C,bit addr + -- 10100000 2 ORL C,/bit addr + -- 10100010 2 MOV C,bit addr + -- 10110000 2 ANL C,/bit addr + Do_B_C_BA <= '1'; + end if; + if OpCode = "10110011" or + OpCode = "11000011" or + OpCode = "11010011" then + -- 10110011 1 CPL C + -- 11000011 1 CLR C + -- 11010011 1 SETB C + Do_B_C_Dir <= '1'; + end if; + if OpCode = "10110010" or + OpCode = "11000010" or + OpCode = "11010010" then + -- 10110010 2 CPL bit addr + -- 11000010 2 CLR bit addr + -- 11010010 2 SETB bit addr + Do_B_BA_Dir <= '1'; + end if; + if OpCode = "10010010" then + -- 10010010 2 MOV bit addr,C + Do_B_MOV <= '1'; + end if; + if OpCode = "00010000" then + -- 00010000 3 JBC bit addr, code addr + Do_B_JBC <= '1'; + end if; + + Last_r <= Last; + end if; + end process; + + -- Accumulator ALU + AddSub(ACC(3 downto 0), AOP2(3 downto 0), Do_A_SUBB, Do_A_SUBB xor (Do_A_Carry and CY_In), AS_Q(3 downto 0), AS_AC); + AddSub(ACC(6 downto 4), AOP2(6 downto 4), Do_A_SUBB, AS_AC, AS_Q(6 downto 4), AS_Carry7); + AddSub(ACC(7 downto 7), AOP2(7 downto 7), Do_A_SUBB, AS_Carry7, AS_Q(7 downto 7), AS_CY); + + -- Mul / Div + + md : T51_MD port map(Clk, ACC, B, Mul_Q, Mul_OV, Div_Q, Div_OV, Div_Rdy); + + AOP2 <= IB when Do_A_Imm = '1' else IA; + + tristate_mux: if tristate/=0 generate + ACC_Q <= "00000000" when Do_A_CLR = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC(0) & ACC(7 downto 1) when Do_A_RR = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= CY_In & ACC(7 downto 1) when Do_A_RRC = '1' else "ZZZZZZZZ"; -- Sets CY + ACC_Q <= ACC(6 downto 0) & ACC(7) when Do_A_RL = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC(6 downto 0) & CY_In when Do_A_RLC = '1' else "ZZZZZZZZ"; -- Sets CY + ACC_Q <= std_logic_vector(unsigned(ACC) + 1) when Do_A_INC = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= std_logic_vector(unsigned(ACC) - 1) when Do_A_DEC = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= not ACC when Do_A_CPL = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC or AOP2 when Do_A_ORL = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC and AOP2 when Do_A_ANL = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC xor AOP2 when Do_A_XRL = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC(3 downto 0) & ACC(7 downto 4) when Do_A_SWAP = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= IA when Do_A_XCH = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ACC(7 downto 4) & IA(3 downto 0) when Do_A_XCHD = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= AOP2 when Do_A_MOV = '1' else "ZZZZZZZZ"; -- No flags + ACC_Q <= ADA(7 downto 0) when Do_A_DA = '1' else "ZZZZZZZZ"; -- Sets CY + ACC_Q <= AS_Q when Do_A_ADD = '1' or Do_A_SUBB = '1' else "ZZZZZZZZ"; -- Sets CY, (AC, OV) + ACC_Q <= Mul_Q(7 downto 0) when Do_A_MUL = '1' else "ZZZZZZZZ"; -- Sets OV + ACC_Q <= Div_Q(7 downto 0) when Do_A_DIV = '1' else "ZZZZZZZZ"; -- Sets OV + + CY_Out <= CJNE_CY when Do_I_CJNE = '1' else 'Z'; + CY_Out <= ADA(8) when Do_A_DA = '1' else 'Z'; + CY_Out <= ACC(0) when Do_A_RRC = '1' else 'Z'; + CY_Out <= ACC(7) when Do_A_RLC = '1' else 'Z'; + CY_Out <= AS_CY xor Do_A_SUBB when Do_A_ADD = '1' or Do_A_SUBB = '1' else 'Z'; + CY_Out <= '0' when Do_A_DIV = '1' or Do_A_MUL = '1' else 'Z'; + + CY_Out <= not CY_In when Do_B_C_Dir = '1' and Do_B_Op = "11" else + '0' when Do_B_C_Dir = '1' and Do_B_Op = "00" else + '1' when Do_B_C_Dir = '1' and Do_B_Op = "01" else 'Z'; + + CY_Out <= CY_In or Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "11" and Do_B_Inv = '0' else + CY_In and Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "00" and Do_B_Inv = '0' else + CY_In or Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "10" and Do_B_Inv = '1' else + Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "10" and Do_B_Inv = '0' else + CY_In and Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "11" and Do_B_Inv = '1' else 'Z'; + + + AC_Out <= AS_AC xor Do_A_SUBB when Do_A_ADD = '1' or Do_A_SUBB = '1' else 'Z'; + + B_Q <= Mul_Q(15 downto 8) when Do_A_MUL = '1' else "ZZZZZZZZ"; -- Sets OV + B_Q <= Div_Q(15 downto 8) when Do_A_DIV = '1' else "ZZZZZZZZ"; -- Sets OV + + OV_Out <= AS_CY xor AS_Carry7 when Do_A_ADD = '1' or Do_A_SUBB = '1' else 'Z'; + OV_Out <= Div_OV when Do_A_DIV = '1' else 'Z'; + OV_Out <= Mul_OV when Do_A_MUL = '1' else 'Z'; + + IDCPBL_Q <= std_logic_vector(unsigned(IA) + 1) when Do_I_INC = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= std_logic_vector(unsigned(IA) - 1) when Do_I_DEC = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= IOP or IA when Do_I_ORL = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= IOP and IA when Do_I_ANL = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= IOP xor IA when Do_I_XRL = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= ACC when Do_A_XCH = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= IA(7 downto 4) & ACC(3 downto 0) when Do_A_XCHD = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= Bit_Result when Do_B_JBC = '1' or Do_B_BA_Dir = '1' or Do_B_MOV = '1' else "ZZZZZZZZ"; + IDCPBL_Q <= MOV_Q when Do_I_MOV = '1' else "ZZZZZZZZ"; -- No flags + IDCPBL_Q <= IA_d when Do_I_MOVD = '1' else "ZZZZZZZZ"; -- No flags + end generate; + + std_mux: if tristate=0 generate + ACC_Q <= "00000000" when Do_A_CLR = '1' else -- No flags + ACC(0) & ACC(7 downto 1) when Do_A_RR = '1' else -- No flags + CY_In & ACC(7 downto 1) when Do_A_RRC = '1' else -- Sets CY + ACC(6 downto 0) & ACC(7) when Do_A_RL = '1' else -- No flags + ACC(6 downto 0) & CY_In when Do_A_RLC = '1' else -- Sets CY + std_logic_vector(unsigned(ACC) + 1) when Do_A_INC = '1' else -- No flags + std_logic_vector(unsigned(ACC) - 1) when Do_A_DEC = '1' else -- No flags + not ACC when Do_A_CPL = '1' else -- No flags + ACC or AOP2 when Do_A_ORL = '1' else -- No flags + ACC and AOP2 when Do_A_ANL = '1' else -- No flags + ACC xor AOP2 when Do_A_XRL = '1' else -- No flags + ACC(3 downto 0) & ACC(7 downto 4) when Do_A_SWAP = '1' else -- No flags + IA when Do_A_XCH = '1' else -- No flags + ACC(7 downto 4) & IA(3 downto 0) when Do_A_XCHD = '1' else -- No flags + AOP2 when Do_A_MOV = '1' else -- No flags + ADA(7 downto 0) when Do_A_DA = '1' else -- Sets CY + AS_Q when Do_A_ADD = '1' or Do_A_SUBB = '1' else -- Sets CY, (AC, OV) + Mul_Q(7 downto 0) when Do_A_MUL = '1' else -- Sets OV + Div_Q(7 downto 0) when Do_A_DIV = '1' else -- Sets OV + (others =>'-'); + + CY_Out <= CJNE_CY when Do_I_CJNE = '1' else + ADA(8) when Do_A_DA = '1' else + ACC(0) when Do_A_RRC = '1' else + ACC(7) when Do_A_RLC = '1' else + AS_CY xor Do_A_SUBB when Do_A_ADD = '1' or Do_A_SUBB = '1' else + '0' when Do_A_DIV = '1' or Do_A_MUL = '1' else + + not CY_In when Do_B_C_Dir = '1' and Do_B_Op = "11" else + '0' when Do_B_C_Dir = '1' and Do_B_Op = "00" else + '1' when Do_B_C_Dir = '1' and Do_B_Op = "01" else + + CY_In or Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "11" and Do_B_Inv = '0' else + CY_In and Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "00" and Do_B_Inv = '0' else + CY_In or Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "10" and Do_B_Inv = '1' else + Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "10" and Do_B_Inv = '0' else + CY_In and Bit_IsOne when Do_B_C_BA = '1' and Do_B_Op = "11" and Do_B_Inv = '1' else + '-'; + + AC_Out <= AS_AC xor Do_A_SUBB when Do_A_ADD = '1' or Do_A_SUBB = '1' else + '-'; + + B_Q <= Mul_Q(15 downto 8) when Do_A_MUL = '1' else -- Sets OV + Div_Q(15 downto 8) when Do_A_DIV = '1' else -- Sets OV + (others =>'-'); + + OV_Out <= AS_CY xor AS_Carry7 when Do_A_ADD = '1' or Do_A_SUBB = '1' else + Div_OV when Do_A_DIV = '1' else + Mul_OV when Do_A_MUL = '1' else + '-'; + + IDCPBL_Q <= std_logic_vector(unsigned(IA) + 1) when Do_I_INC = '1' else -- No flags + std_logic_vector(unsigned(IA) - 1) when Do_I_DEC = '1' else -- No flags + IOP or IA when Do_I_ORL = '1' else -- No flags + IOP and IA when Do_I_ANL = '1' else -- No flags + IOP xor IA when Do_I_XRL = '1' else -- No flags + ACC when Do_A_XCH = '1' else -- No flags + IA(7 downto 4) & ACC(3 downto 0) when Do_A_XCHD = '1' else -- No flags + Bit_Result when Do_B_JBC = '1' or Do_B_BA_Dir = '1' or Do_B_MOV = '1' else + MOV_Q when Do_I_MOV = '1' else -- No flags + IA_d when Do_I_MOVD = '1' else -- No flags + (others =>'-'); + + end generate; + + DJNZ <= '1' when std_logic_vector(unsigned(IA) - 1) /= "00000000" else '0'; + + -- DAA Opcode + DA : process (ACC, CY_In, AC_In) + variable accu : unsigned(8 downto 0); +-- variable lc : std_logic; + variable add : unsigned(7 downto 0); +-- variable do_add_lsb : boolean; + begin + accu := unsigned("0" & ACC); + add := (others =>'0'); +-- do_add_lsb := false; + if AC_In = '1' or accu(3 downto 0) > 9 then +-- accu(3 downto 0) := accu(3 downto 0) + 6; + add(3 downto 0) := "0110"; --6 +-- do_add_lsb := true; + end if; +-- lc := accu(8); + if CY_In = '1' or accu(7 downto 4) > 9 or + (accu(7 downto 4) = 9 and accu(3 downto 0) > 9) then +-- accu := accu + 96; + add(7 downto 4) := "0110"; --6 + end if; + accu := accu + add; +-- accu(8) := accu(8) or lc or CY_In; + ADA <= std_logic_vector(accu); + ADA(8) <= accu(8) or CY_In; -- calculate Carry Out + end process; + + + + + -- Auxiliary ALU + + IOP <= IB when Do_I_Imm = '1' else ACC; + + MOV : process (MOV_Op, IB, ACC, IA_d) + begin + case MOV_Op is + when "0111" => + -- 01110101 3 MOV data addr,#data + -- 0111011i 2 MOV @Ri,#data + -- 01111rrr 2 MOV Rn,#data + MOV_Q <= IB; + when "1000" => + -- 10000101 3 MOV data addr,data addr + -- 1000011i 2 MOV data addr,@Ri + -- 10001rrr 2 MOV data addr,Rn + MOV_Q <= IA_d; + when "1010" => + -- 1010011i 2 MOV @Ri,data addr + -- 10101rrr 2 MOV Rn,data addr + MOV_Q <= IA_d; + when "1111" => + -- 11110000 1 MOVX @DPTR,A + -- 1111001i 1 MOVX @Ri,A + -- 11110101 2 MOV data addr,A + -- 1111011i 1 MOV @Ri,A + -- 11111rrr 1 MOV Rn,A + MOV_Q <= ACC; + when "1100"|"1101"=> + -- 11000000 2 PUSH data addr INC SP: MOV "@SP",<src> + -- 11010000 2 POP data addr MOV <dest>,"@SP": DEC SP + MOV_Q <= IA_d; + when others => + MOV_Q <= "--------"; + end case; + end process; + + + AddSub(IA, IB, '1', '1', CJNE_Q, CJNE_CY_n); + CJNE_CY <= not CJNE_CY_n; +-- CY_Out <= not CJNE_CY_n when Do_I_CJNE = '1' else 'Z'; + + + CJNE_Q_ZERO <= '1' when CJNE_Q = "00000000" else + '0'; + +-- CJNE <= '1' when Do_I_CJNE = '1' and CJNE_Q /= "00000000" else + CJNE <= '1' when Do_I_CJNE = '1' and CJNE_Q_ZERO='0' else + '0' when Do_I_CJNE = '1' else + '1' when AS_Q /= "00000000" else '0'; -- Sets CY + + -- Bit operations + + Bit_Op1 <= IA and not Bit_Pattern; + Bit_Op2 <= Bit_Pattern and not IA when Do_B_Inv = '1' else Bit_Pattern and IA; + Bit_IsOne <= '0' when Bit_Op2 = "00000000" else '1'; + + + + Bit_Result <= IA xor Bit_Pattern when Do_B_BA_Dir = '1' and Do_B_Op = "11" else + Bit_Op1 when (Do_B_BA_Dir = '1' and Do_B_Op = "00") or Do_B_JBC = '1' else + IA or Bit_Pattern when Do_B_BA_Dir = '1' and Do_B_Op = "01" else + Bit_Op1 or (Bit_Pattern and CY_In & CY_In & CY_In & CY_In & CY_In & CY_In & CY_In & CY_In) when Do_B_MOV = '1' else "--------"; + + + + -- Flags + + AC_Wr <= Last_r when (Do_A_ADD = '1' or Do_A_SUBB = '1') and Do_A_CJNE = '0' else '0'; + + OV_Wr <= Last_r when ((Do_A_ADD = '1' or Do_A_SUBB = '1') and Do_A_CJNE = '0') or + Do_A_DIV = '1' or Do_A_MUL = '1' else '0'; + + CY_Wr <= Last_r when Do_A_ADD = '1' or Do_A_SUBB = '1' or + Do_A_RRC = '1' or Do_A_RLC = '1' or + Do_I_CJNE = '1' or Do_A_DA = '1' or + Do_B_C_BA = '1' or Do_B_C_Dir = '1' or + Do_A_DIV = '1' or Do_A_MUL = '1' else '0'; + +end; |