簡單計算機系統綜合設計(CPU)
前言:作為一位來自于大學的大學生,讓我最難忘記的就是這一次CPU的綜合設計了。
基本部件
數字邏輯實驗中我們要求完成的有以下基本部件,使用VHDL源完成程式設計。
0000:指令寄存器IR,
a) 子產品的接口設計
控制信号:LDIR,CLK,I[7…0]
輸入信号:需執行指令I[7…0] 輸出信号:需執行指令out1[7…0]
b) 功能實作
根據指令寄存器IR的功能可知:
當HALT = 1 時,輸出信号 x[7…0] 為高阻态;
否則,當處于時鐘下降沿時,LDIR = 1時,輸出信号out[7…0]為輸入信号I[7…0]。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity IR is
port (LDIR, CLK : in std_logic;
I : in std_logic_vector(7 downto 0);
OUT1 : out std_logic_vector(7 downto 0)
);
end IR;
architecture behavior of IR is
signal command: std_logic_vector(7 downto 0);
begin
OUT1 <= command;
process(CLK)
begin
if (CLK'event and CLK = '0' and LDIR = '1') then
command <= I;
end if;
end process;
end behavior;
0001:指令譯碼器DECODING,
a) 子產品的接口設計
控制信号:EN 輸入信号:需執行指令IR[7…0]
輸出信号:需執行指令IR[7…0],
各項指令的控制信号:MOVA,MOVB,MOVC,ADD,SUB,OR1,NOT1,RSR,RSL,JMP,JZ,JC,IN1,OUT1,NOP,HALT
b) 功能實作
根據指令譯碼器的功能可知:
當EN = 1時,輸入資訊:需執行指令IR[7…0]對應一個指令控制信号。
指令譯碼器需要完成指令機器碼和指令控制信号的一一對應。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity DECODING is
port(EN:in std_logic;
IR:in std_logic_vector(7 downto 0);
MOVA, MOVB, MOVC, ADD, SUB, OR1, NOT1, RSR, RSL, JMP, JZ, JC, IN1, OUT1, NOP, HALT: out std_logic);
end DECODING;
architecture behavior of DECODING is
signal R: std_logic_vector(7 downto 0):="00000000";
signal signalB,signalC: std_logic;
begin
MOVA <= '1' when
IR(7 downto 4) = "1111" and (not (IR(3 downto 2) = "11")) and (not (IR(1 downto 0) = "11")) and EN = '1' else '0';
MOVB <= '1' when
IR(7 downto 4) = "1111" and (IR(3 downto 2) = "11") and (not (IR(1 downto 0) = "11")) and EN = '1' else '0';
MOVC <= '1' when
IR(7 downto 4) = "1111" and (not (IR(3 downto 2) = "11")) and (IR(1 downto 0) = "11") and EN = '1' else '0';
ADD <= '1' when
IR(7 downto 4) = "1001" and EN = '1' else '0';
SUB <= '1' when
IR(7 downto 4) = "0110" and EN = '1' else '0';
OR1 <= '1' when
IR(7 downto 4) = "1011" and EN = '1' else '0';
NOT1 <= '1' when
IR(7 downto 4) = "0101" and EN = '1' else '0';
RSR <= '1' when
IR(7 downto 4) = "1010" and (IR(1 downto 0) = "00") and EN = '1' else '0';
RSL <= '1' when
IR(7 downto 4) = "1010" and (IR(1 downto 0) = "11") and EN = '1' else '0';
JMP <= '1' when
IR(7 downto 0) = "00010000" and EN = '1' else '0';
JZ <= '1' when
IR(7 downto 0) = "00010001" and EN = '1' else '0';
JC <= '1' when
IR(7 downto 0) = "00010010" and EN = '1' else '0';
IN1 <= '1' when
IR(7 downto 4) = "0010" and EN = '1' else '0';
OUT1 <= '1' when
IR(7 downto 4) = "0100" and EN = '1' else '0';
NOP <= '1' when
IR(7 downto 0) = "01110000" and EN = '1' else '0';
HALT <= '1' when
IR(7 downto 0) = "10000000" and EN = '1' else '0';
end behavior;
0010:控制信号産生邏輯 LOGIC,
a) 子產品的接口設計
控制信号:SM
輸入信号:MOVA,MOVB,MOVC,ADD,SUB,OR1,NOT1,RSR,RSL,JMP,JZ,JC,IN1,OUT1,NOP,HALT,C,Z
輸出信号:INPC,LDPC,LDIR,WE,FBUS,FLBUS,FRBUS,CS,DL,XL,M,HALT_out
b) 功能實作
當SM = 1時,輸入資訊:需執行指令IR[7…0]對應一個指令控制信号。
指令譯碼器需要完成指令機器碼和指令控制信号的一一對應。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity control_logism is
port(SM,MOVA,MOVB,MOVC,ADD,SUB,OR1,NOT1,RSR,RSL,JMP,JZ,JC,IN1,OUT1,NOP,HALT,C,Z:in std_logic;
IR: in std_logic_vector(7 downto 0);
RAA,RWBA,MADD: out std_logic_vector(1 downto 0);
S: out std_logic_vector(3 downto 0);
INPC,LDPC,LDIR,WE,FBUS,FLBUS,FRBUS,CS,DL,XL,M,HALT_out: out std_logic
);
end control_logism;
architecture control_logism_behavior of control_logism is
begin
process(MOVA,MOVB,MOVC,ADD,SUB,OR1,NOT1,RSR,RSL,JMP,JZ,JC,C,Z,IN1,OUT1,NOP,HALT,IR)
begin
S(3) <= IR(7);
S(2) <= IR(6);
S(1) <= IR(5);
S(0) <= IR(4);
LDIR <= not SM;
INPC <= (not SM);
LDPC <= JMP or (Z and JZ) or (C and JC);
WE <= ((not MOVA) and (not MOVC) and (not ADD) and (not SUB) and (not OR1) and (not NOT1) and (not RSR) and (not RSL) and (not IN1)) or (not SM);
RAA <= IR(1 downto 0);
RWBA <= IR(3 downto 2);
M <= ADD or SUB or OR1 or NOT1;
FBUS <= MOVA or MOVB or ADD or SUB or OR1 or NOT1 or OUT1;
FLBUS <= RSL;
FRBUS <= RSR;
DL <= (not SM) or MOVC or JMP or JC or JZ;
XL <= MOVB;
MADD(1) <= MOVB;
MADD(0) <= MOVC;
HALT_out <= HALT;
end process;
end control_logism_behavior;
0011:函數發生器ALU,
a) 控制信号:M,S[3…0]
輸入信号:資料A[7…0],B[7…0]
輸出信号:資料COUT[7…0],C,Z
b) 功能實作
根據函數發生器ALU的功能可知:
根據 M,S[3…0],需要判斷:
對資料進行加法運算,減法運算,或運算,取反運算還是不處理;
根據資料A[7…0],B[7…0],可以得到各種運算的結果;
通過運算結果可以得到輸出的資料COUT[7…0],以及C,Z
函數發生器ALU需要完成:
對A口,B口進入的資料進行各種運算并且處理輸出結果。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity model_operator_ALU is
port (
m : in std_logic;
s : in std_logic_vector(3 downto 0);
a, b : in std_logic_vector(7 downto 0);
T : out std_logic_vector(7 downto 0);
cf, zf : out std_logic);
end model_operator_ALU;
architecture Behavior of model_operator_ALU is
signal temp : std_logic_vector(8 downto 0);
signal pf,pf2 : std_logic_vector(0 downto 0);
begin
pf <= "0";
pf2 <= "1";
with m&s select
temp <= (pf&b) + (pf&a) when "11001",
(pf2&b) - (pf&a) when "10110",
(pf&b) or (pf&a) when "11011",
not (pf&b) when "10101",
pf&a when "11111",
pf&a when "01111",
pf&b when "11010",
pf&b when "01010",
pf&b when "00100",
pf&b when "10100",
"011111111" when others;
T <= temp(7 downto 0);
cf <= temp(8);
zf <= not(temp(8) or temp(7) or temp(6) or temp(5) or temp(4) or temp(3) or temp(2) or temp(1) or temp(0));
end Behavior;
0100:移位邏輯SHIFT,
a) 控制信号:FBUS,FLBUS,FRBUS
輸入信号:資料a[7…0] 輸出信号:資料 w[7…0],cf
b) 功能實作
根據移位邏輯的功能可知:
當FBUS = 1時,輸出資料 w[7…0]為輸入資料a[7…0];
當FLBUS = 1時,輸出資料 w[7…0]為輸入資料a[7…0]的邏輯左移;
當FRBUS = 1時,輸出資料 w[7…0]為輸入資料a[7…0]的邏輯右移;
通過結果可以得到cf;
移位邏輯需要完成:對輸入資料a[7…0]進行邏輯移位并且處理輸出結果。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity shift_logic is
port(fbus,flbus,frbus: in std_logic;
a: in std_logic_vector(7 downto 0);
cf: out std_logic;
w: out std_logic_vector(7 downto 0));
end shift_logic;
architecture behavior of shift_logic is
begin
process(fbus,flbus,frbus)
begin
if (flbus = '1' ) then
w <= a(6 downto 0) & '0';
cf <= a(7);
elsif (frbus = '1' ) then
w <= '0' & a(7 downto 1) ;
cf <= a(0);
elsif (fbus = '1') then
w <= a;
elsif (fbus = '0') then
w <= "ZZZZZZZZ";
end if;
end process;
end behavior;
0101:使能信号SM,
a) 控制信号:CLK,EN 輸出信号:SM
b) 功能實作
根據SM信号發生器的功能可知:
當處于時鐘下降沿時,輸出信号與之前狀态的輸出信号相反。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity SM_fun is
port (CLK,EN: in std_logic;
SM: out std_logic);
end SM_fun;
architecture behavior of SM_fun is
signal ls: std_logic:='0';
begin
process(CLK,EN)
begin
if (CLK'event and (CLK = '0') and (EN = '1')) then
ls <= not ls;
end if;
end process;
SM <= ls;
end behavior;
0110:指令計數器PC,
a) 子產品的接口設計
控制信号:LDPC,INPC,clk
輸入資料:位址值 indata[7…0] 輸出資料:位址值 outdata[7…0]
b) 功能實作
根據指令計數器PC的功能可知:
在時鐘的下降沿,若LDPC = 1,輸入外部的位址值,并輸出該位址值;
若INPC = 1,将原先的位址值加一,并輸出該位址值。
VHDL實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity Instruction_counter_PC is
port(LDPC,INPC,CLK: in std_logic;
indata: in std_logic_vector(7 downto 0);
outdata: out std_logic_vector(7 downto 0));
end Instruction_counter_PC;
architecture behavior of Instruction_counter_PC is
signal pc: std_logic_vector(7 downto 0):= "00000000";
begin
process(LDPC,INPC,CLK)
begin
if (CLK'EVENT and CLK = '0' and INPC = '1' and LDPC = '0') then
pc <= pc + 1;
elsif (CLK'EVENT and CLK = '0' and INPC = '0' and LDPC = '1') then
pc <= indata;
end if;
outdata <= pc;
end process;
end behavior;
0111:通用寄存器組REGISTER,
a) 子產品的接口設計
控制信号:WE,RAA[1…0],RWBA[1…0],clk
輸入信号:總線資料I[7…0]
輸出信号:AO[7…0],BO[7…0]
CHECK: register_A [7…0],register_B[7…0],register_C [7…0]
b) 功能實作
根據通用寄存器組的功能可知:
當處于時鐘下降沿時,當WE = 0時:
根據 RWBA[1…0],需要向通用寄存器組中存入資料;
根據 RAA[1…0],RWBA[1…0],向A口和B口輸出資料
通用寄存器組需要完成:
對寄存器A,寄存器B,寄存器C進行資料的輸入和輸出。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity Universal_register_group is
port(
RA : in std_logic_vector(1 downto 0);
WA : in std_logic_vector(1 downto 0);
I : in std_logic_vector(7 downto 0);
WE : in std_logic;
clk : in std_logic;
AO : out std_logic_vector(7 downto 0);
BO : out std_logic_vector(7 downto 0);
register_A : out std_logic_vector(7 downto 0);
register_B : out std_logic_vector(7 downto 0);
register_C : out std_logic_vector(7 downto 0));
end Universal_register_group;
architecture behavior of Universal_register_group is
signal A : std_logic_vector(7 downto 0) := "00000011";
signal B : std_logic_vector(7 downto 0) := "00001100";
signal C : std_logic_vector(7 downto 0) := "00110000";
begin
--Output operation
process(clk)
begin
if(clk'event and clk = '0')then
if(WE = '0') then
if(WA = "00")then
A <= I;
elsif(WA = "01")then
B <= I;
elsif(WA = "10")then
C <= I;
end if;
end if;
end if;
end process;
--output operation
AO <= A when RA = "00" else
B when RA = "01" else
C when RA = "10" or RA = "11";
BO <= A when WA = "00" else
B when WA = "01" else
C when WA = "10" or WA = "11";
register_A <= A;
register_B <= B;
register_C <= C;
end behavior;
1000:選擇器SELECTOR
a) 子產品的接口設計
控制信号:MADD
輸入信号:I0[7…0],I1[7…0],I2[7…0] 輸出信号:OUT1[7…0]
b) 功能實作
根據選擇器的功能可知:
當MADD = 00時,輸出資訊 COUT[7…0] 輸入資訊 S0[7…0];
當MADD = 01時,輸出資訊 COUT[7…0] 輸入資訊 S1[7…0];
當MADD = 10時,輸出資訊 COUT[7…0] 輸入資訊 S2[7…0]。
VHDL的實作如下所示:
library ieee;
use ieee.std_logic_1164.all;
entity selector is
port (MADD : in std_logic_vector(1 downto 0);
I0, I1, I2 : in std_logic_vector(7 downto 0);
OUT1 : out std_logic_vector(7 downto 0)
);
end selector;
architecture behavior of selector is
begin
OUT1 <= I0 when MADD = "00"
else I1 when MADD = "01"
else I2 when MADD = "10"
else "ZZZZZZZZ" when MADD = "11";
end behavior;
1001:存儲器RAM,
a) 子產品的接口設計
控制信号:inclock ( clk ),we (XL),outenab(DL)
輸入信号:address[7…0] 輸出信号:dio[7…0]
b) 功能實作
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPR5EMnR1TyUFROBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3MDN4QDNzAjMzIjMxkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
CPU邏輯圖
CPU邏輯圖
總結
模型機的設計坑比較多
下面我分類記錄了一下:
1:process的應用:我在仿真時發現信号輸出的值一直是預定義信号,後來發現是因為process隻能夠響應信号的變化,在信号一直為某一個值時,process不會作出響應。是以,除了帶有時鐘信号的部件,我一律棄用了process,改為并行。
2.無論我執行哪一個指令,發現通用寄存器組的輸出一直為0,是以我額外增加了register_A, register_B, register_C來CHECK我的信号,最後發現使我的BUS總線沒有輸入,是以我追溯到了我的ALU部分,原來是這裡阻塞了信号,使得ALU和shift_logic的輸出一直為高阻态,導緻BUS總線一直是高阻态。
3.我的指令譯碼器在開始時也是沒有輸出的,在此之前我曾将重寫了指令譯碼器,發現是因為指令譯碼器内部輸入和信号搞反了,這也算是一個低級錯誤了吧。
4.在設計CPU的時候,連線是一個較大的問題,因為好多的信号都會串在一起,是以可以采用不直接連線,而是通過端口的名稱定義為相同,進而間接将它們連接配接起來。
注:
本篇部落格僅用作學習交流使用,新學者還是建議還是自己敲一遍。