n đ−ợc thiết lập hoặc xoá dựa trê kết quả của lda,ad, adc và sbc Các lệh adc và
4.4.2 Khối phục vụ ch−ơng trình
Khối utility này khai báo kiểu con byte độ dài 8 bit kiểu STD_LOGIC_VECTOR, kiểu con ten độ dài 10 bit kiểu STD_LOGIC_VECTOR. Ngoài ra khai báo các hằng số có giá trị là các vector bit của các lệnh. Tên của các lệnh đ−ợc gán cho các mã tác vụ của lệnh đó. Khối utilities trình bày hai hàm add_cv và sub_cv. Hai hàm này thực hiện cộng và trừ hai toán hạng kiểu std_logic_vector có độ dài 8 bit. Kết quả trả về là kiểu bit vector có chiều dài 8 + 2. Trong đó, bit có vị trí 8+1 chỉ thị cờ nhớ, bit có vị trí 8+2 chỉ thị cờ tràn. Hai giá trị ADDR_WIDTH và DATA_WIDTH là chiều dài bit của hai tuyến địa chỉ và dữ liệu.
PACKAGE UTILITY IS
CONSTANT ADDR_WIDTH: INTEGER := 2; CONSTANT DATA_WIDTH: INTEGER :=8; SUBTYPE byte IS std_logic_vector (7 DOWNTO 0);
SUBTYPE ten IS std_logic_vector (9 DOWNTO 0); SUBTYPE nibble IS std_logic_vector (3 DOWNTO 0); FUNCTION add_cv (a, b: byte; cin: std_logic) RETURN ten; FUNCTION sub_cv (a, b: byte; cin: std_logic) RETURN ten; FUNCTION set_if_zero (a: STD_LOGIC_VECTOR) RETURN STD_LOGIC;
CONSTANT zero_8: byte := "00000000";
CONSTANT int_66: STD_LOGIC_VECTOR (11 DOWNTO 0):= "000001100110";
CONSTANT zero_12: STD_LOGIC_VECTOR (11 DOWNTO 0):= "000000000000";
CONSTANT cla: std_logic_vector (3 DOWNTO 0):="0001"; CONSTANT cma: std_logic_vector (3 DOWNTO 0):="0010"; CONSTANT cmc: std_logic_vector (3 DOWNTO 0):="0100"; CONSTANT asl: std_logic_vector (3 DOWNTO 0):="1000";
57 Nguyễn Chí Kiên Chí Kiên
CONSTANT asr: std_logic_vector (3 DOWNTO 0):="1001"; CONSTANT jsr: std_logic_vector (2 DOWNTO 0):="110"; CONSTANT bra: std_logic_vector (3 DOWNTO 0):="1111"; CONSTANT indirect: std_logic:='1';
CONSTANT jmp: std_logic_vector (2 DOWNTO 0):="100"; CONSTANT sta: std_logic_vector (2 DOWNTO 0):="101"; CONSTANT lda: std_logic_vector (2 DOWNTO 0):="000"; CONSTANT ann: std_logic_vector (2 DOWNTO 0):="001"; CONSTANT adc: std_logic_vector (2 DOWNTO 0):="010"; CONSTANT sbc: std_logic_vector (2 DOWNTO 0):="011"; CONSTANT jsr_or_bra:std_logic_vector (1 DOWNTO 0):="11"; CONSTANT a_and_b: STD_LOGIC_VECTOR (5 DOWNTO 0):="000001";
CONSTANT b_compt: STD_LOGIC_VECTOR (5 DOWNTO 0):="000010";
CONSTANT a_input: STD_LOGIC_VECTOR (5 DOWNTO 0):="000100";
CONSTANT a_add_b: STD_LOGIC_VECTOR (5 DOWNTO 0):="001000";
CONSTANT b_input: STD_LOGIC_VECTOR (5 DOWNTO 0):="010000";
CONSTANT a_sub_b: STD_LOGIC_VECTOR (5 DOWNTO 0):="100000";
END UTILITY;
Trong thân khối utility trình bày hai giải thuật thực hiện hai phép toán cộng và trừ. Trong hàm cộng, kết quả phép cộng bit và cờ nhớ của nó đ−ợc tính nh− sau:
Sum := a XOR b XOR carry
Carry := ((a xor b) and carry) or ( a and b)
Vòng for thực hiện 8 phép cộng liên tiếp để tạo ra kết quả và cờ nhớ. Để xác định bit tràn, kiểm tra hai ngõ vào cùng dấu và kết quả khác dấu thì phép tính đã bị
58 Nguyễn Chí Kiên Chí Kiên
tràn. Nếu dấu_a bằng dấu_b và kết quả khác dấu_a thì tràn ng−ợc lại thì không tràn. Đối với phép trừ cũng t−ơng tự nh− phép cộng chỉ khác là tr−ớc khi thực hiện thì lấy số bù của b và cờ tràn.
PACKAGE BODY utility IS
FUNCTION add_cv (a, b: byte; cin: std_logic) RETURN ten IS VARIABLE r, c: ten := "0000000000";
VARIABLE a_sign, b_sign: std_logic := '0'; BEGIN
a_sign := a (a'LEFT); b_sign := b (b'LEFT);
r(0) := a(0) XOR b(0) XOR cin;
c(0):=((a(0) XOR b(0)) AND cin) OR (a(0) AND b(0)); FOR i IN 1 TO (a'LEFT) LOOP
r(i) := a(i) XOR b(i) XOR c(i-1);
c(i) := ((a(i) XOR b(i)) AND c(i-1)) OR (a(i) AND b(i));
END LOOP;
r(a'LEFT+1) := c(a'LEFT);
IF a_sign = b_sign AND r(a'LEFT) /= a_sign THEN r (a'LEFT+2) := '1';
ELSE r (a'LEFT+2) := '0'; END IF;
RETURN r; END add_cv;
FUNCTION sub_cv (a, b: byte; cin: std_logic) RETURN ten IS VARIABLE not_b: byte := zero_8;
VARIABLE not_c: std_logic;
VARIABLE r, c: ten := "0000000000"; VARIABLE a_sign, b_sign: std_logic := '0'; BEGIN
59 Nguyễn Chí Kiên Chí Kiên
not_b := NOT b; not_c := NOT cin; a_sign := a(a'LEFT); b_sign := not_b(b'LEFT);
r(0) := a(0) XOR not_b(0) XOR not_c; c(0) := ((a(0) XOR not_b(0)) AND not_c) OR (a(0) AND not_b(0));
FOR i IN 1 TO (a'LEFT) LOOP
r(i) := a(i) XOR not_b(i) XOR c(i-1);
c(i) := ((a(i) XOR not_b(i)) AND c(i-1)) OR (a(i) AND not_b(i));
END LOOP;
r(a'LEFT+1) := NOT c(a'LEFT);
IF a_sign = b_sign AND r(a'LEFT) = a_sign THEN r(a'LEFT+2) := '1'; ELSE r(a'LEFT+2) := '0'; END IF; RETURN r; END sub_cv; END utility; 4.4.3. Mô tả hành vi cpu
Mô tả hành vi của CPU bằng lệnh cpu: PROCESS (clk_cpu)
Khai báo các biến cần thiết cho ch−ơng trình BEGIN
Wait UNTIL clk_cpu = ‘0’;
IF reset =’0’ THEN Đặt các trạng thái ban đầu ELSE
CASE state IS
WHEN S0 | S10 => Đặt biến về ban đầu
60 Nguyễn Chí Kiên Chí Kiên
IF interrup = ‘1’ THEN Xử lý ngắt quãng
ELSE
Phát tín hiệu độc bộ nhớ END IF;
WHEN S1 =>
IF interrup =’1’ THEN Trở về trạng thái S10 ELSE
Đọc dữ liệu trên bus đ−a vào byte1, tăng PC+ 1 IF byte1 (7 downto 4) = lệnh một byte THEN
Thực hiện lệnh 1 byte ELSE Đặt trạng thái S2; END IF; END IF; WHEN S2 => Phát tín hiệu đọc bộ nhớ đặt trạng thái S3 WHEN S3 =>
Đọc dữ liệu vào byte 2, tăng PC + 1
IF byte1 (7 downto 4) = rẽ nhánh THEN Thực hiện lệnh rẽ nhánh, địa chỉ trong byte 2
ELSIF byte1 (4) /= lệnh gián tiếp AND byte1(7 downto 5)=jmp
THEN
Thực hiện lệnh nhảy trực tiếp ELSE Đặt trạng thái s4 END IF;
WHEN S4 => Đặt trạng thái S5
IF byte1 (7 down to 5) = jsr THEN Phát xung ghi bộ nhớ
61 Nguyễn Chí Kiên Chí Kiên
IF byte1(4) = lệnh gián tiếp THEN Phát byte2 ra tuyến địa chỉ Phát xung đọc bộ nhớ
ELSIFbyte1(7 downto 5)=sta trực tiếp THEN Phát byte1(3-0)&byte2 ra tuyến địa chỉ Nạp ac vào tuyến dữ liệu
Phát xung ghi bộ nhớ ELSE
Phát byte1(3-0)&byte2 ra tuyến địa chỉ Phát xung đọc bộ nhớ
END IF; WHEN S5 =>
IF lệnh jsr THEN Thực hiện lệnh jsr
ELSIF lệnh sta trực tiếp THEN Kết thúc xung ghi
ELSIF lệnh gián tiếp THEN Đọc byte thứ 3 vào byte 2 Đặt trạng thái s6
IF byte1 (7 downto 5) jmp THEN Thực hiện lệnh jmp gián tiếp END IF;
ELSE
Thực hiện lệnh trực tiếp lda, and, adc, sbc END IF;
WHEN S6 =>
Đặt trạngthái S7
IF byte1 (7 downto 5) = sta THEN
Phát byte1(3-0)&byte2 ra tuyến địa chỉ Nạp ac vào tuyến data
62 Nguyễn Chí Kiên Chí Kiên
ELSE
Phát byte1(3-0)&byte2 ra tuyến địa chỉ Phát xung đọc bộ nhớ
END IF; WHEN s7 => IF lệnh sta gián tiếp THEN Kết thúc xung ghi
ELSE Thực hiện lệnh gián tiếp lda, and, adc, sbc
END IF; Trở về trạng thái S10 END IF;
END PROCESS;