-- BEHAVIORAL DESCRIPTION OF PARWAN :
ARCHITECTURE behavioral OF par_central_processing_unit IS
signal ac_out : byte; signal pc_out : twelve;
BEGIN
PROCESS
-- > Declare necessary variables : FIG. 9.16 :
VARIABLE pc : twelve;
VARIABLE ac, byte1, byte2 : byte;
VARIABLE v, c, z, n : qit;
VARIABLE temp : qit_vector (9 DOWNTO 0);
|
BEGIN
IF NOW > run_time THEN WAIT; END IF;
IF interrupt = '1' THEN
-- > Handle interrupt : FIG. 9.17 :
pc := zero_12;
pc_out <= pc;
WAIT FOR cycle_time;
|
ELSE -- no interrupt
-- > Read first byte into byte1, increment pc : FIG.18 :
adbus <= pc;
read_mem <= '1'; WAIT FOR read_high_time;
byte1 := byte (databus);
read_mem <= '0'; WAIT FOR read_low_time;
pc := inc (pc);
pc_out <= pc;
|
IF byte1 (7 DOWNTO 4) = single_byte_instructions THEN
-- > Execute single-byte instructions : FIG.19 :
CASE byte1 (3 DOWNTO 0) IS
WHEN cla =>
ac := zero_8;
ac_out <= ac;
WHEN cma =>
ac := NOT ac;
ac_out <= ac;
IF ac = zero_8 THEN z := '1'; END IF;
n := ac (7);
WHEN cmc =>
c := NOT c;
WHEN asl =>
c := ac (7);
ac := ac(6) & ac (5 DOWNTO 0) & '0';
-- ac := ac (6 DOWNTO 0) & '0';
ac_out <= ac;
n := ac (7);
IF c /= n THEN v := '1'; END IF;
WHEN asr =>
ac := ac (7) & ac (7 DOWNTO 1);
ac_out <= ac;
IF ac = zero_8 THEN z := '1'; END IF;
n := ac (7);
WHEN OTHERS => NULL;
END CASE;
|
ELSE -- two-byte instructions
-- > Read second byte into byte2, increment pc : FIG.20 :
adbus <= pc;
read_mem <= '1'; WAIT FOR read_high_time;
byte2 := byte (databus);
read_mem <= '0'; WAIT FOR read_low_time;
pc := inc (pc);
pc_out <= pc;
|
IF byte1 (7 DOWNTO 5) = jsr THEN
-- > Execute jsr instruction, byte2 has address : FIG.21 :
databus <= wired_byte (pc (7 DOWNTO 0) );
adbus (7 DOWNTO 0) <= byte2;
write_mem <= '1'; WAIT FOR write_high_time;
write_mem <= '0'; WAIT FOR write_low_time;
databus <= "ZZZZZZZZ";
pc (7 DOWNTO 0) := inc (byte2);
pc_out <= pc;
|
ELSIF byte1 (7 DOWNTO 4) = bra THEN
-- > Execute bra instruction, address in byte2 :FIG.22 :
IF
( byte1 (3) = '1' AND v = '1' ) OR
( byte1 (2) = '1' AND c = '1' ) OR
( byte1 (1) = '1' AND z = '1' ) OR
( byte1 (0) = '1' AND n = '1' )
THEN
pc (7 DOWNTO 0) := byte2;
pc_out <= pc;
END IF;
|
ELSE -- all other two-byte instructions
IF byte1 (4) = indirect THEN
-- > Use byte1 & byte2 to get address : FIG.23 :
adbus (11 DOWNTO 8) <= byte1 (3 DOWNTO 0);
adbus (7 DOWNTO 0) <= byte2;
read_mem <= '1'; WAIT FOR read_high_time;
byte2 := byte (databus);
read_mem <= '0'; WAIT FOR read_low_time;
END IF; -- ends indirect
|
IF byte1 (7 DOWNTO 5) = jmp THEN
-- > Execute jmp instruction : FIG.24 :
pc := byte1 (3) & byte1 (2 DOWNTO 0) & byte2;
pc_out <= pc;
|
ELSIF byte1 (7 DOWNTO 5) = sta THEN
-- > Execute sta instruction, write ac : FIG.25 :
adbus <= byte1 (3) & byte1 (2 DOWNTO 0) & byte2;
-- adbus <= byte1 (3 DOWNTO 0) & byte2;
databus <= wired_byte (ac);
write_mem <= '1'; WAIT FOR write_high_time;
write_mem <= '0'; WAIT FOR write_low_time;
databus <= "ZZZZZZZZ";
|
ELSE -- read operand for lda, and, add, sub
-- > Read memory onto databus : FIG.26 - TOP,
-- > Execute lda, and, add & sub : FIG.26 - MIDDLE,
-- > Remove memory from databus : FIG.26 - BOTTOM :
adbus (11 DOWNTO 8) <= byte1 (3 DOWNTO 0);
adbus (7 DOWNTO 0) <= byte2;
read_mem <= '1'; WAIT FOR read_high_time;
CASE byte1 (7 DOWNTO 5) IS
WHEN lda =>
ac := byte (databus);
ac_out <= ac;
WHEN ann =>
ac := ac AND byte (databus);
ac_out <= ac;
WHEN add =>
temp := add_cv (ac, byte (databus), c);
ac := temp (7 DOWNTO 0);
ac_out <= ac;
c := temp (8);
v := temp (9);
WHEN sbb =>
temp := sub_cv (ac, byte (databus), c);
ac := temp (7 DOWNTO 0);
ac_out <= ac;
c := temp (8);
v := temp (9);
WHEN OTHERS => NULL;
END CASE;
IF ac = zero_8 THEN z := '1'; END IF;
n := ac (7);
read_mem <= '0'; WAIT FOR read_low_time;
END IF; -- jmp / sta / lda, and, add, sub
END IF; -- jsr / bra / other double-byte instructions
END IF; -- single-byte / double-byte
END IF; -- interrupt / otherwise
END PROCESS;
END behavioral;
|
--