-------------------------------------------------- -- Model : 8051 Behavioral Model, -- VHDL Entity mc8051.pc_inc.interface -- -- Author : Michael Mayer (mrmayer@computer.org), -- Dr. Hardy J. Pottinger, -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Created at : 09/22/98 18:46:09 -- LIBRARY ieee ; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; LIBRARY mc8051 ; USE mc8051.synth_pack.all; ENTITY pc_inc IS PORT( cycle_states : IN std_logic_vector( 3 DOWNTO 0 ) ; force_lcall : IN std_logic ; int_clk : IN std_logic ; int_rst : IN std_logic ; ir : IN std_logic_vector( 7 DOWNTO 0 ) ; new_ir : IN std_logic ; pc : IN std_logic_vector( 15 DOWNTO 0 ) ; last_cycle : OUT std_logic ; pdat_loc : OUT std_logic_vector( 15 DOWNTO 0 ) ; wr_pc : OUT std_logic ; new_pc : INOUT std_logic_vector( 15 DOWNTO 0 ) ); -- Declarations END pc_inc ; -- -- VHDL Architecture mc8051.pc_inc.spec -- -- Created: -- by - mrmayer.UNKNOWN (eceultra7.ece.umr.edu) -- at - 12:36:08 08/29/98 -- -- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110) -- architecture spec of pc_inc is TYPE four_bit0 IS RANGE 0 TO 3; TYPE four_bit1 IS RANGE 1 TO 4; SUBTYPE bits2 IS unsigned(1 DOWNTO 0); TYPE lookup_entry_type IS RECORD numb_bytes : four_bit0; -- number of bytes numb_cycles : four_bit1; -- number of cycles END RECORD lookup_entry_type; FUNCTION conv_int_to_bits2 (arg : four_bit1) RETURN bits2 IS VARIABLE output : bits2; BEGIN CASE arg IS WHEN 1 => output := "00"; WHEN 2 => output := "01"; WHEN 3 => output := "10"; WHEN 4 => output := "11"; WHEN OTHERS => output := "00"; END CASE; RETURN output; END FUNCTION conv_int_to_bits2; TYPE lookup_table_type IS ARRAY(0 TO 127) OF lookup_entry_type; -- the following lookup table has the number of bytes and cycles for each -- opcode. The are organized as follows (all in hex): -- n0-n5 => opcodes (2n)*10 + 0 - (2n)*10 + 5 -- n6 => opcodes (2n)*10 + 6 - (2n)*10 + 7 -- n7 => opcodes (2n)*10 + 8 - (2n)*10 + F -- n8-nD => opcodes (2n+1)*10 + 0 - (2n+1)*10 + 5 -- nE => opcodes (2n+1)*10 + 6 - (2n+1)*10 + 7 -- nF => opcodes (2n+1)*10 + 8 - (2n+1)*10 + F CONSTANT lookup_table : lookup_table_type := ( 16#00# => (1,1), 16#01# => (2,2), 16#02# => (3,2), 16#03# => (1,1), 16#04# => (1,1), 16#05# => (2,1), 16#06# => (1,1), 16#07# => (1,1), 16#08# => (3,2), 16#09# => (2,2), 16#0A# => (3,2), 16#0B# => (1,1), 16#0C# => (1,1), 16#0D# => (2,1), 16#0E# => (1,1), 16#0F# => (1,1), 16#10# => (3,2), 16#11# => (2,2), 16#12# => (1,2), 16#13# => (1,1), 16#14# => (2,1), 16#15# => (2,1), 16#16# => (1,1), 16#17# => (1,1), 16#18# => (3,2), 16#19# => (2,2), 16#1A# => (1,2), 16#1B# => (1,1), 16#1C# => (2,1), 16#1D# => (2,1), 16#1E# => (1,1), 16#1F# => (1,1), 16#20# => (2,2), 16#21# => (2,2), 16#22# => (2,1), 16#23# => (3,2), 16#24# => (2,1), 16#25# => (2,1), 16#26# => (1,1), 16#27# => (1,1), 16#28# => (2,2), 16#29# => (2,2), 16#2A# => (2,1), 16#2B# => (3,2), 16#2C# => (2,1), 16#2D# => (2,1), 16#2E# => (1,1), 16#2F# => (1,1), 16#30# => (2,2), 16#31# => (2,2), 16#32# => (2,1), 16#33# => (3,2), 16#34# => (2,1), 16#35# => (2,1), 16#36# => (1,1), 16#37# => (1,1), 16#38# => (2,2), 16#39# => (2,2), 16#3A# => (2,2), 16#3B# => (1,2), 16#3C# => (2,1), 16#3D# => (3,2), 16#3E# => (2,1), 16#3F# => (2,1), 16#40# => (2,2), 16#41# => (2,2), 16#42# => (2,2), 16#43# => (1,2), 16#44# => (1,4), 16#45# => (3,2), 16#46# => (2,2), 16#47# => (2,2), 16#48# => (3,2), 16#49# => (2,2), 16#4A# => (2,2), 16#4B# => (1,2), 16#4C# => (2,1), 16#4D# => (2,1), 16#4E# => (1,1), 16#4F# => (1,1), 16#50# => (2,2), 16#51# => (2,2), 16#52# => (2,1), 16#53# => (1,2), 16#54# => (1,4), 16#55# => (1,1), 16#56# => (2,2), 16#57# => (2,2), 16#58# => (2,2), 16#59# => (2,2), 16#5A# => (2,1), 16#5B# => (2,1), 16#5C# => (3,2), 16#5D# => (3,2), 16#5E# => (3,2), 16#5F# => (3,2), 16#60# => (2,2), 16#61# => (2,2), 16#62# => (2,1), 16#63# => (1,1), 16#64# => (1,1), 16#65# => (2,1), 16#66# => (1,1), 16#67# => (1,1), 16#68# => (2,2), 16#69# => (2,2), 16#6A# => (2,1), 16#6B# => (1,1), 16#6C# => (1,1), 16#6D# => (3,2), 16#6E# => (1,1), 16#6F# => (2,2), 16#70# => (1,2), 16#71# => (2,2), 16#72# => (1,2), 16#73# => (1,2), 16#74# => (1,1), 16#75# => (2,1), 16#76# => (1,1), 16#77# => (1,1), 16#78# => (1,2), 16#79# => (2,2), 16#7A# => (1,2), 16#7B# => (1,2), 16#7C# => (1,1), 16#7D# => (2,1), 16#7E# => (1,1), 16#7F# => (1,1) ); SIGNAL pc_plus0, pc_plus1, pc_plus2, pc_plus3 : unsigned(15 DOWNTO 0); SIGNAL cycle_counter : unsigned(1 DOWNTO 0); SIGNAL number_of_bytes : four_bit0; -- number of bytes SIGNAL number_of_cycles : four_bit1; -- number of cycles SIGNAL last_cycle_internal : std_logic; SIGNAL reset_state : std_logic; BEGIN reset_state <= '1' WHEN int_rst = '1' ELSE '0' WHEN cycle_states = s6p2 ELSE reset_state; pc_plus0 <= unsigned(pc) WHEN rising_edge(new_ir) ELSE pc_plus0; pc_plus1 <= pc_plus0 + 1; pc_plus2 <= pc_plus1 + 1; pc_plus3 <= pc_plus2 + 1; -- perfom the table lookup to drive number of bytes & cycles -- (this should be replaced by a ROM -- and latches, where new_ir would be the enable) table_lookup : PROCESS (new_ir) IS VARIABLE lsb_3 : std_logic_vector(2 DOWNTO 0); VARIABLE index_val : unsigned(6 DOWNTO 0); BEGIN IF rising_edge(new_ir) THEN IF ir(3) = '1' THEN lsb_3 := "111"; ELSIF ir(2 DOWNTO 1) = "11" THEN lsb_3 := "110"; ELSE lsb_3 := ir(2 DOWNTO 0); END IF; index_val := unsigned(ir(7 DOWNTO 5) & ir(3) & lsb_3); number_of_bytes <= lookup_table(to_integer(index_val)).numb_bytes; number_of_cycles <= lookup_table(to_integer(index_val)).numb_cycles; END IF; END PROCESS table_lookup; -- define a counter which resets on new_ir, and increments -- with int_clk whenever cycle_state = s6p2. set_cycle_counter : PROCESS (int_clk, reset_state) IS BEGIN IF (reset_state = '1') THEN -- asynchronous reset cycle_counter <= "00"; ELSIF falling_edge(int_clk) AND cycle_states = s6p2 THEN IF last_cycle_internal = '1' THEN -- synchronous reset cycle_counter <= "00"; ELSE -- synchronous increment CASE cycle_counter IS WHEN "00" => cycle_counter <= "01"; WHEN "01" => cycle_counter <= "10"; WHEN "10" => cycle_counter <= "11"; WHEN "11" => cycle_counter <= "11"; WHEN OTHERS => cycle_counter <= "00"; REPORT "BAD CYCLE COUNTER in pc_incrementer"; -- this last entry could probably wrap around to "00" END CASE; END IF; END IF; END PROCESS set_cycle_counter; -- output the last_cycle (combinational logic) last_cycle_internal <= '1' WHEN cycle_counter = conv_int_to_bits2(number_of_cycles) ELSE '0'; last_cycle <= last_cycle_internal; -- output the new pc on the first cycle at s1p2 -- (this process is combinational logic & trisate) output_new_pc : PROCESS (int_clk, reset_state, force_lcall, cycle_counter, cycle_states, number_of_bytes, pc_plus0, pc_plus1, pc_plus2, pc_plus3) IS BEGIN IF reset_state = '0' AND force_lcall = '0' AND cycle_counter = "00" AND cycle_states = s1p2 THEN -- the above conditions correspond to an enable on the tristate CASE number_of_bytes IS WHEN 0 => new_pc <= std_logic_vector(pc_plus0); WHEN 1 => new_pc <= std_logic_vector(pc_plus1); WHEN 2 => new_pc <= std_logic_vector(pc_plus2); WHEN 3 => new_pc <= std_logic_vector(pc_plus3); END CASE; wr_pc <= '1'; ELSE new_pc <= (OTHERS => 'Z'); -- tristate wr_pc <= 'L'; END IF; END PROCESS output_new_pc; -- process to drive the pdata location (pdat_loc) -- this process has combination logic, and -- a set of flip-flops for pdat_loc. -- the enable for the flip flops is a complicated expression for -- all of the if statements, while the input to the ff's is -- multiplexed or selected from the four possible values. drive_pdat_loc : PROCESS (int_clk, reset_state) IS VARIABLE first_half, second_half : BOOLEAN; BEGIN CASE cycle_states IS WHEN s1p1 | s1p2 | s2p1 | s2p2 | s3p1 | s3p2 => first_half := TRUE; second_half := FALSE; WHEN s4p1 | s4p2 | s5p1 | s5p2 | s6p1 | s6p2 => first_half := FALSE; second_half := TRUE; WHEN OTHERS => first_half := FALSE; second_half := FALSE; END CASE; IF reset_state = '1' THEN pdat_loc <= (OTHERS => '0'); ELSIF last_cycle_internal = '1' AND second_half THEN -- output the new pc pdat_loc <= pc; ELSIF cycle_counter = "00" THEN IF first_half THEN pdat_loc <= std_logic_vector(pc_plus1); ELSIF second_half THEN IF std_match(ir,"100-0011") THEN -- check for the MOVC instruction pdat_loc <= new_pc; ELSIF number_of_bytes >= 2 THEN pdat_loc <= std_logic_vector(pc_plus2); END IF; END IF; ELSIF cycle_counter = "01" THEN IF number_of_bytes >= 3 THEN pdat_loc <= std_logic_vector(pc_plus3); END IF; END IF; END PROCESS drive_pdat_loc; END ARCHITECTURE spec; -------------------------------------------------- -- 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; -------------------------------------------------- -- Model : 8051 Behavioral Model, -- VHDL Entity mc8051.pmem_reg.interface -- -- Author : Michael Mayer (mrmayer@computer.org), -- Dr. Hardy J. Pottinger, -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Created at : 09/22/98 19:39:48 -- LIBRARY ieee ; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; LIBRARY mc8051 ; USE mc8051.synth_pack.all; ENTITY pmem_reg IS PORT( call_addr : IN std_logic_vector( 15 DOWNTO 0 ) ; cycle_states : IN std_logic_vector( 3 DOWNTO 0 ) ; force_lcall : IN std_logic ; int_clk : IN std_logic ; int_rst : IN std_logic ; last_cycle : IN std_logic ; new_pc : IN std_logic_vector( 15 DOWNTO 0 ) ; pdata : IN std_logic_vector( 7 DOWNTO 0 ) ; rd_pmem1 : IN std_logic ; rd_pmem2 : IN std_logic ; wr_pc : IN std_logic ; acknow : OUT std_logic ; data_gb : OUT std_logic_vector( 7 DOWNTO 0 ) ; ir : OUT std_logic_vector( 7 DOWNTO 0 ) ; new_ir : OUT std_logic ; pc : OUT std_logic_vector( 15 DOWNTO 0 ) ; pmem1 : OUT std_logic_vector( 7 DOWNTO 0 ) ; pmem2 : OUT std_logic_vector( 7 DOWNTO 0 ) ); -- Declarations END pmem_reg ; -- -- VHDL Architecture mc8051.pmem_reg.spec -- -- Created: -- by - mrmayer.UNKNOWN (eceultra7.ece.umr.edu) -- at - 12:37:22 08/29/98 -- -- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110) -- architecture spec of pmem_reg is SIGNAL pc_reg : std_logic_vector (15 DOWNTO 0); SIGNAL pmem1_reg, pmem2_reg, ir_reg : std_logic_vector (7 DOWNTO 0); SIGNAL pmem1_gd, pmem2_gd, ir_gd : std_logic; SIGNAL new_ir1 : std_logic; BEGIN -- latch for pc pc_reg <= (OTHERS => '0') WHEN int_rst = '1' ELSE new_pc WHEN rising_edge(int_clk) AND wr_pc = '1' ELSE pc_reg; pc <= pc_reg; -- get new ir using flip flops ir_ff : PROCESS (int_clk,int_rst ) IS BEGIN -- In a reset situation, create a NOP until s6p2. IF int_rst = '1' THEN ir_gd <= '1'; ir_reg <= "00000000"; new_ir <= '0'; ELSIF rising_edge(int_clk) THEN IF last_cycle = '1' AND cycle_states = s6p2 THEN ir_gd <= '0'; END IF; IF ir_gd = '0' AND cycle_states = s1p1 THEN IF force_lcall = '1' THEN ir_reg <= "00010010"; -- LCALL forced from interrupt ELSE ir_reg <= pdata; END IF; ir_gd <= '1'; new_ir1 <= '1'; ELSE new_ir <= '0'; new_ir1 <= '0'; END IF; ELSIF falling_edge(int_clk) THEN IF new_ir1 = '1' THEN new_ir <= '1'; END IF; END IF; END PROCESS ir_ff; ir <= ir_reg; -- get first byte of program memory pmem1_ff : PROCESS (int_clk ) IS BEGIN IF rising_edge(int_clk) THEN IF last_cycle = '1' AND cycle_states = s6p2 THEN pmem1_gd <= '0'; END IF; IF pmem1_gd = '0' AND cycle_states = s4p1 THEN IF force_lcall = '1' THEN pmem1_reg <= call_addr(15 DOWNTO 8); -- LCALL forced from interrupt ELSE pmem1_reg <= pdata; END IF; pmem1_gd <= '1'; END IF; END IF; END PROCESS pmem1_ff; pmem1 <= pmem1_reg; -- get second byte of program memory pmem2_ff : PROCESS (int_clk ) IS BEGIN IF rising_edge(int_clk) THEN IF last_cycle = '1' AND cycle_states = s6p2 THEN pmem2_gd <= '0'; END IF; IF ir_gd = '1' AND pmem2_gd = '0' AND cycle_states = s1p1 THEN IF force_lcall = '1' THEN pmem2_reg <= call_addr(7 DOWNTO 0); -- LCALL forced from interrupt ELSE pmem2_reg <= pdata; END IF; pmem2_gd <= '1'; END IF; END IF; END PROCESS pmem2_ff; pmem2 <= pmem2_reg; -- handle the data global bus data_gb <= pmem1_reg WHEN (rd_pmem1 = '1' AND pmem1_gd = '1') ELSE pmem2_reg WHEN (rd_pmem2 = '1' AND pmem2_gd = '1') ELSE (OTHERS => 'Z'); acknow <= '1' WHEN (rd_pmem1 = '1' AND pmem1_gd = '1') OR (rd_pmem2 = '1' AND pmem2_gd = '1') ELSE 'Z'; END ARCHITECTURE spec; -------------------------------------------------- -- Model : 8051 Behavioral Model, -- VHDL Entity mc8051.inter_ctrl.interface -- -- Author : Michael Mayer (mrmayer@computer.org), -- Dr. Hardy J. Pottinger, -- Department of Electrical Engineering -- University of Missouri - Rolla -- -- Created at : 09/22/98 20:14:45 -- LIBRARY ieee ; USE ieee.std_logic_1164.all; USE ieee.numeric_std.all; LIBRARY mc8051 ; USE mc8051.synth_pack.all; ENTITY inter_ctrl IS PORT( P0 : IN std_logic_vector( 7 DOWNTO 0 ) ; acknow : IN std_logic ; cycle_states : IN std_logic_vector( 3 DOWNTO 0 ) ; dptr : IN std_logic_vector( 15 DOWNTO 0 ) ; ea_n : IN std_logic ; int_clk : IN std_logic ; int_rst : IN std_logic ; ir : IN std_logic_vector( 7 DOWNTO 0 ) ; last_cycle : IN std_logic ; pdat_loc : IN std_logic_vector( 15 DOWNTO 0 ) ; rom_data : IN std_logic_vector( 7 DOWNTO 0 ) ; rs : IN std_logic_vector( 1 DOWNTO 0 ) ; addr_gb : OUT std_logic_vector( 7 DOWNTO 0 ) ; ale : OUT std_logic ; indirect_sel : OUT std_logic ; p0_addr : OUT std_logic_vector( 7 DOWNTO 0 ) ; p0_ctrl : OUT std_logic ; p2_addr : OUT std_logic_vector( 7 DOWNTO 0 ) ; p2_ctrl : OUT std_logic ; pdata : OUT std_logic_vector( 7 DOWNTO 0 ) ; psen_n : OUT std_logic ; rd_gb : OUT std_logic ; rd_n : OUT std_logic ; rd_n_ctrl : OUT std_logic ; rom_rd_n : OUT std_logic ; wr_gb : OUT std_logic ; wr_n : OUT std_logic ; wr_n_ctrl : OUT std_logic ; data_gb : INOUT std_logic_vector( 7 DOWNTO 0 ) ); -- Declarations END inter_ctrl ; -- -- VHDL Architecture mc8051.inter_ctrl.spec -- -- Created: -- by - mrmayer.UNKNOWN (eceultra18.ece.umr.edu) -- at - 22:34:31 08/26/98 -- -- Generated by Mentor Graphics' Renoir(TM) 3.0 (Build 110) -- -- Description -- inter_ctrl is responsible for the interface control -- of the 8051. This includes all timing for the folloing -- ports: -- ALE -- PSEN_N -- RD_N -- WR_N -- P0 (in addr / data mode) -- P2 (in addr mode) -- -- It is tied to input port EA_N. -- -- Additional I/O include: -- pdat_loc (IN) - location in program data -- dptr - location for MOVX DPTR -- addr_gb, data_gb, rd_gb, wr_gb, acknow ARCHITECTURE spec OF inter_ctrl IS -- a latched, X01 version of ea_n SIGNAL ea_n_int : std_logic; SIGNAL ale_int : std_logic; SIGNAL psen_n_int, rd_n_int, wr_n_int : std_logic; SIGNAL rom_rd_n_int : std_logic; SIGNAL ia_pmem, ea_pmem, rd_xmem, wr_xmem : std_logic; SIGNAL use_reg : std_logic; SIGNAL reg_value : std_logic_vector(7 DOWNTO 0); SIGNAL data_byte : std_logic_vector(7 DOWNTO 0); SIGNAL p0_alt, p2_alt : std_logic_vector(7 DOWNTO 0); BEGIN rd_n <= rd_n_int; wr_n <= wr_n_int; psen_n <= psen_n_int; ale <= ale_int; p0_addr <= p0_alt; p2_addr <= p2_alt; rom_rd_n <= rom_rd_n_int; pdata <= data_byte; ea_n_int <= to_X01(ea_n) WHEN rising_edge(int_clk) AND ( cycle_states = s1p1 OR cycle_states = s4p1 ) ELSE ea_n_int; rd_xmem <= '1' WHEN std_match(ir,"1110001-") OR std_match(ir,"11100000") ELSE '0'; wr_xmem <= '1' WHEN std_match(ir,"1111001-") OR std_match(ir,"11110000") ELSE '0'; use_reg <= '1' WHEN std_match(ir,"111-001-") ELSE '0'; -- the next signal will change only at s1p1 or s4p1 ia_pmem <= '1' WHEN ea_n_int = '1' AND unsigned(pdat_loc) < 16#1000# ELSE '0'; ea_pmem <= '1' WHEN (rd_xmem = '0' AND wr_xmem = '0') AND ia_pmem = '0' ELSE '0'; -- use the global bus to read the register r0 or r1 for an address, and -- to read / write the accumulator for a data value addr_gb <= "000" & rs & "00" & ir(0) WHEN (use_reg = '1' AND last_cycle = '0') AND (cycle_states = s3p1 OR cycle_states = s3p2) ELSE "11100000" WHEN ((wr_xmem = '1' AND last_cycle = '0') AND (cycle_states = s4p1 OR cycle_states = s4p2)) OR ((rd_xmem = '1' AND last_cycle = '1') AND (cycle_states = s4p1 OR cycle_states = s4p2)) ELSE (OTHERS => 'Z'); rd_gb <= '1' WHEN (wr_xmem = '1' AND last_cycle = '0') AND (cycle_states = s4p1 OR cycle_states = s4p2) ELSE 'Z'; wr_gb <= '1' WHEN (rd_xmem = '1' AND last_cycle = '1') AND (cycle_states = s4p1 OR cycle_states = s4p2) ELSE 'Z'; data_gb <= data_byte WHEN (rd_xmem = '1' AND last_cycle = '1') AND (cycle_states = s4p1 OR cycle_states = s4p2) ELSE (OTHERS => 'Z'); reg_value <= data_gb WHEN (wr_xmem = '1' AND last_cycle = '0') AND acknow = '1' ELSE reg_value; -- drive the internal versions of the handshaking signals ale_int <= '1' WHEN ((cycle_states = s2p1 OR cycle_states = s2p2) AND ea_pmem = '1') OR ((cycle_states = s5p1 OR cycle_states = s5p1) AND (ea_pmem = '1' OR rd_xmem = '1' OR wr_xmem = '1')) ELSE '0'; -- psen_n is set low when doing program fetches. This happens at s3p1 and s6p1 when -- there is no external read /write occurring. It also happens at s6p1 of the last cycle -- of an external read / write when the internal memory accessing is not being used. psen_n_int <= '0' WHEN ((cycle_states = s3p1 OR cycle_states = s3p2 OR cycle_states = s4p1) AND ea_pmem = '1') OR ((cycle_states = s6p1 OR cycle_states = s6p2 OR cycle_states = s1p1) AND (ea_pmem = '1' OR (last_cycle = '1' AND ia_pmem = '0'))) ELSE '1'; rom_rd_n_int <= '0' WHEN (falling_edge(int_clk) AND ia_pmem = '1') AND (cycle_states = s3p1 OR cycle_states = s6p1) ELSE '1' WHEN falling_edge(int_clk) AND (cycle_states = s1p2 OR cycle_states = s4p2) ELSE rom_rd_n_int; rd_n_int <= '0' WHEN (falling_edge(int_clk) AND rd_xmem = '1') AND (last_cycle = '1' AND cycle_states = s1p1) ELSE '1' WHEN (falling_edge(int_clk) AND cycle_states = s4p1) ELSE rd_n_int; wr_n_int <= '0' WHEN (falling_edge(int_clk) AND wr_xmem = '1') AND (last_cycle = '1' AND cycle_states = s1p1) ELSE '1' WHEN (falling_edge(int_clk) AND cycle_states = s4p1) ELSE wr_n_int; p2_alt <= (OTHERS => '0') WHEN int_rst = '1' ELSE dptr(15 DOWNTO 8) WHEN (falling_edge(int_clk) AND cycle_states = s5p1) AND ((rd_xmem = '1' OR wr_xmem = '1') AND use_reg = '0') ELSE pdat_loc(15 DOWNTO 8) WHEN (falling_edge(int_clk) AND ( (cycle_states = s2p1 AND ea_pmem = '1') OR (cycle_states = s5p1 AND ( ea_pmem = '1' OR (last_cycle = '1' AND ia_pmem = '0') )) )) ELSE p2_alt; -- take control of p2 whenever external access of pmem is enabled, or -- when we are in (cycle 1 s5p1) through (cycle 2 s4p2) of external data rd / wr p2_ctrl <= '1' WHEN ea_pmem = '1' OR ( ( (last_cycle = '0' AND std_match(cycle_states,"11--")) OR (last_cycle = '1' AND (NOT std_match(cycle_states,"11--"))) ) AND (wr_xmem = '1' OR rd_xmem = '1') ) ELSE '0'; p0_alt <= (OTHERS => '0') WHEN int_rst = '1' ELSE dptr(7 DOWNTO 0) WHEN (rising_edge(int_clk) AND cycle_states = s5p1) AND ((rd_xmem = '1' OR wr_xmem = '1') AND use_reg = '0') ELSE reg_value WHEN (rising_edge(int_clk) AND cycle_states = s5p1) AND ((rd_xmem = '1' OR wr_xmem = '1') AND use_reg = '1') ELSE pdat_loc(7 DOWNTO 0) WHEN (cycle_states = s2p1 AND ea_pmem = '1') OR (cycle_states = s5p1 AND ( ea_pmem = '1' OR (last_cycle = '1' AND ia_pmem = '0') )) ELSE p0_alt; -- everytime this is set high, it sets all bits in the P0 sfr p0_ctrl <= '1' WHEN ( ea_pmem = '1' AND ((cycle_states = s2p1 OR cycle_states = s2p2) OR (cycle_states = s5p1 OR cycle_states = s5p2)) ) OR ( rd_xmem = '1' AND last_cycle = '0' AND ( (cycle_states = s5p1 OR cycle_states = s5p2) OR cycle_states = s6p1 ) ) OR -- wr_xmem from states (cycle 1, s5p1) to (cycle 2, s4p2) ( wr_xmem = '1' AND ( (last_cycle = '0' AND std_match(cycle_states,"11--")) OR (last_cycle = '1' AND (cycle_states(3) = '1' XOR cycle_states(2) = '1') ) )) OR ( ia_pmem = '0' AND last_cycle = '1' AND (cycle_states = s5p1 OR cycle_states = s5p2)) ELSE '0'; data_byte <= to_x01(p0) WHEN rising_edge(int_clk) AND ( ((cycle_states = s1p1 OR cycle_states = s4p1) AND psen_n_int = '0') OR ((last_cycle = '1' AND cycle_states = s3p1) AND rd_n_int = '0') ) ELSE rom_data WHEN rising_edge(int_clk) AND ( (cycle_states = s1p1 OR cycle_states = s4p1) AND ia_pmem = '1' ) ELSE data_byte; END ARCHITECTURE spec;