-- Model Name : Procedural - Parwan_Functional -- Author : Zainalabedin Navabi -- Last Updated : 09 / 15 / 1996 -- This document is © copyrighted by the Author.


LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
--
LIBRARY EXEMPLAR;
USE EXEMPLAR.exemplar_1164.ALL;
--
LIBRARY WORK;
USE WORK.synthesis_parameters.ALL;
USE WORK.synthesis_utilities.ALL;
USE WORK.alu_operations.ALL;
--

PACKAGE ParFunctional IS
  SIGNAL halt : std_logic := '0';

  SIGNAL cck : std_ulogic := '0';
  SHARED VARIABLE ac_out, ir_out, alu_out, obus : byte;
  SHARED VARIABLE pc_out, mar_out : twelve;
  SHARED VARIABLE dbus : byte;
  SHARED VARIABLE alu_code : std_logic_vector (2 DOWNTO 0):="000";
  SHARED VARIABLE alu_flags, shu_flags, sr_out : nibble;
  SHARED VARIABLE mar_bus : twelve;
  SHARED VARIABLE databus : byte;
  SHARED VARIABLE adbus : twelve;

  PROCEDURE AccZero;
  PROCEDURE AccLoad;
  PROCEDURE IrLoad;  
  PROCEDURE MarPage;  
  PROCEDURE MarOffset;
  PROCEDURE SrLoad;
  PROCEDURE SrCm_carry; 
  PROCEDURE PcReset;
  PROCEDURE PcIncrement;
  PROCEDURE PcPage;
  PROCEDURE PcOffset;
  PROCEDURE ShifterLeft; 
  PROCEDURE ShifterRight;
  PROCEDURE ShifterNoshift;
  PROCEDURE Alu;
  ---------
  PROCEDURE dbus_on_mar_offset_bus;
  PROCEDURE dbus_on_databus;
  PROCEDURE obus_on_dbus;
  PROCEDURE databus_on_dbus;
  PROCEDURE ir_on_mar_page_bus;
  PROCEDURE pc_on_mar_page_bus;
  PROCEDURE pc_on_mar_offset_bus;
  PROCEDURE pc_offset_on_dbus;
  PROCEDURE mar_on_adbus;
    
END ParFunctional;

----------------------------
PACKAGE BODY ParFunctional IS
  PROCEDURE AccZero IS 
  BEGIN
    ac_out := "00000000";
  END AccZero;

  PROCEDURE AccLoad IS 
  BEGIN
    ac_out := obus;
  END AccLoad;
------------
  PROCEDURE IrLoad IS
  BEGIN
    ir_out := obus;
  END IrLoad;
------------
  PROCEDURE MarPage IS
  BEGIN
    mar_out (11 DOWNTO 8) := mar_bus (11 DOWNTO 8);
  END MarPage;

  PROCEDURE MarOffset IS
  BEGIN
    mar_out (7 DOWNTO 0) := mar_bus (7 DOWNTO 0);
  END MarOffset;
------------
  PROCEDURE SrLoad IS
  BEGIN
    sr_out := shu_flags;
  END Srload;
  PROCEDURE SrCm_carry IS
  BEGIN
    sr_out (2) := NOT sr_out (2);  
  END SrCm_carry;
------------
  PROCEDURE PcReset IS
  BEGIN
    pc_out := zero_12;
  END PcReset;
  PROCEDURE PcIncrement IS
  BEGIN
    pc_out := pc_out + "01";
  END PcIncrement;
  PROCEDURE PcPage IS
  BEGIN
     pc_out (11 DOWNTO 8) := mar_out (11 DOWNTO 8);
  END PcPage;
  PROCEDURE PcOffset IS
  BEGIN
     pc_out (7 DOWNTO 0) := mar_out (7 DOWNTO 0);
  END PcOffset;
------------
  PROCEDURE ShifterLeft IS
    VARIABLE v, c, z, n : std_logic; --in_flags 3210  
  BEGIN
    obus := alu_out (6 DOWNTO 0) & '0';
    n := obus (7);
    z := NOT all_or (obus);
    c := alu_out (7);
    v := alu_out (6) XOR alu_out (7);
    shu_flags := v & c & z & n;
  END ShifterLeft;
  
  PROCEDURE ShifterRight IS
    VARIABLE v, c, z, n : std_logic; --in_flags 3210
  BEGIN
    obus := alu_out (7) & alu_out (7 DOWNTO 1);
    n := obus (7);
    z := NOT all_or (obus);
    c := alu_flags(2);
    v := alu_flags(3);
    shu_flags := v & c & z & n;
  END ShifterRight;
  
  PROCEDURE ShifterNoshift IS
    VARIABLE v, c, z, n : std_logic; --in_flags 3210
  BEGIN
    obus := alu_out (7 DOWNTO 0);
    n := alu_flags(0);
    z := alu_flags(1);
    c := alu_flags(2);
    v := alu_flags(3);
    shu_flags := v & c & z & n;
  END ShifterNoshift;
  
  
------------ ******** alu_code has to become a shared variable
  PROCEDURE Alu IS
    VARIABLE t : std_logic_vector (9 DOWNTO 0);
    VARIABLE v, c, z, n : std_logic; --in_flags 3210
  BEGIN
    CASE alu_code IS
      WHEN a_add_b | a_sub_b => 
        t := addsub_cv (ac_out, dbus, sr_out(2), alu_code(1));
        c := t(8);  v := t(9);  -- other flags are set at the end
      WHEN a_and_b =>
        t := "00" & ( dbus AND ac_out );
        c := sr_out(2);  v := sr_out(3);
      WHEN a_input  =>
        t := "00" & dbus;
        c := sr_out(2);  v := sr_out(3);
      WHEN b_input  =>
        t := "00" & ac_out;
        c := sr_out(2);  v := sr_out(3);
      WHEN b_compl =>
        t := "00" & ( NOT ac_out );
        c := sr_out(2);  v := sr_out(3);
      WHEN OTHERS => 
        t := "0000000000"; c:= '0'; v := '0';
    END CASE;
    n := t(7);
    z := NOT all_or (t(7 DOWNTO 0));
    alu_out := t (7 DOWNTO 0);
    alu_flags := v & c & z & n;
  END Alu;  
 --=====================
  PROCEDURE dbus_on_mar_offset_bus IS 
  BEGIN
    mar_bus (7 DOWNTO 0) := dbus;
  END dbus_on_mar_offset_bus;
 ---------------------- 
  PROCEDURE dbus_on_databus IS
  BEGIN
    databus := dbus;
  END dbus_on_databus;
 ---------------------- 
  PROCEDURE obus_on_dbus IS
  BEGIN
    dbus := obus;
  END obus_on_dbus;
 ---------------------- 
  PROCEDURE databus_on_dbus IS
  BEGIN
    dbus := databus;
  END databus_on_dbus;
 ----------------------
  PROCEDURE ir_on_mar_page_bus IS
  BEGIN
    mar_bus (11 DOWNTO 8) := ir_out (3 DOWNTO 0);
  END ir_on_mar_page_bus;
 ---------------------- 
  PROCEDURE pc_on_mar_page_bus IS
  BEGIN
    mar_bus (11 DOWNTO 8) := pc_out (11 DOWNTO 8);
  END pc_on_mar_page_bus;
 ---------------------- 
  PROCEDURE pc_on_mar_offset_bus IS
  BEGIN
    mar_bus (7 DOWNTO 0) := pc_out (7 DOWNTO 0);
  END pc_on_mar_offset_bus;
 ---------------------- 
  PROCEDURE pc_offset_on_dbus IS
  BEGIN
    dbus := pc_out (7 DOWNTO 0);
  END pc_offset_on_dbus;
 ----------------------
  PROCEDURE mar_on_adbus IS
  BEGIN
    adbus := mar_out;
  END mar_on_adbus;  
END ParFunctional;