LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
--
LIBRARY EXEMPLAR;
USE EXEMPLAR.exemplar_1164.ALL;
--
LIBRARY WORK;
USE WORK.synthesis_utilities.ALL;
USE WORK.synthesis_parameters.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;