--------------------------------------------------
-- Model        :   8051 Behavioral Model,
--                  VHDL Entity mc8051.pc_chg.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:01
--
LIBRARY ieee ;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
LIBRARY mc8051 ;
USE mc8051.synth_pack.all;

ENTITY pc_chg IS
   PORT( 
      cmp_true : IN     std_logic ;
      cycle_states : IN     std_logic_vector( 3 DOWNTO 0 )  ;
      dptr : IN     std_logic_vector( 15 DOWNTO 0 )  ;
      int_clk : IN     std_logic ;
      int_rst : IN     std_logic ;
      ir : IN     std_logic_vector( 7 DOWNTO 0 )  ;
      last_cycle : IN     std_logic ;
      new_ir : IN     std_logic ;
      pc : IN     std_logic_vector( 15 DOWNTO 0 )  ;
      pmem1 : IN     std_logic_vector( 7 DOWNTO 0 )  ;
      pmem2 : IN     std_logic_vector( 7 DOWNTO 0 )  ;
      addr_gb : OUT    std_logic_vector( 7 DOWNTO 0 )  ;
      dec_rd_sp : OUT    std_logic ;
      inc_wr_sp : OUT    std_logic ;
      indirect_sel : OUT    std_logic ;
      new_pc : OUT    std_logic_vector( 15 DOWNTO 0 )  ;
      rd_gb : OUT    std_logic ;
      wr_gb : OUT    std_logic ;
      wr_pc : OUT    std_logic ;
      acknow : INOUT  std_logic ;
      data_gb : INOUT  std_logic_vector( 7 DOWNTO 0 ) 
   );

-- Declarations

END pc_chg ;
--
-- VHDL Architecture mc8051.pc_chg.spec
--
-- Created:
--          by - mrmayer.UNKNOWN (eceultra7.ece.umr.edu)
--          at - 12:38:13 08/29/98
--
-- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110)
--
architecture spec of pc_chg is

   SIGNAL temp_reg  : std_logic_vector(15 DOWNTO 0);
   SIGNAL add_result, add_op1, add_op2 : unsigned(15 DOWNTO 0);
   SIGNAL use_2_for_rel, use_1_for_rel : std_logic;
   SIGNAL prefix : std_logic_vector(7 DOWNTO 0);

BEGIN

   -- define some combinational logic to store the pc to the
   -- stack for ACALL and LCALL
   store_pc : PROCESS (ir, last_cycle, cycle_states, pc) IS
   BEGIN
      -- ACALL or LCALL
      -- note the ack from gb is ignore (assumed to work)
      IF std_match(ir,"---10001") OR std_match(ir,"00010010") THEN
         IF last_cycle = '0' AND cycle_states = s3p1 THEN
             data_gb <= pc(7 DOWNTO 0);
             inc_wr_sp <= '1';
         ELSIF last_cycle = '0' AND cycle_states = s4p1 THEN
             data_gb <= pc(15 DOWNTO 8);
             inc_wr_sp <= '1';
         ELSE
             data_gb <= (OTHERS => 'Z');
             inc_wr_sp <= 'Z';
         END IF;
      END IF;
   END PROCESS store_pc;

   -- these two signals define which byte (pmem1 or pmem2) is used for the
   -- relative address
   use_1_for_rel <= '1' WHEN (std_match(ir,"11011---") OR     -- DJNZ Rn, rel
                              std_match(ir,"01--0000") ) OR   -- JC, JNC, JNZ, JZ
                              std_match(ir,"10000000") ELSE   -- SJMP
                    '0';

   use_2_for_rel <= '1' WHEN (std_match(ir,"1011----") AND NOT std_match(ir,"----00--") ) OR  -- CJNE
                             std_match(ir,"11010101") OR        -- DJNZ direct, rel
                             (std_match(ir,"00-10000") OR       -- JBC; JNB
                              std_match(ir,"00100000") ) ELSE   -- JB
                    '0';

   -- since the pmem bytes being read in are signed displacements, the
   -- following will assure that the leading 1s or 0s are correct.
   prefix  <=  "11111111" WHEN use_1_for_rel = '1' AND pmem1(7) = '1' ELSE
               "11111111" WHEN use_2_for_rel = '1' AND pmem2(7) = '1' ELSE
               "00000000";

   -- this should be an adder and a mux
   add_op1 <=  unsigned(prefix & pmem1) WHEN use_1_for_rel = '1' ELSE
               unsigned(prefix & pmem2) WHEN use_2_for_rel = '1' ELSE
               unsigned(prefix & temp_reg(7 DOWNTO 0));  -- will be driven with the value of acc
 

   add_op2 <= unsigned(dptr) WHEN std_match(ir,"01110011") ELSE
              unsigned(pc);

   -- the resulting pc for any relative jumping
   add_result <= add_op1 + add_op2;

   -- get the PC either from the stack, or 
   -- from the pmem signals, or from add_result
   get_pc : PROCESS (int_clk) IS
   BEGIN
     IF falling_edge(int_clk) THEN
      IF std_match(ir,"001-0010") THEN
         -- ret, reti
         IF last_cycle = '0' THEN
            IF cycle_states = s4p1 THEN
               dec_rd_sp <= '1';
            END IF;
            If acknow = '1' THEN
               temp_reg(15 DOWNTO 8) <= data_gb;
               dec_rd_sp <= '0';
            END IF;
         ELSIF last_cycle = '1' THEN
            IF cycle_states = s1p1 THEN
               dec_rd_sp <= '1';
            END IF;
            IF acknow = '1' THEN
               temp_reg(7 DOWNTO 0) <= data_gb;
               dec_rd_sp <= '0';
            END IF;
            IF cycle_states = s4p1 THEN
               new_pc <= temp_reg;
               wr_pc <= '1';
            END IF;
         END IF;

      ELSIF std_match(ir,"----0001") THEN
         -- ACALL, AJMP
         IF last_cycle = '1' AND cycle_states = s4p1 THEN
            new_pc <= pc(15 DOWNTO 11) & ir(7 DOWNTO 5) & pmem1;
            wr_pc <= '1';
         ELSE
            new_pc <= (OTHERS => 'Z');
            wr_pc <= 'Z';
         END IF;

      ELSIF std_match(ir,"00010010") OR std_match(ir,"00000010") THEN
         -- LCALL, LJMP
         IF last_cycle = '1' AND cycle_states = s4p1 THEN
            new_pc <= pmem2 & pmem1;
            wr_pc <= '1';
         ELSE
            new_pc <= (OTHERS => 'Z');
            wr_pc <= 'Z';
         END IF;

      ELSIF std_match(ir,"01110011") THEN  -- JMP @(A + DPTR)
         IF last_cycle = '1' THEN
            IF cycle_states = s1p1 THEN
               addr_gb <= "11100000";  -- E0, or acc
               rd_gb <= '1';
            END IF;
            IF acknow = '1' THEN
               temp_reg <= "00000000" & data_gb;
               rd_gb <= 'Z';
            END IF;
            IF cycle_states = s4p1 THEN
               new_pc <= std_logic_vector(add_result);
               wr_pc <= '1';
            ELSE
               new_pc <= (OTHERS => 'Z');
               wr_pc <= 'Z';
            END IF;
         END IF;

      ELSIF (cmp_true = '1' AND last_cycle = '1') AND
            (use_1_for_rel = '1' OR use_2_for_rel = '1') THEN
         -- The following opcodes require a test result to be
         -- true in order to perform the pc change

         IF last_cycle = '1' AND cycle_states = s4p1 THEN
            new_pc <= std_logic_vector(add_result);
            wr_pc <= '1';
         ELSE
            new_pc <= (OTHERS => 'Z');
            wr_pc <= 'L';
         END IF;

      ELSE -- do nothing
         -- these lines may not be needed, but just in case
         data_gb  <= (OTHERS => 'Z');
         dec_rd_sp <= 'Z';
         inc_wr_sp <= 'Z';
         rd_gb    <= 'Z';
         wr_gb    <= 'Z';
         new_pc   <= (OTHERS => 'Z');
         wr_pc    <= 'Z';
         addr_gb	<= (OTHERS => 'Z');
      END IF;
     END IF;
   END PROCESS get_pc;

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>