-- PicoBlaze
--
-- Constant (K) Coded Programmable State Machine for Spartan-3 Devices.
-- Also suitable for use with Virtex-II(PRO) and Virtex-4 devices.
--
-- Includes additional code for enhanced VHDL simulation. 
--
-- Version : 1.30 
-- Version Date : 14th June 2004
-- Reasons : Avoid issue caused when ENABLE INTERRUPT is used when interrupts are
--           already enabled when an an interrupt input is applied.
--           Improved design for faster ZERO and CARRY flag logic   
--
--
-- Previous Version : 1.20 
-- Version Date : 9th July 2003
--
-- Start of design entry : 19th May 2003
--
-- Ken Chapman
-- Xilinx Ltd
-- Benchmark House
-- 203 Brooklands Road
-- Weybridge
-- Surrey KT13 ORH
-- United Kingdom
--
-- chapman@xilinx.com
--
-- Instruction disassembly concept inspired by the work of Prof. Dr.-Ing. Bernhard Lang.
-- University of Applied Sciences, Osnabrueck, Germany.
--
------------------------------------------------------------------------------------
--
-- NOTICE:
--
-- Copyright Xilinx, Inc. 2003.   This code may be contain portions patented by other 
-- third parties.  By providing this core as one possible implementation of a standard,
-- Xilinx is making no representation that the provided implementation of this standard 
-- is free from any claims of infringement by any third party.  Xilinx expressly 
-- disclaims any warranty with respect to the adequacy of the implementation, including 
-- but not limited to any warranty or representation that the implementation is free 
-- from claims of any third party.  Furthermore, Xilinx is providing this core as a 
-- courtesy to you and suggests that you contact all third parties to obtain the 
-- necessary rights to use this implementation.
--
------------------------------------------------------------------------------------
--
-- Format of this file.
--
-- This file contains the definition of KCPSM3 as one complete module with sections 
-- created using generate loops. This 'flat' approach has been adopted to decrease 
-- the time taken to load the module into simulators and the synthesis process.
--
-- The module defines the implementation of the logic using Xilinx primitives.
-- These ensure predictable synthesis results and maximise the density of the implementation. 
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
-- 
------------------------------------------------------------------------------------
--
-- Library declarations
--
-- Standard IEEE libraries
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library unisim;
use unisim.vcomponents.all;
--
------------------------------------------------------------------------------------
--
-- Main Entity for KCPSM3
--
entity kcpsm3 is
    Port (      address : out std_logic_vector(9 downto 0);
            instruction : in std_logic_vector(17 downto 0);
                port_id : out std_logic_vector(7 downto 0);
           write_strobe : out std_logic;
               out_port : out std_logic_vector(7 downto 0);
            read_strobe : out std_logic;
                in_port : in std_logic_vector(7 downto 0);
              interrupt : in std_logic;
          interrupt_ack : out std_logic;
                  reset : in std_logic;
                    clk : in std_logic);
    end kcpsm3;
--
------------------------------------------------------------------------------------
--
-- Start of Main Architecture for KCPSM3
--	 
architecture low_level_definition of kcpsm3 is
--
------------------------------------------------------------------------------------
--
-- Signals used in KCPSM3
--
------------------------------------------------------------------------------------
--
-- Fundamental control and decode signals
--	 
signal t_state                : std_logic;
signal not_t_state            : std_logic;
signal internal_reset         : std_logic;
signal reset_delay            : std_logic;
signal move_group             : std_logic;
signal condition_met          : std_logic;
signal normal_count           : std_logic;
signal call_type              : std_logic;
signal push_or_pop_type       : std_logic;
signal valid_to_move          : std_logic;
--
-- Flag signals
-- 
signal flag_type              : std_logic;
signal flag_write             : std_logic;
signal flag_enable            : std_logic;
signal zero_flag              : std_logic;
signal sel_shadow_zero        : std_logic;
signal low_zero               : std_logic;
signal high_zero              : std_logic;
signal low_zero_carry         : std_logic;
signal high_zero_carry        : std_logic;
signal zero_carry             : std_logic;
signal zero_fast_route        : std_logic;
signal low_parity             : std_logic;
signal high_parity            : std_logic;
signal parity_carry           : std_logic;
signal parity                 : std_logic;
signal carry_flag             : std_logic;
signal sel_parity             : std_logic;
signal sel_arith_carry        : std_logic;
signal sel_shift_carry        : std_logic;
signal sel_shadow_carry       : std_logic;
signal sel_carry              : std_logic_vector(3 downto 0);
signal carry_fast_route       : std_logic;
--
-- Interrupt signals
-- 
signal active_interrupt       : std_logic;
signal int_pulse              : std_logic;
signal clean_int              : std_logic;
signal shadow_carry           : std_logic;
signal shadow_zero            : std_logic;
signal int_enable             : std_logic;
signal int_update_enable      : std_logic;
signal int_enable_value       : std_logic;
signal interrupt_ack_internal : std_logic;
--
-- Program Counter signals
--
signal pc                     : std_logic_vector(9 downto 0);
signal pc_vector              : std_logic_vector(9 downto 0);
signal pc_vector_carry        : std_logic_vector(8 downto 0);
signal inc_pc_vector          : std_logic_vector(9 downto 0);
signal pc_value               : std_logic_vector(9 downto 0);
signal pc_value_carry         : std_logic_vector(8 downto 0);
signal inc_pc_value           : std_logic_vector(9 downto 0);
signal pc_enable              : std_logic;
--
-- Data Register signals
--
signal sx                     : std_logic_vector(7 downto 0);
signal sy                     : std_logic_vector(7 downto 0);
signal register_type          : std_logic;
signal register_write         : std_logic;
signal register_enable        : std_logic;
signal second_operand         : std_logic_vector(7 downto 0);
--
-- Scratch Pad Memory signals
--
signal memory_data            : std_logic_vector(7 downto 0);
signal store_data             : std_logic_vector(7 downto 0);
signal memory_type            : std_logic;
signal memory_write           : std_logic;
signal memory_enable          : std_logic;
--
-- Stack signals
--
signal stack_pop_data         : std_logic_vector(9 downto 0);
signal stack_ram_data         : std_logic_vector(9 downto 0);
signal stack_address          : std_logic_vector(4 downto 0);
signal half_stack_address     : std_logic_vector(4 downto 0);
signal stack_address_carry    : std_logic_vector(3 downto 0);
signal next_stack_address     : std_logic_vector(4 downto 0);
signal stack_write_enable     : std_logic;
signal not_active_interrupt   : std_logic;
--
-- ALU signals
--
signal logical_result         : std_logic_vector(7 downto 0);
signal logical_value          : std_logic_vector(7 downto 0);
signal sel_logical            : std_logic;
signal shift_result           : std_logic_vector(7 downto 0);
signal shift_value            : std_logic_vector(7 downto 0);
signal sel_shift              : std_logic;
signal high_shift_in          : std_logic;
signal low_shift_in           : std_logic;
signal shift_in               : std_logic;
signal shift_carry            : std_logic;
signal shift_carry_value      : std_logic;
signal arith_result           : std_logic_vector(7 downto 0);
signal arith_value            : std_logic_vector(7 downto 0);
signal half_arith             : std_logic_vector(7 downto 0);
signal arith_internal_carry   : std_logic_vector(7 downto 0);
signal sel_arith_carry_in     : std_logic;
signal arith_carry_in         : std_logic;
signal invert_arith_carry     : std_logic;
signal arith_carry_out        : std_logic;
signal sel_arith              : std_logic;
signal arith_carry            : std_logic;
--
-- ALU multiplexer signals
--
signal input_fetch_type       : std_logic;
signal sel_group              : std_logic;
signal alu_group              : std_logic_vector(7 downto 0);
signal input_group            : std_logic_vector(7 downto 0);
signal alu_result             : std_logic_vector(7 downto 0);
--
-- read and write strobes 
--
signal io_initial_decode      : std_logic;
signal write_active           : std_logic;
signal read_active            : std_logic;
--
--
------------------------------------------------------------------------------------
--
-- Attributes to define LUT contents during implementation for primitives not 
-- contained within generate loops. In each case the information is repeated
-- in the generic map for functional simulation
--
attribute INIT : string; 
attribute INIT of t_state_lut           : label is "1"; 
attribute INIT of int_pulse_lut         : label is "0080";
attribute INIT of int_update_lut        : label is "EAAA";
attribute INIT of int_value_lut         : label is "04";
attribute INIT of move_group_lut        : label is "7400";
attribute INIT of condition_met_lut     : label is "5A3C";
attribute INIT of normal_count_lut      : label is "2F";
attribute INIT of call_type_lut         : label is "1000";
attribute INIT of push_pop_lut          : label is "5400";
attribute INIT of valid_move_lut        : label is "D";
attribute INIT of flag_type_lut         : label is "41FC";
attribute INIT of flag_enable_lut       : label is "8";
attribute INIT of low_zero_lut          : label is "0001";
attribute INIT of high_zero_lut         : label is "0001";
attribute INIT of sel_shadow_zero_lut   : label is "3F";
attribute INIT of low_parity_lut        : label is "6996";
attribute INIT of high_parity_lut       : label is "6996";
attribute INIT of sel_parity_lut        : label is "F3FF";
attribute INIT of sel_arith_carry_lut   : label is "F3";
attribute INIT of sel_shift_carry_lut   : label is "C";
attribute INIT of sel_shadow_carry_lut  : label is "3";
attribute INIT of register_type_lut     : label is "0145";
attribute INIT of register_enable_lut   : label is "8";
attribute INIT of memory_type_lut       : label is "0400";
attribute INIT of memory_enable_lut     : label is "8000";
attribute INIT of sel_logical_lut       : label is "FFE2";
attribute INIT of low_shift_in_lut      : label is "E4";
attribute INIT of high_shift_in_lut     : label is "E4";
attribute INIT of shift_carry_lut       : label is "E4";
attribute INIT of sel_arith_lut         : label is "1F";
attribute INIT of input_fetch_type_lut  : label is "0002";
attribute INIT of io_decode_lut         : label is "0010";
attribute INIT of write_active_lut      : label is "4000";
attribute INIT of read_active_lut       : label is "0100";
--
------------------------------------------------------------------------------------
--
-- Start of KCPSM3 circuit description
--
------------------------------------------------------------------------------------
--	
begin
--
------------------------------------------------------------------------------------
--
-- Fundamental Control
--
-- Definition of T-state and internal reset
--
------------------------------------------------------------------------------------
--
  t_state_lut: LUT1
  --synthesis translate_off
    generic map (INIT => X"1")
  --synthesis translate_on
  port map( I0 => t_state,
             O => not_t_state );

  toggle_flop: FDR
  port map ( D => not_t_state,
             Q => t_state,
             R => internal_reset,
             C => clk);

  reset_flop1: FDS
  port map ( D => '0',
             Q => reset_delay,
             S => reset,
             C => clk);

  reset_flop2: FDS
  port map ( D => reset_delay,
             Q => internal_reset,
             S => reset,
             C => clk);
--
------------------------------------------------------------------------------------
--
-- Interrupt input logic, Interrupt enable and shadow Flags.
--	
-- Captures interrupt input and enables the shadow flags.
-- Decodes instructions which set and reset the interrupt enable flip-flop. 
--
------------------------------------------------------------------------------------
--

  -- Interrupt capture

  int_capture_flop: FDR
  port map ( D => interrupt,
             Q => clean_int,
             R => internal_reset,
             C => clk);

  int_pulse_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0080")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => clean_int,
            I2 => int_enable,
            I3 => active_interrupt,
             O => int_pulse );

  int_flop: FDR
  port map ( D => int_pulse,
             Q => active_interrupt,
             R => internal_reset,
             C => clk);

  ack_flop: FD
  port map ( D => active_interrupt,
             Q => interrupt_ack_internal,
             C => clk);

  interrupt_ack <= interrupt_ack_internal;

  -- Shadow flags

  shadow_carry_flop: FDE
  port map ( D => carry_flag,
             Q => shadow_carry,
            CE => active_interrupt,
             C => clk);

  shadow_zero_flop: FDE
  port map ( D => zero_flag,
             Q => shadow_zero,
            CE => active_interrupt,
             C => clk);

  -- Decode instructions that set or reset interrupt enable

  int_update_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"EAAA")
  --synthesis translate_on
  port map( I0 => active_interrupt,
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => int_update_enable );

  int_value_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"04")
  --synthesis translate_on
  port map( I0 => active_interrupt,
            I1 => instruction(0),
            I2 => interrupt_ack_internal,
             O => int_enable_value );

  int_enable_flop: FDRE
  port map ( D => int_enable_value,
             Q => int_enable,
            CE => int_update_enable,
             R => internal_reset,
             C => clk);
--
------------------------------------------------------------------------------------
--
-- Decodes for the control of the program counter and CALL/RETURN stack
--
------------------------------------------------------------------------------------
--
  move_group_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"7400")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => move_group );

  condition_met_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"5A3C")
  --synthesis translate_on
  port map( I0 => carry_flag,
            I1 => zero_flag,
            I2 => instruction(10),
            I3 => instruction(11),
             O => condition_met );

  normal_count_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"2F")
  --synthesis translate_on
  port map( I0 => instruction(12),
            I1 => condition_met,
            I2 => move_group,
             O => normal_count );

  call_type_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"1000")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => call_type );

  push_pop_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"5400")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => push_or_pop_type );

  valid_move_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"D")
  --synthesis translate_on
  port map( I0 => instruction(12),
            I1 => condition_met,
             O => valid_to_move );
--
------------------------------------------------------------------------------------
--
-- The ZERO and CARRY Flags
--
------------------------------------------------------------------------------------
--
  -- Enable for flags

  flag_type_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"41FC")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => flag_type );

  flag_write_flop: FD
  port map ( D => flag_type,
             Q => flag_write,
             C => clk);

  flag_enable_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"8")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => flag_write,
             O => flag_enable );

  -- Zero Flag

  low_zero_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0001")
  --synthesis translate_on
  port map( I0 => alu_result(0),
            I1 => alu_result(1),
            I2 => alu_result(2),
            I3 => alu_result(3),
             O => low_zero );

  high_zero_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0001")
  --synthesis translate_on
  port map( I0 => alu_result(4),
            I1 => alu_result(5),
            I2 => alu_result(6),
            I3 => alu_result(7),
             O => high_zero );

  low_zero_muxcy: MUXCY
  port map( DI => '0',
            CI => '1',
             S => low_zero,
             O => low_zero_carry );

  high_zero_cymux: MUXCY
  port map( DI => '0',
            CI => low_zero_carry,
             S => high_zero,
             O => high_zero_carry );

  sel_shadow_zero_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"3F")
  --synthesis translate_on
  port map( I0 => shadow_zero,
            I1 => instruction(16),
            I2 => instruction(17),
             O => sel_shadow_zero );

  zero_cymux: MUXCY
  port map( DI => shadow_zero,
            CI => high_zero_carry,
             S => sel_shadow_zero,
             O => zero_carry );

  zero_xor: XORCY
  port map( LI => '0',
            CI => zero_carry,
             O => zero_fast_route);

  zero_flag_flop: FDRE
  port map ( D => zero_fast_route,
             Q => zero_flag,
            CE => flag_enable,
             R => internal_reset,
             C => clk);

  -- Parity detection

  low_parity_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"6996")
  --synthesis translate_on
  port map( I0 => logical_result(0),
            I1 => logical_result(1),
            I2 => logical_result(2),
            I3 => logical_result(3),
             O => low_parity );

  high_parity_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"6996")
  --synthesis translate_on
  port map( I0 => logical_result(4),
            I1 => logical_result(5),
            I2 => logical_result(6),
            I3 => logical_result(7),
             O => high_parity );

  parity_muxcy: MUXCY
  port map( DI => '0',
            CI => '1',
             S => low_parity,
             O => parity_carry );

  parity_xor: XORCY
  port map( LI => high_parity,
            CI => parity_carry,
             O => parity);

  -- CARRY flag selection

  sel_parity_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"F3FF")
  --synthesis translate_on
  port map( I0 => parity,
            I1 => instruction(13),
            I2 => instruction(15),
            I3 => instruction(16),
             O => sel_parity );

  sel_arith_carry_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"F3")
  --synthesis translate_on
  port map( I0 => arith_carry,
            I1 => instruction(16),
            I2 => instruction(17),
             O => sel_arith_carry );

  sel_shift_carry_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"C")
  --synthesis translate_on
  port map( I0 => shift_carry,
            I1 => instruction(15),
             O => sel_shift_carry );

  sel_shadow_carry_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"3")
  --synthesis translate_on
  port map( I0 => shadow_carry,
            I1 => instruction(17),
             O => sel_shadow_carry );

  sel_shadow_muxcy: MUXCY
  port map( DI => shadow_carry,
            CI => '0',
             S => sel_shadow_carry,
             O => sel_carry(0) );

  sel_shift_muxcy: MUXCY
  port map( DI => shift_carry,
            CI => sel_carry(0),
             S => sel_shift_carry,
             O => sel_carry(1) );

  sel_arith_muxcy: MUXCY
  port map( DI => arith_carry,
            CI => sel_carry(1),
             S => sel_arith_carry,
             O => sel_carry(2) );

  sel_parity_muxcy: MUXCY
  port map( DI => parity,
            CI => sel_carry(2),
             S => sel_parity,
             O => sel_carry(3) );

  carry_xor: XORCY
  port map( LI => '0',
            CI => sel_carry(3),
             O => carry_fast_route);

  carry_flag_flop: FDRE
  port map ( D => carry_fast_route,
             Q => carry_flag,
            CE => flag_enable,
             R => internal_reset,
             C => clk);
--
------------------------------------------------------------------------------------
--
-- The Program Counter
--
-- Definition of a 10-bit counter which can be loaded from two sources
--
------------------------------------------------------------------------------------
--	

  invert_enable: INV   -- Inverter should be implemented in the CE to flip flops
  port map(  I => t_state,
             O => pc_enable);  
 
  pc_loop: for i in 0 to 9 generate
  --
  -- Attribute to define LUT contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  --
  attribute INIT : string; 
  attribute INIT of vector_select_mux : label is "E4";
  attribute INIT of value_select_mux  : label is "E4";
  --
  begin

    vector_select_mux: LUT3
    --synthesis translate_off
      generic map (INIT => X"E4")
    --synthesis translate_on
    port map( I0 => instruction(15),
              I1 => instruction(i),
              I2 => stack_pop_data(i), 
               O => pc_vector(i) );

    value_select_mux: LUT3
    --synthesis translate_off
      generic map (INIT => X"E4")
    --synthesis translate_on
    port map( I0 => normal_count,
              I1 => inc_pc_vector(i),
              I2 => pc(i),
               O => pc_value(i) );

     register_bit: FDRSE
     port map ( D => inc_pc_value(i),
                Q => pc(i),
                R => internal_reset,
                S => active_interrupt,
               CE => pc_enable,
                C => clk);

     pc_lsb_carry: if i=0 generate
       begin

         pc_vector_muxcy: MUXCY
         port map( DI => '0',
                   CI => instruction(13),
                    S => pc_vector(i),
                    O => pc_vector_carry(i));

         pc_vector_xor: XORCY
         port map( LI => pc_vector(i),
                   CI => instruction(13),
                    O => inc_pc_vector(i));

         pc_value_muxcy: MUXCY
         port map( DI => '0',
                   CI => normal_count,
                    S => pc_value(i),
                    O => pc_value_carry(i));

         pc_value_xor: XORCY
         port map( LI => pc_value(i),
                   CI => normal_count,
                    O => inc_pc_value(i));
					   					   
       end generate pc_lsb_carry;

     pc_mid_carry: if i>0 and i<9 generate
	 begin

         pc_vector_muxcy: MUXCY
         port map( DI => '0',
                   CI => pc_vector_carry(i-1),
                    S => pc_vector(i),
                    O => pc_vector_carry(i));

         pc_vector_xor: XORCY
         port map( LI => pc_vector(i),
                   CI => pc_vector_carry(i-1),
                    O => inc_pc_vector(i));

         pc_value_muxcy: MUXCY
         port map( DI => '0',
                   CI => pc_value_carry(i-1),
                    S => pc_value(i),
                    O => pc_value_carry(i));

         pc_value_xor: XORCY
         port map( LI => pc_value(i),
                   CI => pc_value_carry(i-1),
                    O => inc_pc_value(i));

       end generate pc_mid_carry;

     pc_msb_carry: if i=9 generate
       begin

         pc_vector_xor: XORCY
         port map( LI => pc_vector(i),
                   CI => pc_vector_carry(i-1),
                    O => inc_pc_vector(i));

          pc_value_xor: XORCY
         port map( LI => pc_value(i),
                   CI => pc_value_carry(i-1),
                    O => inc_pc_value(i));

       end generate pc_msb_carry;

  end generate pc_loop;

  address <= pc;
--
------------------------------------------------------------------------------------
--
-- Register Bank and second operand selection.
--
-- Definition of an 8-bit dual port RAM with 16 locations 
-- including write enable decode.
--
-- Outputs are assigned to PORT_ID and OUT_PORT.
--
------------------------------------------------------------------------------------
--	
  -- Forming decode signal

  register_type_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0145")
  --synthesis translate_on
  port map( I0 => active_interrupt,
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => register_type );

  register_write_flop: FD
  port map ( D => register_type,
             Q => register_write,
             C => clk);

  register_enable_lut: LUT2
  --synthesis translate_off
    generic map (INIT => X"8")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => register_write,
             O => register_enable );

  reg_loop: for i in 0 to 7 generate
  --
  -- Attribute to define RAM contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  --
  attribute INIT : string; 
  attribute INIT of register_bit       : label is "0000"; 
  attribute INIT of operand_select_mux : label is "E4"; 
  --
  begin

    register_bit: RAM16X1D
    --synthesis translate_off
    generic map(INIT => X"0000")
    --synthesis translate_on
    port map (       D => alu_result(i),
                    WE => register_enable,
                  WCLK => clk,
                    A0 => instruction(8),
                    A1 => instruction(9),
                    A2 => instruction(10),
                    A3 => instruction(11),
                 DPRA0 => instruction(4),
                 DPRA1 => instruction(5),
                 DPRA2 => instruction(6),
                 DPRA3 => instruction(7),
                   SPO => sx(i),
                   DPO => sy(i));

    operand_select_mux: LUT3
    --synthesis translate_off
      generic map (INIT => X"E4")
    --synthesis translate_on
    port map( I0 => instruction(12),
              I1 => instruction(i),
              I2 => sy(i),
               O => second_operand(i) );

  end generate reg_loop;

  out_port <= sx;
  port_id <= second_operand;
--
------------------------------------------------------------------------------------
--
-- Store Memory
--
-- Definition of an 8-bit single port RAM with 64 locations 
-- including write enable decode.
--
------------------------------------------------------------------------------------
--	
  -- Forming decode signal

  memory_type_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0400")
  --synthesis translate_on
  port map( I0 => active_interrupt,
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => memory_type );

  memory_write_flop: FD
  port map ( D => memory_type,
             Q => memory_write,
             C => clk);

  memory_enable_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"8000")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => instruction(13),
            I2 => instruction(14),
            I3 => memory_write,
             O => memory_enable );

  store_loop: for i in 0 to 7 generate
  --
  -- Attribute to define RAM contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  --
  attribute INIT : string; 
  attribute INIT of memory_bit : label is "0000000000000000"; 
  --
  begin

    memory_bit: RAM64X1S
    --synthesis translate_off
    generic map(INIT => X"0000000000000000")
    --synthesis translate_on
    port map (       D => sx(i),
                    WE => memory_enable,
                  WCLK => clk,
                    A0 => second_operand(0),
                    A1 => second_operand(1),
                    A2 => second_operand(2),
                    A3 => second_operand(3),
                    A4 => second_operand(4),
                    A5 => second_operand(5),
                     O => memory_data(i));

    store_flop: FD
    port map ( D => memory_data(i),
               Q => store_data(i),
               C => clk);

  end generate store_loop;
--
------------------------------------------------------------------------------------
--
-- Logical operations
--
-- Definition of AND, OR, XOR and LOAD functions which also provides TEST.
-- Includes pipeline stage used to form ALU multiplexer including decode.
--
------------------------------------------------------------------------------------
--
  sel_logical_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"FFE2")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => sel_logical );

  logical_loop: for i in 0 to 7 generate
  --
  -- Attribute to define LUT contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  attribute INIT : string; 
  attribute INIT of logical_lut : label is "6E8A"; 
  --
  begin

    logical_lut: LUT4
    --synthesis translate_off
    generic map (INIT => X"6E8A")
    --synthesis translate_on
    port map( I0 => second_operand(i),
              I1 => sx(i),
              I2 => instruction(13),
              I3 => instruction(14),
               O => logical_value(i));

    logical_flop: FDR
    port map ( D => logical_value(i),
               Q => logical_result(i),
               R => sel_logical,
               C => clk);

  end generate logical_loop;
--
--
------------------------------------------------------------------------------------
--
-- Shift and Rotate operations
--
-- Includes pipeline stage used to form ALU multiplexer including decode.
--
------------------------------------------------------------------------------------
--
  sel_shift_inv: INV   -- Inverter should be implemented in the reset to flip flops
  port map(  I => instruction(17),
             O => sel_shift); 

  -- Bit to input to shift register

  high_shift_in_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"E4")
  --synthesis translate_on
  port map( I0 => instruction(1),
            I1 => sx(0),
            I2 => instruction(0),
             O => high_shift_in );

  low_shift_in_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"E4")
  --synthesis translate_on
  port map( I0 => instruction(1),
            I1 => carry_flag,
            I2 => sx(7),
             O => low_shift_in );

  shift_in_muxf5: MUXF5
  port map(  I1 => high_shift_in,
             I0 => low_shift_in,
              S => instruction(2),
              O => shift_in ); 

  -- Forming shift carry signal

  shift_carry_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"E4")
  --synthesis translate_on
  port map( I0 => instruction(3),
            I1 => sx(7),
            I2 => sx(0),
             O => shift_carry_value );
					   
  pipeline_bit: FD
  port map ( D => shift_carry_value,
             Q => shift_carry,
             C => clk);

  shift_loop: for i in 0 to 7 generate
  begin

    lsb_shift: if i=0 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    attribute INIT : string; 
    attribute INIT of shift_mux_lut : label is "E4";
    --
    begin

      shift_mux_lut: LUT3
      --synthesis translate_off
        generic map (INIT => X"E4")
      --synthesis translate_on
      port map( I0 => instruction(3),
                I1 => shift_in,
                I2 => sx(i+1),
                 O => shift_value(i) );
	   
    end generate lsb_shift;

    mid_shift: if i>0 and i<7 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    attribute INIT : string; 
    attribute INIT of shift_mux_lut : label is "E4";
    --
    begin

      shift_mux_lut: LUT3
      --synthesis translate_off
        generic map (INIT => X"E4")
      --synthesis translate_on
      port map( I0 => instruction(3),
                I1 => sx(i-1),
                I2 => sx(i+1),
                 O => shift_value(i) );
	   
    end generate mid_shift;

    msb_shift: if i=7 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    attribute INIT : string; 
    attribute INIT of shift_mux_lut : label is "E4";
    --
    begin

      shift_mux_lut: LUT3
      --synthesis translate_off
        generic map (INIT => X"E4")
      --synthesis translate_on
      port map( I0 => instruction(3),
                I1 => sx(i-1),
                I2 => shift_in,
                 O => shift_value(i) );
	   
    end generate msb_shift;

    shift_flop: FDR
    port map ( D => shift_value(i),
               Q => shift_result(i),
               R => sel_shift,
               C => clk);

  end generate shift_loop;
--
------------------------------------------------------------------------------------
--
-- Arithmetic operations
--
-- Definition of ADD, ADDCY, SUB and SUBCY functions which also provides COMPARE.
-- Includes pipeline stage used to form ALU multiplexer including decode.
--
------------------------------------------------------------------------------------
--
  sel_arith_lut: LUT3
  --synthesis translate_off
    generic map (INIT => X"1F")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
             O => sel_arith );

  arith_loop: for i in 0 to 7 generate
  --
  -- Attribute to define LUT contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  attribute INIT : string; 
  attribute INIT of arith_lut : label is "96"; 
  --
  begin

    lsb_arith: if i=0 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    attribute INIT : string; 
    attribute INIT of arith_carry_in_lut : label is "6C";
    --
    begin

      arith_carry_in_lut: LUT3
      --synthesis translate_off
        generic map (INIT => X"6C")
      --synthesis translate_on
      port map( I0 => instruction(13),
                I1 => instruction(14),
                I2 => carry_flag,
                 O => sel_arith_carry_in );

      arith_carry_in_muxcy: MUXCY
      port map( DI => '0',
                CI => '1',
                 S => sel_arith_carry_in,
                 O => arith_carry_in);

      arith_muxcy: MUXCY
      port map( DI => sx(i),
                CI => arith_carry_in,
                 S => half_arith(i),
                 O => arith_internal_carry(i));

      arith_xor: XORCY
      port map( LI => half_arith(i),
                CI => arith_carry_in,
                 O => arith_value(i));
	   
    end generate lsb_arith;

    mid_arith: if i>0 and i<7 generate
    begin

      arith_muxcy: MUXCY
      port map( DI => sx(i),
                CI => arith_internal_carry(i-1),
                 S => half_arith(i),
                 O => arith_internal_carry(i));

      arith_xor: XORCY
      port map( LI => half_arith(i),
                CI => arith_internal_carry(i-1),
                 O => arith_value(i));
	   
    end generate mid_arith;

    msb_arith: if i=7 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    attribute INIT : string; 
    attribute INIT of arith_carry_out_lut : label is "2";
    --
    begin

      arith_muxcy: MUXCY
      port map( DI => sx(i),
                CI => arith_internal_carry(i-1),
                 S => half_arith(i),
                 O => arith_internal_carry(i));

      arith_xor: XORCY
      port map( LI => half_arith(i),
                CI => arith_internal_carry(i-1),
                 O => arith_value(i));

      arith_carry_out_lut: LUT1
      --synthesis translate_off
        generic map (INIT => X"2")
      --synthesis translate_on
      port map( I0 => instruction(14),
                 O => invert_arith_carry );

      arith_carry_out_xor: XORCY
      port map( LI => invert_arith_carry,
                CI => arith_internal_carry(i),
                 O => arith_carry_out);

      arith_carry_flop: FDR
      port map ( D => arith_carry_out,
                 Q => arith_carry,
                 R => sel_arith,
                 C => clk);

    end generate msb_arith;

    arith_lut: LUT3
    --synthesis translate_off
    generic map (INIT => X"96")
    --synthesis translate_on
    port map( I0 => sx(i),
              I1 => second_operand(i),
              I2 => instruction(14),
               O => half_arith(i));

    arith_flop: FDR
    port map ( D => arith_value(i),
               Q => arith_result(i),
               R => sel_arith,
               C => clk);

  end generate arith_loop;
--
--
------------------------------------------------------------------------------------
--
-- ALU multiplexer
--
------------------------------------------------------------------------------------
--
  input_fetch_type_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0002")
  --synthesis translate_on
  port map( I0 => instruction(14),
            I1 => instruction(15),
            I2 => instruction(16),
            I3 => instruction(17),
             O => input_fetch_type );

  sel_group_flop: FD
  port map ( D => input_fetch_type,
             Q => sel_group,
             C => clk);

  alu_mux_loop: for i in 0 to 7 generate
  --
  -- Attribute to define LUT contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  attribute INIT : string; 
  attribute INIT of or_lut  : label is "FE"; 
  attribute INIT of mux_lut : label is "E4"; 
  --
  begin

    or_lut: LUT3
    --synthesis translate_off
    generic map (INIT => X"FE")
    --synthesis translate_on
    port map( I0 => logical_result(i),
              I1 => arith_result(i),
              I2 => shift_result(i),
               O => alu_group(i));

    mux_lut: LUT3
    --synthesis translate_off
    generic map (INIT => X"E4")
    --synthesis translate_on
    port map( I0 => instruction(13),
              I1 => in_port(i),
              I2 => store_data(i),
               O => input_group(i));

    shift_in_muxf5: MUXF5
    port map(  I1 => input_group(i),
               I0 => alu_group(i),
                S => sel_group,
                O => alu_result(i) ); 

  end generate alu_mux_loop;
--
------------------------------------------------------------------------------------
--
-- Read and Write Strobes
--
------------------------------------------------------------------------------------
--
  io_decode_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0010")
  --synthesis translate_on
  port map( I0 => active_interrupt,
            I1 => instruction(13),
            I2 => instruction(14),
            I3 => instruction(16),
             O => io_initial_decode );

  write_active_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"4000")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => instruction(15),
            I2 => instruction(17),
            I3 => io_initial_decode,
             O => write_active );

  write_strobe_flop: FDR
  port map ( D => write_active,
             Q => write_strobe,
             R => internal_reset,
             C => clk);

  read_active_lut: LUT4
  --synthesis translate_off
    generic map (INIT => X"0100")
  --synthesis translate_on
  port map( I0 => t_state,
            I1 => instruction(15),
            I2 => instruction(17),
            I3 => io_initial_decode,
             O => read_active );

  read_strobe_flop: FDR
  port map ( D => read_active,
             Q => read_strobe,
             R => internal_reset,
             C => clk);
--
------------------------------------------------------------------------------------
--
-- Program CALL/RETURN stack
--
-- Provided the counter and memory for a 32 deep stack supporting nested 
-- subroutine calls to a depth of 31 levels.
--
------------------------------------------------------------------------------------
--
  -- Stack memory is 32 locations of 10-bit single port.
  
  stack_ram_inv: INV   -- Inverter should be implemented in the WE to RAM
  port map(  I => t_state,
             O => stack_write_enable); 

  stack_ram_loop: for i in 0 to 9 generate
  --
  -- Attribute to define RAM contents during implementation 
  -- The information is repeated in the generic map for functional simulation
  --
  attribute INIT : string; 
  attribute INIT of stack_bit : label is "00000000"; 
  --
  begin

    stack_bit: RAM32X1S
    --synthesis translate_off
    generic map(INIT => X"00000000")
    --synthesis translate_on
    port map (       D => pc(i),
                    WE => stack_write_enable,
                  WCLK => clk,
                    A0 => stack_address(0),
                    A1 => stack_address(1),
                    A2 => stack_address(2),
                    A3 => stack_address(3),
                    A4 => stack_address(4),
                     O => stack_ram_data(i));

    stack_flop: FD
    port map ( D => stack_ram_data(i),
               Q => stack_pop_data(i),
               C => clk);

  end generate stack_ram_loop;

  -- Stack address pointer is a 5-bit counter

  stack_count_inv: INV   -- Inverter should be implemented in the CE to the flip-flops
  port map(  I => active_interrupt,
             O => not_active_interrupt); 

  stack_count_loop: for i in 0 to 4 generate
  begin
  
    register_bit: FDRE
    port map ( D => next_stack_address(i),
               Q => stack_address(i),
               R => internal_reset,
              CE => not_active_interrupt,
               C => clk);

    lsb_stack_count: if i=0 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    --
    attribute INIT : string; 
    attribute INIT of count_lut : label is "6555"; 
    --
    begin
    
      count_lut: LUT4
      --synthesis translate_off
      generic map (INIT => X"6555")
      --synthesis translate_on
      port map( I0 => stack_address(i),
                I1 => t_state,
                I2 => valid_to_move,
                I3 => push_or_pop_type,
                 O => half_stack_address(i) );
    
      count_muxcy: MUXCY
      port map( DI => stack_address(i),
                CI => '0',
                 S => half_stack_address(i),
                 O => stack_address_carry(i));
    
      count_xor: XORCY
      port map( LI => half_stack_address(i),
                CI => '0',
                 O => next_stack_address(i));
    				   					   
    end generate lsb_stack_count;

    mid_stack_count: if i>0 and i<4 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    --
    attribute INIT : string; 
    attribute INIT of count_lut : label is "A999"; 
    --
    begin
    
      count_lut: LUT4
      --synthesis translate_off
      generic map (INIT => X"A999")
      --synthesis translate_on
      port map( I0 => stack_address(i),
                I1 => t_state,
                I2 => valid_to_move,
                I3 => call_type,
                 O => half_stack_address(i) );
    
      count_muxcy: MUXCY
      port map( DI => stack_address(i),
                CI => stack_address_carry(i-1),
                 S => half_stack_address(i),
                 O => stack_address_carry(i));
    
      count_xor: XORCY
      port map( LI => half_stack_address(i),
                CI => stack_address_carry(i-1),
                 O => next_stack_address(i));
    				   					   
    end generate mid_stack_count;


    msb_stack_count: if i=4 generate
    --
    -- Attribute to define LUT contents during implementation 
    -- The information is repeated in the generic map for functional simulation
    --
    attribute INIT : string; 
    attribute INIT of count_lut : label is "A999"; 
    --
    begin
    
      count_lut: LUT4
      --synthesis translate_off
      generic map (INIT => X"A999")
      --synthesis translate_on
      port map( I0 => stack_address(i),
                I1 => t_state,
                I2 => valid_to_move,
                I3 => call_type,
                 O => half_stack_address(i) );
    
      count_xor: XORCY
      port map( LI => half_stack_address(i),
                CI => stack_address_carry(i-1),
                 O => next_stack_address(i));
    				   					   
    end generate msb_stack_count;

  end generate stack_count_loop;

--
------------------------------------------------------------------------------------
--
-- End of description for KCPSM3 macro.
--
------------------------------------------------------------------------------------
--
--**********************************************************************************
-- Code for simulation purposes only after this line
--**********************************************************************************
--
------------------------------------------------------------------------------------
--
-- Code for simulation.
--
-- Disassemble the instruction codes to form a text string variable for display.
-- Determine status of reset and flags and present in the form of a text string.
-- Provide a local variables to simulate the contents of each register and scratch 
-- pad memory location.
--
------------------------------------------------------------------------------------
--
  --All of this section is ignored during synthesis.
  --synthesis translate off

  simulation: process (clk, instruction)
  --
  --complete instruction decode
  --
  variable kcpsm3_opcode : string(1 to 19);
  --
  --Status of flags and processor
  --
  variable kcpsm3_status : string(1 to 13):= "NZ, NC, Reset";

  --
  --contents of each register
  --
  variable s0_contents : std_logic_vector(7 downto 0):=X"00";
  variable s1_contents : std_logic_vector(7 downto 0):=X"00";
  variable s2_contents : std_logic_vector(7 downto 0):=X"00";
  variable s3_contents : std_logic_vector(7 downto 0):=X"00";
  variable s4_contents : std_logic_vector(7 downto 0):=X"00";
  variable s5_contents : std_logic_vector(7 downto 0):=X"00";
  variable s6_contents : std_logic_vector(7 downto 0):=X"00";
  variable s7_contents : std_logic_vector(7 downto 0):=X"00";
  variable s8_contents : std_logic_vector(7 downto 0):=X"00";
  variable s9_contents : std_logic_vector(7 downto 0):=X"00";
  variable sa_contents : std_logic_vector(7 downto 0):=X"00";
  variable sb_contents : std_logic_vector(7 downto 0):=X"00";
  variable sc_contents : std_logic_vector(7 downto 0):=X"00";
  variable sd_contents : std_logic_vector(7 downto 0):=X"00";
  variable se_contents : std_logic_vector(7 downto 0):=X"00";
  variable sf_contents : std_logic_vector(7 downto 0):=X"00";
  --
  --contents of each scratch pad memory location
  --
  variable spm00_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm01_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm02_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm03_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm04_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm05_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm06_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm07_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm08_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm09_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0a_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0b_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0c_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0d_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0e_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm0f_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm10_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm11_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm12_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm13_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm14_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm15_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm16_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm17_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm18_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm19_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1a_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1b_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1c_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1d_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1e_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm1f_contents : std_logic_vector(7 downto 0):=X"00";  
  variable spm20_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm21_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm22_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm23_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm24_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm25_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm26_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm27_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm28_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm29_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2a_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2b_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2c_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2d_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2e_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm2f_contents : std_logic_vector(7 downto 0):=X"00";  
  variable spm30_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm31_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm32_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm33_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm34_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm35_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm36_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm37_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm38_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm39_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3a_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3b_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3c_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3d_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3e_contents : std_logic_vector(7 downto 0):=X"00";
  variable spm3f_contents : std_logic_vector(7 downto 0):=X"00";
  --
  --temporary variables
  --
  variable     sx_decode : string(1 to 2);                     --sX register specification
  variable     sy_decode : string(1 to 2);                     --sY register specification
  variable     kk_decode : string(1 to 2);                     --constant value specification
  variable    aaa_decode : string(1 to 3);                     --address specification
  --
  --------------------------------------------------------------------------------
  --
  -- Function to convert 4-bit binary nibble to hexadecimal character
  --
  --------------------------------------------------------------------------------
  --
  function hexcharacter (nibble: std_logic_vector(3 downto 0))
  return character is
  variable hex: character;
  begin
    case nibble is
      when "0000" => hex := '0';
      when "0001" => hex := '1';
      when "0010" => hex := '2';
      when "0011" => hex := '3';
      when "0100" => hex := '4';
      when "0101" => hex := '5';
      when "0110" => hex := '6';
      when "0111" => hex := '7';
      when "1000" => hex := '8';
      when "1001" => hex := '9';
      when "1010" => hex := 'A';
      when "1011" => hex := 'B';
      when "1100" => hex := 'C';
      when "1101" => hex := 'D';
      when "1110" => hex := 'E';
      when "1111" => hex := 'F';
      when others => hex := 'x';
    end case;
    return hex;
  end hexcharacter;
  --
  --------------------------------------------------------------------------------
  --
  begin
     
    -- decode first register
    sx_decode(1) := 's';
    sx_decode(2) := hexcharacter(instruction(11 downto 8));             

    -- decode second register
    sy_decode(1) := 's';
    sy_decode(2) := hexcharacter(instruction(7 downto 4));  

    -- decode constant value
    kk_decode(1) := hexcharacter(instruction(7 downto 4));
    kk_decode(2) := hexcharacter(instruction(3 downto 0));

    -- address value
    aaa_decode(1) := hexcharacter("00" & instruction(9 downto 8));
    aaa_decode(2) := hexcharacter(instruction(7 downto 4));
    aaa_decode(3) := hexcharacter(instruction(3 downto 0));

    -- decode instruction
    case instruction(17 downto 12) is
      when "000000" => kcpsm3_opcode := "LOAD " & sx_decode & ',' & kk_decode & "         ";
      when "000001" => kcpsm3_opcode := "LOAD " & sx_decode & ',' & sy_decode & "         ";
      when "001010" => kcpsm3_opcode := "AND " & sx_decode & ',' & kk_decode & "          ";
      when "001011" => kcpsm3_opcode := "AND " & sx_decode & ',' & sy_decode & "          ";
      when "001100" => kcpsm3_opcode := "OR " & sx_decode & ',' & kk_decode & "           ";
      when "001101" => kcpsm3_opcode := "OR " & sx_decode & ',' & sy_decode & "           ";
      when "001110" => kcpsm3_opcode := "XOR " & sx_decode & ',' & kk_decode & "          ";
      when "001111" => kcpsm3_opcode := "XOR " & sx_decode & ',' & sy_decode & "          ";
      when "010010" => kcpsm3_opcode := "TEST " & sx_decode & ',' & kk_decode & "         ";
      when "010011" => kcpsm3_opcode := "TEST " & sx_decode & ',' & sy_decode & "         ";
      when "011000" => kcpsm3_opcode := "ADD " & sx_decode & ',' & kk_decode & "          ";
      when "011001" => kcpsm3_opcode := "ADD " & sx_decode & ',' & sy_decode & "          ";
      when "011010" => kcpsm3_opcode := "ADDCY " & sx_decode & ',' & kk_decode & "        ";
      when "011011" => kcpsm3_opcode := "ADDCY " & sx_decode & ',' & sy_decode & "        ";
      when "011100" => kcpsm3_opcode := "SUB " & sx_decode & ',' & kk_decode & "          ";
      when "011101" => kcpsm3_opcode := "SUB " & sx_decode & ',' & sy_decode & "          ";
      when "011110" => kcpsm3_opcode := "SUBCY " & sx_decode & ',' & kk_decode & "        ";
      when "011111" => kcpsm3_opcode := "SUBCY " & sx_decode & ',' & sy_decode & "        ";
      when "010100" => kcpsm3_opcode := "COMPARE " & sx_decode & ',' & kk_decode & "      ";
      when "010101" => kcpsm3_opcode := "COMPARE " & sx_decode & ',' & sy_decode & "      ";
      when "100000" => 
        case instruction(3 downto 0) is
          when "0110" => kcpsm3_opcode := "SL0 " & sx_decode & "             ";
          when "0111" => kcpsm3_opcode := "SL1 " & sx_decode & "             ";
          when "0100" => kcpsm3_opcode := "SLX " & sx_decode & "             ";
          when "0000" => kcpsm3_opcode := "SLA " & sx_decode & "             ";
          when "0010" => kcpsm3_opcode := "RL " & sx_decode & "              ";
          when "1110" => kcpsm3_opcode := "SR0 " & sx_decode & "             ";
          when "1111" => kcpsm3_opcode := "SR1 " & sx_decode & "             ";
          when "1010" => kcpsm3_opcode := "SRX " & sx_decode & "             ";
          when "1000" => kcpsm3_opcode := "SRA " & sx_decode & "             ";
          when "1100" => kcpsm3_opcode := "RR " & sx_decode & "              ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when "101100" => kcpsm3_opcode := "OUTPUT " & sx_decode & ',' & kk_decode & "       ";
      when "101101" => kcpsm3_opcode := "OUTPUT " & sx_decode & ",(" & sy_decode & ")     ";
      when "000100" => kcpsm3_opcode := "INPUT " & sx_decode & ',' & kk_decode & "        ";
      when "000101" => kcpsm3_opcode := "INPUT " & sx_decode & ",(" & sy_decode & ")      ";
      when "101110" => kcpsm3_opcode := "STORE " & sx_decode & ',' & kk_decode & "        ";
      when "101111" => kcpsm3_opcode := "STORE " & sx_decode & ",(" & sy_decode & ")      ";
      when "000110" => kcpsm3_opcode := "FETCH " & sx_decode & ',' & kk_decode & "        ";
      when "000111" => kcpsm3_opcode := "FETCH " & sx_decode & ",(" & sy_decode & ")      ";
      when "110100" => kcpsm3_opcode := "JUMP " & aaa_decode & "           ";
      when "110101" =>
        case instruction(11 downto 10) is
          when "00" => kcpsm3_opcode := "JUMP Z," & aaa_decode & "         ";
          when "01" => kcpsm3_opcode := "JUMP NZ," & aaa_decode & "        ";
          when "10" => kcpsm3_opcode := "JUMP C," & aaa_decode & "         ";
          when "11" => kcpsm3_opcode := "JUMP NC," & aaa_decode & "        ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when "110000" => kcpsm3_opcode := "CALL " & aaa_decode & "           ";
      when "110001" =>
        case instruction(11 downto 10) is
          when "00" => kcpsm3_opcode := "CALL Z," & aaa_decode & "         ";
          when "01" => kcpsm3_opcode := "CALL NZ," & aaa_decode & "        ";
          when "10" => kcpsm3_opcode := "CALL C," & aaa_decode & "         ";
          when "11" => kcpsm3_opcode := "CALL NC," & aaa_decode & "        ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when "101010" => kcpsm3_opcode := "RETURN             ";
      when "101011" =>
        case instruction(11 downto 10) is
          when "00" => kcpsm3_opcode := "RETURN Z           ";
          when "01" => kcpsm3_opcode := "RETURN NZ          ";
          when "10" => kcpsm3_opcode := "RETURN C           ";
          when "11" => kcpsm3_opcode := "RETURN NC          ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when "111000" =>
        case instruction(0) is
          when '0' => kcpsm3_opcode := "RETURNI DISABLE    ";
          when '1' => kcpsm3_opcode := "RETURNI ENABLE     ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when "111100" =>
        case instruction(0) is
          when '0' => kcpsm3_opcode := "DISABLE INTERRUPT  ";
          when '1' => kcpsm3_opcode := "ENABLE INTERRUPT   ";
          when others => kcpsm3_opcode := "Invalid Instruction";
        end case;
      when others => kcpsm3_opcode := "Invalid Instruction";
    end case;

    if clk'event and clk='1' then 

      --reset and flag status information
      if reset='1' or reset_delay='1' then
        kcpsm3_status := "NZ, NC, Reset";
       else
        kcpsm3_status(7 to 13) := "       ";
        if flag_enable='1' then
          if zero_carry='1' then
            kcpsm3_status(1 to 4) := " Z, ";
           else
            kcpsm3_status(1 to 4) := "NZ, ";
          end if;
          if sel_carry(3)='1' then
            kcpsm3_status(5 to 6) := " C";
           else
            kcpsm3_status(5 to 6) := "NC";
          end if;
        end if;
      end if;

      --simulation of register contents
      if register_enable='1' then
        case instruction(11 downto 8) is
          when "0000" => s0_contents := alu_result;
          when "0001" => s1_contents := alu_result;
          when "0010" => s2_contents := alu_result;
          when "0011" => s3_contents := alu_result;
          when "0100" => s4_contents := alu_result;
          when "0101" => s5_contents := alu_result;
          when "0110" => s6_contents := alu_result;
          when "0111" => s7_contents := alu_result;
          when "1000" => s8_contents := alu_result;
          when "1001" => s9_contents := alu_result;
          when "1010" => sa_contents := alu_result;
          when "1011" => sb_contents := alu_result;
          when "1100" => sc_contents := alu_result;
          when "1101" => sd_contents := alu_result;
          when "1110" => se_contents := alu_result;
          when "1111" => sf_contents := alu_result;
          when others => null;
        end case;
      end if;

      --simulation of scratch pad memory contents
      if memory_enable='1' then
        case second_operand(5 downto 0) is
          when "000000" => spm00_contents := sx;
          when "000001" => spm01_contents := sx;
          when "000010" => spm02_contents := sx;
          when "000011" => spm03_contents := sx;
          when "000100" => spm04_contents := sx;
          when "000101" => spm05_contents := sx;
          when "000110" => spm06_contents := sx;
          when "000111" => spm07_contents := sx;
          when "001000" => spm08_contents := sx;
          when "001001" => spm09_contents := sx;
          when "001010" => spm0a_contents := sx;
          when "001011" => spm0b_contents := sx;
          when "001100" => spm0c_contents := sx;
          when "001101" => spm0d_contents := sx;
          when "001110" => spm0e_contents := sx;
          when "001111" => spm0f_contents := sx;
          when "010000" => spm10_contents := sx;
          when "010001" => spm11_contents := sx;
          when "010010" => spm12_contents := sx;
          when "010011" => spm13_contents := sx;
          when "010100" => spm14_contents := sx;
          when "010101" => spm15_contents := sx;
          when "010110" => spm16_contents := sx;
          when "010111" => spm17_contents := sx;
          when "011000" => spm18_contents := sx;
          when "011001" => spm19_contents := sx;
          when "011010" => spm1a_contents := sx;
          when "011011" => spm1b_contents := sx;
          when "011100" => spm1c_contents := sx;
          when "011101" => spm1d_contents := sx;
          when "011110" => spm1e_contents := sx;
          when "011111" => spm1f_contents := sx;
          when "100000" => spm20_contents := sx;
          when "100001" => spm21_contents := sx;
          when "100010" => spm22_contents := sx;
          when "100011" => spm23_contents := sx;
          when "100100" => spm24_contents := sx;
          when "100101" => spm25_contents := sx;
          when "100110" => spm26_contents := sx;
          when "100111" => spm27_contents := sx;
          when "101000" => spm28_contents := sx;
          when "101001" => spm29_contents := sx;
          when "101010" => spm2a_contents := sx;
          when "101011" => spm2b_contents := sx;
          when "101100" => spm2c_contents := sx;
          when "101101" => spm2d_contents := sx;
          when "101110" => spm2e_contents := sx;
          when "101111" => spm2f_contents := sx;
          when "110000" => spm30_contents := sx;
          when "110001" => spm31_contents := sx;
          when "110010" => spm32_contents := sx;
          when "110011" => spm33_contents := sx;
          when "110100" => spm34_contents := sx;
          when "110101" => spm35_contents := sx;
          when "110110" => spm36_contents := sx;
          when "110111" => spm37_contents := sx;
          when "111000" => spm38_contents := sx;
          when "111001" => spm39_contents := sx;
          when "111010" => spm3a_contents := sx;
          when "111011" => spm3b_contents := sx;
          when "111100" => spm3c_contents := sx;
          when "111101" => spm3d_contents := sx;
          when "111110" => spm3e_contents := sx;
          when "111111" => spm3f_contents := sx;
          when others => null;
        end case;
      end if;

    end if;

  end process simulation;
  
  --synthesis translate on
--
--**********************************************************************************
-- End of simulation code.
--**********************************************************************************
--
--
end low_level_definition;
--
------------------------------------------------------------------------------------
--
-- END OF FILE KCPSM3.VHD
--
------------------------------------------------------------------------------------
