Presentation is loading. Please wait.

Presentation is loading. Please wait.

理查一號 CPU - Richard CPU1 日期 : 2019/1/17.

Similar presentations


Presentation on theme: "理查一號 CPU - Richard CPU1 日期 : 2019/1/17."— Presentation transcript:

1 理查一號 CPU - Richard CPU1 日期 : 2019/1/17

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

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

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

5 發現理查一號 最後、我決定看看網路上是否有人教人設計 CPU,找到很多, 但是真正將程式與原理講得很清楚的很少,華聖頓大學的 William D. Richard 在 Introduction To Digital Logic And Computer Design 課程中,將 CPU 的設計原理講得很清楚,然後更用 200 行的 VHDL 設計出一顆 CPU, 接著再加入記憶體後建構出一台測試電腦,總共寫了 315 行的 VHDL 程式,並且在 投影片 當中詳細的交待了其設計細節, 並給出模擬的結果,非常令人激賞。 以下我們將深入解析這顆 CPU 的設計方式與運作原理,我們將這顆 CPU 稱為 理察一號。 5 陳鍾誠 /1/17

6 理查一號的架構 6 陳鍾誠 /1/17

7 暫存器集 – 5個 pc : 程式計數器 (Program Counter)
alu : ALU的輸出暫存器 (Arithmetic Unit Output) iReg :指令暫存器 (Instruction Register) acc : 累積器 (Accumulator) iar : 間接定址暫存器 (Indirect Address Register) 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, 算術結果暫存器 7 陳鍾誠 /1/17

8 理查一號的指令集 代碼 指令 說明 運算方法 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

9 指令集說明 在上述指令表中,halt 與 negate 由於沒有運算元(參數),因此被編碼為 16 進位的 0000 與 0001
其他指令都具有一個記憶體位址運算元,這些指令的前 4 個 bit 用來表示運算碼, 後 12 個 bit 用來表示記憶體位址(運算元:參數) 指令共可分為四群,第一群為載入運算 (load, dload, iload) ,第二群為儲存 (dstore, istore) 第三群為分枝 (br, brZero, brZero, brPos, brNeg), 第四群只有一個指令,就是加法運算 (add)。 9 陳鍾誠 /1/17

10 指令解碼器的設計 procedure decode is begin -- Instruction decoding.
case iReg(15 downto 12) is when 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; 10 陳鍾誠 /1/17

11 指令提取階段 fetch 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 -- 降: if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if; 關閉記憶體 11 陳鍾誠 /1/17

12 算術指令 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; 12 陳鍾誠 /1/17

13 立即載入指令 mload 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; -- 本指令結束,前進到下一個指令 13 陳鍾誠 /1/17

14 直接載入指令 dload 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 指令結束,前進到下一個指令 14 陳鍾誠 /1/17

15 間接載入指令 iload 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 指令結束,前進到下一個指令 15 陳鍾誠 /1/17

16 直接儲存指令 dstore 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 指令結束,前進到下一個指令 16 陳鍾誠 /1/17

17 直接儲存指令 dstore 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 指令結束,前進到下一個指令 17 陳鍾誠 /1/17

18 跳躍指令 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 指令結束,前進到下一個指令 18 陳鍾誠 /1/17

19 理查一號的介面 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 simulation pcX, iarX : out std_logic_vector(adrLength-1 downto 0); iregX, accX, aluX : out std_logic_vector(wordSize-1 downto 0)); end cpu; 19 陳鍾誠 /1/17

20 ALU 的設計 alu <= (not acc) + x"0001" when state = negate
else acc + dbus when state = add else (alu'range => '0'); 20 陳鍾誠 /1/17

21 理查一號的狀態 理查一號採用 Mealy 型有限狀態機的設計方式 理查一號當中的狀態有 每個指令最多 分為 8 個時脈 (t0-t7)。
在理查一號中,輸出由狀態 state 與時脈 t0-t7 決定。 理查一號當中的狀態有 標準狀態: reset, fetch, halt 指令狀態:negate, mload, dload, iload, dstore, istore, brahch, brZero, brPos, brNeg, add 等。 每個指令最多 分為 8 個時脈 (t0-t7)。 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; 21 陳鍾誠 /1/17

22 重開機 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 => 22 陳鍾誠 /1/17

23 ALU 的 VHDL 程式 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; 23 陳鍾誠 /1/17


Download ppt "理查一號 CPU - Richard CPU1 日期 : 2019/1/17."

Similar presentations


Ads by Google