實驗目的,實驗目的,說明實驗儀器、設備等說明參見《計算機組成實驗C》實驗及課程設計指導書
程序代碼
8bit ALU設計:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY ALU_8BIT IS
PORT(INPUT_D : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
CTRL_S : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
SEL, WT, CIN, CLK : IN STD_LOGIC;
COUT : BUFFER STD_LOGIC;
OUTPUT_F : BUFFER STD_LOGIC_VECTOR(7 DOWNTO 0);
DIGITAL_DATA : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);--七段數碼管控制
SEG_SEL : OUT STD_LOGIC_VECTOR(2 DOWNTO 0));--掃描刷新
END ENTITY ALU_8BIT;
ARCHITECTURE FRAME1 of ALU_8BIT IS
SHARED VARIABLE REG_A, REG_B : STD_LOGIC_VECTOR(7 DOWNTO 0);--寄存器A,B存放加數,被加數
SHARED VARIABLE RECEIVE : STD_LOGIC_VECTOR(8 DOWNTO 0);
SIGNAL OUTPUT_SEL : STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL DATA : STD_LOGIC_VECTOR(4 DOWNTO 0);
--全加器
FUNCTION ARITH_ADD(A, B : STD_LOGIC_VECTOR(7 DOWNTO 0); CIN : STD_LOGIC) RETURN STD_LOGIC_VECTOR IS
VARIABLE SINT, AA, BB : STD_LOGIC_VECTOR(8 DOWNTO 0);--9BIT長,防止溢出
BEGIN
AA := '0' & A;--高位補零
BB := '0' & B;
SINT := AA + BB + CIN;
RETURN SINT;
END ARITH_ADD;
--邏輯右移
FUNCTION SHIFT_RIGHT_LOGIC(A : STD_LOGIC_VECTOR(7 DOWNTO 0)) RETURN STD_LOGIC_VECTOR IS
VARIABLE AA : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
AA(6 DOWNTO 0) := A(7 DOWNTO 1);
AA(7) := '0';--高位補零
RETURN AA;
END SHIFT_RIGHT_LOGIC;
--邏輯左移
FUNCTION SHIFT_LEFT_LOGIC(A : STD_LOGIC_VECTOR(7 DOWNTO 0)) RETURN STD_LOGIC_VECTOR IS
VARIABLE AA : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
AA(7 DOWNTO 1) := A(6 DOWNTO 0);
AA(0) := '0';--低位補零
RETURN AA;
END SHIFT_LEFT_LOGIC;
--算術右移
FUNCTION SHIFT_RIGHT_ARITH(A : STD_LOGIC_VECTOR(7 DOWNTO 0)) RETURN STD_LOGIC_VECTOR IS
VARIABLE AA : STD_LOGIC_VECTOR(7 DOWNTO 0);--臨時寄存器保留值
BEGIN
AA(6 DOWNTO 0) := A(7 DOWNTO 1);
AA(7) := A(7);
RETURN AA;
END SHIFT_RIGHT_ARITH;
BEGIN
PROCESS(CTRL_S, SEL, WT, CIN, CLK)
BEGIN
IF RISING_EDGE(CLK) THEN
IF(WT = '0') THEN
IF(SEL = '1') THEN
REG_A := INPUT_D;
ELSE
REG_B := INPUT_D;
END IF;
END IF;
CASE(CTRL_S) IS
WHEN "000" => OUTPUT_F <= "00000000";--清零
WHEN "001" => OUTPUT_F <= REG_A AND REG_B;--按位與
WHEN "010" => OUTPUT_F <= REG_A OR REG_B;--按位或
WHEN "011" => OUTPUT_F <= REG_A XOR REG_B;--按位異或
WHEN "100" => RECEIVE := ARITH_ADD(REG_A, REG_B, CIN); OUTPUT_F <= RECEIVE(7 DOWNTO 0); COUT <= RECEIVE(8);--全加器
WHEN "101" => OUTPUT_F <= SHIFT_LEFT_LOGIC(REG_A);--邏輯左移一位
WHEN "110" => OUTPUT_F <= SHIFT_RIGHT_LOGIC(REG_A);--邏輯右移一位
WHEN "111" => OUTPUT_F <= SHIFT_RIGHT_ARITH(REG_A);--算術右移一位
WHEN OTHERS => NULL;
END CASE;
OUTPUT_SEL <= OUTPUT_SEL + 1;--譯碼掃描
CASE(OUTPUT_SEL) IS
WHEN "000" => DATA(3 DOWNTO 0) <= REG_A(7 DOWNTO 4);DATA(4)<='0';
WHEN "001" => DATA(3 DOWNTO 0) <= REG_A(3 DOWNTO 0);DATA(4)<='0';
WHEN "010" => DATA(4)<='1';--最高位1,三號數碼管不亮
WHEN "011" => DATA(3 DOWNTO 0) <= REG_B(7 DOWNTO 4);DATA(4)<='0';
WHEN "100" => DATA(3 DOWNTO 0) <= REG_B(3 DOWNTO 0);DATA(4)<='0';
WHEN "101" => DATA(3 DOWNTO 0) <= "0001"; DATA(4)<= NOT(COUT);
WHEN "110" => DATA(3 DOWNTO 0) <= OUTPUT_F(7 DOWNTO 4);DATA(4)<='0';
WHEN "111" => DATA(3 DOWNTO 0) <= OUTPUT_F(3 DOWNTO 0);DATA(4)<='0';
WHEN OTHERS => NULL;
END CASE;
CASE(CONV_INTEGER(DATA)) IS--數碼管顯示
WHEN 0 => DIGITAL_DATA <= X"3F";
WHEN 1 => DIGITAL_DATA <= X"06";
WHEN 2 => DIGITAL_DATA <= X"5B";
WHEN 3 => DIGITAL_DATA <= X"4F";
WHEN 4 => DIGITAL_DATA <= X"66";
WHEN 5 => DIGITAL_DATA <= X"6D";
WHEN 6 => DIGITAL_DATA <= X"7D";
WHEN 7 => DIGITAL_DATA <= X"07";
WHEN 8 => DIGITAL_DATA <= X"7F";
WHEN 9 => DIGITAL_DATA <= X"6F";
WHEN 10 => DIGITAL_DATA <= X"77";
WHEN 11 => DIGITAL_DATA <= X"7C";
WHEN 12 => DIGITAL_DATA <= X"39";
WHEN 13 => DIGITAL_DATA <= X"5E";
WHEN 14 => DIGITAL_DATA <= X"79";
WHEN 15 => DIGITAL_DATA <= X"71";
WHEN OTHERS =>DIGITAL_DATA <= X"00";
END CASE;
SEG_SEL <= OUTPUT_SEL-1;
END IF;
END PROCESS;
END FRAME1;
簡易CPU設計:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity CPU is
port(CLK,Wr,Rd,RESET:in std_logic;--WR,RD,寫/讀控制,低電平有效
RA,M:in std_logic_vector(1 downto 0);--RA1 RA0控制4個通用寄存器 M1 M0控制PC寄存器四種操作
D: in std_logic_vector(7 downto 0);--ALU輸出
INPUT:in std_logic_vector(7 downto 0);--外部置數
output:buffer std_logic_vector(7 downto 0);--輸出到暫存器
Sin,Sout:in std_logic;--Sin控制置數或從ALU中讀取數據,Sout控制輸出R0-R3或PC寄存器的值到ALU暫存器
SEL:buffer std_logic_vector(2 downto 0);
LED7:out std_logic_vector(7 downto 0)
);
end entity CPU;
architecture one of CPU is
shared variable R0,R1,R2,R3,PC,temp:std_logic_vector(7 downto 0);
signal DATA:std_logic_vector(3 downto 0);
signal SEL_temp:std_logic_vector(2 downto 0);
signal times:std_logic_vector(7 downto 0);
begin
process(CLK,RESET,M)
begin
if CLK'event and CLK='0' then
times<=times+1;
if RESET='0' then PC:="00000000";
else -- RESET ='1'
if times ="0" then
case M is
when "11" =>
if Sin='0' then
PC:=D(7 downto 0);
else
PC:=INPUT(7 downto 0);
end if;
when "01" =>PC:=PC+1;
when "10" =>PC:=PC-1;
when others=>null;
end case;
end if;
end if;
end if;
end process;
process(RA,Wr,Rd,Sin,Sout,INPUT)
begin
case RA is
when "00" => if Wr='0' and Rd='1' then
if Sin='0' then --爲0表示從ALU中讀取數據
R0:=D(7 downto 0); --寫入數據到寄存器
else --Sin爲1表示從輸入端讀取數據
R0:=INPUT(7 downto 0);
end if;
elsif Wr='1' and Rd='0' then temp:=R0;
end if;
when "01" => if Wr='0' and Rd='1' then
if Sin='0' then --爲0表示從ALU中讀取數據
R1:=D(7 downto 0); --寫入數據到寄存器
else --Sin爲1表示從輸入端讀取數據
R1:=INPUT(7 downto 0);
end if;
elsif Wr='1' and Rd='0' then temp:=R1;
end if;
when "10" => if Wr='0' and Rd='1' then
if Sin='0' then --爲0表示從ALU中讀取數據
R2:=D(7 downto 0); --寫入數據到寄存器
else --Sin爲1表示從輸入端讀取數據
R2:=INPUT(7 downto 0);
end if;
elsif Wr='1' and Rd='0' then temp:=R2;
end if;
when "11" => if Wr='0' and Rd='1' then
if Sin='0' then --爲0表示從ALU中讀取數據
R3:=D(7 downto 0); --寫入數據到寄存器
else --Sin爲1表示從輸入端讀取數據
R3:=INPUT(7 downto 0);
end if;
elsif Wr='1' and Rd='0' then temp:=R3;
end if;
when others => null;
end case;
if Sout='0' then
output<=PC;
else
output<=temp;
end if;
end process;
process(CLK)
begin
if CLK'event and CLK='1' then
SEL_temp<=SEL_temp+1;
if SEL_temp>="111" then SEL_temp<="000";
end if;
SEL<=SEL_temp;
case SEL_temp is
when "000"=>DATA<=D(7 downto 4);
when "001"=>DATA<=D(3 downto 0);
when "010"=>DATA<=INPUT(7 downto 4);
when "011"=>DATA<=INPUT(3 downto 0);
when "100"=>DATA<=temp(7 downto 4);
when "101"=>DATA<=temp(3 downto 0);
when "110"=>DATA<=PC(7 downto 4);
when "111"=>DATA<=PC(3 downto 0);
when others=>NULL;
end case;
end if;
end process;
process(DATA)
begin
case DATA is
WHEN "0000"=> LED7<="00111111";--0
WHEN "0001"=> LED7<="00000110";--1
WHEN "0010"=> LED7<="01011011";--2
WHEN "0011"=> LED7<="01001111";--3
WHEN "0100"=> LED7<="01100110";--4
WHEN "0101"=> LED7<="01101101";--5
WHEN "0110"=> LED7<="01111101";--6
WHEN "0111"=> LED7<="00000111";--7
WHEN "1000"=> LED7<="01111111";--8
WHEN "1001"=> LED7<="01101111";--9
WHEN "1010"=> LED7<="01110111";--10
WHEN "1011"=> LED7<="01111100";--11
WHEN "1100"=> LED7<="00111001";--12
WHEN "1101"=> LED7<="01011110";--13
WHEN "1110"=> LED7<="01111001";--14
WHEN "1111"=> LED7<="01110001";--15
WHEN OTHERS =>NULL;
end case;
end process;
end architecture one;
連線參考圖:
說明:ALU_8BIT模塊直接使用實驗4代碼,在該實驗中存在功能閒置情況——DIGITAL_DATA,SEG_SEL數碼管動態掃描顯示模塊停用。
引腳鎖定參考:
引腳鎖定並非最優解決方案,僅供參考。