------------------------------------------------------------
-- Copyright Mentor Graphic Corporation 1991. 
-- All rights reserved.  
------------------------------------------------------------
--
--  Model Title:  control unit
--  Date Created: 95/10/29 (SUN)
--  Author:       T. Ohstuka ( tootsuka@ss.titech.ac.jp )
--
------------------------------------------------------------
-- Model Description: 
--
-----------------------------------------------------------
--
LIBRARY IEEE,ARITHMETIC ;
USE IEEE.STD_LOGIC_1164.ALL ;
USE ARITHMETIC.STD_LOGIC_ARITH.ALL ;

LIBRARY work ;

ENTITY cu_syn IS
   PORT (
         sp_load           :  OUT   STD_LOGIC ;   -- load signal for SP
         acc_load          :  OUT   STD_LOGIC ;   -- load signal for ACC
         rotate_right      :  OUT   STD_LOGIC ;   -- rotate right signal of ACC
         rotate_left       :  OUT   STD_LOGIC ;   -- rotate left signal of ACC
         shift_right       :  OUT   STD_LOGIC ;   -- shift right signal of ACC
         shift_left        :  OUT   STD_LOGIC ;   -- shift left signal of ACC
         zfc_acc_on        :  OUT   STD_LOGIC ;   -- zero flag condition which ACC is zero or not
         zfc_alu_on        :  OUT   STD_LOGIC ;   -- zero flag condition which ALU result is zero
         mar_load          :  OUT   STD_LOGIC ;   -- load signal for MAR
         add_with_carry    :  OUT   STD_LOGIC ;   -- add with carry signal
         sub_with_borrow   :  OUT   STD_LOGIC ;   -- substract with borrow signal 
         pc_out            :  OUT   STD_LOGIC ;   -- output signal for PC
         sp_out            :  OUT   STD_LOGIC ;   -- output signal for SP
         acc_out           :  OUT   STD_LOGIC ;   -- output signal for ACC
         if_carry          :  OUT   STD_LOGIC ;   -- carry jump condition
         if_zero           :  OUT   STD_LOGIC ;   -- zero jump condition
         pc_load           :  OUT   STD_LOGIC ;   -- load signal for PC
         clk1              :  IN    STD_LOGIC ;   -- phase 1 clock
         clk2              :  IN    STD_LOGIC ;   -- phase 2 clock
         io_write          :  OUT   STD_LOGIC ;   -- I/O write signal
         init              :  IN    STD_LOGIC ;   -- initialize signal
         carry             :  IN    STD_LOGIC ;   -- carry flag
         zero              :  IN    STD_LOGIC ;   -- zero flag
         active            :  OUT   STD_LOGIC ;   -- active signal ( RUN signal )
         mrd               :  OUT   STD_LOGIC ;   -- memory read signal
         mwr               :  OUT   STD_LOGIC ;   -- memory write signal
         ir                :  IN    STD_LOGIC_VECTOR(7 DOWNTO 0) ;   -- instruction resistor
         alu_f_ctl         :  OUT   STD_LOGIC_VECTOR(4 DOWNTO 0) ;   -- ALU function control (M,S3,S2,S1,S0)
         c_ctl             :  OUT   STD_LOGIC_VECTOR(2 DOWNTO 0) ;   -- ALU carry control (A,B,C)
         stop0             :  OUT   STD_LOGIC ;   -- stop signal
         last_cycle0       :  OUT   STD_LOGIC ;   -- last cycle of the instruction ( ir_clear )
         rff0              :  IN    STD_LOGIC     -- output of run FF
        ) ;
END cu_syn ;

-- ---------------------------------------------------------
--Copyright Mentor Graphic Corporation 1991.
--All rights reserved.
-----------------------------------------------------------
--Arch. Body for entity declared in 
------------------------------------------------------------
LIBRARY IEEE,ARITHMETIC ;
LIBRARY work ;

USE IEEE.STD_LOGIC_1164.ALL ;
USE ARITHMETIC.STD_LOGIC_ARITH.ALL ;

ARCHITECTURE behav1 OF cu_syn IS

SIGNAL   unused0,unused1,unused2,unused3,unused4,unused5,unused6 : STD_LOGIC ;
SIGNAL   ir_clear, ir_load, ir_enable  : STD_LOGIC ;    -- internal use for sequencing
SIGNAL   stop, last_cycle              : STD_LOGIC ;    -- internal use for stepwise execution
SIGNAL   if_c, if_z                    : STD_LOGIC ;    -- for conditional jump operation control
SIGNAL   f_ctl                         : STD_LOGIC_VECTOR(4 DOWNTO 0) ;   -- internal use for alu_f_ctl

CONSTANT cssize : POSITIVE := 4096 ;   -- SIZE OF CONTROL STRAGE
CONSTANT cswidth : POSITIVE := 40 ;    -- size of control word

SIGNAL   csar            : STD_LOGIC_VECTOR(11 DOWNTO 0) ; -- control strage address register 
SIGNAL   mir             : STD_LOGIC_VECTOR(cswidth-1 DOWNTO 0) ; -- micro instruction register
SIGNAL   rff             : STD_LOGIC ;                   -- RUN flip flop
SIGNAL   decode_alu_mode : STD_LOGIC_VECTOR(3 DOWNTO 0) ; -- decode the alu mode

BEGIN

rff <= rff0 ;
csar_process : PROCESS(clk1)
  -- process for the control strage(memory) address register
  BEGIN

  IF ((clk1='1') AND (clk1'LAST_VALUE='0') AND (clk1'EVENT) ) THEN
    IF ( init = '1' OR ir_clear = '1' ) THEN
      -- clear the control strage register
      csar <= "000000000000" ;
    ELSIF ( ir_load = '1' ) THEN
      -- load the instruction code from RAM into control storage address register
      csar <= ir & "0000" ;
    ELSIF ( ir_enable = '1' ) THEN
      -- increment the control strage address register
      csar <= csar + "000000000001" ;
    END IF;
  END IF ;

  END PROCESS csar_process ;

mir_process : PROCESS(clk2)
   -- procress for micro instruction register
   BEGIN

   IF ((clk2='1') AND (clk2'LAST_VALUE='0') AND (clk2'EVENT) ) THEN
    IF ( rff = '1' ) THEN
      CASE csar IS
       -- Add Instructions yourself !! --
       -- instruction fetch cycle
          --+-- CSAR ----+          +--------- micro instruction code ------+
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       -- fetch cycle
       WHEN "000000000000" => mir <="0000000000000000000010010000000000000011";--000.  MAR   <-PC 
       WHEN "000000000001" => mir <="0000000000000000010010000011000000000011";--001.  PC    <-INC(PC)
       WHEN "000000000010" => mir <="0000000000000000000000001000000000000101";--002.  IR    <-MS(MAR)
                                                                     --(IR,0000) --> CSAR ;
       -- clrc : clear carry flag
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "000000010000" => mir <="0000000000000000000000000000011000001001";--010.  CARRY <- 0              
                                                                     --(0)       --> CSAR ;
       -- setc : set carry flag
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "000000100000" => mir <="0000000000000000000000000000100000001001";--020.  CARRY <- 1              
                                                                     --(0)       --> CSAR ;
       -- dec : decrement acc
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "000100000000" => mir <="0000010000010000000000100011001111111001";--100.  ACC   <- DEC(ACC)
                                                                     --(0)       --> CSAR ;
       -- inc : increment acc
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "000100010000" => mir <="0000010000010000000000100011001000001001";--110.  ACC   <- INC(ACC)
                                                                     --(0)       --> CSAR ;
       -- shl : shift acc to left
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001000000000" => mir <="0000000000100010000000100000110000001001";--200.  ACC   <- shl(ACC)
                                                                     --(0)       --> CSAR ;
       -- shr : shift acc to right
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001000010000" => mir <="0000000000100001000000100000101000001001";--210.  ACC   <- shr(ACC)
                                                                     --(0)       --> CSAR ;
       -- rotl : rotate acc to left
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001000100000" => mir <="0000000000101000000000100000110000001001";--210.  ACC   <- rotl(ACC)
                                                                     --(0)       --> CSAR ;
       -- rotr : rotate acc to right
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001000110000" => mir <="0000000000100100000000100000101000001001";--210.  ACC   <- rotl(ACC)
                                                                     --(0)       --> CSAR ;
       -- jp : jump directly
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001100000000" => mir <="0000000000000000000010010000000000000011";--300.  MAR   <- PC
       WHEN "001100000001" => mir <="0000000000000000010000001000000110101001";--301.  PC    <- MS(MAR)
                                                                     --(0)       --> CSAR ;
       -- jc : jump if carry is high
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001100010000" => mir <="0000000000000000000010010000000000000011";--310.  MAR   <- PC
       WHEN "001100010001" => mir <="0000000000000000001000001000000110101001";--311.  PC    <- MS(MAR)if carry
                                                                     --(0)       --> CSAR ;
       -- jz : jump if zero is high
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "001100100000" => mir <="0000000000000000000010010000000000000011";--320.  MAR   <- PC
       WHEN "001100100001" => mir <="0000000000000000000100001000000110101001";--321.  PC    <- MS(MAR)if zero
                                                                     --(0)       --> CSAR ;
       -- add : add memory data to ACC without carry
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "110000000000" => mir <="0000000000000000000010010000000000000011";--c00.  MAR   <- PC             
       WHEN "110000000001" => mir <="0000000000000000010010000011000000000011";--c01.  PC    <- INC(PC)        
       WHEN "110000000010" => mir <="0000000000000000000000011000000110100011";--c02.  MAR   <- MS(MAR)        
       WHEN "110000000011" => mir <="0000010000010000000000101000001010011001";--c03.  ACC   <- ACC + MS(MAR)
                                                                     --(0)       --> CSAR ;
       -- addi : add immediately to ACC without carry
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "110000010000" => mir <="0000000000000000000010010000000000000011";--c10.  MAR   <- PC             
       WHEN "110000010001" => mir <="0000000000000000010010000011000000000011";--c11.  PC    <- INC(PC)        
       WHEN "110000010010" => mir <="0000010000000000000000101000001010011001";--c12.  ACC   <- ACC + #OPR        
                                                                     --(0)       --> CSAR ;
       -- load : load acc memory data to ACC
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "110110000000" => mir <="0000000000000000000010010000000000000011";--d80.  MAR   <- PC             
       WHEN "110110000001" => mir <="0000000000000000010010000011000000000011";--d81   PC    <- INC(PC)        
       WHEN "110110000010" => mir <="0000000000000000000000011000000110100011";--d82.  MAR   <- MS(MAR)        
       WHEN "110110000011" => mir <="0000010000100000000000001000000110101001";--d83.  ACC   <- MS(MAR)        
                                                                     --(0)       --> CSAR ;
       -- load : load acc immediately
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN "110110010000" => mir <="0000000000000000000010010000000000000011";--d90.  MAR   <- PC
       WHEN "110110010001" => mir <="0000000000000000010010000011000000000011";--d91   PC    <- INC(PC)
       WHEN "110110010010" => mir <="0000010000100000000000001000000110101001";--d92.  ACC   <- MS(MAR)        
                                                                     --(0)       --> CSAR ;
                     ----------------+---------+---------+---------+---------
                     ----------------9876543210987654321098765432109876543210
       WHEN OTHERS         => mir <="0000000000000000000000000000000000000000";
      END CASE ;
     ELSE
       mir <= "0000000000000000000000000000000000000000" ;
     END IF ;
   END IF ;

 END PROCESS mir_process ;

   -- decode the ALU function mode
   decode_alu_mode <= carry & if_c & zero & if_z ;
   WITH decode_alu_mode SELECT
     alu_f_ctl <= "11010"  WHEN "1100",
                  "11010"  WHEN "0011",
                  "11010"  WHEN "1111",
                  f_ctl    WHEN OTHERS ;

   -- interconnection
   last_cycle <= ir_clear ;
   if_carry <= if_c ;
   if_zero  <= if_z ;


-- mir bit assignment

   unused5           <= mir(39) ;
   unused4           <= mir(38) ;
   unused3           <= mir(37) ;
   unused2           <= mir(36) ;

   sp_load           <= mir(35) ;
   acc_load          <= mir(34) ;
   io_write          <= mir(33) ;
   unused1           <= mir(32) ;

   unused0           <= mir(31) ;
   unused6           <= mir(30) ;
   zfc_acc_on        <= mir(29) ;
   zfc_alu_on        <= mir(28) ;

   rotate_left       <= mir(27) ;
   rotate_right      <= mir(26) ;
   shift_left        <= mir(25) ;
   shift_right       <= mir(24) ;

   stop              <= mir(23) ;
   pc_load           <= mir(22) ;
   if_c              <= mir(21) ;
   if_z              <= mir(20) ;

   pc_out            <= mir(19) ;
   sp_out            <= mir(18) ;
   acc_out           <= mir(17) ;
   mar_load          <= mir(16) ;

   mrd               <= mir(15) ;
   mwr               <= mir(14) ;
   add_with_carry    <= mir(13) ;
   sub_with_borrow   <= mir(12) ;

   c_ctl(2)          <= mir(11) ;
   c_ctl(1)          <= mir(10) ;
   c_ctl(0)          <= mir(9) ;
   f_ctl(4)          <= mir(8) ;

   f_ctl(3)          <= mir(7) ;
   f_ctl(2)          <= mir(6) ;
   f_ctl(1)          <= mir(5) ;
   f_ctl(0)          <= mir(4) ;

   ir_clear          <= mir(3) ;
   ir_load           <= mir(2) ;
   ir_enable         <= mir(1) ;
   active            <= mir(0) ;
-- I/O interface 
   stop0 <= stop ;
   last_cycle0 <= last_cycle ;
 
END behav1;