標(biāo)題: 繼電器是如何成為CPU的—《穿越計算機的迷霧》整理和總結(jié) [打印本頁]

作者: 51黑fan    時間: 2016-1-30 01:22
標(biāo)題: 繼電器是如何成為CPU的—《穿越計算機的迷霧》整理和總結(jié)
——《穿越計算機的迷霧》整理和總結(jié)
究竟是如何設(shè)計的電路,具有計算和控制的智力?
這一點也不高深。本系列文章從初中學(xué)的最簡單的電路圖說起,看看能不能從最初的有一個繼電器的電路,畫到一個簡單的CPU。電路圖用multisim12.0繪制,這樣就可以看到效果了。
(注:雖然現(xiàn)代計算機是用半導(dǎo)體材料制作芯片的,但是電路原理和繼電器材料沒有不同。本人愚鈍,只理解了繼電器,還沒有研究電子管、晶體管這些器件的工作原理。而繼電器原理簡單,用作講解數(shù)字電路原理再好不過。)
PS:需要本文的multisim12電路圖文件的話,麻煩點個贊并留下你的Email~

從電池、開關(guān)和繼電器開始
上圖左上角是一個很普通的電路,由電池、開關(guān)電流表和燈泡組成。這個是初中物理學(xué)過的。
上圖右上角是對左上角電路的簡單變形,用VCC代替了電池,用接地符號實現(xiàn)了回路。相當(dāng)于把電池拆開來畫了。電路功能是一樣的。本文此后的電路圖一般都采用VCC和接地表示電源。因為你會發(fā)現(xiàn)只有這樣的畫法能夠讓我們方便理解之后的電路圖。
然后往下看,第三個電路圖,那個圈圈里圈著個K的藍(lán)色的東西,表示的是繼電器。當(dāng)繼電器左側(cè)有電流通過時,右側(cè)的電路就斷開;反之則聯(lián)通。(對應(yīng)地,也有那種左側(cè)有電流通過時,右側(cè)的電路就聯(lián)通;反之則斷開的繼電器,稍后會用到)這個電路想讓你知道的是,可以用繼電器實現(xiàn)這樣的功能:控制左側(cè)的電路的通斷,即可改變右側(cè)電路的通斷。換個方式說,就是左側(cè)的電路通斷情況決定了右側(cè)的電路的通斷情況。再往抽象了說,就是左側(cè)電路代表了"輸入"(Input)這個概念,右側(cè)電路代表了"輸出"(Output)這個概念。繼電器則代表了"計算"(或者"算法"、"處理"等)(CPU)這個概念。硬件就是用這種電器設(shè)備的固有物理性質(zhì)提供了最初的計算能力。
再往下看第四個電路圖,它和第三個的區(qū)別就在于用VCC和接地符號代替了電池。初次看電路,我們有必要經(jīng)歷一次從電池到VCC和接地符號的過渡。以后的電路圖,我們將直接使用VCC和接地符號,請務(wù)必在此處適應(yīng)這樣的畫法。
然后是最下邊這個電路。和第四個電路相比,它用一個"非門"的符號代替了"繼電器、右側(cè)電路電源和繼電器的接地"這三個符號。也就是說一個"非門"實際上就是"繼電器、右側(cè)電路電源和繼電器的接地"這三個東西的組合,而且畫的時候省略了電源和接地符號
之前在學(xué)校里學(xué)數(shù)字電路,我就是想不明白邏輯門的電源在哪兒,整個電路的通路在哪兒,所以一直學(xué)不好,F(xiàn)在有個這個電路圖,感覺一切豁然開朗。

用繼電器做個與門剛剛我們用繼電器做出了"非門"?梢钥吹街灰靡粋繼電器就可以了。與門的電路如下圖所示。
與門由兩個繼電器(這兩個繼電器用的都是跟做非門的繼電器通斷情形相反的那種)構(gòu)成,只有當(dāng)兩個繼電器左側(cè)都通電時,右側(cè)電路才能聯(lián)通。這樣就實現(xiàn)了"與"的功能。"與門"的符號是一個躺著封口的U形。
注:本文里我做的電路圖片都是GIF格式的,你可以在瀏覽器里看到隨著開關(guān)的開閉,輸入和輸出電路上的燈泡是如何變化的。每個圖上都有(bitzhuwei*cnblogs*com)標(biāo)識我的博客地址,不過每個GIF圖的最后一幀都去掉了這個標(biāo)識。這樣,看到一幀沒有標(biāo)識的時候,就知道下一幀將是GIF圖的第一幀了。

用繼電器做個或門"非門"、"與門"做出來了,"或門"也就不難理解了,直接上圖大家體會吧。(導(dǎo)線交叉的地方,如果有個紅點,表示是聯(lián)通的,否則就是互不相干的)"或門"的符號像一個子彈。

用繼電器做個異或門"異或門"的功能是:左側(cè)的兩個輸入電路一個聯(lián)通另一個不聯(lián)通時,右側(cè)電路聯(lián)通;否則右側(cè)電路不聯(lián)通。這次先畫符號,大家可以先自己嘗試用繼電器畫"異或門",鍛煉一下思維,然后再向下看答案。
答案揭曉!"異或門"的實現(xiàn)如下圖所示。乍看很復(fù)雜,其實是有邏輯的。最右邊的兩個繼電器其實是一個"或門",最左邊兩個繼電器是兩個"非門",中間兩上兩下共四個繼電器,是兩個"與門"。這樣就好理解了。AB兩個輸入電路為A通、B不通的時候,整個"異或門"會通過下方的路線使燈泡亮;若A不通、B通,則會通過上方的線路使燈泡亮。其他情況燈泡都不會亮。


做一些看起來可用的東西與或非異或邏輯門電路雖然重要,卻離構(gòu)造CPU相距較遠(yuǎn),做出來似乎也沒什么成就感。那么我們用這些過于基礎(chǔ)的器件,做一些有用的東西吧!

小小約定為了表達(dá)方便,我們約定一下,邏輯門電路的輸入(輸出)線上有電流的時候,我們說輸入為1(輸出為1),否則就說輸入為0(輸出為0)。

振蕩器振蕩器能夠不斷地輸出0、1、0、1、0、1、0、1……這樣的信號。這種東西雖然一時說不上有什么用,不過一定是有用到的時候的。振蕩器做起來也簡單得離譜?聪聢D所示電路。
把非門的輸出端連到輸入端上。當(dāng)輸出為1時,輸入也就成了1,那么輸出就得變成0;然后輸入也跟著變成0,這樣輸出又變回了1。循環(huán)翻轉(zhuǎn)無休無止。振蕩器能翻轉(zhuǎn)多快,就看繼電器的反應(yīng)有多快了。(現(xiàn)代計算機用晶體管代替了繼電器,晶體管比繼電器翻轉(zhuǎn)速度快得多,所以能夠得到的頻率更高,計算機的速度更快。而且晶體管比繼電器省電)話說multisim12仿真的翻轉(zhuǎn)速度也夠可以的,本人截圖也費了不少勁。
順便給一個用繼電器做振蕩器的實際應(yīng)用的例子:上學(xué)的時候上下課的鈴聲就是用繼電器做的振蕩器完成的。0101信號用錘子敲打鐵盔表達(dá)了出來。

加法器剛剛約定了,用1和0表示電路的通斷。電路只有通斷這兩種狀態(tài),所以計算機只用0和1來表示數(shù),這就是二進(jìn)制啊。關(guān)于二進(jìn)制和十進(jìn)制的內(nèi)容別人寫得太多了,我就不提啦。要計算兩個多位二進(jìn)制數(shù)的和,可以分別計算各個數(shù)位上的結(jié)果,而各個數(shù)位的計算方法又是相同的,即"被加數(shù)+加數(shù)=>和的值+進(jìn)位的值"。這用邏輯門表示如下圖。
A和B表示加數(shù)和被加數(shù),C表示前一位計算的進(jìn)位的值,C1燈泡表示本次計算的進(jìn)位的值,S1燈泡表示本次計算的和的值。我找了半天,也沒在multisim12里找到一位二進(jìn)制數(shù)的加法器件的符號,大家看這個圖就可以了。
要計算多位數(shù),把單位數(shù)加法器首尾相連就可以了,如下圖所示。這兩張圖是從《穿越計算機的迷霧》中拿來的。如果侵權(quán),請告訴我,不然我就偷個懶不自己畫啦。

寄存器學(xué)匯編的時候聽過這個東西,"寄存"這個詞讓我感覺寄人籬下可憐巴巴的。寄存器的功能是把數(shù)據(jù)(約定里說的0和1,實際就是電路的通斷狀態(tài))保存下來,以后還可以取出來用。寄存器這東西比之前的器件都復(fù)雜,需要一步一步來做。

R-S觸發(fā)器先看下面這個電路,這是各種有存儲功能的器件的基礎(chǔ)。
上圖展示的是在R和S開關(guān)都斷開的情況下啟動電路得到的結(jié)果!洞┰接嬎銠C的迷霧》里說這種情況下,哪個燈泡亮是不一定的,就看哪個邏輯門轉(zhuǎn)的快了。不過我用multisim12仿真的時候,兩個燈泡是在忽亮忽滅不停地閃。這可以說是非正常人類使用R-S觸發(fā)器的情況。下面再看看正常人類使用R-S觸發(fā)器的情況。
R-S觸發(fā)器的R是Reset,意思是把Q燈泡重置為0,S是Set,意思是把Q燈泡置為1?梢钥吹剑婚]合S,則Q亮NQ不亮;只閉合R,則Q不亮NQ亮;同時閉合RS,則Q和NQ都不亮;同時斷開RS,則Q和NQ保持剛才的狀態(tài)不變。

D觸發(fā)器既然要保存數(shù)據(jù),我們就要求只在希望保存某個數(shù)據(jù)的時候存進(jìn)去,否則就不理他。所以我們給R-S觸發(fā)器加一個新的輸入作為控制端,只有控制端為1的時候才能保存新來的數(shù)據(jù)。這里也把RS端合并為一個D端,用一個非門實現(xiàn)了只能使R和S有且只有一個開關(guān)是閉合的(即要么Q燈泡變?yōu)?要么Q燈泡變?yōu)?)。
D觸發(fā)器的符號我也沒在multisim里找到,大家看這個吧。

上升沿D觸發(fā)器我們只希望在某一瞬間把數(shù)據(jù)存起來,而不是像D觸發(fā)器那樣,控制端為1的整個時間端都會保存新數(shù)據(jù)。(這樣最安全)于是我們在D觸發(fā)器基礎(chǔ)上設(shè)計了上升沿D觸發(fā)器。這個觸發(fā)器只在控制端從0變?yōu)?的瞬間存儲新數(shù)據(jù)。是不是很奇妙的設(shè)計?
上升沿D觸發(fā)器使用了兩個D觸發(fā)器,再加一個非門,就OK了。平時,我們把要存儲的數(shù)據(jù)(D開關(guān))放好。然后,當(dāng)控制端CP為斷開時,圖中上面那個D觸發(fā)器是能夠存數(shù)據(jù)的,但是下面那個存不了。就是說新數(shù)據(jù)已經(jīng)到了兩個D觸發(fā)器之間的導(dǎo)線上。在控制端CP閉合的瞬間,上面的D觸發(fā)器無法再存新數(shù)據(jù)了,而下面的D觸發(fā)器可以存新數(shù)據(jù)了,那么它存的是哪個新數(shù)據(jù)?只能是剛剛在兩個D觸發(fā)器之間的導(dǎo)線上的數(shù)據(jù)了。這個瞬間之后,新數(shù)據(jù)無法通過上面的D觸發(fā)器,自然也就無法保存了。
這次我終于在multisim12里找到了上升沿D觸發(fā)器的符號。

乒乓觸發(fā)器這是個有點類似振蕩器的器件。兩者的區(qū)別在于,振蕩器是自動地改變輸出,乒乓觸發(fā)器是在輸入一個上升沿的時候改變輸出。電路圖如下所示。
可以看出,乒乓觸發(fā)器其實就是把上升沿D觸發(fā)器的非Q輸出端接到了輸入端。很顯然每次存的新數(shù)據(jù)總是和輸出信號相反。
乒乓觸發(fā)器可以用來做計數(shù)器。計數(shù)器有這樣的功能:每收到一個上升沿的信號,就增加1。例如下圖所示的能統(tǒng)計二進(jìn)制的00000到11111(即0到31)這32個數(shù)。計數(shù)器的每一位計數(shù)器件都是一個乒乓觸發(fā)器。燈泡亮表示1,燈泡滅表示0。

走馬燈利用上升沿D觸發(fā)器還可以做"走馬燈"。走馬燈是每次都讓前面一個燈泡亮的設(shè)備,最后一個燈泡亮過之后,又從第一個燈泡開始亮,循環(huán)往復(fù)。下圖所示電路就是一個有5個燈泡循環(huán)走馬的走馬燈。為了在電路剛接通的時候讓第一個燈亮起來,我加了兩個開關(guān)S1和S2,大家可以分析一下怎么用S1和S2。這有助于加深體會上升沿D觸發(fā)器的功能,并加速對更復(fù)雜器件的理解。

寄存器終于到這個小玩意了!
能保存5位二進(jìn)制數(shù)的寄存器如下圖所示。其實就是5個上升沿D觸發(fā)器并列起來而已。
想保存數(shù)據(jù)的時候,調(diào)整好D0、D1、D2、D3、D4五個開關(guān)(實際應(yīng)用的時候就可能是其他電路的輸出導(dǎo)線了),然后斷開再閉合一下控制端的開關(guān)S5即可,數(shù)據(jù)就保存到了5個上升沿D觸發(fā)器的Q端。
我這里只畫了保存5位數(shù)的寄存器,是因為再畫就太大了,在word里圖就看不清楚了。我們知道現(xiàn)在計算機的寄存器已經(jīng)到32位或者64位了。那就是有32或64個并列的上升沿D觸發(fā)器組成一個寄存器。我們也看到了一個上升沿D觸發(fā)器需要幾十個繼電器(晶體管),那么一個寄存器就需要上千個繼電器(晶體管)了。而CPU里包含的寄存器、加法器等運算器還有各種控制器,其包含的繼電器(晶體管)數(shù)目上百萬也就很好理解了。內(nèi)存條里的內(nèi)存也是用上升沿D觸發(fā)器和一個門電路組成存儲一位(一個bit,8個bit是一個字節(jié))的存儲結(jié)構(gòu)的,其包含的繼電器(晶體管)數(shù)目可想而知有多少。


中場休息到這里,做CPU需要的基礎(chǔ)器件就差不多全了。不過再寫下去就太長了,不利于理解和記憶。因此暫且中場休息,下一篇再繼續(xù)介紹如何構(gòu)造一個簡單的CPU。
前面介紹的各自器件,可以用下表描述其繼承關(guān)系。(索性把下一篇文章要介紹的器件也列出來了)
繼電器








非門電路







與門電路







或門電路







異或門電路






振蕩器







加法器







寄存器








R-S
D
D↑
乒乓
計數(shù)器






走馬燈







寄存器
多個數(shù)的加法器






存儲器
多bit存儲器
多字存儲器
有地址譯碼器的存儲器
控制器








手動







半自動







全自動









自言自語自大學(xué)始,學(xué)軟件工程至今已有7年。一共找到這么幾本好書:《穿越計算機的迷霧》、《Orange'S OS:一個操作系統(tǒng)的實現(xiàn)》、《CLR via C#》。
讀《穿》就是為了弄明白一個問題:為什么計算機能夠計算?《穿》在下面這張圖中讓我明白了我一直想不明白的問題。
讀《Orange》也是為了弄明白一個問題:進(jìn)程到底是什么?
讀《CLR via C#》還是為了弄明白一個問題:.NET虛擬機里都有什么?
想知道的東西還有很多,抓緊一切機會去求索~


上一篇已經(jīng)從電池、開關(guān)、燈泡和繼電器開始,畫出了設(shè)計CPU所需的基本器件。這些器件將成為設(shè)計CPU的磚瓦木料。這一篇就用這些基本器件做一個CPU的雛形。

本篇所需基礎(chǔ)器件
傳輸門下圖所示的傳輸門的作用是:當(dāng)左邊的"~1G"端輸入為0時,左側(cè)的1A41A3、1A2、1A1會直接傳輸?shù)接覀?cè)對應(yīng)的1Y*,就像一條線直接1A*連接到1Y*一樣;當(dāng)左邊的"~1G"端輸入為1時,左側(cè)的1A4、1A3、1A2、1A1都不能傳輸?shù)接覀?cè)對應(yīng)的1Y*,就像從1A*1Y*的連線被剪斷了一樣。
注:本文里我做的電路圖片都是GIF格式的,你可以在瀏覽器里看到隨著開關(guān)的開閉,輸入和輸出電路上的燈泡是如何變化的。每個圖上都有(bitzhuwei*cnblogs*com)標(biāo)識我的博客地址,不過每個GIF圖的最后一幀都去掉了這個標(biāo)識。這樣,看到一幀沒有標(biāo)識的時候,就知道下一幀將是GIF圖的第一幀了。
傳輸門的原理很簡單,就是在每個1A*1Y*之間的連線上放個繼電器而已,如下圖所示。(取自《穿》)


寄存器在上一篇已經(jīng)說明了寄存器的原理,這里僅僅是為了說明"74LS194"這個帶有各種無聊管腳的四位寄存器的用法。將"~CLR"、"S1"和"S0"置為1,"SR"和"SL"置為0,然后,"74LS194"就是一個簡單的四位寄存器了。(本人在multisim12.0里只找到了這個靠譜的四位寄存器,湊合用吧。)


數(shù)值顯示器為了更直觀地看到CPU的運算結(jié)果,我們將使用"DCD_HEX"這個東西。它能夠把輸入的"0101"顯示為"5",把"1010"顯示為"A"。
本文還要用一個四位的加法器,直接在下面這個簡陋的CPU里看就好了,不再單獨展示。

一個簡陋的CPU現(xiàn)在一切就緒,可以開始設(shè)計CPU了!
CPU包括運算器和控制器兩部分。我們首先做出運算器,然后逐步實現(xiàn)控制器,最后感受一下用機器語言編程的過程。本文實現(xiàn)的CPU雖然功能及其簡陋,但是能夠傳達(dá)出當(dāng)前真實CPU的原理。

運算器和手動控制器現(xiàn)在我們要做的這個CPU,字長是4位,只能做兩個數(shù)的加法。實現(xiàn)了運算器和手動版的控制器的CPU如下圖所示。我們把這個版本稱為version1的CPU。
上圖中,"Add"是加法器,能執(zhí)行兩個4位數(shù)的加法運算。"RA"和"TR"是寄存器,"GAA"和"GBA"是傳輸門。"4""3""2""1"用來準(zhǔn)備需要相加的數(shù)據(jù)(0到15),"KTR""KRA""KGA""KGB"是用來控制傳輸門通斷和寄存器脈沖的開關(guān)。
在上圖所示的GIF動畫中,顯示了"5+1+2+4"這個過程。這個過程可以分為4個步驟:①加載一個數(shù)值(Load);②加上一個數(shù)值(Add);③加上一個數(shù)值(Add);④加上一個數(shù)值(Add)。具體來說,每一個步驟要做的事情是:
指令
內(nèi)容
加載一個數(shù)(Load)
準(zhǔn)備數(shù)據(jù)(0101); KGB↓, KGA↑; KRA↓↑
加一個數(shù)(Add)
準(zhǔn)備數(shù)據(jù)(0001); KGB↓, KGA↑; KTR↓↑; KGA↓, KGB↑; KRA↓↑
加一個數(shù)(Add)
準(zhǔn)備數(shù)據(jù)(0002); KGB↓, KGA↑; KTR↓↑; KGA↓, KGB↑; KRA↓↑
加一個數(shù)(Add)
準(zhǔn)備數(shù)據(jù)(0004); KGB↓, KGA↑; KTR↓↑; KGA↓, KGB↑; KRA↓↑

你可以看到,每次執(zhí)行(Add)這一步,要做的事情(搬動開關(guān))是一樣的,規(guī)律性極強。這意味著可以用簡化的方式控制"KTR""KRA""KGA""KGB"這幾個開關(guān)的狀態(tài)。經(jīng)過簡化的CPU就有一定的自動化控制的性質(zhì)了,如下圖所示。我們把這個版本的CPU稱為version2的CPU。
Verison2要比剛才的verison1進(jìn)化了一些。為便于理解,我們保留原來的"KTR""KRA""KGA""KGB"這四個開關(guān)(把它們挪到了右上角,因為實在沒地方放了),但讓它們永遠(yuǎn)保持閉合的狀態(tài)。這是想說明:version2里新增的電路只是實現(xiàn)了更加自動化地控制"KTR""KRA""KGA""KGB"的開閉,它沒有改變version1中電路的工作流程。
Version2中的"KLoad"和"KAdd"開關(guān)分別代表了"Load"和"Add"這兩個指令。當(dāng)"KLoad"閉合時,表示CPU要進(jìn)行加載操作,這會把"4""3""2""1"上的數(shù)據(jù)存入寄存器"RA";當(dāng)"KAdd"閉合時,表示CPU要進(jìn)行相加操作,這會把"4""3""2""1"上的數(shù)據(jù)與"RA"當(dāng)前的數(shù)據(jù)相加,然后相加的結(jié)果又存儲到"RA"。
Version2中的"K0"和"K1"兩個開關(guān)會依次的開閉,即兩者總有一個是斷開且另一個是閉合的(若出現(xiàn)其它情況那就是電路設(shè)計錯了)。所以實際上"K0"和"K1"可以用一個"2位循環(huán)移位寄存器"代替。(為便于理解,仍然保留"K0"和"K1"這兩個開關(guān),只不過讓它們永遠(yuǎn)保持閉合的狀態(tài))
Version2中,只需重復(fù)"準(zhǔn)備指令,準(zhǔn)備數(shù)據(jù),執(zhí)行指令(K↓↑↓↑)"這樣的操作,就能完成version1中的控制功能。這需要一個從"KLoad""KAdd""K0""K1"到"KTR""KRA""KGA""KGB"的轉(zhuǎn)換電路,即version2電路圖中的上半部分,如下圖所示。
這需要一點點設(shè)計邏輯電路的知識,本文直接列出真值表,據(jù)此即可畫出轉(zhuǎn)換電路。(想知道如何推導(dǎo)的話,請查閱《穿》或者數(shù)字電路類書籍)
Kload
Kadd
K0
K1
KGA
KRA
KTR
KGB
1
0
1
0
1
1
0
0
0
1
1
0
1
0
1
0
0
1
0
1
0
1
0
1

其中"KLoad""KAdd""K0""K1"為輸入,"KTR""KRA""KGA""KGB"為輸出。只有如上三種輸入情況下,輸出部分會有1;其它的輸入情況下,輸出全部為0,所以就不需要列出來了。
舉個例子,"KGA"="KLoad""~KAdd""K0""~K1" + "~KLoad""KAdd""K0""~K1"=("KLoad" "KAdd")"K0""~K1",據(jù)此可以畫出"KGA"的轉(zhuǎn)換電路。
在version2中,CPU要做的就是重復(fù)"準(zhǔn)備指令,準(zhǔn)備數(shù)據(jù),執(zhí)行指令(K↓↑↓↑)"這件事。其中執(zhí)行指令這一步是完全重復(fù)完全自動化的(只要用振蕩器替換K就可以),而準(zhǔn)備指令和準(zhǔn)備數(shù)據(jù)還需要手工操作。每次要執(zhí)行哪個指令、要準(zhǔn)備的數(shù)據(jù)是多少,這都是沒有規(guī)律的,可改進(jìn)的方法就是:把指令和數(shù)據(jù)按順序保存到一些特別的寄存器里,需要的時候取出來用。這些特別的寄存器,就是內(nèi)存。

內(nèi)存所謂飯前便后要洗手,一個完整的衛(wèi)生間,除了有若干坑位,還得有洗手池配套。類似的,學(xué)習(xí)CPU的結(jié)構(gòu)原理,也得把"內(nèi)存"牽出來溜溜,否則無法說明計算機編程的本質(zhì)。CPU+內(nèi)存才是一個完整的計算機(核心),才能展現(xiàn)出CPU的功能。由此也能聯(lián)系到,將鼠標(biāo)鍵盤顯示器等稱為"外部"設(shè)備的道理。
最基本的內(nèi)存單元能夠存儲和讀寫一個位(bit),是由一個上升沿D觸發(fā)器和傳輸門組成,如下圖所示。傳輸門電路我沒有找到只有一位的,拿這個四位GAA的湊合看吧。
內(nèi)存單元的符號如下圖所示。(取自《穿》)
把8個bit單元的讀寫端分別連起來,就可以存儲一個字節(jié)(8bit)。下圖是能夠存儲5bit的內(nèi)存單元。(取自《穿》)此圖所示的結(jié)構(gòu),我們稱之為"一層"。
存儲4bit的一層的符號如下圖所示。這時我學(xué)會了multisim12里的"層次塊"這個東西,下圖就是用層次塊畫的,這樣可以將復(fù)雜的電路封裝起來,省地方了,還能復(fù)用。所以說模塊化的思想在硬件設(shè)計里就有了。("用層次塊替換…"和VS里的"Extract Method…"功能是何其類似。
用一層一層的內(nèi)存單元,即可構(gòu)成存儲器。對于有8層的存儲器,需要3個bit表示需要讀寫的層數(shù)(23=8)。地址譯碼器的作用是:輸入101時,輸出的第5個(從0開始計數(shù))引腳為1,其余均為0。有了地址譯碼器,存儲器對外只需很少的地址線(例如10根)即可使用很多層(例如1024層)。這也符合了軟件設(shè)計中接口盡可能簡單的原則。本文所用的RAM存儲器的結(jié)構(gòu)如下圖所示。其中左邊的"3-8translator"就是譯碼器。
其層次塊符號如下圖所示。
這個RAM有三條地址線(Addr3Addr2Addr1),能夠表示23=8個字(層),每個字的長度是4bit。這個小小的RAM剛好夠存儲(5+1+2+4)這個示例的指令和數(shù)據(jù),下面就用這個RAM繼續(xù)進(jìn)化CPU。
這里也順便把"3-8translator"譯碼器的電路實現(xiàn)貼出來吧,如下圖所示。


9位循環(huán)移位寄存器在version2里用的"2位循環(huán)移動寄存器"只需要一個乒乓觸發(fā)器(詳見上一篇)就可以了,但是后面要做的全自動控制器,需要一個"9位循環(huán)移位寄存器",且這個寄存器要在加電時自動將第一個輸出管腳置為1,其余為0。具有這樣的功能的寄存器如下圖所示。
如上圖所示,第二行有4個D↑觸發(fā)器,其中最左邊的那個負(fù)責(zé)第一個輸出管腳,即應(yīng)該在加電時就置為1的那個管腳。這是通過左下方的電路實現(xiàn)的,其原理大家自己琢磨吧,無非是利用反饋電路實現(xiàn)了只生效一次這個功能而已。"9位循環(huán)移位寄存器"的符號如下圖所示,其中"D0"是第一個輸出管腳。
還有一個3bit的計數(shù)器,在上一篇里已經(jīng)提過計數(shù)器,這里直接上圖。
其層次塊表示如下圖所示。


自動控制器有了內(nèi)存,我們就要把指令和數(shù)據(jù)存進(jìn)去。存儲數(shù)據(jù)很好理解,是多少就寫入多少。存指令之前,我們需要為每條指令分配一個4位的編碼,比如0000表示Load,1111表示Add,然后用這個指令碼控制"KLoad"和"KAdd"的開閉,所以這又是一個轉(zhuǎn)換電路。有了這個轉(zhuǎn)換電路,就可以只用"K"開關(guān)來完成"準(zhǔn)備指令、準(zhǔn)備數(shù)據(jù)、執(zhí)行"這些操作了。全部自動化的CPU如下圖所示。我們將這個版本的CPU稱為version3的CPU。
這里的"ALU"是用層次塊表示的version1里的電路,因為不這樣的話,電路太大,而且不容易重點突出自動控制器的工作流程。同樣的,"ShiftRegister9bit"、"Translator"、"Counter3bit"、"RAM8F4bit"都是層次塊表示的電路。
"ShiftRegister9bit"會依次將輸出端置為1,這可以從上方的三個數(shù)值顯示器看出來。"Counter3bit"是3bit的計數(shù)器。"RAM8F4bit"是8層(每層4bit)的內(nèi)存。"Translator"實現(xiàn)了控制信號的自動控制,"Translator"的內(nèi)部實現(xiàn)如下圖所示。
Version3所示的下半部分展示了譯碼電路,即把代表指令的4bit信號轉(zhuǎn)換為指令信號的電路。由于我們指定Load和Add指令的代碼(0000和1111)都是很規(guī)則的,所以譯碼電路也比較簡單,如下圖所示。
Version3的CPU用"9位循環(huán)移位寄存器"等器件實現(xiàn)了"取指令、分析指令,取數(shù)、執(zhí)行"的全部自動化,其中取指令、分析指令、取數(shù)、執(zhí)行分別占用了移位寄存器的t0- t2、t3、t4-t6、t7-t8這9個階段。
注:如果用振蕩器替換了"K",這個CPU會不停地運轉(zhuǎn)下去,這樣就得不到我們想要的結(jié)果0xC(十進(jìn)制的12)了。所以還需要添加"停機"指令。不過到這里已經(jīng)說清了CPU的控制器是如何一步步實現(xiàn)自動化的,不再繼續(xù)講述如何添加新的指令。

最原始的機器語言編程在給出上文的自動控制器里,我們只說了從內(nèi)存里取指令和數(shù)據(jù),而沒有說這些指令和數(shù)據(jù)是如何寫進(jìn)去的。其實寫進(jìn)去的過程就是(機器語言)編程的過程。最簡單的,你可以用撥動開關(guān)的方式,調(diào)整好要寫入的位置,再調(diào)整好要寫入的數(shù)值,把指令和數(shù)據(jù)一個字一個字地寫入內(nèi)存。最初的計算機編程就是用類似這樣的方式(打孔紙帶)編程的。(這個過程實在無聊,本文就不展示了,有興趣的話自己拿multisim玩玩就好~)
用助記符和一些宏來代替機器碼,這就是匯編語言。用C語言這種方式封裝了匯編語言的編程方法,就是面向過程編程。用C++C# Java這樣的語言封裝了面向過程的語言,就是面向?qū)ο蟮木幊谭椒。用if(..){…}代替JMP指令這種東西比較容易想象,但用"封裝繼承多態(tài)"這種飄渺的概念代替面向過程編程就有點困難了。我在另一篇文章《用C表達(dá)面向?qū)ο笳Z言的機制——C#版》中作了分析和總結(jié),現(xiàn)在終于算是從繼電器一路走到面向?qū)ο缶幊塘恕?br />
總結(jié)本系列文章只此兩篇就結(jié)束了。貌似太少算不上一個系列,不過管他呢,反正問題寫清楚就行了。如果有誰想做個實用的CPU,不妨用VHDLSystemC也是用于硬件設(shè)計的,是用C++寫的一個類庫。我本科的時候用過,也不錯。
感謝博客園眾多園友推薦的好書,寫本篇之前惡補了一陣,受益匪淺!現(xiàn)和我讀的幾本書一起陳列出來,方便查找。點擊推薦者即可跳轉(zhuǎn)到其博客上。
書名
作者
推薦者
《穿越計算機的迷霧》
李忠
BIT祝威
《編碼:隱匿在計算機軟硬件背后的語言》(《編碼的奧秘》)
Charles Petzold
(伍衛(wèi)國, 王宣政, 孫燕妮 譯)
armstronglaw, ClarkZhou, hywin, 天邊彩云, Create Chen, Florian
《計算機系統(tǒng)要素——從零開始構(gòu)建現(xiàn)代計算機》
Noam Nisan, Shimon Schocken
(周維, 宋磊, 陳曦 譯)
吳飛
《CPU自制入門》
水頭一壽, 米澤遼, 藤田裕士
(趙謙 譯)
平如水
《CPU芯片邏輯設(shè)計技術(shù)》
朱子玉, 李亞民
吳飛
《30天自制操作系統(tǒng)》
川合秀實
(周自恒, 李黎明, 曾祥江, 張文旭 譯)
薛遺山
《Orange'S:一個操作系統(tǒng)的實現(xiàn)》
于淵
BIT祝威

本文作為整理和總結(jié)性質(zhì)的文章,不求面面俱到,只為整理思路。想從燈泡開始一點一點地了解計算機的構(gòu)成的話,建議看《編碼的奧秘-隱匿在計算機背后的軟硬件語言》(這一本的中文翻譯也不錯)。

后續(xù)
了解了硬件的設(shè)計原理,又寫過那么多的程序,下一步就該做個操作系統(tǒng)了。這次要寫個真實可用的操作系統(tǒng)出來,不必像研究CPU一樣只能弄個超簡化的仿真模型玩了。再次感謝博客園眾多園友推薦的好書,讀了這幾本書我才相信能在個把月內(nèi)做出一個有圖形界面的操作系統(tǒng)。如果再把網(wǎng)絡(luò)協(xié)議和瀏覽器整進(jìn)來,豈不就可以順利暢游網(wǎng)絡(luò)?


作者: 真愛    時間: 2016-2-4 09:15
很好的東西,學(xué)習(xí)了,慢慢研究

作者: qgjkwfn    時間: 2017-12-25 18:18
不錯的思路,由淺入深!
作者: Jackis    時間: 2019-6-26 17:11
厲害厲害,講的很淺顯易懂,學(xué)習(xí)了。
作者: 94525403    時間: 2019-6-27 22:01
很好的學(xué)習(xí)資料。先下載下來學(xué)習(xí)一下




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1