減法器的設計與實現並用解碼器顯示16、10進位

来源:https://www.cnblogs.com/xiaoniuhululu/archive/2023/05/25/17431072.html
-Advertisement-
Play Games

大家新年好,我是呼嚕嚕,在上一篇[簡易加法器](https://mp.weixin.qq.com/s/ahuk_JH8iyH8bwh3VQxpOw)里我們瞭解了半加器和全加器的設計與實現,今天我們來看下CPU中減法器是如何實現的。文章比較長,大家可以收藏反覆觀看 ## 電腦為什麼利用反碼來實現減法 ...


大家新年好,我是呼嚕嚕,在上一篇簡易加法器里我們瞭解了半加器和全加器的設計與實現,今天我們來看下CPU中減法器是如何實現的。文章比較長,大家可以收藏反覆觀看

電腦為什麼利用反碼來實現減法?

我們來看一個最常見的例子,2-1 =1這是減法,但它等同於 2+ (-1) =1 這其實是加法。從運算邏輯上來說,減法可以通過加法來實現,這是可行的。
從硬體電路層面說,我們很容易讓電子實現彙總的效果,但是將電子群拆分出多個更小的集群,是不容易的。還有一個好處是利用加法器能實現減法的效果的話,就不需要再為減法器專門設計電路了,降低了電路的複雜度。

由於電腦採用的是二進位,和我們天生熟悉的十進位還是有區別的,那麼二進位能否實現用加法來實現減法效果?

很幸運地是,當初那群電腦那群工程師大拿將二進位玩的是爐火純青,通過原碼->反碼->補碼,一步步實現了二進位通過加法來實現減法效果。其中原理大家感興趣地,可以看看筆者之前的一篇文章 電腦中數值和字元串怎麼用二進位表示?

補碼真的是一個天生完美的奇妙存在,基於補碼的機制,減法可以轉化為加法,也就意味著電腦可以通過加法器實現減法。

看完筆者的那篇文章,我們知道了補碼產生的手動:正數原碼不變,負數的符號位不變, 其餘各位取反, 最後一位+1

image

減法器的實現

要實現原碼到補碼的轉換,需要一個取反器,我們先來寫出減法邏輯的真值表:

image

通過真值表,我們可以很容易發現這其實就是一個異或門(相同為0,不同為1)

我們來實現一個8位的取反器,由於是8位的,所以輸入選這8位輸入,還得連一個8位的分線器,輸出類似。異或門得有8個,每個都需和控制是否取反的輸入相連。

image

我們將之前的全加器和減法器結合起來,需要註意的是補碼需要取反再+1,取反可以將輸入和取反器相連,+1可以將全加器最低位的進位控制取反的輸入相連即可,極簡單又巧妙

image

我們來啟動模擬,看下效果:

image

上圖計算結果,相當於:

1+1 =2
1-1 =0

但是上面有個問題是,1-1=0時,雖然燈泡是0,但是旁邊的溢出標誌顯示溢出了,我們還需改造一下。我們這裡簡單地,就直接讓減法不溢出即可(這種處理方式還是比較粗暴的,但是實現起來比較簡單)
我們來寫出溢出輸入IY,是否取反輸入IF(如果取反,就代表是減法操作),溢出輸出O的真值表關係

IY IF O
0 0 0
1 0 1
0 1 0
0 1 0

我們可以推出公式:O=非IF * IY,所以需要非門和與門

image

這樣就減法時,就不會溢出了。但其實這個加法器只能做正數的減法(也就是輸入A得大於等於輸入B),如果最後結果為負數的,還是有bug的。我們後面有機會再優化

7段數位管16進位顯示

由於用燈泡表示二進位,每次得出的結果,還要我們去換算成10進位,非常不直觀,我們接下來利用數位管,來將二進位數"翻譯"成10進位數。

我們這邊利用的是7段數位管來實現的,數位管其實就是多個LED燈,不同的位控制不同的LED。從第0位到第7位,通過控制不同的LED來組合出數字。第7位比較特殊,數位管顯示的是點

image

我們用上面的電路,一一將0~F16個數顯示出來,各個開關的情況記錄成下麵的表:

數值 開關(2進位) HEX(16進位)
0 0011 1111 0x3F
1 0011 0000 0x06
2 0101 1011 0x5B
3 0100 1111 0x4F
4 0110 0110 0x66
5 0110 1101 0x6D
6 0111 1101 0x7D
7 0000 0111 0x07
8 0111 1111 0x7F
9 0110 1111 0x6F
A 0111 0111 0x77
b 0111 1100 0x7C
C 0011 1001 0x39
D 0101 1100 0x5E
E 0111 1001 0x79
F 0111 0001 0x71

這其實就是7段數位管的共陰極對照表,還有共陽極對照表這裡我們就不展示了。

如果直接用組合電路來封裝8位輸入,7段數位管的16進位顯示,的確是可以的,但如果是16位,32位,64位輸入,電路會異常的複雜,我們這邊用儲存器ROM來實現這個功能

ROM只讀存儲器,是以非破壞性讀出方式工作,它非易失性存儲器,當電源被移除時,其數據內容不會被擦除,它還有個特點就是只能讀出而不能寫入信息,其所存的數據,一般是裝入整機前事先寫好的,整機工作過程中只能讀出。

需要註意的是: 雖然ROM和硬碟有一些共性,但不能簡單地說ROM就是硬碟

常常與ROM相比的還有一個RAM(隨機存取存儲器),也就是我們常說的主存,是與CPU直接交換數據的內部存儲器,它的特點:隨機存取、數據易失、對靜電敏感、訪問速度快、需要刷新。RAM在斷電以後保存在上面的數據會自動消失

我們使用ROM和7段數位管來顯示16進位的數0~F,選用地址位寬為4,數據位寬為8,只需把對應的數據提前寫入對應的地址中即可。

這裡需要註意一下,為什麼我們選用地址位寬為4,數據位寬為8的ROM

首先我們需要明白(1111 1111)2 = (f f)16, 7段數位管可以表示0~F 16進位數,我們可以用2個7段數位管並聯將8位二進位數解碼成16進位數。
我們就先考慮1個7段數位管和ROM的關係,單個"f"也就是第16個數,也就是說4位二進位,即4位輸入,最大值為16

  1. 地址位寬為4, 可以保證定址2^4=16,分別對應十六進位下的0~F
  2. 數據位寬為8,相當於2個7段數位管,一個7段數位管需要4位輸入,2個就是8位輸入

我們想顯示16進位數,0~F,我們需要4位二進位輸入,其最大值1111,就是16(F),結合上面的共陰極對照表,我們就能總結下麵的表:

A3 A2 A1 A0 Number HEX(16進位)
0 0 0 0 0 0x3F
0 0 0 1 1 0x06
0 0 1 0 2 0x5B
0 0 1 1 3 0x4F
0 1 0 0 4 0x66
0 1 0 1 5 0x6D
0 1 1 0 6 0x7D
0 1 1 1 7 0x07
1 0 0 0 8 0x7F
1 0 0 1 9 0x6F
1 0 1 0 A 0x77
1 0 1 1 b 0x7C
1 1 0 0 C 0x39
1 1 0 1 d 0x5E
1 1 1 0 E 0x79
1 1 1 1 F 0x71

根據對應關係,我們把電路和存儲器相應地址數據預先填進去

image

我們啟動模擬看下效果:

image

測試完成後,將4個開關換成4位輸入。接著我們將2個4位16進位解碼器並聯,就成了8位16進位解碼器,並封裝一下:

image

並將它與上文的全加器與減法器結合起來:

image

nice!

7段數位管10進位顯示

通過上一小節,我們成功把8位二進位數,"翻譯"成16進位數,但距離我們更熟悉的十進位還是有點距離的,我們本小節繼續改進7段數位管,實現10進位的解碼

由於(1111 1111)2 = (255)10, 最大值為255

ROM需要8位地址位寬,2^8 = 256,確保能夠將256個數(0 ~255)全部找到;255是3位數,我們至少需要3個數位管(也就是我們上一小節封裝的4位16進位解碼管),1個數位管需要4位輸入,所以ROM數位管的數據位寬為12

更多精彩文章在公眾號「小牛呼嚕嚕

電路實現:我們可以使用8個開關,來表示8位輸入;選用8位地址位寬且數據位寬為12的ROM,通過8位3針腳的分線器和3個4位16進位解碼管相連即可。

由於ROM的查找表有255個數,不能像之前一樣一個個手動填寫,我們可以利用Python來實現(電腦中需要有Python3的環境)。

image

將其另存到桌面上為test.bin文件,用vscode打開該文件(需要安裝 hex editor插件來顯示二進位),以小端顯示:

image

test.py:

with open('test.bin', 'wb') as f:
    for i in range(256):
        var = str(i)
        var = int(var, base=16) //先轉成16進位
        byte = var.to_bytes(2, byteorder='little')// 再轉化成二進位,以顯示小端
        print(byte)
        f.write(byte)

將其放到test.bin 同級目錄後,直接運行命令python test,py後,test.bin就變成了:

image

這種55 02 其實是 25531 02 231 , 像這種55 02 就是小端表示法。

將test.bin 重新載入到ROM中

image

我們來啟動模擬看看:
image

我們將輸入替換開關,然後封裝成8位10進位解碼器電路,接上之前的減法器的電路:
image

21選擇器 增強 10進位顯示

我們現在有個需求,001,前面的0不想要,就想要1,我們藉助21選擇器來實現 高位為零時,數位管不亮

我們先來看一下1位21選擇器,首先有2個輸入,分別為A和B,以及一個有效位EN,一個輸出S。我們的目的是實現:有效輸出A,無效輸出B。根據目的我們可以寫出真值表:

EN A B S
0 0 0 0
0 0 1 1
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 1

我們可以得出公式 S = EN與A + 非EN與B,進而可以畫出電路圖

image

封裝後,模擬一下:

image

我們繼續畫出8位21選擇器,只需將8個1位21選擇器組合在一起:

image

將其封裝一下,接著模擬測試:
image

7段數位管10進位顯示增強的電路,我們再重新設計一下:

image

更多精彩文章在公眾號「小牛呼嚕嚕

最後把其封裝一下,放到減法器和加法器的電路中,演示一下:

image

完美,這樣就實現了我們的目的。

尾語

本文我們將上一小篇文章中的簡易加法器進行來改進,通過補碼,讓加法器也是運算減法。接著為了讓我們觀察結果更加方便,我們使用了7段數位管實現了 16進位、10進位顯示,最終優化了10進位顯示,使其只顯示有效位的數值。

本系列到目前為止主要是組合邏輯電路的相關知識,後續我們會探究時序邏輯電路的奧秘,來看看開關究竟是如何實現CPU除計算功能外另一個重要的功能"記憶功能"。


參考資料:

  1. 一個8位二進位CPU的設計和實現,躊躇月光
  2. 《編碼:隱匿在電腦軟硬體背後的語言》
  3. 《穿越電腦的迷霧》
  4. 深入淺出電腦組成原理,徐文浩
  5. 運行記憶體,百度百科

全文完,感謝您的閱讀,如果我的文章對你有所幫助的話,還請點個免費的,你的支持會激勵我輸出更高質量的文章,感謝!

原文鏡像:https://mp.weixin.qq.com/s/QXWm-s-v3VuYV7s4-uE7yA

電腦內功、源碼解析、科技故事、項目實戰、面試八股等更多硬核文章,首發於公眾號「小牛呼嚕嚕」,我們下期再見!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • > ML.Net - 開源的跨平臺機器學習框架 > - 支持CPU/GPU訓練 > - 輕鬆簡潔的預測代碼 > - 可擴展其他的機器學習平臺 > - 跨平臺 ![img](https://img2023.cnblogs.com/blog/1339560/202305/1339560-20230524 ...
  • 文件比較平常都是用Beyond Compare,可以說離不開的神器,特別是針對代碼比較這塊,確實挺好用的。 不過Beyond Compare平常拿它主要是用來做代碼比較,用來做一些大批量的二進位文件比較,其實有點不是很方便。 於是造輪子,重新寫了一個簡單的文件夾比較的小工具。 平常主要是拿來做一些N ...
  • 遞歸演算法本質: 1、方法的自我調用 2、有明確的終止條件 3、每次調用時,問題規模在不斷減少。通過遞減,最終到達終止條件 ...
  • Centos7安裝配置 # 一 、 安裝 安裝就不多做詳述,選擇好自己的鏡像設置好路徑即可 # 二 、配置 #### 2.1 網路配置 桌面右鍵進入 `cmd` 命令編輯視窗,在 Linux 中設置網路的相關配置都需要管理員許可權,需要先切換到 root 用戶。 ```markdown vim /et ...
  • # 伺服器磁碟滿了!!! 事發突然,我在給博客的圖片新增的時候,發現上傳文件和下載文件一直報錯。因為我用的是`1Panel`面板去管理伺服器,話不多說看圖: ![image](https://img2023.cnblogs.com/blog/3091176/202305/3091176-202305 ...
  • 目錄 一、shell簡述 二、shell腳本 三、重定向 四、管道符 五、變數 六、shell腳本基本知識 七、預定義變數小實驗 一、shell簡述 概念:shell解釋器,翻譯官功能,與內核進行溝通的應用程式。 把代碼翻譯為二進位,讓內核處理,負責接收用戶輸入的操作指令(命令)併進行解釋,將需要執 ...
  • 需要先安裝svn linux版打開終端執行 sudo pacman -S svn 安裝完成後執行一下 svn --version 出現這個就說明svn已經安裝完成了,這個時候我們可以執行 svn checkout [路徑] 就可以檢出svn伺服器上相關內容了 但是這個有的時候我們打開文件管理器想要看 ...
  • ZBar是一種流行的二維碼掃描和解碼工具,它在嵌入式系統中擁有廣泛的應用。在嵌入式系統中,我們面臨著有限的資源和更嚴格的性能要求,因此,選擇適當的庫來完成特定的任務非常重要。 ZBar適用於各種嵌入式平臺,包括ARM、x86和MIPS等處理器架構。它可以輕鬆地整合到各種嵌入式系統中,如智能家居設備、 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...