-------------------------------------------------- -- 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;