理查一號 cpu - richard cpu1

23
作作 : 作作作 作作 : 作作作作作作作作作 Email: [email protected] URL : http://ccc.kmit.edu.tw 作作 : 111/06/14 理理 CPU - Richard CPU1

Upload: taini

Post on 20-Mar-2016

105 views

Category:

Documents


1 download

DESCRIPTION

理查一號 CPU - Richard CPU1. 自己設計 CPU ,有可能嗎 ?. 想自己設計 CPU ,有可能嗎?這可是工業上的不傳之祕,哪有可能自己做一顆? 真的是這樣嗎? 或許 20 年前是這樣的,但現在可就不是了,有了 VHDL 與 FPGA 之後,我們真的可以用程式寫出一顆 CPU ,包含記憶體與測試案例都可以在你的 PC 上模擬出來後,燒到 FPGA 當中,就成了一顆 FPGA CPU 了。. 用程式寫出一顆 CPU. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 理查一號  CPU - Richard CPU1

作者 : 陳鍾誠單位 : 金門技術學院資管系Email: [email protected] : http://ccc.kmit.edu.tw

日期 : 112/04/24

理查一號 CPU- Richard CPU1

Page 2: 理查一號  CPU - Richard CPU1

自己設計 CPU ,有可能嗎 ? 想自己設計 CPU ,有可能嗎?這可是工業上的不傳之祕,哪有可能自己做一顆? 真的是這樣嗎? 或許 20 年前是這樣的,但現在可就不是了,有了 VHDL 與 FPGA 之後,我們真的可以用程式寫出一顆 CPU ,包含記憶體與測試案例都可以在你的 PC 上模擬出來後,燒到 FPGA 當中,就成了一顆 FPGA CPU 了。

2 陳鍾誠 - 112/04/24

Page 3: 理查一號  CPU - Richard CPU1

用程式寫出一顆 CPU 當我在金門技術學院教計算機組織這門課的時候,開使對於自己設計一顆 CPU 有了 強烈的興趣,或許是因為我很喜歡程式設計,只要看到可以寫程式做出來的東西就 很想自己寫一個,因為、有了 FPGA 之後, CPU 居然變成一種軟體了。

3 陳鍾誠 - 112/04/24

Page 4: 理查一號  CPU - Richard CPU1

失敗的嘗試 也可能是因為心虛,教計算機結構的老師沒有自己設計過 CPU ,那也太遜咖了, 於是、我花了三個星期,反覆的用 Altera 的 Quartus 設計修改一顆自己設計的 CPU , 但還是無法成功。

4 陳鍾誠 - 112/04/24

Page 5: 理查一號  CPU - Richard CPU1

發現理查一號 最後、我決定看看網路上是否有人教人設計 CPU ,找到很多, 但是真正將程式與原理講得很清楚的很少,華聖頓大學的 William D. Richard 在 Introduction To Digital Logic And

Computer Design 課程中,將 CPU 的設計原理講得很清楚,然後更用 200 行的 VHDL 設計出一顆 CPU , 接著再加入記憶體後建構出一台測試電腦,總共寫了 315 行的 VHDL 程式,並且在 投影片 當中詳細的交待了其設計細節, 並給出模擬的結果,非常令人激賞。

以下我們將深入解析這顆 CPU 的設計方式與運作原理,我們將這顆 CPU 稱為 理察一號。 5 陳鍾誠 - 112/04/24

Page 6: 理查一號  CPU - Richard CPU1

理查一號的架構

6 陳鍾誠 - 112/04/24

Page 7: 理查一號  CPU - Richard CPU1

暫存器集 – 5 個 pc : 程式計數器 (Program Counter) alu : ALU 的輸出暫存器 (Arithmetic Unit Output) iReg : 指令暫存器 (Instruction Register) acc : 累積器 (Accumulator) iar : 間接定址暫存器 (Indirect Address Register)

7 陳鍾誠 - 112/04/24

signal pc: std_logic_vector(adrLength-1 downto 0); -- program counter, 程式計數器signal iReg: std_logic_vector(wordSize-1 downto 0); -- instruction register, 指令暫存器signal iar: std_logic_vector(adrLength-1 downto 0); -- indirect address register, 間接位址暫存器signal acc: std_logic_vector(wordSize-1 downto 0); -- accumulator, 累積器signal alu: std_logic_vector(wordSize-1 downto 0); -- alu output, 算術結果暫存器

Page 8: 理查一號  CPU - Richard CPU1

理查一號的指令集代碼 指令 說明 運算方法0000 halt 暫停 (halt execution)0001 negate 反相 (negation) ACC := -ACC

1xxx load 立即載入 (immediate load) if sign bit of xxx is 0 then ACC := 0xxx else ACC := fxxx

2xxx dload 直接載入 (direct load) ACC := M[0xxx]

3xxx iload 間接載入 (indirect load) ACC := M[M[0xxx]]

4xxx dstore 直接儲存 (direct store) M[0xxx] := ACC

5xxx istore 間接儲存 (indirect store) M[M[0xxx]] := ACC

6xxx br 分枝 (branch) PC := 0xxx

7xxx brZero 零分枝 (branch if zero) if ACC = 0 then PC := 0xxx

8xxx brPos 正分枝 (branch if positive) if ACC > 0 then PC := 0xxx

9xxx brNeg 負分枝 (branch if negative) if ACC < 0 then PC := 0xxx

axxx add 加法 ACC := ACC + M[0xxx]8

Page 9: 理查一號  CPU - Richard CPU1

指令集說明 在上述指令表中, halt 與 negate 由於沒有運算元 ( 參數 ) ,因此被編碼為 16 進位的 0000 與 0001

其他指令都具有一個記憶體位址運算元,這些指令的前 4 個 bit 用來表示運算碼, 後 12 個 bit 用來表示記憶體位址 ( 運算元 : 參數 )

指令共可分為四群,第一群為載入運算 (load, dload, iload) ,第二群為儲存 (dstore, istore) 第三群為分枝 (br, brZero, brZero, brPos, brNeg) , 第四群只有一個指令,就是加法運算 (add) 。

9 陳鍾誠 - 112/04/24

Page 10: 理查一號  CPU - Richard CPU1

指令解碼器的設計

10 陳鍾誠 - 112/04/24

procedure decode is begin-- Instruction decoding.case iReg(15 downto 12) iswhen x"0" =>

if iReg(11 downto 0) = x"000" then state <= halt;

elsif iReg(11 downto 0) = x"001" then state <= negate;

end if;when x"1" => state <= mload;when x"2" => state <= dload;when x"3" => state <= iload;when x"4" => state <= dstore;when x"5" => state <= istore;when x"6" => state <= branch;when x"7" => state <= brZero;when x"8" => state <= brPos;when x"9" => state <= brNeg;when x"a" => state <= add;when others => state <= halt;end case;

end procedure decode;

Page 11: 理查一號  CPU - Richard CPU1

指令提取階段 fetch

11 陳鍾誠 - 112/04/24

when fetch =>

-- 降 : if tick = t0 then m_en <= ‘1’; aBus <= pc; end if; 讓 aBus<=pc, 啟動記憶體 , 以讀取指令 if tick = t1 then -- 擷取狀態 , 時態 (t1)

iReg <= dBus; -- 此時, dBus 上應已有指令,將其放入指令暫存器 iReg

end if;

if tick = t2 then -- 擷取狀態 , 時態 (t2)

decode; pc <= pc + '1'; tick <= t0; -- 解碼,同時將 pc 前進到下一個指令,回到 t0

end if;

-- 降 : if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if; 關閉記憶體

Page 12: 理查一號  CPU - Richard CPU1

算術指令

12 陳鍾誠 - 112/04/24

when halt => tick <= t0; -- do nothing -- 暫停狀態

when negate => acc <= alu; wrapup; -- 負號指令 , 將 alu 的輸出傳回累積器 acc 中

when add => -- 處理 add 加法指令-- 降 : if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;

if tick = t1 then acc <= alu; end if; -- t1, 將 alu 的輸出暫存器傳給累積器 acc

-- 降 : if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;

if tick = t2 then wrapup; end if; -- t2, add 指令結束,前進到下一個指令

when others => state <= halt;

Page 13: 理查一號  CPU - Richard CPU1

立即載入指令 mload

13 陳鍾誠 - 112/04/24

when mload => -- 處理 mload 立即值載入指令 ,

-- 擴展立即值 ireg(11..0) 為 16 位元,送到累積器 if iReg(11) = '0' then -- sign extension

acc <= x"0" & ireg(11 downto 0); -- 若符號位元為 0, 則將指令暫存器 ireg(11-0)

補 0

else

acc <= x"f" & ireg(11 downto 0); -- 若符號位元為 1, 則將指令暫存器 ireg(11-0) 補 1

end if;

wrapup; -- 本指令結束,前進到下一個指令

Page 14: 理查一號  CPU - Richard CPU1

直接載入指令 dload

14 陳鍾誠 - 112/04/24

when dload => -- 處理 dload 記憶體載入指令-- t0 : 讓 aBus<=iReg(11..0), 啟動記憶體 , 以讀取資料-- 降 : if tick = t0 then m_en <= ‘1’; aBus <= x“0” & iReg(11 downto 0); end if;

if tick = t1 then acc <= dBus; end if; -- t1, 將資料匯流排 dBus 的資料傳給累積器 acc

-- 降 : if tick = t2 then m_en <= ‘0’; aBus <= (aBus‘range => ’0‘); end if; 關閉記憶體 if tick = t2 then wrapup; end if; -- t2, dload 指令結束,前進到下一個指令

Page 15: 理查一號  CPU - Richard CPU1

間接載入指令 iload

15 陳鍾誠 - 112/04/24

when iload => -- 處理 iload 記憶體間接載入指令-- 降 : if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;

if tick = t1 then iar <= dBus; end if; -- t1, 將資料匯流排 dBus 的資料傳給間接位址暫存器 iar

-- 降 : if tick = t2 then m_en <= ‘0’; aBus <= (aBus‘range => ’0‘); end if; 關閉記憶體-- 降 : if tick = t3 then m_en <= ‘1’; aBus <= iar; end if; 讓 aBus<=iar, 啟動記憶體 , 以讀取資料if tick = t4 then acc <= dBus; end if; -- t4, 將資料匯流排 dBus 的資料傳給累積器 acc

-- 降 : if tick = t5 then m_en <= ‘0’; aBus <= (abus‘range => ’0‘); end if; 關閉記憶體if tick = t5 then wrapup; end if; -- t5, iload 指令結束,前進到下一個指令

Page 16: 理查一號  CPU - Richard CPU1

直接儲存指令 dstore

16 陳鍾誠 - 112/04/24

when dstore => -- 處理 dstore 記憶體儲存指令-- 降 :if tick = t0 then m_en <= ‘1’; aBus <= x“0” & iReg(11 downto 0); end if;

-- 讓 aBus<=iReg(11..0), 啟動記憶體 , 以寫入資料-- 降 :if tick = t1 then m_rw <= ‘0’; dBus <= acc; end if;

-- 將累積器 acc 傳到資料匯流排 dBus, 等待寫出-- 降 :if tick = t3 then m_rw <= ‘1’; end if; 啟動寫出動作-- 降 :if tick = t4 then

-- 降 : m_en <= ‘0’; aBus <= (abus‘range => ’0‘); dBus <= (dBus’range => ‘Z’); 關閉記憶體-- 降 :end if;

if tick = t4 then wrapup; end if; -- t4, dstore 指令結束,前進到下一個指令

Page 17: 理查一號  CPU - Richard CPU1

直接儲存指令 dstore

17 陳鍾誠 - 112/04/24

when istore => -- 處理 istore 記憶體間接儲存指令-- 降 :if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;

if tick = t1 then iar <= dBus; end if; -- t1, 將資料匯流排 dBus 的資料傳給間接位址暫存器 iar

-- 降 :if tick = t2 then m_en <= ‘0’; aBus <= (aBus‘range => ’0‘); end if; 關閉記憶體-- 降 :if tick = t3 then m_en <= ‘1’; aBus <= iar; end if; 讓 aBus<=iar, 啟動記憶體 , 以寫入資料-- 降 :if tick = t4 then m_rw <= ‘0’; dBus <= acc; end if; 關閉記憶體-- 降 :if tick = t6 then m_rw <= ‘1’; end if; 啟動寫出動作-- 降 :if tick = t7 then

-- 降 : m_en <= ‘0’; aBus <= (abus‘range => ’0‘); dBus <= (dBus’range => ‘Z’); 關閉記憶體-- 降 :end if;

if tick = t7 then wrapup; end if; -- t7, istore 指令結束,前進到下一個指令

Page 18: 理查一號  CPU - Richard CPU1

跳躍指令

18 陳鍾誠 - 112/04/24

when branch => -- 處理 branch 無條件跳躍指令 pc <= x"0" & iReg(11 downto 0); -- 將跳躍位址 iReg(11..0) 傳給程式計數器 pc

wrapup; -- branch 指令結束,前進到下一個指令when brZero => -- 處理 brZero 零跳躍指令 if acc = x"0000" then pc <= x"0" & iReg(11 downto 0); end if; -- 如果累積器 acc=0, 則 pc<=iReg(11..0)

wrapup; -- brZero 指令結束,前進到下一個指令when brPos => -- 處理 brPos 正跳躍指令 if acc(15) = '0' and acc /= x"0000" then -- 如果累積器 acc > 0,

pc <= x"0" & iReg(11 downto 0); -- 則 pc<=iReg(11..0)

end if;

wrapup; -- brPos 指令結束,前進到下一個指令when brNeg => -- 處理 brNeg 負跳躍指令 if acc(15) = ‘1’ then pc <= x“0” & iReg(11 downto 0); end if; -- 如果累積器 acc < 0, 則 pc<=iReg(11..0)

wrapup; -- brNeg 指令結束,前進到下一個指令

Page 19: 理查一號  CPU - Richard CPU1

理查一號的介面

19 陳鍾誠 - 112/04/24

entity cpu is port (clk, reset : in std_logic;m_en, m_rw : out std_logic; aBus : out std_logic_vector(adrLength-1 downto 0);dBus : inout std_logic_vector(wordSize-1 downto 0);

-- these signals "exported" so they can be monitored in post-P&R simulationpcX, iarX : out std_logic_vector(adrLength-1 downto 0);iregX, accX, aluX : out std_logic_vector(wordSize-1 downto 0));

end cpu;

Page 20: 理查一號  CPU - Richard CPU1

ALU 的設計

20 陳鍾誠 - 112/04/24

alu <= (not acc) + x"0001" when state = negate else acc + dbus when state = add else (alu'range => '0');

Page 21: 理查一號  CPU - Richard CPU1

理查一號的狀態 理查一號採用 Mealy 型有限狀態機的設計方式

Mealy 型狀態機的由輸入與狀態兩者決定。 在理查一號中,輸出由狀態 state 與時脈 t0-t7 決定。

理查一號當中的狀態有 標準狀態: reset, fetch, halt 指令狀態: negate, mload, dload, iload, dstore, istore, brahch, brZero,

brPos, brNeg, add 等。 每個指令最多分為 8 個時脈 (t0-t7) 。

21 陳鍾誠 - 112/04/24

type state_type is (reset_state, fetch, halt, negate, mload, dload, iload,dstore, istore, branch, brZero, brPos, brNeg, add

);

signal state: state_type;

type tick_type is (t0, t1, t2, t3, t4, t5, t6, t7);signal tick: tick_type;

Page 22: 理查一號  CPU - Richard CPU1

重開機

22 陳鍾誠 - 112/04/24

if reset = '1' then state <= reset_state; tick <= t0; pc <= (pc'range => '0'); iReg <= (iReg'range => '0'); acc <= (acc'range => '0'); iar <= (iar'range => '0');else tick <= nextTick(tick) ; -- advance time by default case state is when reset_state => state <= fetch; tick <= t0; when fetch =>…

Page 23: 理查一號  CPU - Richard CPU1

ALU 的 VHDL 程式

23 陳鍾誠 - 112/04/24

entity top is port(clk, reset: in STD_LOGIC;mem_enX, mem_rwX : out std_logic;aBusX : out std_logic_vector(adrLength-1 downto 0);dBusX : out std_logic_vector(wordSize-1 downto 0);pcX, iarX : out std_logic_vector(adrLength-1 downto 0);iregX, accX, aluX : out std_logic_vector(wordSize-1 downto 0));

end top;