OpenCores
URL https://opencores.org/ocsvn/cortexi/cortexi/trunk

Subversion Repositories cortexi

[/] [cortexi/] [trunk/] [CortexI.vhd] - Rev 3

Compare with Previous | Blame | View Log

LIBRARY ieee;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
use work.CortexIinclude.ALL;
 
Library UNISIM;
use UNISIM.vcomponents.all;
 
ENTITY CortexI IS
   PORT(
     clk     : in  std_logic;
     rst     : in  std_logic;
     irq     : in  std_logic;
     addr    : out std_logic_vector(31 downto 0);
     wrl     : out std_logic;
     wrh     : out std_logic;
     datain  : in  std_logic_vector(15 downto 0);
     dataout : out std_logic_vector(15 downto 0)
   );
END CortexI;
 
ARCHITECTURE behavior OF CortexI IS
 
  constant STATE_FETCH  : std_logic_vector(6 downto 0) := "0000000";
  constant STATE_READ1  : std_logic_vector(6 downto 0) := "0000001";
  constant STATE_READ2  : std_logic_vector(6 downto 0) := "0000010";
  constant STATE_WRITE1 : std_logic_vector(6 downto 0) := "0000011";
  constant STATE_WRITE2 : std_logic_vector(6 downto 0) := "0000100";
  constant STATE_RD0L   : std_logic_vector(6 downto 0) := "0000101";
  constant STATE_RD0H   : std_logic_vector(6 downto 0) := "0000110";
  constant STATE_RD1L   : std_logic_vector(6 downto 0) := "0000111";
  constant STATE_RD1H   : std_logic_vector(6 downto 0) := "0001000";
  constant STATE_RD2L   : std_logic_vector(6 downto 0) := "0001001";
  constant STATE_RD2H   : std_logic_vector(6 downto 0) := "0001010";
  constant STATE_RD3L   : std_logic_vector(6 downto 0) := "0001011";
  constant STATE_RD3H   : std_logic_vector(6 downto 0) := "0001100";
  constant STATE_RD4L   : std_logic_vector(6 downto 0) := "0001101";
  constant STATE_RD4H   : std_logic_vector(6 downto 0) := "0001110";
  constant STATE_RD5L   : std_logic_vector(6 downto 0) := "0001111";
  constant STATE_RD5H   : std_logic_vector(6 downto 0) := "0010000";
  constant STATE_RD6L   : std_logic_vector(6 downto 0) := "0010001";
  constant STATE_RD6H   : std_logic_vector(6 downto 0) := "0010010";
  constant STATE_RD7L   : std_logic_vector(6 downto 0) := "0010011";
  constant STATE_RD7H   : std_logic_vector(6 downto 0) := "0010100";
  constant STATE_RDPL   : std_logic_vector(6 downto 0) := "0010101";
  constant STATE_RDPH   : std_logic_vector(6 downto 0) := "0010110";
  constant STATE_WR0L   : std_logic_vector(6 downto 0) := "0010111";
  constant STATE_WR0H   : std_logic_vector(6 downto 0) := "0011000";
  constant STATE_WR1L   : std_logic_vector(6 downto 0) := "0011001";
  constant STATE_WR1H   : std_logic_vector(6 downto 0) := "0011010";
  constant STATE_WR2L   : std_logic_vector(6 downto 0) := "0011011";
  constant STATE_WR2H   : std_logic_vector(6 downto 0) := "0011100";
  constant STATE_WR3L   : std_logic_vector(6 downto 0) := "0011101";
  constant STATE_WR3H   : std_logic_vector(6 downto 0) := "0011110";
  constant STATE_WR4L   : std_logic_vector(6 downto 0) := "0011111";
  constant STATE_WR4H   : std_logic_vector(6 downto 0) := "0100000";
  constant STATE_WR5L   : std_logic_vector(6 downto 0) := "0100001";
  constant STATE_WR5H   : std_logic_vector(6 downto 0) := "0100010";
  constant STATE_WR6L   : std_logic_vector(6 downto 0) := "0100011";
  constant STATE_WR6H   : std_logic_vector(6 downto 0) := "0100100";
  constant STATE_WR7L   : std_logic_vector(6 downto 0) := "0100101";
  constant STATE_WR7H   : std_logic_vector(6 downto 0) := "0100110";
  constant STATE_WRPL   : std_logic_vector(6 downto 0) := "0100111";
  constant STATE_WRPH   : std_logic_vector(6 downto 0) := "0101000";
  constant STATE_RESET0 : std_logic_vector(6 downto 0) := "0101001";
  constant STATE_RESET1 : std_logic_vector(6 downto 0) := "0101010";
  constant STATE_RESET2 : std_logic_vector(6 downto 0) := "0101011";
  constant STATE_RESET3 : std_logic_vector(6 downto 0) := "0101100";
  constant STATE_IRQ    : std_logic_vector(6 downto 0) := "0101101";
  constant STATE_IRQ1   : std_logic_vector(6 downto 0) := "0101110";
  constant STATE_IRQ2   : std_logic_vector(6 downto 0) := "0101111";
  constant STATE_IRQ3   : std_logic_vector(6 downto 0) := "0110000";
  constant STATE_IRQ4   : std_logic_vector(6 downto 0) := "0110001";
  constant STATE_IRQ5   : std_logic_vector(6 downto 0) := "0110010";
  constant STATE_IRQ6   : std_logic_vector(6 downto 0) := "0110011";
  constant STATE_IRQ7   : std_logic_vector(6 downto 0) := "0110100";
  constant STATE_IRQ8   : std_logic_vector(6 downto 0) := "0110101";
  constant STATE_IRQ9   : std_logic_vector(6 downto 0) := "0110110";
  constant STATE_IRQ10  : std_logic_vector(6 downto 0) := "0110111";
  constant STATE_IRQ11  : std_logic_vector(6 downto 0) := "0111000";
  constant STATE_IRQ12  : std_logic_vector(6 downto 0) := "0111001";
  constant STATE_IRQ13  : std_logic_vector(6 downto 0) := "0111010";
  constant STATE_IRQ14  : std_logic_vector(6 downto 0) := "0111011";
  constant STATE_IRQ15  : std_logic_vector(6 downto 0) := "0111100";
  constant STATE_IRQ16  : std_logic_vector(6 downto 0) := "0111101";
  constant STATE_IRQ17  : std_logic_vector(6 downto 0) := "0111110";
  constant STATE_RET    : std_logic_vector(6 downto 0) := "0111111";
  constant STATE_RET1   : std_logic_vector(6 downto 0) := "1000000";
  constant STATE_RET2   : std_logic_vector(6 downto 0) := "1000001";
  constant STATE_RET3   : std_logic_vector(6 downto 0) := "1000010";
  constant STATE_RET4   : std_logic_vector(6 downto 0) := "1000011";
  constant STATE_RET5   : std_logic_vector(6 downto 0) := "1000100";
  constant STATE_RET6   : std_logic_vector(6 downto 0) := "1000101";
  constant STATE_RET7   : std_logic_vector(6 downto 0) := "1000110";
  constant STATE_RET8   : std_logic_vector(6 downto 0) := "1000111";
  constant STATE_RET9   : std_logic_vector(6 downto 0) := "1001000";
  constant STATE_RET10  : std_logic_vector(6 downto 0) := "1001001";
  constant STATE_RET11  : std_logic_vector(6 downto 0) := "1001010";
  constant STATE_RET12  : std_logic_vector(6 downto 0) := "1001011";
  constant STATE_RET13  : std_logic_vector(6 downto 0) := "1001100";
  constant STATE_RET14  : std_logic_vector(6 downto 0) := "1001101";
  constant STATE_RET15  : std_logic_vector(6 downto 0) := "1001110";
  constant STATE_RET16  : std_logic_vector(6 downto 0) := "1001111";
  constant STATE_RET17  : std_logic_vector(6 downto 0) := "1010000";
 
  constant CODE_LSL1   : std_logic_vector(6 downto 0) := "0000000";
  constant CODE_LSR1   : std_logic_vector(6 downto 0) := "0000001";
  constant CODE_ASR1   : std_logic_vector(6 downto 0) := "0000010";
  constant CODE_ADD1   : std_logic_vector(6 downto 0) := "0000011";
  constant CODE_SUB1   : std_logic_vector(6 downto 0) := "0000100";
  constant CODE_ADD2   : std_logic_vector(6 downto 0) := "0000110";
  constant CODE_SUB2   : std_logic_vector(6 downto 0) := "0000111";
  constant CODE_MOV1   : std_logic_vector(6 downto 0) := "0001000";
  constant CODE_CMP1   : std_logic_vector(6 downto 0) := "0001001";
  constant CODE_ADD3   : std_logic_vector(6 downto 0) := "0001010";
  constant CODE_SUB3   : std_logic_vector(6 downto 0) := "0001011";
  constant CODE_AND1   : std_logic_vector(6 downto 0) := "0001100";
  constant CODE_EOR1   : std_logic_vector(6 downto 0) := "0001101";
  constant CODE_LSL2   : std_logic_vector(6 downto 0) := "0001110";
  constant CODE_LSR2   : std_logic_vector(6 downto 0) := "0001111";
  constant CODE_ASR2   : std_logic_vector(6 downto 0) := "0010000";
  constant CODE_ADC1   : std_logic_vector(6 downto 0) := "0010001";
  constant CODE_SBC1   : std_logic_vector(6 downto 0) := "0010010";
  constant CODE_ROR1   : std_logic_vector(6 downto 0) := "0010011";
  constant CODE_TST1   : std_logic_vector(6 downto 0) := "0010100";
  constant CODE_NEG1   : std_logic_vector(6 downto 0) := "0010101";
  constant CODE_CMP2   : std_logic_vector(6 downto 0) := "0010110";
  constant CODE_CMN1   : std_logic_vector(6 downto 0) := "0010111";
  constant CODE_ORR1   : std_logic_vector(6 downto 0) := "0011000";
  constant CODE_MUL1   : std_logic_vector(6 downto 0) := "0011001";
  constant CODE_BIC1   : std_logic_vector(6 downto 0) := "0011010";
  constant CODE_MVN1   : std_logic_vector(6 downto 0) := "0011011";
  constant CODE_ADD4   : std_logic_vector(6 downto 0) := "0011100";
  constant CODE_CMP3   : std_logic_vector(6 downto 0) := "0011101";
  constant CODE_CPY1   : std_logic_vector(6 downto 0) := "0011110";
  constant CODE_BX1    : std_logic_vector(6 downto 0) := "0011111";
  constant CODE_LDR1   : std_logic_vector(6 downto 0) := "0100000";
  constant CODE_STR1   : std_logic_vector(6 downto 0) := "0100001";
  constant CODE_STRH1  : std_logic_vector(6 downto 0) := "0100010";
  constant CODE_STRB1  : std_logic_vector(6 downto 0) := "0100011";
  constant CODE_LDRSB1 : std_logic_vector(6 downto 0) := "0100100";
  constant CODE_LDR2   : std_logic_vector(6 downto 0) := "0100101";
  constant CODE_LDRH1  : std_logic_vector(6 downto 0) := "0100110";
  constant CODE_LDRB1  : std_logic_vector(6 downto 0) := "0100111";
  constant CODE_LDRSH1 : std_logic_vector(6 downto 0) := "0101000";
  constant CODE_STR2   : std_logic_vector(6 downto 0) := "0101001";
  constant CODE_LDR3   : std_logic_vector(6 downto 0) := "0101010";
  constant CODE_STRB2  : std_logic_vector(6 downto 0) := "0101011";
  constant CODE_LDRB2  : std_logic_vector(6 downto 0) := "0101100";
  constant CODE_STRH2  : std_logic_vector(6 downto 0) := "0101101";
  constant CODE_LDRH2  : std_logic_vector(6 downto 0) := "0101110";
  constant CODE_STR3   : std_logic_vector(6 downto 0) := "0101111";
  constant CODE_LDR4   : std_logic_vector(6 downto 0) := "0110000";
  constant CODE_ADD5   : std_logic_vector(6 downto 0) := "0110001";
  constant CODE_ADD6   : std_logic_vector(6 downto 0) := "0110010";
  constant CODE_ADD7   : std_logic_vector(6 downto 0) := "0110011";
  constant CODE_SUB4   : std_logic_vector(6 downto 0) := "0110100";
  constant CODE_SXTH1  : std_logic_vector(6 downto 0) := "0110101";
  constant CODE_SXTB1  : std_logic_vector(6 downto 0) := "0110110";
  constant CODE_UXTH1  : std_logic_vector(6 downto 0) := "0110111";
  constant CODE_UXTB1  : std_logic_vector(6 downto 0) := "0111000";
  constant CODE_PUSH1  : std_logic_vector(6 downto 0) := "0111001";
  constant CODE_POP1   : std_logic_vector(6 downto 0) := "0111010";
  constant CODE_STMIA1 : std_logic_vector(6 downto 0) := "0111011";
  constant CODE_LDMIA1 : std_logic_vector(6 downto 0) := "0111100";
  constant CODE_BCC1   : std_logic_vector(6 downto 0) := "0111101";
  constant CODE_SWI1   : std_logic_vector(6 downto 0) := "0111110";
  constant CODE_B1     : std_logic_vector(6 downto 0) := "0111111";
  constant CODE_BLX1   : std_logic_vector(6 downto 0) := "1000000";
  constant CODE_BLX2   : std_logic_vector(6 downto 0) := "1000001";
  constant CODE_BL1    : std_logic_vector(6 downto 0) := "1000010";
  constant CODE_NOP    : std_logic_vector(6 downto 0) := "1000011";  
  constant CODE_XXX    : std_logic_vector(6 downto 0) := "1111111";
 
  constant N_FLAG : integer := 31;
  constant Z_FLAG : integer := 30;
  constant C_FLAG : integer := 29;
  constant V_FLAG : integer := 28;
 
  constant WRITE_B_LOW   : std_logic_vector(3 downto 0) := "0000";
  constant WRITE_B_HIGH  : std_logic_vector(3 downto 0) := "0001";
  constant WRITE_H_BOTH  : std_logic_vector(3 downto 0) := "0010";
  constant WRITE_H_LOW   : std_logic_vector(3 downto 0) := "0011";
  constant WRITE_H_HIGH  : std_logic_vector(3 downto 0) := "0100";
  constant WRITE_W_LOW   : std_logic_vector(3 downto 0) := "0101";
  constant WRITE_W_HIGH  : std_logic_vector(3 downto 0) := "0110";
  constant WRITE_W_LOWB  : std_logic_vector(3 downto 0) := "0111";
  constant WRITE_W_MID   : std_logic_vector(3 downto 0) := "1000";
  constant WRITE_W_HIGHB : std_logic_vector(3 downto 0) := "1001";
 
  constant ADDR_PC : std_logic_vector(1 downto 0) := "00";
  constant ADDR_SP : std_logic_vector(1 downto 0) := "01";
  constant ADDR_RS : std_logic_vector(1 downto 0) := "10";
  constant ADDR_RT : std_logic_vector(1 downto 0) := "11";
 
 
  type typeRegisters is array (0 to 15) of std_logic_vector(31 downto 0);
 
  signal theRegisters : typeRegisters;
  signal cpsrRegister : std_logic_Vector(31 downto  0);
  signal cpuState     : std_logic_vector( 6 downto  0);
  signal opcode       : std_logic_vector(15 downto  0);
  signal addrMux      : std_logic_vector( 1 downto  0);
  signal address      : std_logic_vector(31 downto  0);
  signal irq_d        : std_logic;
  signal irqRequest   : std_logic;
  signal writeL       : std_logic;
  signal writeH       : std_logic;
  signal shiftResult  : std_logic_vector(31 downto  0);
  signal cyShiftOut   : std_logic;
  signal shiftMode    : std_logic_vector( 2 downto  0);
  signal shiftCount   : std_logic_vector( 4 downto  0);
  signal shiftIn      : std_logic_vector(31 downto  0);
  signal LDMread      : std_logic_vector( 7 downto  0);
 
  signal unitControl  : std_logic_vector( 6 downto  0);
  signal unitControl2 : std_logic_vector( 6 downto  0);
 
  signal factor1      : std_logic_vector(31 downto  0);
  signal factor2      : std_logic_vector(31 downto  0);
  signal product      : std_logic_vector(63 downto  0);
 
  signal branch       : std_logic;
 
  signal datain20  : integer range 0 to 15;
  signal datain53  : integer range 0 to 15;
  signal datain86  : integer range 0 to 15;
  signal datain108 : integer range 0 to 15;
 
  signal opcode20  : integer range 0 to 15;
  signal opcode53  : integer range 0 to 15;
  signal opcode86  : integer range 0 to 15;
  signal opcode108 : integer range 0 to 15;
 
  component bshifter Port (
           din   : in  std_logic_vector(31 downto 0);
           size  : in  std_logic_vector( 1 downto 0);
           mode  : in  std_logic_vector( 2 downto 0);
           count : in  std_logic_vector( 4 downto 0);
           cyOut : out std_logic;
           dout  : out std_logic_vector(31 downto 0)
         );
  end component;
 
  component Multiplier   -- 32 x 32 = 64 bit unsigned product multiplier
    port(a    : in  std_logic_vector(31 downto 0);  -- multiplicand
         b    : in  std_logic_vector(31 downto 0);  -- multiplier
         p    : out std_logic_vector(63 downto 0)); -- product
  end component;
 
begin
 
  datain20  <= conv_integer("0" & datain( 2 downto 0));
  datain53  <= conv_integer("0" & datain( 5 downto 3));
  datain86  <= conv_integer("0" & datain( 8 downto 6));
  datain108 <= conv_integer("0" & datain(10 downto 8));
  opcode20  <= conv_integer("0" & opcode( 2 downto 0));
  opcode53  <= conv_integer("0" & opcode( 5 downto 3));
  opcode86  <= conv_integer("0" & opcode( 8 downto 6));
  opcode108 <= conv_integer("0" & opcode(10 downto 8));
 
--#################################################################
--  barrel shifter
  shiftMode <= BS_LSL when (unitControl = CODE_LSL1) or (unitControl = CODE_LSL2) else
               BS_LSR when (unitControl = CODE_LSR1) or (unitControl = CODE_LSR2) else
               BS_ASR when (unitControl = CODE_ASR1) or (unitControl = CODE_ASR2) else
               BS_ROR;
  shiftCount <= datain(10 downto 6)
       when (unitControl = CODE_LSL1) or (unitControl = CODE_LSR1) or (unitControl = CODE_ASR1) else
            theRegisters(datain53)(4 downto 0);
  shiftIn <= theRegisters(datain53)
       when (unitControl = CODE_LSL1) or (unitControl = CODE_LSR1) or (unitControl = CODE_ASR1) else
            theRegisters(datain20);
  barrelShifter :  bshifter Port map(
           din   => shiftIn,     --: in  std_logic_vector(31 downto 0);
           size  => SIZE_32BIT,  --: in  std_logic_vector( 1 downto 0);
           mode  => shiftMode,   --: in  std_logic_vector( 2 downto 0);
           count => shiftCount,  --: in  std_logic_vector( 4 downto 0);
           cyOut => cyShiftOut,  --: out std_logic;
           dout  => shiftResult  --: out std_logic_vector(31 downto 0)
         );
 
--#################################################################
--  multiplier
  multip : Multiplier Port map(
           a => factor1,
           b => factor2,
           p => product
         );
  factor1 <= theRegisters(datain20);
  factor2 <= theRegisters(datain53);
 
--#################################################################
-- decodes instruction bits to control bits for other ARMT units
  process(datain)
  begin
    case datain(15 downto 11) is
      when "00000" =>    unitControl <= CODE_LSL1;
      when "00001" =>    unitControl <= CODE_LSR1;
      when "00010" =>    unitControl <= CODE_ASR1;
      when "00011" =>
        case datain(10 downto 9) is
          when "00" =>   unitControl <= CODE_ADD1;
          when "01" =>   unitControl <= CODE_SUB1;
          when "10" =>   unitControl <= CODE_ADD2;
          when "11" =>   unitControl <= CODE_SUB2;
          when others => unitControl <= CODE_XXX;
        end case;
      when "00100" =>    unitControl <= CODE_MOV1;
      when "00101" =>    unitControl <= CODE_CMP1;
      when "00110" =>    unitControl <= CODE_ADD3;
      when "00111" =>    unitControl <= CODE_SUB3;
      when "01000" =>
        if datain(10) = '0' then
          case datain(9 downto 6) is
            when "0000" => unitControl <= CODE_AND1;
            when "0001" => unitControl <= CODE_EOR1;
            when "0010" => unitControl <= CODE_LSL2;
            when "0011" => unitControl <= CODE_LSR2;
            when "0100" => unitControl <= CODE_ASR2;
            when "0101" => unitControl <= CODE_ADC1;
            when "0110" => unitControl <= CODE_SBC1;
            when "0111" => unitControl <= CODE_ROR1;
            when "1000" => unitControl <= CODE_TST1;
            when "1001" => unitControl <= CODE_NEG1;
            when "1010" => unitControl <= CODE_CMP2;
            when "1011" => unitControl <= CODE_CMN1;
            when "1100" => unitControl <= CODE_ORR1;
            when "1101" => unitControl <= CODE_MUL1;
            when "1110" => unitControl <= CODE_BIC1;
            when "1111" => unitControl <= CODE_MVN1;
            when others => unitControl <= CODE_XXX;
          end case;
        else
          case datain(9 downto 8) is
            when "00" => unitControl <= CODE_ADD4;
            when "01" => unitControl <= CODE_CMP3;
            when "10" => unitControl <= CODE_CPY1; -- MOV
            when "11" => unitControl <= CODE_BX1;
            when others => unitControl <= CODE_XXX;
          end case;
        end if;
      when "01001" =>    unitControl <= CODE_LDR1;
      when "01010" =>
        case datain(10 downto 9) is
          when "00" => unitControl <= CODE_STR1;
          when "01" => unitControl <= CODE_STRH1;
          when "10" => unitControl <= CODE_STRB1;
          when "11" => unitControl <= CODE_LDRSB1;
          when others =>     unitControl <= CODE_XXX;
        end case;
      when "01011" =>
        case datain(10 downto 9) is
          when "00" => unitControl <= CODE_LDR2;
          when "01" => unitControl <= CODE_LDRH1;
          when "10" => unitControl <= CODE_LDRB1;
          when "11" => unitControl <= CODE_LDRSH1;
          when others =>     unitControl <= CODE_XXX;
        end case;
      when "01100" =>    unitControl <= CODE_STR2;
      when "01101" =>    unitControl <= CODE_LDR3;
      when "01110" =>    unitControl <= CODE_STRB2;
      when "01111" =>    unitControl <= CODE_LDRB2;
      when "10000" =>    unitControl <= CODE_STRH2;
      when "10001" =>    unitControl <= CODE_LDRH2;
      when "10010" =>    unitControl <= CODE_STR3;
      when "10011" =>    unitControl <= CODE_LDR4;
      when "10100" =>    unitControl <= CODE_ADD5;
      when "10101" =>    unitControl <= CODE_ADD6;
      when "10110" =>
        case datain(10 downto 7) is
          when "0000" => unitControl <= CODE_ADD7;
          when "0001" => unitControl <= CODE_SUB4;
          when "0100" =>
            if datain(6) = '0' then
                         unitControl <= CODE_SXTH1;
            else
                         unitControl <= CODE_SXTB1;
            end if;
          when "0101" =>
            if datain(6) = '0' then
                         unitControl <= CODE_UXTH1;
            else
                         unitControl <= CODE_UXTB1;
            end if;
          when "1000" | "1001" | "1010" | "1011" =>
                         unitControl <= CODE_PUSH1;  
          when others => unitControl <= CODE_XXX;
        end case;
      when "10111" =>
        if datain(10 downto 8) = "100" or datain(10 downto 8) = "101" then
                         unitControl <= CODE_POP1;  
        else
                         unitControl <= CODE_NOP;
        end if;
      when "11000" =>    unitControl <= CODE_STMIA1;
      when "11001" =>    unitControl <= CODE_LDMIA1;
      when "11010" | "11011" => 
--        if datain(11 downto 8) = "1111" then
--                         unitControl <= CODE_SWI1;
--        else
                         unitControl <= CODE_BCC1;
--        end if;
      when "11100" =>    unitControl <= CODE_B1;
      when "11101" =>    unitControl <= CODE_BLX1;
      when "11110" =>    unitControl <= CODE_BLX2;
      when "11111" =>    unitControl <= CODE_BL1;
      when others =>     unitControl <= CODE_XXX;
    end case; -- datain(15 downto 11)
  end process;
 
  wrl  <= writeL;
  wrH  <= writeH;
--#################################################################
--      address bus multiplexer
  addr <= theRegisters(15) when addrMux = ADDR_PC else
          theRegisters(13) when addrMux = ADDR_SP else
          address;
 
--#################################################################
--      check flags for branch
  process(datain, cpsrRegister)
  begin
    case datain(11 downto 8) is
      when "0000" => -- EQ
        if cpsrRegister(Z_FLAG) = '1' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0001" => -- NE
        if cpsrRegister(Z_FLAG) = '0' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0010" => -- CS
        if cpsrRegister(C_FLAG) = '1' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0011" => -- CC
        if cpsrRegister(C_FLAG) = '0' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0100" => -- MI
        if cpsrRegister(N_FLAG) = '1' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0101" => -- PL
        if cpsrRegister(N_FLAG) = '0' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0110" => -- VS
        if cpsrRegister(V_FLAG) = '1' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "0111" => -- VC
        if cpsrRegister(V_FLAG) = '0' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1000" => -- HI
        if cpsrRegister(C_FLAG) = '1' and cpsrRegister(Z_FLAG) = '0' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1001" => -- LS
        if cpsrRegister(C_FLAG) = '0' or cpsrRegister(Z_FLAG) = '1' then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1010" => -- GE
        if cpsrRegister(N_FLAG) = cpsrRegister(V_FLAG) then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1011" => -- LT
        if cpsrRegister(N_FLAG) /= cpsrRegister(V_FLAG) then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1100" => -- GT
        if cpsrRegister(Z_FLAG) = '0' and (cpsrRegister(N_FLAG) = cpsrRegister(V_FLAG)) then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1101" => -- LE
        if cpsrRegister(Z_FLAG) = '1' or (cpsrRegister(N_FLAG) /= cpsrRegister(V_FLAG)) then
          branch <= '1';
        else
          branch <= '0';
        end if;
      when "1110" => -- AL
        branch <= '1';
      when others =>
        branch <= '0';
    end case; -- datain(11 downto 8)
  end process;
 
--#################################################################  
-- ARMT cpu main state machine
  process(rst, clk)
    variable tres : std_logic_vector(32 downto 0);
    variable tsum : std_logic_vector(31 downto 0);
    variable op1  : std_logic;
    variable op2  : std_logic;
    variable opr  : std_logic;
  begin
    if rising_edge(clk) then
      if rst = '0' then
        theRegisters( 0) <= x"00000000";
        theRegisters( 1) <= x"00000000";
        theRegisters( 2) <= x"00000000";
        theRegisters( 3) <= x"00000000";
        theRegisters( 4) <= x"00000000";
        theRegisters( 5) <= x"00000000";
        theRegisters( 6) <= x"00000000";
        theRegisters( 7) <= x"00000000";
        theRegisters( 8) <= x"00000000";
        theRegisters( 9) <= x"00000000";
        theRegisters(10) <= x"00000000";
        theRegisters(11) <= x"00000000";
        theRegisters(12) <= x"00000000";
        theRegisters(13) <= x"00000000"; -- SP
        theRegisters(14) <= x"00000000"; -- LR
        theRegisters(15) <= x"00000000"; -- PC
        cpsrRegister     <= x"00000000";
        cpuState <= STATE_RESET0;
        writeL   <= '1';
        writeH   <= '1';
        LDMread  <= x"00";
        addrMux  <= ADDR_PC;
        address  <= x"00000000";
        irq_d    <= '1';
        irqRequest <= '0';
        unitControl2 <= "0000000";
      else
        irq_d <= irq;
        if (irq = '0') and (irq_d = '1') then --and (flagI = '0') then -- irq falling edge ?
          irqRequest <= '1';
        end if;
        case cpuState is
          when STATE_RESET0 => -- ##################################################
            theRegisters(13)(15 downto 0) <= datain;  -- STACK low
            theRegisters(15) <= theRegisters(15) + 2;
            cpuState <= STATE_RESET1;
          when STATE_RESET1 => -- ##################################################
            theRegisters(13)(31 downto 16) <= datain; -- STACK high
            theRegisters(15) <= theRegisters(15) + 2;
            cpuState <= STATE_RESET2;
          when STATE_RESET2 => -- ##################################################
            address(15 downto 0) <= datain and x"FFFE"; -- PC low make even address
            theRegisters(15) <= theRegisters(15) + 2;
            cpuState <= STATE_RESET3;
          when STATE_RESET3 => -- ##################################################
            theRegisters(15) <= datain & address(15 downto 0); -- PC high
            cpuState <= STATE_FETCH;
          when STATE_IRQ =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= cpsrRegister(15 downto 0);
            cpuState <= STATE_IRQ1;
          when STATE_IRQ1 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(15)(31 downto 16);
            cpuState <= STATE_IRQ2;
          when STATE_IRQ2 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(15)(15 downto 0);
            cpuState <= STATE_IRQ3;
          when STATE_IRQ3 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(14)(31 downto 16); -- ??? FFFFFFF9
            cpuState <= STATE_IRQ4;
          when STATE_IRQ4 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(14)(15 downto 0); -- ??? FFFFFFF9
            cpuState <= STATE_IRQ5;
          when STATE_IRQ5 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(12)(31 downto 16);
            cpuState <= STATE_IRQ6;
          when STATE_IRQ6 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(12)(15 downto 0);
            cpuState <= STATE_IRQ7;
          when STATE_IRQ7 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(3)(31 downto 16);
            cpuState <= STATE_IRQ8;
          when STATE_IRQ8 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(3)(15 downto 0);
            cpuState <= STATE_IRQ9;
          when STATE_IRQ9 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(2)(31 downto 16);
            cpuState <= STATE_IRQ10;
          when STATE_IRQ10 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(2)(15 downto 0);
            cpuState <= STATE_IRQ11;
          when STATE_IRQ11 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(1)(31 downto 16);
            cpuState <= STATE_IRQ12;
          when STATE_IRQ12 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(1)(15 downto 0);
            cpuState <= STATE_IRQ13;
          when STATE_IRQ13 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(0)(31 downto 16);
            cpuState <= STATE_IRQ14;
          when STATE_IRQ14 =>  -- ####################################################
            theRegisters(13) <= theRegisters(13) - 2;
            dataout  <= theRegisters(0)(15 downto 0);
            cpuState <= STATE_IRQ15;
          when STATE_IRQ15 =>  -- ####################################################
            writeL <= '1';
            writeH <= '1';
            theRegisters(14) <= x"FFFFFFF9"; -- exception return value
            address <= x"00000008";  -- NMI vector
            addrMux <= ADDR_RS;
            cpuState <= STATE_IRQ16;
          when STATE_IRQ16 =>  -- ###################################################
            theRegisters(15)(15 downto 0) <= datain and x"FFFE";
            address <= address + 2;
            cpuState <= STATE_IRQ17;
          when STATE_IRQ17 =>  -- ###################################################
            theRegisters(15)(31 downto 16) <= datain;
            addrMux <= ADDR_PC;
            cpuState <= STATE_FETCH;
          when STATE_RET =>  -- #####################################################
            addrMux <= ADDR_SP;
            cpuState <= STATE_RET1;
          when STATE_RET1 => -- #####################################################
            theRegisters(0)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET2;
          when STATE_RET2 => -- #####################################################
            theRegisters(0)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET3;
          when STATE_RET3 => -- #####################################################
            theRegisters(1)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET4;
          when STATE_RET4 => -- #####################################################
            theRegisters(1)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET5;
          when STATE_RET5 => -- #####################################################
            theRegisters(2)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET6;
          when STATE_RET6 => -- #####################################################
            theRegisters(2)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET7;
          when STATE_RET7 => -- #####################################################
            theRegisters(3)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET8;
          when STATE_RET8 => -- #####################################################
            theRegisters(3)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET9;
          when STATE_RET9 => -- #####################################################
            theRegisters(12)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET10;
          when STATE_RET10 => -- #####################################################
            theRegisters(12)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET11;
          when STATE_RET11 => -- #####################################################
            theRegisters(14)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET12;
          when STATE_RET12 => -- #####################################################
            theRegisters(14)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET13;
          when STATE_RET13 => -- #####################################################
            theRegisters(15)(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET14;
          when STATE_RET14 => -- #####################################################
            theRegisters(15)(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET15;
          when STATE_RET15 => -- #####################################################
            cpsrRegister(15 downto 0) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            cpuState <= STATE_RET16;
          when STATE_RET16 => -- #####################################################
            cpsrRegister(31 downto 16) <= datain;
            theRegisters(13) <= theRegisters(13) + 2;
            addrMux  <= ADDR_PC;
            cpuState <= STATE_FETCH;  
          when STATE_FETCH => -- ###################################################
            unitControl2 <= unitControl;
            opcode       <= datain;
            if irqrequest = '1' then -- irq ???
              irqrequest <= '0';
              cpuState <= STATE_IRQ;
              theRegisters(13) <= theRegisters(13) - 2;
             -- theRegisters(15) <= theRegisters(15) + 2;
              addrMux  <= ADDR_SP;
              dataout  <= cpsrRegister(31 downto 16);
              writeL   <= '0';
              writeH   <= '0';
            else
              case unitControl is
                when CODE_LSL1 | CODE_LSR1 | CODE_ASR1 |
                     CODE_LSL2 | CODE_LSR2 | CODE_ASR2 |
                     CODE_ROR1 =>
                  theRegisters(datain20) <= shiftResult;
                  cpsrRegister(N_FLAG) <= shiftResult(31);
                  if shiftResult = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  cpsrRegister(C_FLAG) <= cyShiftOut;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_CPY1 => -- Rd = Rm
                  if (datain(7) & datain(2 downto 0) = "1111") then
                    theRegisters(conv_integer(datain(7) & datain(2 downto 0))) <=
                    theRegisters(conv_integer(datain(6 downto 3)));
                  else
                    theRegisters(conv_integer(datain(7) & datain(2 downto 0))) <=
                    theRegisters(conv_integer(datain(6 downto 3)));
                    theRegisters(15) <= theRegisters(15) + 2;
                  end if;
                when CODE_ADD4 => -- Rd = Rd + Rm
                  if (datain(7) & datain(2 downto 0) = "1111") then
                    theRegisters(conv_integer(datain(7) & datain(2 downto 0))) <=
                                theRegisters(conv_integer(datain(7) & datain(2 downto 0))) +
                                theRegisters(conv_integer(datain(6 downto 3)));
                  else
                    theRegisters(conv_integer(datain(7) & datain(2 downto 0))) <=
                                theRegisters(conv_integer(datain(7) & datain(2 downto 0))) +
                                theRegisters(conv_integer(datain(6 downto 3)));
                    theRegisters(15) <= theRegisters(15) + 2;
                  end if;
                when CODE_ADD6 => -- Rn = SP + imm
                  theRegisters(datain108) <=
                                theRegisters(13) +
                                (x"00000" & "00" & datain(7 downto 0) & "00");
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_ADD7 => -- SP = SP + imm
                  theRegisters(13) <= theRegisters(13) +
                                    (x"00000" & "000" & datain(6 downto 0) & "00");
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_SUB4 => -- SP = SP - imm
                  theRegisters(13) <= theRegisters(13) -
                                    (x"00000" & "000" & datain(6 downto 0) & "00");
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_ADD1 =>
                  tres := ("0" & theRegisters(datain53)) +
                          ("0" & theRegisters(datain86));
                  theRegisters(datain20) <=
                          theRegisters(datain53) +
                          theRegisters(datain86);
                  cpsrRegister(C_FLAG) <= tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain53)(31);
                  op2 := theRegisters(datain86)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and op2 and not opr) or
                                          (not op1 and not op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_SUB1 =>
                  tres := ("0" & theRegisters(datain53)) -
                          ("0" & theRegisters(datain86));
                  theRegisters(datain20) <=
                          theRegisters(datain53) -
                          theRegisters(datain86);
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain53)(31);
                  op2 := theRegisters(datain86)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;              
                when CODE_ADD2 =>
                  tres := ("0" & theRegisters(datain53)) +
                          ("0" & x"0000000" & "0" & datain(8 downto 6));
                  theRegisters(datain20) <=
                          theRegisters(datain53) +
                          (x"0000000" & "0" & datain(8 downto 6));
                  cpsrRegister(C_FLAG) <= tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain53)(31);
                  op2 := '0';
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and op2 and not opr) or
                                          (not op1 and not op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_SUB2 =>
                  tres := ("0" & theRegisters(datain53)) -
                          ("0" & x"0000000" & "0" & datain(8 downto 6));
                  theRegisters(datain20) <=
                          theRegisters(datain53) -
                          (x"0000000" & "0" & datain(8 downto 6));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain53)(31);
                  op2 := '0';
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_MOV1 =>
                  tres := "0" & x"000000" & datain(7 downto 0);
                  theRegisters(datain108) <= x"000000" & datain(7 downto 0);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_CMP1 =>
                  tres := ("0" & theRegisters(datain108)) -
                          ("0" & x"000000" & datain(7 downto 0));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain108)(31);
                  op2 := '0';
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_ADD3 =>
                  tres := ("0" & theRegisters(datain108)) +
                          ("0" & x"000000" & datain(7 downto 0));
                  theRegisters(datain108) <=
                          theRegisters(datain108) +
                          (x"000000" & datain(7 downto 0));
                  cpsrRegister(C_FLAG) <= tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain108)(31);
                  op2 := '0';
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and op2 and not opr) or
                                          (not op1 and not op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_SUB3 =>
                  tres := ("0" & theRegisters(datain108)) -
                          ("0" & x"000000" & datain(7 downto 0));
                  theRegisters(datain108) <=
                          theRegisters(datain108) -
                          (x"000000" & datain(7 downto 0));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain108)(31);
                  op2 := '0';
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_AND1 =>
                  tres := ("0" & theRegisters(datain20)) and
                          ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          theRegisters(datain20) and
                          theRegisters(datain53);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_EOR1 =>
                  tres := ("0" & theRegisters(datain20)) xor
                          ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          theRegisters(datain20) xor
                          theRegisters(datain53);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_ADC1 =>
                  tres := ("0" & theRegisters(datain20)) +
                          ("0" & theRegisters(datain53)) +
                          (x"00000000" & cpsrRegister(C_FLAG));
                  theRegisters(datain20) <=
                          theRegisters(datain20) +
                          theRegisters(datain53) +
                          ("000" & x"0000000" & cpsrRegister(C_FLAG));
                  cpsrRegister(C_FLAG) <= tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain20)(31);
                  op2 := theRegisters(datain53)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and op2 and not opr) or
                                          (not op1 and not op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_SBC1 =>
                  tres := ("0" & theRegisters(datain20)) -
                          ("0" & theRegisters(datain53)) -
                          ("000" & x"0000000" & (not cpsrRegister(C_FLAG)));
                  theRegisters(datain20) <=
                          theRegisters(datain20) -
                          theRegisters(datain53) -
                          ("000" & x"0000000" & (not cpsrRegister(C_FLAG)));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain20)(31);
                  op2 := theRegisters(datain53)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_TST1 =>
                  tres := ("0" & theRegisters(datain20)) and
                          ("0" & theRegisters(datain53));
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_NEG1 =>
                  tres := ("0" & x"00000000") -
                          ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          x"00000000" -
                          theRegisters(datain53);
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain20)(31);
                  op2 := theRegisters(datain53)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_CMP2 =>
                  tres := ("0" & theRegisters(datain20)) -
                          ("0" & theRegisters(datain53));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain20)(31);
                  op2 := theRegisters(datain53)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_CMN1 =>
                  tres := ("0" & theRegisters(datain20)) +
                          ("0" & theRegisters(datain53));
                  cpsrRegister(C_FLAG) <= tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(datain20)(31);
                  op2 := theRegisters(datain53)(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and op2 and not opr) or
                                          (not op1 and not op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_ORR1 =>
                  tres := ("0" & theRegisters(datain20)) or
                          ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          theRegisters(datain20) or
                          theRegisters(datain53);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_MUL1 =>
                  theRegisters(datain20) <= product(31 downto 0);
                  cpsrRegister(N_FLAG) <= product(31);
                  if product(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;                
                  theRegisters(15) <= theRegisters(15) + 2;			        
                when CODE_BIC1 =>
                  tres := ("0" & theRegisters(datain20)) and
                          not ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          theRegisters(datain20) and
                          not theRegisters(datain53);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_MVN1 =>
                  tres := not ("0" & theRegisters(datain53));
                  theRegisters(datain20) <=
                          not theRegisters(datain53);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_CMP3 =>
                  tres := ("0" & theRegisters(conv_integer(datain(7) & datain(2 downto 0)))) -
                          ("0" & theRegisters(conv_integer(datain(6) & datain(5 downto 3))));
                  cpsrRegister(C_FLAG) <= not tres(32);
                  cpsrRegister(N_FLAG) <= tres(31);
                  if tres(31 downto 0) = 0 then
                    cpsrRegister(Z_FLAG) <= '1';
                  else
                    cpsrRegister(Z_FLAG) <= '0';
                  end if;
                  op1 := theRegisters(conv_integer(datain(7) & datain(2 downto 0)))(31);
                  op2 := theRegisters(conv_integer(datain(6) & datain(5 downto 3)))(31);
                  opr := tres(31);
                  cpsrRegister(V_FLAG) <= (op1 and not op2 and not opr) or
                                          (not op1 and op2 and opr);
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_BX1 =>
                  if theRegisters(14) = x"FFFFFFF9" then  -- EXC_RETURN ?
                    if datain(6 downto 3) = "1110" then
                      cpuState <= STATE_RET;
                    else
                      theRegisters(15) <= theRegisters(conv_integer(datain(6 downto 3)))(31 downto 1) & "0";
                      theRegisters(14) <= theRegisters(15) + 2;
                    end if;
                  else
                    theRegisters(15) <= theRegisters(conv_integer(datain(6 downto 3)))(31 downto 1) & "0";
                    if datain(6 downto 3) /= "1110" then
                      theRegisters(14) <= theRegisters(15) + 2;
                    end if;                  
                  end if;                  
                when CODE_LDR1 =>
                  address  <= (theRegisters(15) and x"FFFFFFFC") +
                              (x"00000" & "00" & datain(7 downto 0) & "00") + x"00000004";
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;
                when CODE_LDR4 =>
                  address  <= theRegisters(13) +
                              (x"00000" & "00" & datain(7 downto 0) & "00");
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;
                when CODE_STR1 | CODE_STRH1 =>
                  address  <= theRegisters(datain53) +
                              theRegisters(datain86);
                  addrMux  <= ADDR_RS;
                  writeL   <= '0';
                  writeH   <= '0';
                  dataout  <= theRegisters(datain20)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_STRB1 =>
                  address  <= theRegisters(datain53) +
                              theRegisters(datain86);
                  tsum     := theRegisters(datain53) +
                              theRegisters(datain86);
                  addrMux  <= ADDR_RS;
                  if tsum(0) = '0' then
                    writeL   <= '0';
                    writeH   <= '1';
                  else
                    writeL   <= '1';
                    writeH   <= '0';
                  end if;
                  dataout  <= theRegisters(datain20)(7 downto 0) &
                              theRegisters(datain20)(7 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_LDRSB1 | CODE_LDR2 | CODE_LDRH1 | CODE_LDRB1 | CODE_LDRSH1 =>
                  address  <= theRegisters(datain53) +
                              theRegisters(datain86);
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;
                when CODE_STR2 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "0" & datain(10 downto 6) & "00");
                  addrMux  <= ADDR_RS;
                  writeL   <= '0';
                  writeH   <= '0';
                  dataout  <= theRegisters(datain20)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_LDR3 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "0" & datain(10 downto 6) & "00");
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;
                when CODE_STRB2 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "000" & datain(10 downto 6));
                  tsum     := theRegisters(datain53) +
                              (x"000000" & "000" & datain(10 downto 6));
                  addrMux  <= ADDR_RS;
                  if tsum(0) = '0' then
                    writeL   <= '0';
                    writeH   <= '1';
                  else
                    writeL   <= '1';
                    writeH   <= '0';
                  end if;
                  dataout  <= theRegisters(datain20)(7 downto 0) &
                              theRegisters(datain20)(7 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_LDRB2 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "000" & datain(10 downto 6));
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;
                when CODE_LDRH2 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "00" & datain(10 downto 6) & "0");
                  addrMux  <= ADDR_RS;
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_READ1;                
                when CODE_STRH2 =>
                  address  <= theRegisters(datain53) +
                              (x"000000" & "00" & datain(10 downto 6) & "0");
                  addrMux  <= ADDR_RS;
                  writeL   <= '0';
                  writeH   <= '0';
                  dataout  <= theRegisters(datain20)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_STR3 =>
                  address  <= theRegisters(13) +
                              (x"00000" & "00" & datain(7 downto 0) & "00");
                  addrMux  <= ADDR_RS;
                  writeL   <= '0';
                  writeH   <= '0';
                  dataout  <= theRegisters(datain108)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_WRITE1;
                when CODE_ADD5 =>
                  theRegisters(datain108) <= 
                      theRegisters(15) + (x"00000" & "00" & datain(7 downto 0) & "00");
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_FETCH;
                when CODE_SXTH1 =>
                  theRegisters(datain20) <= 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) & 
                      theRegisters(datain53)(15) &
                      theRegisters(datain53)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_FETCH;
                when CODE_SXTB1 =>
                  theRegisters(datain20) <= 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7) & 
                      theRegisters(datain53)(7 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_FETCH;
                when CODE_UXTH1 =>
                  theRegisters(datain20) <= x"0000" &
                      theRegisters(datain53)(15 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_FETCH;
                when CODE_UXTB1 =>
                  theRegisters(datain20) <= x"000000" &
                      theRegisters(datain53)(7 downto 0);
                  theRegisters(15) <= theRegisters(15) + 2;
                  cpuState <= STATE_FETCH;
                when CODE_PUSH1 =>
                  theRegisters(15) <= theRegisters(15) + 2;
                  if datain(8 downto 0) = 0 then
                    cpuState <= STATE_FETCH;
                  else
                    theRegisters(13) <= theRegisters(13) - 2;
                    addrMux  <= ADDR_SP;
                    writeL   <= '0';
                    writeH   <= '0';
                    if datain(8) = '1' then
                      dataout <= theRegisters(14)(31 downto 16);
                      cpuState <= STATE_WRPH;
                    elsif datain(7) = '1' then
                      dataout <= theRegisters(7)(31 downto 16);
                      cpuState <= STATE_WR7H;
                    elsif datain(6) = '1' then
                      dataout <= theRegisters(6)(31 downto 16);
                      cpuState <= STATE_WR6H;
                    elsif datain(5) = '1' then
                      dataout <= theRegisters(5)(31 downto 16);
                      cpuState <= STATE_WR5H;
                    elsif datain(4) = '1' then
                      dataout <= theRegisters(4)(31 downto 16);
                      cpuState <= STATE_WR4H;
                    elsif datain(3) = '1' then
                      dataout <= theRegisters(3)(31 downto 16);
                      cpuState <= STATE_WR3H;
                    elsif datain(2) = '1' then
                      dataout <= theRegisters(2)(31 downto 16);
                      cpuState <= STATE_WR2H;
                    elsif datain(1) = '1' then
                      dataout <= theRegisters(1)(31 downto 16);
                      cpuState <= STATE_WR1H;
                    else
                      dataout <= theRegisters(0)(31 downto 16);
                      cpuState <= STATE_WR0H;
                    end if;
                  end if;
                when CODE_POP1 =>
                  theRegisters(15) <= theRegisters(15) + 2;
                  if datain(8 downto 0) = 0 then
                    cpuState <= STATE_FETCH;
                  else
                    addrMux  <= ADDR_SP;
                    if datain(0) = '1' then
                      cpuState <= STATE_RD0L;
                    elsif datain(1) = '1' then
                      cpuState <= STATE_RD1L;
                    elsif datain(2) = '1' then
                      cpuState <= STATE_RD2L;
                    elsif datain(3) = '1' then
                      cpuState <= STATE_RD3L;
                    elsif datain(4) = '1' then
                      cpuState <= STATE_RD4L;
                    elsif datain(5) = '1' then
                      cpuState <= STATE_RD5L;
                    elsif datain(6) = '1' then
                      cpuState <= STATE_RD6L;
                    elsif datain(7) = '1' then
                      cpuState <= STATE_RD7L;
                    else
                      cpuState <= STATE_RDPL;
                    end if;
                  end if;
                when CODE_NOP =>
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_STMIA1 =>
                  theRegisters(15) <= theRegisters(15) + 2;
                  if datain(7 downto 0) = 0 then
                    cpuState <= STATE_FETCH;
                  else
                    address  <= theRegisters(datain108);
                    addrMux  <= ADDR_RS;
                    writeL   <= '0';
                    writeH   <= '0';
                    if datain(0) = '1' then
                      dataout <= theRegisters(0)(15 downto 0);
                      cpuState <= STATE_WR0H;
                    elsif datain(1) = '1' then
                      dataout <= theRegisters(1)(15 downto 0);
                      cpuState <= STATE_WR1H;
                    elsif datain(2) = '1' then
                      dataout <= theRegisters(2)(15 downto 0);
                      cpuState <= STATE_WR2H;
                    elsif datain(3) = '1' then
                      dataout <= theRegisters(3)(15 downto 0);
                      cpuState <= STATE_WR3H;
                    elsif datain(4) = '1' then
                      dataout <= theRegisters(4)(15 downto 0);
                      cpuState <= STATE_WR4H;
                    elsif datain(5) = '1' then
                      dataout <= theRegisters(5)(15 downto 0);
                      cpuState <= STATE_WR5H;
                    elsif datain(6) = '1' then
                      dataout <= theRegisters(6)(15 downto 0);
                      cpuState <= STATE_WR6H;
                    else
                      dataout <= theRegisters(7)(15 downto 0);
                      cpuState <= STATE_WR7H;
                    end if;
                  end if;
                when CODE_LDMIA1 =>
                  LDMread <= x"00";
                  theRegisters(15) <= theRegisters(15) + 2;
                  if datain(7 downto 0) = 0 then
                    cpuState <= STATE_FETCH;
                  else
                    address  <= theRegisters(datain108);
                    addrMux  <= ADDR_RS;
                    if datain(0) = '1' then
                      cpuState <= STATE_RD0L;
                    elsif datain(1) = '1' then
                      cpuState <= STATE_RD1L;
                    elsif datain(2) = '1' then
                      cpuState <= STATE_RD2L;
                    elsif datain(3) = '1' then
                      cpuState <= STATE_RD3L;
                    elsif datain(4) = '1' then
                      cpuState <= STATE_RD4L;
                    elsif datain(5) = '1' then
                      cpuState <= STATE_RD5L;
                    elsif datain(6) = '1' then
                      cpuState <= STATE_RD6L;
                    else
                      cpuState <= STATE_RD7L;
                    end if;
                  end if;              
                when CODE_BCC1 =>
                  if branch = '1' then
                    theRegisters(15) <= theRegisters(15) + (
                      datain(7) & datain(7) & datain(7) & datain(7) & 
                      datain(7) & datain(7) & datain(7) & datain(7) & 
                      datain(7) & datain(7) & datain(7) & datain(7) & 
                      datain(7) & datain(7) & datain(7) & datain(7) & 
                      datain(7) & datain(7) & datain(7) & datain(7) & 
                      datain(7) & datain(7) & datain(7) &  
                      datain(7 downto 0) & "0") + x"00000004";                      
                  else
                    theRegisters(15) <= theRegisters(15) + 2;
                  end if;
                when CODE_B1 =>
                  theRegisters(15) <= theRegisters(15) + (
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10 downto 0) & "0") + x"00000004";   
                when CODE_BLX2 =>                  
                  theRegisters(14) <= theRegisters(15) + (
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) & datain(10) & datain(10) & datain(10) & 
                    datain(10) &
                    datain(10 downto 0) & x"000") + x"00000004";   
                  theRegisters(15) <= theRegisters(15) + 2;
                when CODE_BL1 =>
                  theRegisters(15) <= theRegisters(14) + (x"00000" &
                    datain(10 downto 0) & "0");   
                  theRegisters(14) <= theRegisters(15) + 2;
 
                when others =>
                  cpuState <= STATE_FETCH;
              end case; -- unitControl
            end if; -- irqrequest
          when STATE_READ1 => -- ##################################################
            case unitControl2 is
              when CODE_LDRH1 | CODE_LDRH2 =>
                theRegisters(opcode20)(15 downto 0) <= datain;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
              when CODE_LDRSH1 =>
                theRegisters(opcode20)(15 downto 0) <= datain;
                theRegisters(opcode20)(31 downto 16) <=
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & 
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & 
                    datain(15) & datain(15) & datain(15) & datain(15);
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
              when CODE_LDR1 | CODE_LDR4 =>
                theRegisters(opcode108)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_READ2;
              when CODE_LDR2 | CODE_LDR3 =>
                theRegisters(opcode20)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_READ2;
              when CODE_LDRSB1 =>
                if address(0) = '0' then
                  theRegisters(opcode20)(7 downto 0) <= datain(7 downto 0);
                  theRegisters(opcode20)(31 downto 8) <=
                    datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & 
                    datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & 
                    datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & 
                    datain(7) & datain(7) & datain(7) & datain(7) & datain(7) & datain(7);
                else
                  theRegisters(opcode20)(7 downto 0) <= datain(15 downto 8);
                  theRegisters(opcode20)(31 downto 8) <=
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & 
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & 
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & 
                    datain(15) & datain(15) & datain(15) & datain(15) & datain(15) & datain(15);
                end if;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
              when CODE_LDRB1 | CODE_LDRB2 =>
                if address(0) = '0' then
                  theRegisters(opcode20)(7 downto 0) <= datain(7 downto 0);
                else
                  theRegisters(opcode20)(7 downto 0) <= datain(15 downto 8);
                end if;
                theRegisters(opcode20)(31 downto 8) <= x"000000";
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_READ2 => -- ##################################################
            case unitControl2 is
              when CODE_LDR1 | CODE_LDR4 =>
                theRegisters(opcode108)(31 downto 16) <= datain;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
              when CODE_LDR2 | CODE_LDR3 =>
                theRegisters(opcode20)(31 downto 16) <= datain;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD0L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(0)(15 downto 0) <= datain;
                cpuState <= STATE_RD0H;
              when CODE_LDMIA1 =>
                LDMread(0) <= '1';
                theRegisters(0)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD0H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD0H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(0)(31 downto 16) <= datain;
                if opcode(8 downto 1) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(1) = '1' then
                    cpuState <= STATE_RD1L;
                  elsif opcode(2) = '1' then
                    cpuState <= STATE_RD2L;
                  elsif opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 1) = 0 then
                  addrMux  <= ADDR_PC;
                  if opcode108 = 0 then
                    theRegisters(0)(31 downto 16) <= datain;
                  else
                    theRegisters(opcode108) <= address + 2;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(0)(31 downto 16) <= datain;
                  if opcode(1) = '1' then
                    cpuState <= STATE_RD1L;
                  elsif opcode(2) = '1' then
                    cpuState <= STATE_RD2L;
                  elsif opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD1L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(1)(15 downto 0) <= datain;
                cpuState <= STATE_RD1H;
              when CODE_LDMIA1 =>
                LDMread(1) <= '1';
                theRegisters(1)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD1H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD1H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(1)(31 downto 16) <= datain;
                if opcode(8 downto 2) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(2) = '1' then
                    cpuState <= STATE_RD2L;
                  elsif opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 2) = 0 then
                  theRegisters(1)(31 downto 16) <= datain;
                  if opcode108 /= 1 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(1)(31 downto 16) <= datain;
                  if opcode(2) = '1' then
                    cpuState <= STATE_RD2L;
                  elsif opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD2L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(2)(15 downto 0) <= datain;
                cpuState <= STATE_RD2H;
              when CODE_LDMIA1 =>
                LDMread(2) <= '1';
                theRegisters(2)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD2H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD2H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(2)(31 downto 16) <= datain;
                if opcode(8 downto 3) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 3) = 0 then
                  addrMux  <= ADDR_PC;
                  theRegisters(2)(31 downto 16) <= datain;
                  if opcode108 /= 2 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(2)(31 downto 16) <= datain;
                  if opcode(3) = '1' then
                    cpuState <= STATE_RD3L;
                  elsif opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD3L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(3)(15 downto 0) <= datain;
                cpuState <= STATE_RD3H;
              when CODE_LDMIA1 =>
                LDMread(3) <= '1';
                theRegisters(3)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD3H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD3H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(3)(31 downto 16) <= datain;
                if opcode(8 downto 4) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 4) = 0 then
                  addrMux  <= ADDR_PC;
                  theRegisters(3)(31 downto 16) <= datain;
                  if opcode108 /= 3 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(3)(31 downto 16) <= datain;
                  if opcode(4) = '1' then
                    cpuState <= STATE_RD4L;
                  elsif opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD4L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(4)(15 downto 0) <= datain;
                cpuState <= STATE_RD4H;
              when CODE_LDMIA1 =>
                LDMread(4) <= '1';
                theRegisters(4)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD4H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD4H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(4)(31 downto 16) <= datain;
                if opcode(8 downto 5) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 5) = 0 then
                  addrMux  <= ADDR_PC;
                  theRegisters(4)(31 downto 16) <= datain;
                  if opcode108 /= 4 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(4)(31 downto 16) <= datain;
                  if opcode(5) = '1' then
                    cpuState <= STATE_RD5L;
                  elsif opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD5L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(5)(15 downto 0) <= datain;
                cpuState <= STATE_RD5H;
              when CODE_LDMIA1 =>
                LDMread(5) <= '1';
                theRegisters(5)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD5H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD5H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(5)(31 downto 16) <= datain;
                if opcode(8 downto 6) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  elsif opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7 downto 6) = 0 then
                  addrMux  <= ADDR_PC;
                  theRegisters(5)(31 downto 16) <= datain;
                  if opcode108 /= 5 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(5)(31 downto 16) <= datain;
                  if opcode(6) = '1' then
                    cpuState <= STATE_RD6L;
                  else
                    cpuState <= STATE_RD7L;
                  end if;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD6L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(6)(15 downto 0) <= datain;
                cpuState <= STATE_RD6H;
              when CODE_LDMIA1 =>
                LDMread(7) <= '1';
                theRegisters(6)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD6H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD6H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(6)(31 downto 16) <= datain;
                if opcode(8 downto 7) = 0 then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(7) = '1' then
                    cpuState <= STATE_RD7L;
                  else
                    cpuState <= STATE_RDPL;
                  end if;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                if opcode(7) = '0' then
                  addrMux  <= ADDR_PC;
                  theRegisters(6)(31 downto 16) <= datain;
                  if opcode108 /= 6 then
                    if LDMread(opcode108) /= '1' then
                      theRegisters(opcode108) <= address + 2;
                    end if;
                  end if;
                  cpuState <= STATE_FETCH;
                else
                  theRegisters(6)(31 downto 16) <= datain;              
                  cpuState <= STATE_RD7L;
                end if;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD7L => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(7)(15 downto 0) <= datain;
                cpuState <= STATE_RD7H;
              when CODE_LDMIA1 =>
                LDMread(7) <= '1';
                theRegisters(7)(15 downto 0) <= datain;
                address <= address + 2;
                cpuState <= STATE_RD7H;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RD7H => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(7)(31 downto 16) <= datain;
                if opcode(8) = '0' then
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;
                else
                  cpuState <= STATE_RDPL;
                end if;
              when CODE_LDMIA1 =>
                address <= address + 2;
                theRegisters(7)(31 downto 16) <= datain;
                if opcode108 /= 7 then
                  if LDMread(opcode108) /= '1' then
                    theRegisters(opcode108) <= address + 2;
                  end if;
                end if;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RDPL => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                if theRegisters(14) = x"FFFFFFF9" then
                  cpuState <= STATE_RET;
                else
                  theRegisters(13) <= theRegisters(13) + 2;
                  theRegisters(15)(15 downto 0) <= datain;
                  cpuState <= STATE_RDPH;
                end if;
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_RDPH => -- ##################################################
            case unitControl2 is
              when CODE_POP1 =>
                theRegisters(13) <= theRegisters(13) + 2;
                theRegisters(15)(31 downto 16) <= datain;
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
 
 
          when STATE_WRITE1 => -- ##################################################
            case unitControl2 is
              when CODE_STR1 | CODE_STR2 =>
                address <= address + 2;
                dataout  <= theRegisters(opcode20)(31 downto 16);
                cpuState <= STATE_WRITE2;
              when CODE_STRH1 | CODE_STRB1 | CODE_STRB2 | CODE_STRH2 =>
                addrMux  <= ADDR_PC;
                writeL   <= '1';
                writeH   <= '1';
                cpuState <= STATE_FETCH;
              when CODE_STR3 =>
                address <= address + 2;
                dataout  <= theRegisters(opcode108)(31 downto 16);
                cpuState <= STATE_WRITE2;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WRITE2 => -- ##################################################
            case unitControl2 is
              when CODE_STR1 | CODE_STR2 | CODE_STR3 =>
                addrMux  <= ADDR_PC;
                writeL   <= '1';
                writeH   <= '1';
                cpuState <= STATE_FETCH;
 
              when others =>
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WRPH =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(14)(15 downto 0);
                cpuState <= STATE_WRPL;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WRPL =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(7 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(7) = '1' then
                    dataout <= theRegisters(7)(31 downto 16);
                    cpuState <= STATE_WR7H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(31 downto 16);
                    cpuState <= STATE_WR6H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(31 downto 16);
                    cpuState <= STATE_WR5H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(31 downto 16);
                    cpuState <= STATE_WR4H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(31 downto 16);
                    cpuState <= STATE_WR3H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR7H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(7)(15 downto 0);
                cpuState <= STATE_WR7L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(7)(31 downto 16);
                cpuState <= STATE_WR7L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR7L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(6 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(6) = '1' then
                    dataout <= theRegisters(6)(31 downto 16);
                    cpuState <= STATE_WR6H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(31 downto 16);
                    cpuState <= STATE_WR5H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(31 downto 16);
                    cpuState <= STATE_WR4H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(31 downto 16);
                    cpuState <= STATE_WR3H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                writeL <= '1';
                writeH <= '1';
                addrMux <= ADDR_PC;
                theRegisters(opcode108) <= address + 2;
                cpuState <= STATE_FETCH;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR6H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(6)(15 downto 0);
                cpuState <= STATE_WR6L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(6)(31 downto 16);
                cpuState <= STATE_WR6L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR6L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(5 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(5) = '1' then
                    dataout <= theRegisters(5)(31 downto 16);
                    cpuState <= STATE_WR5H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(31 downto 16);
                    cpuState <= STATE_WR4H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(31 downto 16);
                    cpuState <= STATE_WR3H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7) = '0' then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  dataout <= theRegisters(7)(15 downto 0);
                  cpuState <= STATE_WR7H;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR5H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(5)(15 downto 0);
                cpuState <= STATE_WR5L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(5)(31 downto 16);
                cpuState <= STATE_WR5L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR5L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(4 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(4) = '1' then
                    dataout <= theRegisters(4)(31 downto 16);
                    cpuState <= STATE_WR4H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(31 downto 16);
                    cpuState <= STATE_WR3H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 6) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR4H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(4)(15 downto 0);
                cpuState <= STATE_WR4L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(4)(31 downto 16);
                cpuState <= STATE_WR4L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR4L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(3 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(3) = '1' then
                    dataout <= theRegisters(3)(31 downto 16);
                    cpuState <= STATE_WR3H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 5) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(5) = '1' then
                    dataout <= theRegisters(5)(15 downto 0);
                    cpuState <= STATE_WR5H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR3H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(3)(15 downto 0);
                cpuState <= STATE_WR3L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(3)(31 downto 16);
                cpuState <= STATE_WR3L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR3L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(2 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(2) = '1' then
                    dataout <= theRegisters(2)(31 downto 16);
                    cpuState <= STATE_WR2H;
                  elsif opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 4) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(4) = '1' then
                    dataout <= theRegisters(4)(15 downto 0);
                    cpuState <= STATE_WR4H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(15 downto 0);
                    cpuState <= STATE_WR5H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR2H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(2)(15 downto 0);
                cpuState <= STATE_WR2L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(2)(31 downto 16);
                cpuState <= STATE_WR2L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR2L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(1 downto 0) = 0 then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  if opcode(1) = '1' then
                    dataout <= theRegisters(1)(31 downto 16);
                    cpuState <= STATE_WR1H;
                  else
                    dataout <= theRegisters(0)(31 downto 16);
                    cpuState <= STATE_WR0H;
                  end if;
                end if;
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 3) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(3) = '1' then
                    dataout <= theRegisters(3)(15 downto 0);
                    cpuState <= STATE_WR3H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(15 downto 0);
                    cpuState <= STATE_WR4H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(15 downto 0);
                    cpuState <= STATE_WR5H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR1H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(1)(15 downto 0);
                cpuState <= STATE_WR1L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(1)(31 downto 16);
                cpuState <= STATE_WR1L;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR1L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                if opcode(0) = '0' then
                  writeL   <= '1';
                  writeH   <= '1';
                  addrMux  <= ADDR_PC;
                  cpuState <= STATE_FETCH;    
                else                  
                  theRegisters(13) <= theRegisters(13) - 2;
                  dataout <= theRegisters(0)(31 downto 16);
                  cpuState <= STATE_WR0H;
                end if;
            when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 2) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(2) = '1' then
                    dataout <= theRegisters(2)(15 downto 0);
                    cpuState <= STATE_WR2H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(15 downto 0);
                    cpuState <= STATE_WR3H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(15 downto 0);
                    cpuState <= STATE_WR4H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(15 downto 0);
                    cpuState <= STATE_WR5H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR0H =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                theRegisters(13) <= theRegisters(13) - 2;
                dataout  <= theRegisters(0)(15 downto 0);
                cpuState <= STATE_WR0L;
              when CODE_STMIA1 =>
                address <= address + 2;
                dataout <= theRegisters(0)(31 downto 16);
                cpuState <= STATE_WR0L;
 
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
          when STATE_WR0L =>  -- ##################################################
            case unitControl2 is
              when CODE_PUSH1 =>
                writeL   <= '1';
                writeH   <= '1';
                addrMux  <= ADDR_PC;
                cpuState <= STATE_FETCH;    
              when CODE_STMIA1 =>
                address <= address + 2;
                if opcode(7 downto 1) = 0 then
                  writeL <= '1';
                  writeH <= '1';
                  addrMux <= ADDR_PC;
                  theRegisters(opcode108) <= address + 2;
                  cpuState <= STATE_FETCH;
                else
                  if opcode(1) = '1' then
                    dataout <= theRegisters(1)(15 downto 0);
                    cpuState <= STATE_WR1H;
                  elsif opcode(2) = '1' then
                    dataout <= theRegisters(2)(15 downto 0);
                    cpuState <= STATE_WR2H;
                  elsif opcode(3) = '1' then
                    dataout <= theRegisters(3)(15 downto 0);
                    cpuState <= STATE_WR3H;
                  elsif opcode(4) = '1' then
                    dataout <= theRegisters(4)(15 downto 0);
                    cpuState <= STATE_WR4H;
                  elsif opcode(5) = '1' then
                    dataout <= theRegisters(5)(15 downto 0);
                    cpuState <= STATE_WR5H;
                  elsif opcode(6) = '1' then
                    dataout <= theRegisters(6)(15 downto 0);
                    cpuState <= STATE_WR6H;
                  else
                    dataout <= theRegisters(7)(15 downto 0);
                    cpuState <= STATE_WR7H;
                  end if;
                end if;
 
              when others =>
                writeL <= '1';
                writeH <= '1';
                cpuState <= STATE_FETCH;
            end case; -- unitControl2
 
 
 
          when others =>
            cpuState <= STATE_FETCH;
        end case; -- cpuState
      end if; -- rst = '0'
    end if; -- rising_edge(clk)
  end process;
 
 
end behavior;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.