--------------------------------------------------
-- Model        :   8051 Behavioral Model,
--                  VHDL Entity mc8051.al_unit.interface
--
-- Author       :   Michael Mayer (mrmayer@computer.org),
--                  Dr. Hardy J. Pottinger,
--                  Department of Electrical Engineering
--                  University of Missouri - Rolla
--
-- Created at   :   09/19/98 20:02:07
--
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
LIBRARY mc8051 ;
USE mc8051.cpu_pack.all;
USE mc8051.synth_pack.all;

ENTITY al_unit IS
   PORT( 
      ac : IN     std_logic ;
      alu_cmd : IN     std_logic_vector( 3 DOWNTO 0 )  ;
      bit_loc : IN     std_logic_vector( 2 DOWNTO 0 )  ;
      cpu_rst : IN     std_logic ;
      cy : IN     std_logic ;
      data_alu : IN     std_logic_vector( 2 DOWNTO 0 )  ;
      int_clk : IN     std_logic ;
      ov : IN     std_logic ;
      set_ac_ov : IN     std_logic ;
      set_cy : IN     std_logic ;
      tmp1 : IN     std_logic_vector( 7 DOWNTO 0 )  ;
      tmp1_done : IN     std_logic ;
      tmp2 : IN     std_logic_vector( 7 DOWNTO 0 )  ;
      use_acc_0 : IN     std_logic ;
      use_cy : IN     std_logic ;
      ac_out : OUT    std_logic ;
      alu_result : OUT    std_logic_vector( 7 DOWNTO 0 )  ;
      cmp_true : OUT    std_logic ;
      cy_out : OUT    std_logic ;
      ov_out : OUT    std_logic
   );

-- Declarations

END al_unit ;
--
-- VHDL Architecture mc8051.al_unit.spec
--
-- Created:
--          by - mrmayer.UNKNOWN (eceultra20.ece.umr.edu)
--          at - 23:25:29 09/02/98
--
-- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110)
--


-- the organization is such:
--  tmp1 and tmp2 contain two data paramaters to be used,
--  tmp1 may be complemented and will then be converted to unsigned (arith1)
--  tmp2 may likely be the acc and will be converted to unsigned (arith2)
--  ctrl lines will cause these two arith's to be added, (or hence subtracted
--    if 2's complement was takes on tmp1) or logically combined.
--  Bit functions may also be performed.  Flags changed.
--  A comparison will be made between the answer and arith2.
--  The answer will be output to dest.
--  This all happens before done goes high (one clock cycle after rdy
--  goes high - triggered by tmp1_reg).

-- input ports:  alu_cmd(3 DOWNTO 0);   data_alu(2 DOWNTO 0);
--      set_cy
--      set_ac_ov
--      use_cy
--      use_old_flags
--      bit_loc (2 DOWNTO 0);
--      cpl_tmp1

-- output ports
--      test_result
--      result (7 DOWNTO 0);
--      ac_out, ov_out, cy_out, wr_out

architecture spec of al_unit is

    SIGNAL rdy, rdy_clk, done, done_clk : std_logic;

    SIGNAL cy_tmp, ac_tmp, ov_tmp       : std_logic;
    SIGNAL cy_tmp1 : std_logic;
    -- SIGNAL cy_old, ac_old, ov_old       : std_logic;
    SIGNAL bit_instr			    : std_logic;  -- '1' if its a bit instr
    SIGNAL bit1, bit2, bit_ans          : std_logic;
    SIGNAL tmp1_eq_tmp2, bit_to_insert  : std_logic;
    SIGNAL tmp1_with_bit                : std_logic_vector(7 DOWNTO 0);

    -- the parts of answer, separate to get info for ac, cy, ov
    SIGNAL add_en, sub_en               : std_logic;
    SIGNAL arith1_ls, arith2_ls, add_ls : unsigned(4 DOWNTO 0);
    SIGNAL arith1_ms, arith2_ms, add_ms : unsigned(3 DOWNTO 0);
    SIGNAL add_msb                      : std_logic;
    SIGNAL arith_ans                    : unsigned(7 DOWNTO 0);
    SIGNAL tmp1_7_XOR_tmp2_7            : std_logic;

    -- signals for the pre-processing to occur on the temp registers
    SIGNAL tmp1_post, tmp2_post         : std_logic_vector(7 DOWNTO 0);
    SIGNAL tmp1_2, tmp1_3               : unsigned(7 DOWNTO 0);

begin

------------------- BEGIN HANDSHAKING and CONTROL PROCESSING
   -- The following are flip - flops
   -- rdy is set on a clock edge after it receives tmp1_done
--   rdy_clk <= tmp1_done AND int_clk;
-- 
--   rdy <= '0' WHEN done = '1' OR cpu_rst = '1' ELSE
--          '1' WHEN rising_edge(rdy_clk) ELSE
--          rdy;
--
--   -- alu_done is set one clock cycle after rdy (delayed just to be safe)
--   done_clk <= rdy AND int_clk;
--   done <= '0' WHEN cpu_rst = '1' ELSE
--           '1' WHEN rising_edge(done_clk) ELSE
--           done;
--
--   alu_done <= done;

-------------- DETERMINE THE ANSWER HERE
   -- assign the answer to the output port result
   alu_result <= tmp1_post                           WHEN alu_cmd = pass_tmp1 ELSE
                 tmp2_post                           WHEN alu_cmd = pass_tmp2 ELSE
                 tmp2_post                           WHEN alu_cmd = rotate    ELSE
                 tmp1_with_bit                       WHEN bit_instr = '1'     ELSE
                 std_logic_vector(arith_ans);

------------- BEGIN PRE OPERAND PROCESSING
   -- first decide to complement the temp1 register
   tmp1_2 <= unsigned(NOT tmp1) WHEN std_match(data_alu,t1_cpl_val) ELSE
             unsigned(tmp1);

   -- second perform any necessay inc / dec
   tmp1_3 <= tmp1_2 + 1 WHEN std_match(data_alu,t1_inc_val) ELSE
             tmp1_2 - 1 WHEN std_match(data_alu,t1_dec_val) ELSE
             tmp1_2;

   -- third, decide if need to use cpl, inc/dec, swap, or just plain tmp1
   tmp1_post <= tmp1(7 DOWNTO 4) & tmp2(3 DOWNTO 0) WHEN std_match(alu_cmd,xchd1) ELSE
                std_logic_vector(tmp1_3)            WHEN std_match(alu_cmd,std_alu_data) ELSE
                tmp1;

------------- BEGIN BIT STUFF
   bit_instr <= '1' WHEN std_match(alu_cmd,"11--") ELSE '0';

   -- use a selector to get the corret bit for bit1
   bit1 <= cy      WHEN use_cy = '1'    ELSE
           tmp1(0) WHEN bit_loc = "000" ELSE
           tmp1(1) WHEN bit_loc = "001" ELSE
           tmp1(2) WHEN bit_loc = "010" ELSE
           tmp1(3) WHEN bit_loc = "011" ELSE
           tmp1(4) WHEN bit_loc = "100" ELSE
           tmp1(5) WHEN bit_loc = "101" ELSE
           tmp1(6) WHEN bit_loc = "110" ELSE
           tmp1(7) WHEN bit_loc = "111" ELSE
           'X';

   -- bit2 is input to the bit operator, and equal bit1 or /bit1
   -- cpl bit1 if cpl_bit_logic
   bit2    <=  NOT bit1 WHEN std_match(alu_cmd,cpl_bit_logic) ELSE bit1;  

   -- perform bit operations
   bit_ans <= bit2 AND cy WHEN std_match(data_alu,anl_instr) ELSE -- anl instr
              bit2 OR cy  WHEN std_match(data_alu,orl_instr) ELSE -- orl instr
              bit2;

   bit_to_insert <= '0'         WHEN alu_cmd = clr_bit ELSE
                    '1'         WHEN alu_cmd = set_bit ELSE
                    bit_ans;

   -- figure out where the bit gets inserted
   tmp1_with_bit(0) <= bit_to_insert WHEN bit_loc = "000" ELSE tmp1(0);
   tmp1_with_bit(1) <= bit_to_insert WHEN bit_loc = "001" ELSE tmp1(1);
   tmp1_with_bit(2) <= bit_to_insert WHEN bit_loc = "010" ELSE tmp1(2);
   tmp1_with_bit(3) <= bit_to_insert WHEN bit_loc = "011" ELSE tmp1(3);
   tmp1_with_bit(4) <= bit_to_insert WHEN bit_loc = "100" ELSE tmp1(4);
   tmp1_with_bit(5) <= bit_to_insert WHEN bit_loc = "101" ELSE tmp1(5);
   tmp1_with_bit(6) <= bit_to_insert WHEN bit_loc = "110" ELSE tmp1(6);
   tmp1_with_bit(7) <= bit_to_insert WHEN bit_loc = "111" ELSE tmp1(7);

   tmp1_eq_tmp2 <= '1' WHEN std_match(tmp1_post,tmp2_post) ELSE '0';

   cmp_true <= bit_ans      WHEN bit_instr = '1' ELSE  -- for JB, JNB, JC, JBC, etc.
                  tmp1_eq_tmp2 WHEN std_match(alu_cmd,compare_1_2) ELSE  -- for JZ
                  NOT tmp1_eq_tmp2;            -- for JNZ, DJNZ, CJNE

------------- END BIT STUFF
   
------------- BEGIN ARITHMATIC & LOGIC
   arith1_ls <= unsigned('0' & tmp1(3 DOWNTO 0));
   arith2_ls <= unsigned('0' & tmp2(3 DOWNTO 0));
   arith1_ms <= unsigned('0' & tmp1(6 DOWNTO 4));
   arith2_ms <= unsigned('0' & tmp2(6 DOWNTO 4));
   -- FULL ADDER WITH AC, OV, AND CY INFO
   -- add first 4 bits and store ac
   add_ls <= arith2_ls + arith1_ls;
   -- need to complement the ac if it is a subtraction
   ac_tmp <= NOT add_ls(4) WHEN std_match(data_alu,t1_cpl_val) ELSE
             add_ls(4);
   -- add next 3 bits (to get ov info)
   add_ms <= (arith2_ms + arith1_ms) + ("000" & add_ls(4));
   -- find the msb
   tmp1_7_XOR_tmp2_7 <= tmp1(7) XOR tmp2(7);
   add_msb <= tmp1_7_XOR_tmp2_7 XOR add_ms(3);
   -- find the carry bit 
   cy_tmp1 <= (tmp1_7_XOR_tmp2_7 AND add_ms(3)) OR 
             (tmp1(3) AND tmp2(3));
   cy_tmp  <= NOT cy_tmp1  WHEN std_match(data_alu,t1_cpl_val) ELSE
              cy_tmp1;

   -- ov represents (carry from bit 6 to 7) XOR (cy);
   ov_tmp  <= cy_tmp XOR add_ms(3);
   ---- mmayer is ov correct?  I think so.

   -- mimic the arithmatic and logic units   
   arith_ans <= add_msb & add_ms(2 DOWNTO 0) & add_ls(3 DOWNTO 0)
                                  WHEN std_match(alu_cmd ,add_instr) ELSE
                unsigned(tmp1_post) AND unsigned(tmp2_post) WHEN std_match(data_alu,anl_instr) ELSE
                unsigned(tmp1_post) OR  unsigned(tmp2_post) WHEN std_match(data_alu,orl_instr) ELSE
                unsigned(tmp1_post) XOR unsigned(tmp2_post) WHEN std_match(data_alu,xrl_instr) ELSE
                NOT unsigned(tmp2_post)        WHEN std_match(data_alu,cpl_instr) ELSE
                unsigned(tmp2_post);


   -- need to do mul and div and da

------------- END ARITHMATIC & LOGIC

   -- write bits to psw
   cy_out <= bit_ans    WHEN (bit_instr AND set_cy) = '1'   ELSE
             cy_tmp     WHEN set_cy = '1'     ELSE
             cy;
   ac_out <= ac_tmp     WHEN set_ac_ov = '1'  ELSE
             ac;
   ov_out <= ov_tmp     WHEN set_ac_ov = '1'  ELSE
             ov;
   -- WHAT IS THIS NEXT LINE FOR?  -- mrmayer
   -- wr_out <= done;
                          
end architecture spec;

<div align="center"><br /><script type="text/javascript"><!--
google_ad_client = "pub-7293844627074885";
//468x60, Created at 07. 11. 25
google_ad_slot = "8619794253";
google_ad_width = 468;
google_ad_height = 60;
//--></script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script><br />&nbsp;</div>