notice : 這篇文章僅僅具有上機實驗的參考作用,並且需要配套的文件
_寄存器
信號邊緣
信號的一個 上升沿(rising edge) 是數字信號從低電平向高電平的轉換;是下圖的某些紅色豎線
實踐上高低電平的轉變不是瞬間完成的,信號邊緣不一定與時間軸垂直,有一定的延遲
rising edge-triggered
如果一個 觸發器/Flip-flop/latch 忽略高電平轉向低電平,只有當接入的時間脈沖信號從低電平向高電平轉變(rising edge)才被觸發;
這個觸發器就被稱為rising edge-triggered
下面介紹logisim中的寄存器
輸入端:
使能Enable |
Enable=0時,使寄存器不能被時鍾信號觸發 |
時鍾電路輸入端 |
|
清空Reset |
Reset =1 時,寄存器值被清空 |
數據 |
被時鍾觸發時,儲存到寄存器里的值 |
輸出端
一個輸出當前寄存器值的端口
電路時鍾
能產生像時鍾一樣精確的震盪電路
_定點乘法運算
原碼一位乘法
補碼一位乘法
booth算法
假設有一個8位乘數multiplier:0111 1110,將產生6行非零的部分積;如果將multiplier記成1 0 0 0 0 0 -1 0 就可以大大減少非零行的數目
這種變換稱為booth encoding,保證每兩個連續位中最多只有一個是1或-1;這一變換把乘數變換成一個四進制形式
改進的booth encoding
編碼如下
|
|
|
|
0 |
0 |
0 |
0 |
0 |
0 |
1 |
X |
0 |
1 |
0 |
X |
0 |
1 |
1 |
2X |
1 |
0 |
0 |
-2X |
1 |
0 |
1 |
-X |
1 |
1 |
0 |
-X |
1 |
1 |
1 |
-0 |
所以 0111 1110 改寫為01(1) 11(1) 11(1) 10(0) → 10(2Y) 00 00 -10(-2Y)
回過頭來看經典的booth算法,如下圖,是不是很簡單
|
|
|
0 |
0 |
+0 |
0 |
1 |
+X |
1 |
0 |
-X |
1 |
1 |
+0 |
同時符號位增加一位,以便檢驗溢出(見課本)
部分積 0
部分積 0+00.1001
部分積 00.0010 01(>>2)
+11.0111
部分積 11.1001 01
部分積 11.1110 0101
+00.1001
=00.0111 0101
電路設計一位補碼乘法器
輸入被乘數X,與乘數Y
被乘數X符號位要增加一位
第8,9位是符號位
乘數Y后面要加一位0
然后把Y booth編碼:
用yn表示y_(i+1)y_i
本文非常亂
yn怎么產生呢?需要寄存器 {Memory}→Register
假設Y右移后的值是R(9位),存在一個寄存器里面
auto R=bitset<9>(Y); iter_num=0; yn=bitset<2>(0b00); while(rising_edge){ iter_num++; if(iter_num==10) exit(0); elseif(iter_num==1) R=Y'; else R=R>>1; yn[0]=R[0]; yn[1]=R[1]; } |
iter_num可以用計數器實現 {Memory}→counter
隧道Ckt就是exit信號
根據booth編碼,求出 部分積PPi
如果 yn = 10 , 加法器還需要進位,才算求出-x的補碼
部分積與之前累積的部分相加
紅箭頭標明了兩個9位數之間的相加過程
剩下部分
建兩個寄存器,一個寄存器放乘積的高8位,一個放低8位,
目前為止出現的三個寄存器都用同一個時鍾的上升沿觸發,並用ckt隧道啟動
每次求出的和(上圖紅箭頭的輸出部分:)記為S
S的最低位記作L
LOW寄存器存放的數記為Q
L作為最高位與(Q>>1)存入LOW寄存器,
S其余位存入HIGH寄存器,並右移作為下一次的被加數(上圖左邊的紅箭頭);