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; USE WORK.global_environment.ALL; -- ENTITY par_control_unit IS PORT ( -- register control signals: load_ac, zero_ac, load_ir, increment_pc, load_page_pc, load_offset_pc, reset_pc, load_page_mar, load_offset_mar, load_sr, cm_carry_sr, -- bus connection control signals: pc_on_mar_page_bus, ir_on_mar_page_bus, pc_on_mar_offset_bus, dbus_on_mar_offset_bus, pc_offset_on_dbus, obus_on_dbus, databus_on_dbus, mar_on_adbus, dbus_on_databus, -- logic unit function control outputs: arith_shift_left, arith_shift_right, no_shift, alu_operate : OUT std_logic := '0'; alu_code : OUT std_logic_vector (2 DOWNTO 0) := ('0', '0', '0'); -- memory control and other external signals: read_mem, write_mem : OUT std_logic; interrupt : IN std_logic ); END par_control_unit; -- ARCHITECTURE Concurrent OF par_control_unit IS TYPE cpu_states IS (initial, instr_fetch, do_one_bytes, opnd_fetch, do_indirect, do_two_bytes, do_jsr, continue_jsr, do_branch); SIGNAL present_state, next_state : cpu_states; BEGIN clocking : PROCESS (cck, interrupt) BEGIN IF (interrupt = '1') THEN present_state <= initial; ELSIF cck'EVENT THEN present_state <= next_state; END IF; END PROCESS clocking; -- sequencing : PROCESS ( present_state, interrupt ) CONSTANT dis : TIME := 1 NS; BEGIN -- memory control and other external signals: read_mem <= '0'; write_mem <= '0'; CASE present_state IS WHEN initial => -------------------------------------------1 IF (interrupt = '1') THEN reset_pc <= NOT reset_pc'DRIVING_VALUE AFTER 1*dis; next_state <= initial; ELSE -- pc to mar pc_on_mar_page_bus <= NOT pc_on_mar_page_bus'DRIVING_VALUE AFTER 1*dis; pc_on_mar_offset_bus <= NOT pc_on_mar_offset_bus'DRIVING_VALUE AFTER 1*dis; load_page_mar <= NOT load_page_mar'DRIVING_VALUE AFTER 2*dis; load_offset_mar <= NOT load_offset_mar'DRIVING_VALUE AFTER 5*dis; next_state <= instr_fetch; END IF; WHEN instr_fetch => ---------------------------------------2 -- read memory into ir mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; read_mem <= '1' AFTER 1*dis; databus_on_dbus <= NOT databus_on_dbus'DRIVING_VALUE AFTER 1.6 ns;--1*dis; alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= a_input AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; load_ir <= NOT load_ir'DRIVING_VALUE AFTER 4*dis; -- increment pc increment_pc <= NOT increment_pc'DRIVING_VALUE AFTER 1*dis; next_state <= do_one_bytes; WHEN do_one_bytes => --------------------------------------3 pc_on_mar_page_bus <= NOT pc_on_mar_page_bus'DRIVING_VALUE AFTER 1*dis; pc_on_mar_offset_bus <= NOT pc_on_mar_offset_bus'DRIVING_VALUE AFTER 4*dis; load_page_mar <= NOT load_page_mar'DRIVING_VALUE AFTER 2*dis; load_offset_mar <= NOT load_offset_mar'DRIVING_VALUE AFTER 5*dis; IF (ir_out.val (7 DOWNTO 4) /= single_byte_instructions) THEN next_state <= opnd_fetch; ELSE CASE ir_out.val (3 DOWNTO 0) IS WHEN cla => zero_ac <= NOT zero_ac'DRIVING_VALUE AFTER 4*dis; load_ac <= NOT load_ac'DRIVING_VALUE AFTER 4*dis; WHEN cma => alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= b_compl AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; load_sr <= NOT load_sr'DRIVING_VALUE AFTER 4*dis; load_ac <= NOT load_ac'DRIVING_VALUE AFTER 4*dis; WHEN cmc => cm_carry_sr <= NOT cm_carry_sr'DRIVING_VALUE AFTER 4*dis; WHEN asl => alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= b_input AFTER 2*dis; arith_shift_left <= NOT arith_shift_left'DRIVING_VALUE AFTER 3*dis; load_sr <= NOT load_sr'DRIVING_VALUE AFTER 4*dis; load_ac <= NOT load_ac'DRIVING_VALUE AFTER 4*dis; WHEN asr => alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= b_input AFTER 2*dis; arith_shift_right <= NOT arith_shift_right'DRIVING_VALUE AFTER 3*dis; load_sr <= NOT load_sr'DRIVING_VALUE AFTER 4*dis; load_ac <= NOT load_ac'DRIVING_VALUE AFTER 4*dis; WHEN hlt => halt <= '1'; WHEN OTHERS => NULL; END CASE; next_state <= instr_fetch; END IF; WHEN opnd_fetch => ----------------------------------------4 -- read memory into mar offset mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; read_mem <= '1' AFTER 1*dis; databus_on_dbus <= NOT databus_on_dbus'DRIVING_VALUE AFTER 1.6 ns;--1*dis; dbus_on_mar_offset_bus <= NOT dbus_on_mar_offset_bus'DRIVING_VALUE AFTER 4*dis; load_offset_mar <= NOT load_offset_mar'DRIVING_VALUE AFTER 5*dis; IF ( ir_out.val (7 DOWNTO 6) /= jsr_or_bra ) THEN ir_on_mar_page_bus <= NOT ir_on_mar_page_bus'DRIVING_VALUE AFTER 1*dis; load_page_mar <= NOT load_page_mar'DRIVING_VALUE AFTER 2*dis; IF ( ir_out.val (4) = indirect ) THEN next_state <= do_indirect; ELSE next_state <= do_two_bytes; END IF; ELSE --jsr or bra, do not alter mar page IF ( ir_out.val (5) = '0' ) THEN -- jsr next_state <= do_jsr; ELSE next_state <= do_branch; END IF; END IF; increment_pc <= NOT increment_pc'DRIVING_VALUE AFTER 1*dis; WHEN do_indirect => ---------------------------------------5 -- read actual operand from memory into mar offset mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; read_mem <= '1' AFTER 1*dis; databus_on_dbus <= NOT databus_on_dbus'DRIVING_VALUE AFTER 1.6 ns; --1*dis; dbus_on_mar_offset_bus <= NOT dbus_on_mar_offset_bus'DRIVING_VALUE AFTER 4*dis; load_offset_mar <= NOT load_offset_mar'DRIVING_VALUE AFTER 5*dis; next_state <= do_two_bytes; WHEN do_two_bytes => --------------------------------------6 IF ( ir_out.val (7 DOWNTO 5) = jmp ) THEN load_page_pc <= NOT load_page_pc'DRIVING_VALUE AFTER 1*dis; load_offset_pc <= NOT load_offset_pc'DRIVING_VALUE AFTER 1*dis; next_state <= instr_fetch; ELSIF ( ir_out.val (7 DOWNTO 5) = sta ) THEN -- mar on adbus, ac on databus, write to memory mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= b_input AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; obus_on_dbus <= NOT obus_on_dbus'DRIVING_VALUE AFTER 4*dis; dbus_on_databus <= NOT dbus_on_databus'DRIVING_VALUE AFTER 5*dis; write_mem <= '1' AFTER 6*dis; next_state <= initial; ELSIF ( ir_out.val (7) = '0' ) THEN ------ lda, and, add, sub -- mar on adbus, read memory for operand, perform operation mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; read_mem <= '1' AFTER 1*dis; databus_on_dbus <= NOT databus_on_dbus'DRIVING_VALUE AFTER 1.6 ns; --1*dis; IF ( ir_out.val (6) = '0' ) THEN ---- lda, and IF ( ir_out.val (5) = '0' ) THEN -- lda alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= a_input AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; ELSE -- and alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= a_and_b AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; END IF; ELSE ---- add, sub IF ( ir_out.val (5) = '0' ) THEN -- add alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= a_add_b AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; ELSE -- sub alu_operate <= NOT alu_operate'DRIVING_VALUE AFTER 2*dis; alu_code <= a_sub_b AFTER 2*dis; no_shift <= NOT no_shift'DRIVING_VALUE AFTER 3*dis; END IF; END IF; load_sr <= NOT load_sr'DRIVING_VALUE AFTER 4*dis; load_ac <= NOT load_ac'DRIVING_VALUE AFTER 4*dis; next_state <= initial; ELSE next_state <= initial; --never happens END IF; WHEN do_jsr => --------------------------------------------7 -- write pc offset to top of subroutine mar_on_adbus <= NOT mar_on_adbus'DRIVING_VALUE AFTER 1*dis; pc_offset_on_dbus <= NOT pc_offset_on_dbus'DRIVING_VALUE AFTER 1.6 ns; --1*dis; dbus_on_databus <= NOT dbus_on_databus'DRIVING_VALUE AFTER 5*dis; write_mem <= '1' AFTER 6*dis; -- address of subroutine to pc load_offset_pc <= NOT load_offset_pc'DRIVING_VALUE AFTER 6*dis;--check it next_state <= continue_jsr; WHEN continue_jsr => --------------------------------------8 increment_pc <= NOT increment_pc'DRIVING_VALUE AFTER 1*dis; next_state <= initial; WHEN do_branch => -----------------------------------------9 IF ( all_or (sr_out.val AND ir_out.val (3 DOWNTO 0)) = '1') THEN load_offset_pc <= NOT load_offset_pc'DRIVING_VALUE AFTER 1*dis; END IF; next_state <= initial; END CASE; END PROCESS sequencing; END Concurrent;