[No0000166]CPU的组成结构及其原理
中央處理器(Central Processing Unit, CPU)
CPU的基本架構(gòu)和工作原理其實(shí)百科上講得已經(jīng)相當(dāng)清楚了,不過我覺得有些事情呢還是給個(gè)例子出來比較方便學(xué)習(xí)。
本文會(huì)先從內(nèi)存地址,計(jì)算機(jī)的一般架構(gòu)之類的基礎(chǔ)知識(shí)出發(fā),然后逐步為讀者"拼裝"出一個(gè)超級(jí)簡(jiǎn)單的8-bit CPU。。。就像下圖這樣(大圖點(diǎn)開)
這就是本文的目標(biāo):拼裝這樣一個(gè)結(jié)構(gòu)的CPU
-----------------------------------------------------------------------------------------------------------------------
上面那個(gè)大圖里有幾個(gè)梯形的符號(hào)
它們叫做數(shù)據(jù)選擇器(Multiplexer),也叫多路選擇器或多路開關(guān)
已經(jīng)知道這個(gè)東西是干啥的童鞋直接跳過此樓吧。。
這圖是一個(gè)2選1選擇器,A,B,S為輸入,Z為輸出,它們可取的值當(dāng)然都只有0和1
怎么工作的呢?
以該圖為例:
當(dāng)S=1的時(shí)候,輸出值Z = 輸入值B
當(dāng)S=0的時(shí)候,輸出值Z = 輸入值A
比如說A=1,B=0,S=0的時(shí)候輸出是多少?S=0就是說:選擇A的值輸出,也就是說輸出值Z=A=1
就這么簡(jiǎn)單
同樣地,我們也可以有4選1選擇器
只不過控制輸入S變成了兩位(00,01,10,11,分別對(duì)應(yīng)一二三四),道理還是一樣的
如果你對(duì)這個(gè)東東怎么做成的感興趣的話。。。下面就是4選1選擇器的其中一種電路 = =
哦,還有。。本文使用的邏輯門符號(hào)均是ANSI/IEEE Std 91-1984中的Distinctive shape,不是用方框符號(hào)。。。= =
你只要知道數(shù)據(jù)選擇器是干啥的就好,不用惦記上邊那電路。。
------------------------------------------------------------------------------------------------------------
1. 計(jì)算機(jī)架構(gòu)(Computer Architecture)
CPU、內(nèi)部存儲(chǔ)器(Internal Storage Device)和輸入/輸出設(shè)備(Input/Output Device, I/O)是電子計(jì)算機(jī)三大核心部件。內(nèi)部儲(chǔ)存器可以是硬盤,內(nèi)存,緩存等;輸入設(shè)備可以是鼠標(biāo),鍵盤;輸出設(shè)備可以有屏幕,音箱等等。。
當(dāng)你打開電腦硬盤上安裝的某個(gè)程序時(shí),你的操作系統(tǒng)會(huì)把硬盤上的相應(yīng)內(nèi)容放入內(nèi)存中。至于怎么放,在內(nèi)存的什么地方放那可是一門大學(xué)問,光這個(gè)就夠一般人喝一壺的。。相關(guān)知識(shí)可以在大學(xué)的操作系統(tǒng)課程里學(xué)到
比如說你放個(gè)音樂。要放音樂,先用鼠標(biāo)點(diǎn)開一個(gè)mp3文件,于是你就使用了一個(gè)輸入設(shè)備。這個(gè)輸入設(shè)備會(huì)把一個(gè)中斷請(qǐng)求(Interrupt Request)送到CPU那邊,結(jié)合來自操作系統(tǒng)的信息后CPU就知道:哦,你用鼠標(biāo)點(diǎn)開那個(gè)mp3文件了!于是:
1. CPU執(zhí)行操作系統(tǒng)里關(guān)于文件關(guān)聯(lián)的代碼,于是你的電腦就知道要用WMP打開文件了
2. 你的操作系統(tǒng)開始把WMP這個(gè)程序里含有的指令和mp3文件的內(nèi)容從硬盤上拉進(jìn)內(nèi)存里(還是CPU的工作)
3. 然后你的CPU開始一條一條地(雙核的話那你就當(dāng)成兩條兩條地好了)執(zhí)行內(nèi)存里的WMP程序指令(也就是如何解碼mp3),并且把解碼后的PCM比特流傳到聲卡上,再由聲卡把數(shù)字信號(hào)轉(zhuǎn)換成模擬信號(hào)送到音箱/耳機(jī)(輸出設(shè)備)里。So now you have music!
又比如說你要編輯一個(gè)txt文件。還是先得用鼠標(biāo)點(diǎn)開文件,又用了一次輸入設(shè)備。于是:
1. CPU執(zhí)行操作系統(tǒng)里關(guān)于文件關(guān)聯(lián)的代碼,于是你的電腦就知道要用notepad打開文件了
2. 你的操作系統(tǒng)把notepad的程序指令和文件內(nèi)容拉進(jìn)內(nèi)存
3. 然后你的CPU又開始執(zhí)行Notepad程序的指令了
4. 每當(dāng)你敲一次鍵盤(還是輸入設(shè)備!!),都會(huì)向CPU發(fā)送一個(gè)中斷請(qǐng)求好讓CPU知道你敲了某個(gè)鍵。比如說你敲個(gè)Y,那么CPU就會(huì)把Y這個(gè)字符寫進(jìn)內(nèi)存里。然后你要保存的時(shí)候操作系統(tǒng)就會(huì)把內(nèi)存里改過的東東倒進(jìn)硬盤里!~
。。。好吧我承認(rèn)實(shí)際過程跟這兒說的不大一樣并且復(fù)雜得多,有些細(xì)節(jié)會(huì)在后面詳細(xì)講,but that's the basic idea.
這大約就是CPU,輸入/輸出設(shè)備和內(nèi)存之間的互動(dòng)方式了。
---------------------------------------------------------------------------------------------------
2.內(nèi)存(Memory)
內(nèi)存就是暫時(shí)存儲(chǔ)程序以及數(shù)據(jù)的地方,比如當(dāng)我們?cè)谑褂?/span>WPS處理文稿時(shí),當(dāng)你在鍵盤上敲入字符時(shí),它就被存入內(nèi)存中,當(dāng)你選擇存盤時(shí),內(nèi)存中的數(shù)據(jù)才會(huì)被存入硬盤。一斷電內(nèi)存上的東東就沒了
內(nèi)存里的數(shù)據(jù)是根據(jù)內(nèi)存地址(Memory Address)來組織的。每個(gè)地址都是獨(dú)特的,每個(gè)地址一般來說對(duì)應(yīng)著一個(gè)字節(jié)(byte)=8 bit,我們管這叫Byte addressable memory.
在32 bit的系統(tǒng)上,內(nèi)存地址的長度就是32 bit。那么一個(gè)32 bit長度的二進(jìn)制數(shù)最大可以表示的數(shù)是多少呢?很簡(jiǎn)單,2^32 = 4294967296。也就是說,32 bit的內(nèi)存地址最大可以對(duì)應(yīng)4294967296字節(jié)的內(nèi)存!
這個(gè)數(shù)字換算一下就可以得出它相當(dāng)于4GB?,F(xiàn)在你知道為什么32位系統(tǒng)不支持4GB以上的內(nèi)存了嗎?
------------------------------------------------------------------------------------------------------
3. 指令編碼(Instruction Encoding)
終于要說點(diǎn)正經(jīng)的了。。前面說過CPU會(huì)執(zhí)行內(nèi)存/緩存中的程序指令,可是這些指令是以什么樣的形式儲(chǔ)存在內(nèi)存里的呢?要知道所謂的指令其實(shí)就是一長串的0和1而已。那CPU如何從這些0和1里知道指令是什么呢?這就是指令編碼的內(nèi)容了。
先說說CPU。您說,CPU能干啥?其實(shí)很簡(jiǎn)單,無非就是加減乘除,讀寫內(nèi)存,邏輯運(yùn)算什么的。若是復(fù)雜些的CPU可能指令集要大些,不過基本的指令大概就這些。CPU內(nèi)部也有自己的儲(chǔ)存單元,叫做寄存器(Register),也是暫時(shí)用來放數(shù)據(jù)的地方,速度特別快,容量特別小。
就拿我經(jīng)常用的NIOS II來說,它內(nèi)部有32個(gè)寄存器,它可以執(zhí)行的指令包括(不好意思我要用匯編語言了=_=):
add rA,rB,rC #把寄存器rB,rC里的數(shù)加起來,結(jié)果放入寄存器rC
addi rB, rA, IMM16 #把rA里的數(shù)跟一個(gè)16位的數(shù)相加,結(jié)果放入rB
beq rB,rA,LABEL #若rA=rB,則跳到LABEL指定的內(nèi)存地址開始執(zhí)行指令,否則繼續(xù)按照內(nèi)存地址順序執(zhí)行指令
stwio rB, b_o(rA) #從內(nèi)存地址rA+b_o處讀取一個(gè)字節(jié),數(shù)據(jù)放入rB
ldwio rB, b_o(rA) #從內(nèi)存地址rA+b_o處開始寫入一個(gè)字節(jié),寫入的數(shù)據(jù)在rB里
。
。
等等
總結(jié)起來,CPU可以有以下幾個(gè)功能:
1.進(jìn)行寄存器之間的運(yùn)算和比較
2.由寄存器內(nèi)指定的地址讀寫內(nèi)存
3.分支指令,類似于C語言里的if語句。比如跳到某個(gè)寄存器里指定的內(nèi)存地址開始讀取并執(zhí)行指令
當(dāng)然,更復(fù)雜的指令集是有可能的,不過這里就不說了
---------------------------------------------------------------------------------------------
我知道讀者可能好幾樓沒見著個(gè)圖有點(diǎn)煩躁了,不過請(qǐng)有些耐心,等開始拼裝CPU的時(shí)候圖片絕對(duì)多。。。
Anyway,繼續(xù)說指令編碼
大致來說,上面的指令可以分為三大類:I-type,R-type,J-type
P.S.這種分類適用于MIPS架構(gòu)的處理器,其他我就不知道了
1. I-type
以32 bit為例。一條I-type指令包括四個(gè)元素:
兩個(gè)寄存器編號(hào),一個(gè)16位數(shù)字和一個(gè)操作碼
31-27位代表指令里寄存器rA的編號(hào)
26-22位代表寄存器rB的編號(hào)
21-6位是一個(gè)16位的二進(jìn)制數(shù)
5-0位是操作碼
例子:
NIOS II匯編指令 addi r6,r7,310表示把寄存器r7里的數(shù)加上310,結(jié)果放入寄存器r6。如果我們規(guī)定addi運(yùn)算對(duì)應(yīng)的六位操作碼是000011,那么請(qǐng)問整條指令的編碼是?
解答:
寄存器r6的編號(hào)是6,即00110
寄存器r7的編號(hào)是7,即00111
數(shù)字310對(duì)應(yīng)的二進(jìn)制數(shù)是0000000100110110
addi的操作碼是000011
所以整條指令的編碼就是00110 00111 0000000100110110 000011
-----------------------r6-----r7--------310---------addi------
共32位!
這就是I-type指令在內(nèi)存里存在的形式!!~
----------------------------------------------------------------------------
2. R-type
還是以32 bit為例。一條R-type指令通常包括四個(gè)元素:
三個(gè)寄存器編號(hào),一個(gè)操作碼
31-27位是寄存器rA的編號(hào)
26-22位是寄存器rB的編號(hào)
21-17位是寄存器rC(一般來說這個(gè)是目標(biāo)寄存器)的編號(hào)
16-6位是OPX,是操作碼
5-0位。。你當(dāng)它沒用吧,寫上000000就好 = =
例子:
匯編指令 add r10,r9,r8是典型的R-type指令。它表示把寄存器r9,r8里的數(shù)加起來,然后把結(jié)果寫入寄存器r10(目標(biāo)寄存器)。若規(guī)定add運(yùn)算的操作碼為00000011111,請(qǐng)問整條指令的編碼是?
解答:
寄存器r10的編號(hào)是10,即01010
寄存器r9的編號(hào)是9,即01001
寄存器r8的編號(hào)是8,即01000
add運(yùn)算操作碼是00000011111
OP = 000000
所以整條指令的二進(jìn)制編碼是01001 01000 01010 00000011111 000000
---------------------------r9-----r8---r10------add-------OP
共32位!
-----------------------------------------------------------------------------------------
3. J-Type
一條32bit的J-Type指令包含兩個(gè)元素:
一個(gè)26位的數(shù)字(通常是內(nèi)存地址)和一個(gè)6位的操作碼
31-6位是數(shù)字
5-0位是操作碼
例子:
匯編指令 call ROUTINE_3是典型的J-Type指令,它表示該指令執(zhí)行完畢后CPU將從ROUTINE_3開始的內(nèi)存地址讀取并執(zhí)行其他指令。若ROUTINE_3開頭指令的內(nèi)存地址是0x00002b3c,call的操作碼是000000,請(qǐng)問整條指令的二進(jìn)制編碼是?
解答:
16進(jìn)制數(shù)0x00002b3c = 0000 0000 0000 0000 0010 1011 0011 1101
call操作碼是000000
所以整個(gè)指令的編碼是00000000000000000010101100111101 000000
------------------------------ROUTINE_3--------------call--
還是32位!
4.再說些CPU的事情
讓我試著用圖片總結(jié)一下前面的基礎(chǔ)知識(shí)。。
上圖概括了CPU和計(jì)算機(jī)其他部分的互動(dòng)方式。該圖與實(shí)際的計(jì)算機(jī)有很大差距,but you get the idea...現(xiàn)在讓我們把注意力集中在CPU身上!
CPU只知道執(zhí)行指令,而指令是在內(nèi)存里的(實(shí)際上不一定,但是為了讓事情簡(jiǎn)單些,我們假設(shè)指令都是在內(nèi)存里的)。所以CPU需要從內(nèi)存里取出指令,這一步叫做提取(Fetch)。
CPU還需要知道這條指令是干什么的,所以被編碼過的指令會(huì)被傳到CPU的控制電路那邊解碼以正確設(shè)置控制信號(hào),這樣CPU才能正確執(zhí)行指令,這一步叫解碼(Decode)。
上面兩步完成后CPU就可以執(zhí)行該條指令了,也就是執(zhí)行(Execute)
運(yùn)算后的結(jié)果經(jīng)常需要保存,用來進(jìn)行下一個(gè)指令的運(yùn)算。那保存在哪里呢?無非就是寄存器組和內(nèi)存。這一步叫做寫回(Writeback)
CPU的結(jié)構(gòu)簡(jiǎn)圖(省略了到輸入/輸出設(shè)備的連接):
時(shí)鐘信號(hào)(Clock Signal)說白了其實(shí)就是一個(gè)頻率很高的方波,就像這樣:
它控制著CPU內(nèi)核的工作節(jié)奏,每當(dāng)時(shí)鐘信號(hào)由0變1(rising edge)的時(shí)候,CPU里面的元件就會(huì)做點(diǎn)什么。
數(shù)據(jù)通路(Datapath)是一個(gè)能夠執(zhí)行任何指令集內(nèi)的指令的電路,但是它需要控制電路告訴它應(yīng)該在什么時(shí)候執(zhí)行什么指令。數(shù)據(jù)通路包括了寄存器組,算術(shù)邏輯單元(Arithmetic logic unit, ALU)以及很多其他的元件。
控制電路負(fù)責(zé)解碼指令并且正確設(shè)置控制信號(hào),于是數(shù)據(jù)通路就能根據(jù)這些控制信號(hào)知道應(yīng)當(dāng)執(zhí)行哪一條指令。
----------------------------------------------------------------------------------------------------------
5. 好了,開始搭CPU吧 = =
如果讀者到目前為止都還能懂的話,那么恭喜!你終于有了足夠的基礎(chǔ)知識(shí)來搭建一個(gè)簡(jiǎn)單的CPU了。
當(dāng)然了,CPU這玩意不是說搭就搭的。我們的CPU能干些什么?能執(zhí)行些什么指令?指令是怎么編碼的?它由哪些小模塊組成?都有哪些控制信號(hào)?這些問題都必須有明確的回答。
從現(xiàn)在開始,我強(qiáng)烈建議讀者拿幾張空白的紙出來記下這些問題的回答,因?yàn)槲覀兗磳⒚鎸?duì)的是眾多的指令,模塊以及控制信號(hào)。這可比拼裝家具復(fù)雜多了,如果不記下來的話到時(shí)大概會(huì)頭暈?zāi)垦!?/span>
當(dāng)初LZ對(duì)這個(gè)CPU做一丁點(diǎn)兒小改動(dòng)的時(shí)候,可得對(duì)著一張電路圖,大大的控制信號(hào)表格以及超長的Verilog HDL代碼,花了不少時(shí)間和草稿紙呢
I will be back tomorrow or after 3 hours...~
--------------------------------------------------------------------------------------------------------------
我們的CPU能做什么?
從現(xiàn)在開始將進(jìn)入本文最復(fù)雜,最能繞暈人的部分,請(qǐng)做好準(zhǔn)備。。
下面要開始說明這個(gè)CPU的規(guī)格,信息量略大,推薦寫在紙上記著。
現(xiàn)在我們對(duì)下面的行**幾個(gè)簡(jiǎn)化約定(要是不簡(jiǎn)化的話,讀者就會(huì)看到一大堆密密麻麻的描述文字),請(qǐng)務(wù)必記好。
TMP = MEM[R2]
這個(gè)語句表示從寄存器R2指定的內(nèi)存地址讀取數(shù)據(jù),然后把讀到的數(shù)據(jù)賦值給TMP。
舉個(gè)例子:如果寄存器R2里的數(shù)字是0001 0011
而內(nèi)存地址0001 0011處所存的數(shù)據(jù)是1111 1111
那么這個(gè)語句就表示TMP被賦值1111 1111,TMP = 1111 1111
MEM[R2] = TMP
這個(gè)語句表示TMP的值被寫入內(nèi)存,寫入的位置是內(nèi)存地址R2。
舉個(gè)例子:如果TMP = 1111 1110,R2 = 0000 0001
那么這個(gè)語句就表示內(nèi)存地址0000 0001處的數(shù)據(jù)變成了1111 1110
R1 = TMP
這個(gè)語句表示寄存器R1寫入TMP的值
舉個(gè)例子:如果TMP = 0000 1111
那么這個(gè)語句表示寄存器R1里的數(shù)字變成了0000 1111
PC = PC + 1
幾乎每個(gè)指令都會(huì)帶有這個(gè)語句,意思是PC寄存器里的數(shù)字加1
PC寄存器中有指令所在的內(nèi)存地址。每執(zhí)行完一條指令后,這個(gè)內(nèi)存地址一般都會(huì)加1,好讓CPU調(diào)出下一條指令
-------------------------------------------------------------------------------------------------
前面說過,我們的CPU是8-bit的,也就是說它最多只能支持2^8=256個(gè)內(nèi)存地址。我們的CPU內(nèi)部將會(huì)有四個(gè)通用寄存器(General Purpose Register)R0~R3,一個(gè)PC寄存器(Program Counter Register),每個(gè)寄存器容量為8 bit。這個(gè)CPU不支持中斷,意味著它不接受鍵盤和鼠標(biāo)的輸入,只會(huì)從內(nèi)存里讀取并執(zhí)行指令。另外,CPU內(nèi)部還有兩個(gè)特殊的比特位,N和Z。如果某個(gè)運(yùn)算的結(jié)果是負(fù)數(shù),那么N就會(huì)被設(shè)定為1;如果某個(gè)運(yùn)算結(jié)果為零,那么Z就被設(shè)定為1。我們將會(huì)在跳轉(zhuǎn)指令里用到這兩個(gè)比特位。
該CPU可以執(zhí)行10種指令:
1. LOAD R1 (R2)
實(shí)現(xiàn)方法:
TMP = MEM[R2]
R1 = TMP
PC = PC + 1
這條指令是把內(nèi)存地址R2處的數(shù)據(jù)讀出來,然后放進(jìn)寄存器R1里。接著PC寄存器加一為下一條指令做準(zhǔn)備??闯鰜砹藛?#xff1f;下面將不再有這種文字描述,全部使用簡(jiǎn)寫。
2. STORE R1 (R2)
實(shí)現(xiàn)方法:
MEM[R2] = R1
PC = PC + 1
3. ADD R1 R2 [加法運(yùn)算]
實(shí)現(xiàn)方法:?
TMP = R1 + R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1
4. SUB R1 R2 [減法運(yùn)算]
實(shí)現(xiàn)方法:
TMP = R1 - R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1
5. NAND R1 R2 [NAND邏輯運(yùn)算]
實(shí)現(xiàn)方法:
TMP = R1 NAND R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1
6. ORI IMM5 [OR邏輯運(yùn)算]
實(shí)現(xiàn)方法:
TMP = R1 OR IMM5, IMM5是一個(gè)5-bit的二進(jìn)制數(shù)
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1
7. SHIFT L/R R1 IMM2 [移位運(yùn)算]
實(shí)現(xiàn)方法:
IF (L) THEN TMP = R1 << IMM2
ELSE TMP = R1 >> IMM2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1
8. BZ IMM4 [如果Z=1,就跳過IMM4個(gè)指令]
實(shí)現(xiàn)方法:
IF (Z == 1) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1
9. BNZ IMM4 [跟上一條指令相反]
實(shí)現(xiàn)方法:
IF (Z == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1
10. BPZ IMM4 [若N = 0,就跳過IMM4個(gè)指令]
實(shí)現(xiàn)方法:
IF (N == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1
這些描述都比較抽象,做拼裝的時(shí)候這些東西應(yīng)該會(huì)表現(xiàn)得更具體些。
---------------------------------------------------------------------------------------------------
CPU的指令編碼
前5個(gè)指令的編碼方式都是:
7-6位是寄存器R1的編號(hào)
5-4位是寄存器R2的編號(hào)
3-0位是操作碼
ORI指令的編碼
SHIFT指令的編碼
三個(gè)跳轉(zhuǎn)指令的編碼
--------------------------------------------------------------------------------------------------------------------------
數(shù)據(jù)通路的設(shè)計(jì)
這個(gè)CPU的數(shù)據(jù)通路將由以下部件組成:
寄存器
data in ---------- 寫入寄存器數(shù)據(jù),8條線,因?yàn)槭?/span>8-bit的
data out ---------- 輸出寄存器的數(shù)據(jù),8條線,因?yàn)槭?/span>8-bit的
控制信號(hào)write ---------- 是否允許寫入數(shù)據(jù)。是的話write = 1, 否則 write = 0
clock ---------- 時(shí)鐘信號(hào)
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
數(shù)據(jù)選擇器
相信諸位都應(yīng)該知道這玩意怎么工作的吧?當(dāng)然輸入輸出都是8條線
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
通用寄存器組
通用寄存器R0-R3都在這里面。
reg1,reg2 ----------說明指令里涉及哪兩個(gè)寄存器
regw ---------- 指明要往哪個(gè)寄存器里寫數(shù)據(jù)(應(yīng)該是2條線,沒畫出來)
data0 ---------- 從reg1指定的寄存器中輸出數(shù)據(jù)
data1 ---------- 從reg2指定的寄存器中輸出數(shù)據(jù)
dataw ---------- 實(shí)際寫入寄存器的數(shù)據(jù)從這里進(jìn)去(應(yīng)該是8條線,沒畫出來)
控制信號(hào)write ---------- 是否允許寫入數(shù)據(jù)?是的話write = 1,否則write = 0
clock ---------- 時(shí)鐘信號(hào)
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
算術(shù)邏輯單元(ALU)
這個(gè)模塊就是CPU做運(yùn)算的地方了。它能實(shí)現(xiàn)加減法,NAND和OR運(yùn)算,以及移位運(yùn)算。
In0,In1 ---------- 輸入
控制信號(hào)ALUop ---------- 告訴ALU應(yīng)該做哪個(gè)運(yùn)算
Z,N ---------- 前面提過的特殊比特位,ALU要負(fù)責(zé)根據(jù)運(yùn)算結(jié)果設(shè)置Z和N
OUT ---------- 運(yùn)算結(jié)果輸出
-----------------------------------------------------------------------------------------------------------------
繼續(xù)說CPU組件。。。
指令內(nèi)存
addr ---------- 指定從哪個(gè)內(nèi)存地址讀取指令
Out ---------- 從內(nèi)存里輸出的指令在這里去往CPU
控制信號(hào)Read ---------- 是否允許讀取指令?是的話Read = 1, 否則 Read = 0
我們假設(shè)指令內(nèi)存是只讀(Read Only)的
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
數(shù)據(jù)內(nèi)存
addr ---------- 指定從哪個(gè)內(nèi)存地址讀取數(shù)據(jù)
Din ---------- 往內(nèi)存里寫的數(shù)據(jù)從這里進(jìn)去
Dout ---------- 從內(nèi)存里讀取的數(shù)據(jù)從這里出去
Clock ---------- 時(shí)鐘信號(hào)
控制信號(hào)MemWrite ---------- 是否允許數(shù)據(jù)寫入內(nèi)存?是的話MemWrite = 1, 否則為0
控制信號(hào)MemRead ---------- 是否允許讀取?是的話MemRead = 1,否則為0
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
現(xiàn)在我們要用上面的模塊去組裝CPU的數(shù)據(jù)通路。
首先,無論執(zhí)行的是哪一條指令,CPU都必須先從內(nèi)存里把指令調(diào)出來,前面說過這一步叫做提取。此步驟由下圖的電路執(zhí)行。
這個(gè)電路由一個(gè)PC寄存器(Program Counter Register)和指令內(nèi)存組成。PC寄存器里儲(chǔ)存的是該條指令所在的內(nèi)存地址,然后指令內(nèi)存會(huì)根據(jù)PC寄存器指定的地址向CPU輸出相應(yīng)的指令??刂菩盘?hào)PCWrite決定是否允許更改PC寄存器里的數(shù)字,如果允許那么PCWrite = 1, 否則為0
-------------------------------------------------------------------------------------------------
能執(zhí)行加法指令的電路
前面說過加法指令ADD R1 R2的編碼形式如下
該指令會(huì)把寄存器R1和R2里的數(shù)字加起來,然后把結(jié)果寫回R1。
INST線的3-0位是操作碼,會(huì)被送到控制電路那邊解碼。解碼后控制電路會(huì)設(shè)置好各個(gè)控制信號(hào)使得CPU的數(shù)據(jù)通路執(zhí)行加法運(yùn)算。我們以后再詳細(xì)說說控制電路的事情,現(xiàn)在讓我們來看看在數(shù)據(jù)通路里,INST線7-4位是如何使用的。
上圖是一個(gè)可以執(zhí)行加法指令的電路(圖里的數(shù)字有點(diǎn)小錯(cuò)誤,不要在意)
INST 7-6位代表R1的編號(hào),作為通用寄存器組的reg1和regw輸入
INST 5-4位代表R2的編號(hào),作為reg2的輸入
然后R1和R2里的數(shù)據(jù)從data0,data1輸出,送到ALU做加法運(yùn)算(ALUop會(huì)告訴ALU做加法運(yùn)算)
TMP = R1 + R2完成
然后加法運(yùn)算的結(jié)果被送到寄存器組的dataw輸入。這時(shí)RFWrite = 1。由于此時(shí)regw指定的寄存器編號(hào)是R1,所以加法運(yùn)算的結(jié)果就被寫回了寄存器R1
R1 = TMP完成
此外,ALU還會(huì)把N和Z這兩個(gè)特殊的比特位根據(jù)運(yùn)算結(jié)果設(shè)置好
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;完成
這條指令還沒完,我們需要把PC寄存器里的數(shù)字加一,這樣CPU才能取得下一條指令。因此還得加點(diǎn)東西。
有了上面那個(gè)電路之后
PC = PC + 1就可以完成了
同樣的電路也可以用作執(zhí)行SUB和NAND指令。唯一不同的是控制信號(hào)ALUop會(huì)讓ALU做減法或者NAND運(yùn)算。
-----------------------------------------------------------------------------------------
執(zhí)行ORI指令的電路
ORI IMM5的編碼
這個(gè)指令會(huì)把寄存器R1里的數(shù)字與一個(gè)5-bit的二進(jìn)制數(shù)做OR運(yùn)算,然后把結(jié)果寫回R1
要實(shí)現(xiàn)這個(gè)指令只需把上面的電路稍作更改即可
可以看到這個(gè)電路增加了兩個(gè)數(shù)據(jù)選擇器(圖中的reg0,reg1應(yīng)分別為reg1,reg2)
首先,因?yàn)?/span>ORI指令總是在寄存器R1上進(jìn)行操作,不像ADD,SUB,NAND等其他指令需要指定在哪些寄存器上進(jìn)行操作,所以我們加入一個(gè)控制信號(hào)為R1Sel的選擇器。
當(dāng)執(zhí)行ORI指令時(shí),R1Sel = 1,這樣reg1的輸入在執(zhí)行ORI指令時(shí)總會(huì)是01
所以data0輸出也總是會(huì)輸出R1的數(shù)據(jù)到ALU
這時(shí),ALU的另外一個(gè)輸入應(yīng)當(dāng)是指令里的IMM5,而不是從寄存器組那邊過來的輸入
于是我們加入另一個(gè)控制信號(hào)為ALU2的選擇器,這樣我們就可以選擇是從寄存器組還是從INST線那邊輸入ALU數(shù)據(jù)。
當(dāng)執(zhí)行ORI指令時(shí),ALU2 = 1,這樣ALU就會(huì)把INST 7-3位的5-bit二進(jìn)制數(shù)作為輸入
然后控制信號(hào)ALUop告訴ALU進(jìn)行OR運(yùn)算
TMP = R1 OR IMM5完成
結(jié)果寫回R1
R1 = TMP完成
ALU根據(jù)運(yùn)算結(jié)果設(shè)置N和Z
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;完成
PC寄存器加一,CPU為下一條指令做好準(zhǔn)備
PC = PC + 1完成
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
能執(zhí)行內(nèi)存讀取以及SHIFT指令的電路
LOAD R1 (R2)
STORE R1 (R2)
由于這兩條指令里的R2部分總是作為地址使用,所以寄存器R2的輸出要連到數(shù)據(jù)內(nèi)存的addr輸入;而R1在STORE指令中是作為數(shù)據(jù)源的寄存器使用的,所以連接到Datain輸入。R1在LOAD指令中是作為放內(nèi)存讀出數(shù)據(jù)的寄存器使用的,所以連回到寄存器組的dataw輸入。中間加了一個(gè)RFin選擇器,這樣寄存器組就可以選擇是從ALU還是從數(shù)據(jù)內(nèi)存那邊寫入數(shù)據(jù)。
現(xiàn)在我們要把數(shù)據(jù)內(nèi)存加入我們的電路里,如下圖:
最后我們還把ALU2選擇器擴(kuò)展了一下,使得執(zhí)行SHIFT指令時(shí)ALU能夠選擇從INST線讀到運(yùn)算需要的數(shù)據(jù)(圖中的INST 5-2應(yīng)當(dāng)為INST 4-3,因?yàn)?/span>SHIFT指令的IMM2在指令編碼的4-3位)。
然后這個(gè)CPU的數(shù)據(jù)通路就基本完成了!!
轉(zhuǎn)載于:https://www.cnblogs.com/Chary/p/No0000166.html
總結(jié)
以上是生活随笔為你收集整理的[No0000166]CPU的组成结构及其原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天猫首页迷思之-jquery实现左侧广告
- 下一篇: android 5.0 下载编译