1 / 23

理查一號 CPU - Richard CPU1

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

taini
Download Presentation

理查一號 CPU - Richard CPU1

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 理查一號 CPU- Richard CPU1

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

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

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

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

  6. 理查一號的架構 6

  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

  8. 理查一號的指令集 8

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

  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; elsifiReg(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

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

  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

  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

  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

  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

  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

  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

  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

  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

  20. ALU 的設計 alu <= (not acc) + x"0001" when state = negate else acc + dbuswhen state = add else (alu'range => '0'); 20

  21. 理查一號的狀態 • 理查一號採用 Mealy 型有限狀態機的設計方式 • Mealy 型狀態機的由輸入與狀態兩者決定。 • 在理查一號中,輸出由狀態 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

  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

  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

More Related