最近在學習coursera上的一門課:Build a Modern Computer from First Principles: From Nand to Tetris,我會堅持更新這一系列的部落格,作為記錄自己學習的過程,同時也倒逼自己去把學會的東西再講出來,來深入理解。
其實我們生活中所有的電子裝置都是基於邏輯閘電路(後面會解釋)來構造的。這是很神奇的一件事情,我在中學的時候就好奇計算機是如何完成這一些複雜的操作的,我相信很多人也都好奇過。這門課的願景就是帶我們從一個最基礎的電路開始,構造出一個完整的計算機。
布林代數
在數學和數理邏輯中,邏輯代數(有時也稱開關代數、布林代數)是代數的一個分支,其變數的值僅為真和假兩種真值(通常記作 1 和 0)。邏輯代數是喬治·布林(George Boole)在他的第一本書《邏輯的數學分析》(1847年)中引入的,並在他的《思想規律的研究》(1854年)中更充分的提出了邏輯代數。
這段話來自維基百科,布林其實是一個人名,因為布林代數就是他提出的,所以用他的名字來命名。這裡不會深入講解布林代數,我們只講我們用得到的部分。
還是以數學為例,數學中最基礎的四則運算是加
,減
,乘
,除
,同樣的,布林代數也有很多計算方式,最基礎的是應該是:與
,或
,非
。
在開始講具體的計算之前,我們需要把前提記住:布林代數變數的值僅為真和假兩種真值(通常記作 1 和 0,真為1,假為0)。
與
因為布林代數變數的值僅為真和假兩種真值,所以我們其實可以把所有的情況都列出來,形成一張表,這張表就是我們平時所說的真值表。
與
的真值表如下:
x | y | x與y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
從上面也可以看出,對於\(n\)個變數的真值表,會有\(2^n\)種情況。
x與y
其實就是當x
和y
都是1的時候,結果為1,也就是x
和y
都是真的時候,結果為真。
你也可以有你自己的理解方式,比如我們一開始學加法的時候,老師告訴我們1+1=2
其實就是一個蘋果加一個蘋果等於2個蘋果。那麼x與y
你也可以這麼理解:假如你想出去旅遊要徵詢爸爸媽媽的意見,x代表爸爸的意見,x=1代表爸爸同意,y代表媽媽的意見,y=1代表媽媽同意,為0則是不同意。那麼與
的意思就是,爸爸與媽媽都同意了,才是通過。
我們平時表述x加y
用符號+
來表示:x+y
;同樣的,與
也有它的符號:\(x\)與\(y\) \(\Rightarrow\) \(x \cdot y\)
或
或
的真值表如下:
x | y | x或y |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
用上面的例子來說,或
就是爸爸或媽媽同意了,就算是通過了。
同樣地,符號表示如下:\(x\)或\(y\) \(\Rightarrow\) \(x + y\)
非
非
和上面的與
,或
有點不一樣,真值表如下:
x | 非x |
---|---|
0 | 1 |
1 | 0 |
非
其實就是對x
去相反的值,從字面意思也可以理解。
符號表示如下:非\(x\) \(\Rightarrow\) \(\overline{x}\)
與非
與非
的字面意思是與
運算和非
運算的結合。
與非
的真值表如下:
x | y | x與非y |
---|---|---|
0 | 0 | 1 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
與非
就是對與
計算出來的結果,再做非
計算。其符號表示如下:\(x\)與非\(y\) \(\Rightarrow\) \(\overline{x \cdot y}\)
這裡把與非
單獨拿出來講,是因為在電路中,我們可以用一個與非
元件,構造出其餘所有的元件。這樣我們只需要弄懂一個電路圖即可。我們這節課的主旨是搞明白,如何從用電路表達布林邏輯,至於電路的效率等方面,則是硬體工程師們考慮的內容了。其實學習就是這樣,我們需要抓住主線,明確目的。如果我們陷入布林邏輯或者電路圖的細節中不可自拔,那就是路走偏了。
邏輯電路
邏輯電路是指完成邏輯運算的電路。這種電路,一般有若干個輸入端和一個 或幾個輸出端,當輸入訊號之間滿足某一特定邏輯關係時,電路就開通,有輸 出;否則,電路就關閉,無輸出。所以,這種電路又叫邏輯閘電路,簡稱閘電路。
這段話來自百度百科,可能比較拗口,我們直接來看實現。
與非門
如圖所示,I1
,I2
是輸入,NPN
是一個三極體(當I1
或I2
加電的時候,上下兩端連通),我們用1表示有電,用0表示沒電,那麼只有當I1
,I2
都是1的時候,Output
才是0。我們可以用真值表中的例子來驗證一下。
為了簡化表示,我們用如下的符號來表示與非門:
到這裡我們邁出了第一步,我們用一個物理上真實存在的電路圖,表示出了一種布林運算邏輯。那麼下面我們就用這個電路圖來構造其餘的電路圖。
非門
非門的實現如下:
也就是我們只需要在電路圖上把與非門的2個輸入連起來,就可以得到一個非門:這個時候與非門的2個輸入永遠都是相等的,當2個輸入都是1的時候,輸出為0,當2個輸入都是0的時候,輸出為1。
非門的符號如下所示:
與門
類似地,與門的實現如下:
符號表示如下:
或門
或門的實現如下:
符號表示如下:
回顧
這一節我們實現了用電路去表示基礎的閘電路。邁出了關鍵的一步,但是一直用畫圖的方式去表達電路也比較麻煩,下一節我們會簡單學習一門硬體描述語言(HDL:hardware description language)來表示電路的實現方式,一步一步去抽象,實現更多的元件。從而構造出一個完整的電腦。
再聊一個題外話:抽象。抽象是軟體工程師很重要的一個技能。在這裡,我們用或非門
構造出了非門
,與門
,或門
,那麼我們可以把構造的過程理解成一個抽象的過程,構造出的閘電路可以直接供我們使用,而不必每次去畫幾個或非門,然後把他們連起來。當然目前的閘電路比較簡單,我們的感知不是很強烈,如果我們構造了一個由幾十個或非門構造出的某門
,那麼抽象就顯得尤為重要了。其實平時寫程式碼也是如此,我們應該把公用的部分,抽象出一個模組或者一個工具類。