SWJTU計算機組成實驗C-實驗六 運算器的設計

實驗目的,實驗目的,說明實驗儀器、設備等說明參見《計算機組成實驗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數碼管動態掃描顯示模塊停用。

引腳鎖定參考:


引腳鎖定並非最優解決方案,僅供參考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章