日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

verilog乘法器以及booth编码改进

發(fā)布時(shí)間:2024/3/7 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 verilog乘法器以及booth编码改进 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第一章 整數(shù)乘法器

1.1 整數(shù)的概念

整數(shù)在IEEE 的規(guī)定上有,短整數(shù)short integer , 中整數(shù)integer 和 長(zhǎng)整數(shù)long integer ,它們之間的關(guān)系如下:

?

?

整數(shù)

字節(jié)空間

取值范圍

短整數(shù)

一個(gè)字節(jié)

-127 ~ 127

中整數(shù)

兩個(gè)字節(jié)

-32767~32767

長(zhǎng)整數(shù)

和四個(gè)字節(jié)

-2147483647~2147483647

?

?

在這里筆者以短整數(shù)為筆記的主角。

?

?

短整數(shù)的最高位是符號(hào)位,符號(hào)位的正負(fù)表示了該值是“正還是負(fù)”?。正值的表示方法很簡(jiǎn)單,反之負(fù)值的表示方法是以補(bǔ)碼來(lái)表示。

?

?

+127 亦即8'b0111_1111;

+4 亦即8'b0000_0100;

-127 亦即8'b1000_0001;

-4 亦即8'b1111_1100;

?

?

補(bǔ)碼在英文又叫2nd?implementation?? , 其實(shí)是“正值的求反又加一”的操作。(哎~年輕時(shí)的筆者曾經(jīng)這個(gè)東西頭疼過(guò))。一個(gè)負(fù)值表示如-4 ,是由+4 求反由加一后而成。

?

?

8'b0000_0100;? // 正值4

8'b1111_1011;? // 求反

8'b1111_1100;? // 加1 , 負(fù)值4

那么符號(hào)位和正值,負(fù)值,補(bǔ)碼,取值由有什么關(guān)系呢?舉個(gè)例子 :A = 8'b0111_1111 (+127) 和B = 8'b1000_0001 ( -127 )。

當(dāng)我們?cè)谶M(jìn)行判斷一個(gè)短整數(shù)是正值還是負(fù)值的時(shí)候,我們可以這樣表示:

?if ( !A[7] ) ...? // A是正值

?if ( B[7] ) ...? // B是負(fù)值

在事實(shí)的事實(shí)上。我們知道短整數(shù) 28?,亦即取值范圍是0~255,但是符號(hào)位的出現(xiàn)吃掉了最高位,所以造成由28?的取值范圍變成27?= 0~127 。

你知道嗎?在短整數(shù)家族里面永遠(yuǎn)存在一個(gè)幽靈成員。該成員很神秘,它不是正值,即不是負(fù)值或者0值。而且它的能力也不可忽視,它劃分了正值和負(fù)值的邊界,它就是8'b1000_0000。

+127 ??? 8'b0111_1111;

劃分????? 8'b1000_0000;

-127 ???? 8'b1000_0001;

換句話(huà)說(shuō),在8'b1000_0000 之前的都是正值 ,然而在8'b1000_0000 之后是負(fù)值。如果讀者硬是要說(shuō)8'b1000_0000 是 “負(fù)0”,筆記也無(wú)話(huà)可說(shuō)......

從上述的內(nèi)容,我們可以知道:正值可以進(jìn)行求反又加一之后成為負(fù)值。那么負(fù)值如何變成正值?同樣的一個(gè)道理“負(fù)值求反又加一后,成為正值”。

8'b1111_1100;? // 負(fù)4

8'b0000_0011;? // 求反

8'b0000_0100;? // 加1 , 正4

?

1.2 傳統(tǒng)乘法的概念

筆者還記得筆者在上小學(xué)三年級(jí)的時(shí)候,老師在黑板上寫(xiě)上3 x 4 = 12。筆者對(duì)這神秘的數(shù)學(xué)公式迷糊了頭腦。后來(lái)老師解釋道: " 3粒蘋(píng)果重復(fù)加上4 次等于12粒蘋(píng)果",小時(shí)的筆者頓時(shí)恍然大悟!

當(dāng)筆者上了初中,老師在黑板上寫(xiě)上3 + -4 = -1。大伙們都明白那是整數(shù),但是初中的筆者,腦袋過(guò)很遲鈍。因?yàn)樵诂F(xiàn)實(shí)中,初中的筆者認(rèn)為沒(méi)有“-3粒蘋(píng)果”類(lèi)似實(shí)體的概念純?cè)?#xff0c;后來(lái)老師解釋道:“ 小明欠小黃4粒蘋(píng)果,后來(lái)小明還了小黃3粒蘋(píng)果,結(jié)果小明還欠小黃一粒蘋(píng)果 ”,初中的筆者又恍然大悟。

又在初中,當(dāng)老師又在黑板上寫(xiě)上如下的內(nèi)容。那時(shí)候的筆者,嘴巴長(zhǎng)得大大 ,有好一段時(shí)間說(shuō)不出話(huà)來(lái) 。好一段時(shí)間筆者都是自己在嘀咕....

?3 x 4 = 12;??? " 3粒蘋(píng)果重復(fù)疊加4次,等于12粒蘋(píng)果"

-3 x 4 = -12;? ? " 欠3粒蘋(píng)果,重復(fù)欠4次,等于欠12粒蘋(píng)果"

3 x -4 = -12;??? " 欠4粒蘋(píng)果,重復(fù)欠3次,等于欠12粒蘋(píng)果"

-3 x -4 = 12;??? " @#¥%#¥*!%……" ( 嘀咕中... )

讀者們不要笑,上述的故事確實(shí)是筆者的真實(shí)故事。那時(shí)候的筆者,真的拿不到整數(shù)的乘法的門(mén)兒,考試還常常滿(mǎn)江紅,真的悲劇的初衷時(shí)代......

在傳統(tǒng)的概念上乘法等價(jià)于“重復(fù)幾次”。打個(gè)比方:B = 4;A x B 亦即A要重復(fù)加四次才能得到答案。

然而在乘法中“負(fù)值正值的關(guān)系”就是“異或的關(guān)系”。

A值

B值

結(jié)果

正(0)

正(0)

正(0)

正(0)

負(fù)(1)

負(fù)(1)

負(fù)(1)

正(0)

負(fù)(1)

負(fù)(1)

負(fù)(1)

正(0)

?A x B = C;

?3 x 4 = 12;???

-3 x 4 = -12;???

3 x -4 = -12;???

-3 x -4 = 12;?

從上面的內(nèi)容看來(lái),無(wú)論A值和B值是什么樣的“正值和負(fù)值的關(guān)系”,結(jié)果C都是一樣。

那么我們可以換一個(gè)想法:

“在作乘法的時(shí)候只是我們只要對(duì)正值進(jìn)行操作。然而“負(fù)值和正值的結(jié)果”,我們用“異或”關(guān)系來(lái)判斷... ”

實(shí)驗(yàn)一 :傳統(tǒng)的乘法器

該乘法器的大致操作如下:

(一)在初始化之際,取乘數(shù)和被乘數(shù)的正負(fù)關(guān)系,然后取被乘數(shù)和乘數(shù)的正值。

(二)每一次累加操作,遞減一次乘數(shù)。直到乘數(shù)的值為零,表示操作結(jié)束。

(三)輸出結(jié)果根據(jù)正負(fù)關(guān)系取得。

multiplier_module.v



第3~11行是該模塊的輸入輸出。看到Start_Sig 和Done_Sig 是仿順序操作的標(biāo)志性結(jié)構(gòu),不明白的去看筆者之前寫(xiě)的筆記。Multiplicand 和Multiplier (被乘數(shù)和乘數(shù)),都是8位位寬,所以輸出Product 是16位位寬。

第16~21行是該模塊所使用的寄存器,i寄存表示步驟,Mcand 用來(lái)暫存Multiplicand 的正值,Mer 用來(lái)暫存Multiplier 的正值,Temp 寄存器是操作空間。然而isNeg 標(biāo)志寄存器是用來(lái)寄存Multiplicand 和Multiplier 之間的正負(fù)關(guān)系。

在步驟0(36~45行)是初始化的步驟。第39行isNeg寄存“乘數(shù)和被乘數(shù)之間的正負(fù)關(guān)系”。第40行,Mcand寄存 Multiplicand 的正值,該行表示:如果被乘數(shù)的符號(hào)位是邏輯1的話(huà),就將負(fù)值轉(zhuǎn)換為正值,然后Mcand寄存該值,否則Mcand直接寄存Multiplicand 的值。第41行是用來(lái)寄存Multiplier 的正值,該行的操作和40行很相識(shí)。

在步驟1(47~49行),是“重復(fù)加幾次”的操作。Temp寄存器的每一次值的疊加,Mer寄存就遞減(49行)。直到Mer的值等于0(48行),就進(jìn)入下一個(gè)步驟。步驟2~3是產(chǎn)生完成信號(hào)。

在62行,Product輸出信號(hào)的輸出值是由isNeg寄存器作決定,如果isNeg是邏輯1,那么Temp的結(jié)果從負(fù)值轉(zhuǎn)換為正值。否則直接輸出Temp的值。

multiplier_module.vt


?

第16~22行是復(fù)位信號(hào)和時(shí)鐘信號(hào)的激勵(lì)。第26~35行是multiplier_module.v 的實(shí)例化。

第39行以下和普通的仿順序操作的寫(xiě)法一樣,不明白的話(huà)請(qǐng)看筆者以往寫(xiě)過(guò)的筆記。

步驟0~3, 會(huì)輸入不同的乘數(shù)和被乘數(shù)來(lái)激勵(lì)multiplier_module.v。

仿真結(jié)果:


?實(shí)驗(yàn)說(shuō)明:

其實(shí)傳統(tǒng)的乘法器是很容易的,但是短整數(shù)的出現(xiàn),負(fù)值和正值隨著出現(xiàn),使得設(shè)計(jì)上難以下手。但是只要掌握負(fù)值和正值的關(guān)系以后,乘法只作正值也“無(wú)問(wèn)題”。只要在輸出下一點(diǎn)手腳就行了。

實(shí)驗(yàn)結(jié)論:

傳統(tǒng)的乘法器雖然簡(jiǎn)單,但是它有一個(gè)致命的問(wèn)題。就是被乘數(shù)越大就越消耗時(shí)鐘。具體的原因在下一章節(jié)解釋......

1.3 傳統(tǒng)乘法器的改進(jìn)

Verilog HDL 語(yǔ)言所描述的乘法器的消耗是以“時(shí)鐘”作為時(shí)間單位。反之,組合邏輯所建立的乘法器是以“廣播時(shí)間”作為時(shí)間單位。說(shuō)簡(jiǎn)單點(diǎn)就是,Verilog HDL 語(yǔ)言所描述的乘法器“快不快”是根據(jù)“時(shí)鐘消耗”作為評(píng)估。

假設(shè)A = 10 , B = 20,? A x B ,那么時(shí)鐘的消耗至少需要20個(gè),因?yàn)锳值需要累加20次才能得到結(jié)果。到底有沒(méi)有什么辦法,改進(jìn)這個(gè)缺點(diǎn)呢?

有學(xué)過(guò)乘法的朋友都知道A ( B ) = B ( A )。如果以實(shí)驗(yàn)一的乘法器作為基礎(chǔ),那么A( B ) 和B( A ) 所消耗的時(shí)間就不一樣了。所以我們可以這樣改進(jìn):

如果被乘數(shù)小于乘數(shù),那么被乘數(shù)和乘數(shù)互換。

{ Multiplier , Multiplicand } = Multiplicand < Multiplier ? { Multiplicand ,Multiplier } :

???????????????????????? {Multiplier ,Multiplicand };

?

舉個(gè)例子:Multiplicand = 2 ,Multiplicand = 10 ;

更換之前 被乘數(shù)2 需要10次的累加,才能得到結(jié)果。 更換之后 被乘數(shù)為10 乘數(shù)為2,亦即被乘數(shù)10只要累加2次就能得到結(jié)果。

如此一來(lái),可以減少不少時(shí)鐘的消耗。

?

實(shí)驗(yàn)二: 傳統(tǒng)乘法器改進(jìn)

和實(shí)驗(yàn)一相比,在進(jìn)行累加操作之間,多了一個(gè)被乘數(shù)和乘數(shù)比較的步驟。

(一)在初始化之際,取乘數(shù)和被乘數(shù)的正負(fù)關(guān)系,然后取被乘數(shù)和乘數(shù)的正值。

(二)乘數(shù)和被乘數(shù)比較,如果被乘數(shù)小于乘數(shù),結(jié)果乘數(shù)和被乘數(shù)互換。

(三)每一次累加操作,遞減一次乘數(shù)。直到乘數(shù)的值為零,表示操作結(jié)束。

(四)輸出結(jié)果根據(jù)正負(fù)關(guān)系取得。

multiplier_module_2.v


和實(shí)驗(yàn)一先比,添加了一個(gè)比較的步驟(46~49行)。仿真結(jié)果:

仿真.vt 文件和實(shí)驗(yàn)一樣。


?

在仿真的結(jié)果上,10 x 2 和2 x 10 的時(shí)鐘消耗都一樣。

實(shí)驗(yàn)說(shuō)明:

與實(shí)驗(yàn)一的乘法器比較,關(guān)于時(shí)鐘的消耗多少都有改進(jìn)。

實(shí)驗(yàn)結(jié)論:

傳統(tǒng)的乘法器無(wú)論如何改進(jìn)也好,當(dāng)遇見(jiàn)如127 x 127 的乘數(shù)和被乘數(shù),咋也看不出什么優(yōu)化......

1.4 補(bǔ)碼君存在的意義

每一個(gè)人都有存在的意義,有的人用一生的時(shí)間去尋找自己的存在意義,有的人則是經(jīng)過(guò)生活的大反轉(zhuǎn),看到了自己存在意義,有的人則不聞不問(wèn)... 當(dāng)然補(bǔ)碼也有存在的意義,只是在前面的實(shí)驗(yàn)被筆者濫用而已。

補(bǔ)碼不僅可以執(zhí)行正值和負(fù)值轉(zhuǎn)換,其實(shí)補(bǔ)碼存在的意義,就是避免計(jì)算機(jī)去做減法的操作。

? ?? 1101 ??? -3補(bǔ)

+ ?? 1000??? 8

????? 0101??? 5

?

假設(shè)-3 + 8,只要將-3 轉(zhuǎn)為補(bǔ)碼形式,亦即0011 => 1101,然后和8,亦即1000相加

就會(huì)得到5,亦即0101。至于溢出的最高位可以無(wú)視掉。

1101 ??? -3補(bǔ)

+???? 1110???? -2補(bǔ)

?? 1011??? -5補(bǔ)

其實(shí)你知道嗎,如Quartus II 綜合器 ,當(dāng)我們使用“-”算術(shù)操作符的時(shí)候,其實(shí)就是使用補(bǔ)碼的形式,具體如下:

A = 8'd5;

B = 8'd9;

A -B 等價(jià)于A + ( ~B + 1'b1 );

在實(shí)際的操作中,綜合器都會(huì)如上優(yōu)化。

?

1.5:Booth算法乘法器

傳統(tǒng)的乘法器是有極限的,因此位操作乘法器就出現(xiàn)了。筆者在網(wǎng)上沖浪找資源的時(shí)候,還常常撞到許多稀奇古怪的位操作乘法器。但是有一種位操作乘法器,吸引了筆者的眼球,它就是Booth算法乘法器。實(shí)際上Booth 算法是一種“加碼”乘法運(yùn)算。

Booth 算法的概念也很簡(jiǎn)單,我們先從數(shù)學(xué)的角度去理解看看:

?

B[0]

B[-1]

加碼結(jié)果

0

0

0(無(wú)操作)

0

1

1(+被乘數(shù))

1

0

1(-被乘數(shù))

1

1

0(無(wú)操作)

?

B[-1] 是什么?先假設(shè)B是2的,然而B(niǎo)的最低位的右邊后一個(gè)“負(fù)一位”那就是B[-1]。

0010 0? // LSB 右邊出現(xiàn)的就是-1位

那么上面那個(gè)加碼表和乘法又有什么關(guān)系呢?其實(shí)要加碼的目標(biāo)是“乘數(shù)”,假設(shè)乘數(shù)為2, 那么乘數(shù)2的加碼過(guò)程會(huì)是如下。

一開(kāi)始的時(shí)候在乘數(shù)2的“負(fù)一位”加上一個(gè)默認(rèn)0值

0010?0

先判斷[0: -1],結(jié)果是2'b00,表示“0”亦即沒(méi)有操作

0010 0

判斷[2: 1],結(jié)果是2'b01,表示“1”亦即“-被乘數(shù)”操作

0010 0

判斷[1: 0],結(jié)果是2'b10,表示“1”亦即“+被乘數(shù)”操作

0010 0

判斷[3: 2],結(jié)果是2'b00,表示“0”亦即沒(méi)有操作

0010 0

舉個(gè)例子,被乘數(shù)為7,0111; 乘數(shù)為2,0010;結(jié)果會(huì)是什么?

????? 0111? ???? - A被乘數(shù)

????? 0010?0? - B乘數(shù)

? ==========

????? 0110? ??? - 乘數(shù)加碼

? ==========

????? 0000???? 0

?? 111001??????1?(- 7)

??? 0111?????? 1 (+7)

?? 0000 ?????? 0

? ==========

?? 0001110???? 14???

? ==========????????

?

?


?

?

從左邊的操作過(guò)程中,我們可以看到乘數(shù)被加碼以后,

操作的結(jié)果是14。

從數(shù)學(xué)的角度看來(lái),確實(shí)Booth算法是麻煩的存在,但是在位操作的角度來(lái)看就不是這么一回事。實(shí)際上在千奇百怪的位操作乘法中,Booth算法其中可以容納“補(bǔ)碼”亦即“負(fù)數(shù)”來(lái)執(zhí)行操作。

B[0]

B[-1]

加碼結(jié)果

0

0

無(wú)操作,右移一位

0

1

+被乘數(shù),右移一位

1

0

-被乘數(shù),右移一位

1

1

無(wú)操作,右移一位

?

上面的圖表是位操作時(shí)候的Booth 算法。Booth算法在位操作的時(shí)候,它使用一個(gè)很有個(gè)性的空間,就是P空間。

?

先假設(shè):被乘數(shù)A 為7 (0111),乘數(shù)B為2 (0010) ,它們n均為4位,所以P空間的容量是n x 2 + 1 , 亦即9 位。

_ _ _ _ _ _ _ _? _? // P空間

那么P空間如何實(shí)現(xiàn)乘法的位操作呢?

一開(kāi)始先求出-1 (被乘數(shù))

?A = 0111,A= 1001

然后初始化P 空間, 默認(rèn)為0

?P = 0000 0000 0

P空間的[4..1] 填入乘數(shù)

?P = 0000 0010 0

判斷P[1:0],是2'b00 亦即“無(wú)操作”

?P = 0000 0010 0

判斷P[8], 如果是邏輯0右移一位補(bǔ)0,反之補(bǔ)1。

?P = 0000 0001 0

判斷P[1:0],是2'b10 亦即“-被乘數(shù)”。

?P = 0000 0001 0

P空間的[8..5] 和 被乘數(shù)?A相加。

?P = 0000 0001 0

?+? 1001?????

?P = 1001 0001 0

判斷P[8], 如果是邏輯0右移一位,補(bǔ)0,反之補(bǔ)1

?P = 1100 1000 1

判斷P[1:0],是2'b01 亦即“+被乘數(shù)”。

?P = 1100 1000 1

P空間的[8..5] 和 被乘數(shù) A 相加。

?p = 1100 1000 1

?+? 0111?????

?P = 0011 1000 1?無(wú)視最高位溢出

判斷P[8], 如果是邏輯0右移一位補(bǔ)0,反之補(bǔ)1

?P = 0001 1100 0

判斷P[1:0],是2'b00 亦即“無(wú)操作”

?P = 0001 1100 0

判斷P[8], 如果是邏輯0右移一位,補(bǔ)0,反之補(bǔ)1

?P = 0000 1110 0

最終P空間的[8..1] 就是最終答案。

?P =?0000 1110?0

從上面的操作看來(lái),由于乘數(shù)和被乘數(shù)均為n 位所以 “判斷P[1:0],后操作,之后移位”的操作僅執(zhí)行四次而已。

?


?

如左邊的循環(huán)圖。A為被乘數(shù),A為被乘數(shù)補(bǔ)碼形式(-1(A) ),B為乘數(shù),n為乘數(shù)和被乘數(shù)的位寬,P為操作空間。

?

一開(kāi)始P空間會(huì)初始化,然后P空間的[4..1]

位會(huì)填入B。然后進(jìn)入P[1:0]的判斷。每一次的判斷過(guò)后的操作都會(huì)導(dǎo)致P空間右移一次,至于右移過(guò)后的最高位是補(bǔ)0還是補(bǔ)1,是由當(dāng)時(shí)P[8]說(shuō)了算。

?

?

當(dāng)循環(huán)n 次以后,最終結(jié)果會(huì)是P[8:1]。

?

實(shí)驗(yàn)三:Booth算法乘法器

實(shí)驗(yàn)中建立的Booth算法乘法器大致的步驟正如1.5章節(jié)所描述的那樣。

booth_multiplier_module.v



第13~15行是仿真的輸出(S - Simulation , Q - Output)。第20~25行定義了該模塊所使用的寄存器。a寄存器用來(lái)寄存A 值,s寄存器用來(lái)寄存-1(A) 的值,p寄存器是P空間。輸入信號(hào)A和B均為8位位寬,所以p寄存器是17位位寬。至于X寄存器是用來(lái)表示n位,用來(lái)指示n 次循環(huán)。

步驟0(40~41行),初始化了a,s寄存器。p[8:1]填入B值,亦即乘數(shù),其余的位均為0值。

步驟1(43~51行)是用來(lái)判斷p[1:0] 的操作。步驟2(53~55行)是執(zhí)行右移一位,是補(bǔ)0還是補(bǔ)1,完全取決于p[16]。步驟1~2會(huì)重復(fù)交替執(zhí)行,直到X的值達(dá)到8次,就會(huì)進(jìn)入下一步步驟。

步驟3~4(57~61行)是用來(lái)產(chǎn)生完成信號(hào)。第68行輸出信號(hào)product 是由p空間的[16..1]來(lái)驅(qū)動(dòng)。第72~74行是仿真用的輸出信號(hào),功能如字面上的意思。

booth_multiplier_module.vt



?

在仿真中,從步驟0~3(59~73行),激勵(lì)了不同A和B的值(被乘和數(shù)乘數(shù))。

仿真結(jié)果:

P空間的詳細(xì)操作過(guò)程,自己代開(kāi)modelsim看吧,界面有限的關(guān)系。從仿真結(jié)果上可以看到,4次的乘法操作所使用的時(shí)間都一樣,尤其是-127 x -127 的情形,不像傳統(tǒng)乘法器那樣累加127次,才能得到結(jié)果。(p空間的[ Width :1]是用來(lái)填入乘數(shù)B,然而p空間的[Width * 2 : Width + 1 ] 是用來(lái)執(zhí)行和被乘數(shù)A的操作)

實(shí)驗(yàn)結(jié)論:

按常理來(lái)說(shuō)8位的乘數(shù)和被乘數(shù),位操作會(huì)是使用8個(gè)時(shí)鐘而已,但是實(shí)驗(yàn)3的乘法器,需要先操作后移位的關(guān)系,所以多出8個(gè)時(shí)鐘的消耗......

?

1.6 筆者情有獨(dú)鐘的步驟i

在筆者初學(xué)Verilog HDL語(yǔ)言,筆者老是捉不好Verilog HDL 語(yǔ)言和時(shí)序的關(guān)系,吃了不少苦頭。世界就是很巧妙,腦子里就忽然間冒出步驟i。

?

步驟i是什么?

有關(guān)《Verilog HDL 那些事兒》那本筆記,雖然筆者的實(shí)例都和“它”有關(guān)。但是在筆記中,筆者只是微微的帶過(guò)“步驟i是仿順序操作相關(guān)的寫(xiě)法... ”。但是要探討步驟i是什么,那不是初學(xué)Verilog HDL 的任務(wù)。步驟i的用法很簡(jiǎn)單,從概念上和“順序操作”很類(lèi)似,它可以補(bǔ)助初學(xué)者不必過(guò)度依賴(lài)功能仿真,也能“從代碼中看到時(shí)序”。

如果從低級(jí)建模的角度去探討步驟i,低級(jí)建模里面有一個(gè)準(zhǔn)則,就是“一個(gè)模塊一個(gè)功能”,步驟i好比這個(gè)準(zhǔn)則的支持者。步驟i從0開(kāi)始,表示了這個(gè)模塊開(kāi)始工作,直到i被清理,這也表示了這個(gè)模塊已經(jīng)結(jié)束工作。或者可以這樣說(shuō)“一個(gè)模塊不會(huì)出現(xiàn)兩個(gè)步驟i”。

?

具體上,步驟i的“值”是指示著“第幾個(gè)時(shí)鐘沿”發(fā)生,然而Verilog HDL語(yǔ)言里的“步驟”和C語(yǔ)言里的“步驟”是不一樣。C語(yǔ)言里的“步驟”就好比“把大象放進(jìn)冰箱需要幾個(gè)步驟... ”。相反的Verilog HDL 語(yǔ)言里的“步驟”,有如“時(shí)間點(diǎn)”的觀念。


如上面的示意圖所示, 在這個(gè)時(shí)間點(diǎn)里所發(fā)生的“決定”會(huì)產(chǎn)生不一樣的未來(lái)。然而在這個(gè)時(shí)間點(diǎn)里“可以允許不同的決定在這一刻存在”。舉一個(gè)例子:A的初值是4,B的初值是0。

?

case( i )

0:

begin A <= A + 2'd2; B <= B + 2'd3; i <= i + 1'b1; end

1:

if( A > 3 ) begin B <= A; A = 0; i <= i + 1'b1; end

else if i <= i + 1'b1;

?

咋看是一個(gè)簡(jiǎn)單的代碼,但是你知道里邊包含的秘密嗎?

在i = 0的時(shí)候,A 累加2,B 累加3。

在i = 1的時(shí)候,如果A大于3,就B寄存A的值將A清零。

無(wú)論是i等于0還是等于1,它們“只是這一時(shí)間點(diǎn)發(fā)生的決定”,結(jié)果會(huì)在這個(gè)時(shí)間點(diǎn)的過(guò)后發(fā)生。如果用“生動(dòng)”的話(huà)來(lái)描述的話(huà)。

在時(shí)間點(diǎn)0的時(shí)候,這個(gè)模塊決定A累加2,B累加3。然后在時(shí)間點(diǎn)0過(guò)后,結(jié)果就產(chǎn)生。直到迎來(lái)下一個(gè)時(shí)間點(diǎn),這個(gè)模塊才能再一次作決定。

在時(shí)間點(diǎn)1的時(shí)候,這個(gè)模塊判斷A是否大于3。那么,問(wèn)題來(lái)了“這個(gè)模塊是以什么作為基礎(chǔ),判斷A大于3呢?”。答案很簡(jiǎn)單就是“時(shí)間點(diǎn)1的過(guò)去的結(jié)果”或者說(shuō)“在時(shí)間點(diǎn)0過(guò)后所產(chǎn)生的結(jié)果”。


上圖完全將上述的內(nèi)容表達(dá)了出來(lái)。在這里筆者有一個(gè)很在意的問(wèn)題,那就是"<=" 賦值操作符。在眾多的參考書(shū)中“<=”賦值操作符被解釋為“時(shí)間沿有效的賦值操作符”。筆者初學(xué)的時(shí)候的,完全不知道它是蝦米... 如果換做時(shí)間點(diǎn)的概念來(lái)說(shuō)“<=”的操作符,表示了“在這個(gè)時(shí)間點(diǎn)下決定”專(zhuān)用的賦值操作符。

與“=”賦值操作符不一樣,它是沒(méi)有時(shí)間點(diǎn)的概念的賦值操作符。所以在always @ ( posedge CLK ... ) 有效區(qū)域內(nèi),它是不適合使用,因?yàn)樗鼤?huì)破壞這個(gè)模塊的時(shí)間和結(jié)果。

我們的人生,下錯(cuò)了決定只要知錯(cuò),吸取教訓(xùn)還有從來(lái)的機(jī)會(huì)。但是模塊下錯(cuò)了決定,就影響它的一生,所以我們?cè)诰庉嫷臅r(shí)候要特別小心,不然會(huì)可能因我們的疏忽,導(dǎo)致了這個(gè)模塊的一生悲劇。

小時(shí)候,筆者讀道德教育的時(shí)候,有一句話(huà)是筆者一生受用,那就是“先三思而后行”。

這個(gè)又和上述的內(nèi)容有什么關(guān)系呢?

我們知道“時(shí)間點(diǎn)”的概念就是“就是在這個(gè)時(shí)間點(diǎn)決定了什么,這個(gè)時(shí)間點(diǎn)的過(guò)后會(huì)產(chǎn)生什么”。難道模塊的世界就是那么現(xiàn)實(shí), 就連三思的機(jī)會(huì)也沒(méi)有嗎?這是一個(gè)很好的問(wèn)題......

舉個(gè)例子,有一個(gè)模塊他有A ,B和C三個(gè)寄存器,它們的初值都是0:

case( i )

?? 0:

?? begin A <= 3; B <= 4; C <= 0; i <= i + 1'b1; end

?? 1:

?? begin

?????? C <= A + B;

?????? if( C > 0 ) begin A <= 0; B <= 0 ; end

?????? else begin A <= 1; B <= 1; end

?????? i <= i + 1'b1;

?? end

從上面的代碼,我們可以知道。在時(shí)間點(diǎn)0,該模塊決定了A 等于3,B等于4,C等于0。然后到了時(shí)間1, 問(wèn)題來(lái)了“在時(shí)間點(diǎn)1,該模塊是以什么作為基礎(chǔ)去判斷C 的值呢?是時(shí)間點(diǎn)1過(guò)去的C值,還是在這一個(gè)瞬間A + B 所產(chǎn)生的值?”。


答案如上圖所示,if是以時(shí)間點(diǎn)1過(guò)去的C值作為判斷的基礎(chǔ)。所以說(shuō)模塊的現(xiàn)實(shí)是很殘忍的,它們不但沒(méi)有重來(lái)的機(jī)會(huì),就連“思考”的時(shí)間也不給它。它們"只能以當(dāng)前時(shí)間點(diǎn)過(guò)去的值,作為當(dāng)前時(shí)間點(diǎn)下決定的參考......? ( 寫(xiě)到這里, 筆者流淚了! )


實(shí)際上“=”不是不可以在always @ ( posedge CLK ... ) 里出現(xiàn),只不過(guò)它比較危險(xiǎn)。

case( i )

?? 0:

?? begin A <= 3; B <= 4; C <= 0; i <= i + 1'b1; end

?? 1:

?? begin

?????? C = A + B;

?????? if( C > 0 ) begin A <= 0; B <= 0 ; end

?????? else begin A <= 1; B <= 1; end

?????? i <= i + 1'b1;

?? end

筆者將上面的代碼稍微修改了一下, 在步驟1 變成了C = A + B。


如果把步驟i按照“時(shí)間點(diǎn)”的概念,結(jié)果會(huì)是如上圖。在時(shí)間點(diǎn)1,“=”造成了一個(gè)而外的時(shí)間停止空間,在這個(gè)空間里C 不但可以“作決定”,而且“即時(shí)得到結(jié)果”。在某種程度上,它的存在會(huì)破壞和諧,如果沒(méi)有步驟i的控制,它很容易暴走。筆者在設(shè)計(jì)模塊中,除非出現(xiàn)“不得已”的情況,否則筆者在always @ ( posedge CLK ... )區(qū)域內(nèi),絕對(duì)不會(huì)使用它。

?

1.7 Booth算法乘法器的改進(jìn)

在實(shí)驗(yàn)三中所建立的Booth算法乘法器,要完成一次乘法計(jì)算,至少要消耗16個(gè)時(shí)鐘,而且其中8個(gè)時(shí)間就是消耗在移位的方面上。那么有什么辦法改進(jìn) 實(shí)驗(yàn)三中的Booth算法乘法器呢?

在1.6章節(jié),筆者說(shuō)了步驟i有如時(shí)間點(diǎn)的概念,假設(shè)我這樣修改實(shí)驗(yàn)三的Booth乘法器 :

case ( i )

???

?? 0: ... 初始化

??

?? 1,2,3,4,5,6,7,8:

?? begin

?????? if( p[1:0] == 2'b01 ) p <= { p[16] , p[16:9] + a , p[8:1] };

?????? else if( p[1:0] == 2'b10 ) p <= { p[16] , p[16:9] + s , p[8:1]};

?????? else p <= { p[16] , p[16:1]};

?????? i <= i + 1'b1;

?? end

從上面的代碼,讀者能看出什么破綻嗎?我們嘗試回憶Booth算法的流程圖,先判斷p[1:0] 的操作,然后右移一位,最高位補(bǔ)0還是補(bǔ)1,是取決與 經(jīng)p[1:0]操作之后的p[16]。

那么問(wèn)題來(lái)了,從上面的代碼看來(lái)p <= { p[16] , p[16:9] + a , p[8:1]}; 其中的p[16] 是以當(dāng)前時(shí)間點(diǎn)的過(guò)去值作為基礎(chǔ),而不是p[1:0]操作過(guò)后的值, 所以上面的代碼不行!

case( i )

?

0: ... 初始化

?

1,2,3,4,5,6,7,8:

begin

??? Diff1 = p[16:9] + a;? Diff2 = p[16:9] +s;

???

??? if( p[1:0] == 2'b01 ) p <= { Diff1[7] , Diff1 , p[8:1]};

??? else if( p[1:0] == 2'b10 ) p <= { Diff2[7] , Diff2 , p[8:1]};

??? else p <= { p[16] , p[16:1]};

?

??? i <= i + 1'b1;

end

?

上面的代碼表示了,在步驟1~8里Diff1 寄存了p[16:9] + a 的結(jié)果,反之Diff2 寄存了p[16:9] + s的結(jié)果。然后判斷p[1:0] 再來(lái)決定p 的結(jié)果是取決于Diff1 ,Diff2 或者其他。和第一段的代碼不同,第二段代碼的p輸出值是一致的。在這里有一個(gè)重點(diǎn)是,Diff1 和Diff2 沒(méi)有使用“<=”而是使用“=”,換一句話(huà)說(shuō),Diff1 和Diff2 結(jié)果的產(chǎn)生在“該時(shí)間點(diǎn)作決定的時(shí)候”,亦即“取得即時(shí)的結(jié)果”,而不是該時(shí)間點(diǎn)過(guò)后,才產(chǎn)生結(jié)果。

實(shí)驗(yàn)四:Booth算法乘法器改進(jìn)

基于實(shí)驗(yàn)三的Booth算法乘法器,從原先的一次乘法需要16次、個(gè)時(shí)鐘,優(yōu)化至8個(gè)時(shí)鐘。

booth_multiplier_module_2.v



?

同樣是Booth 算法的原理,和實(shí)驗(yàn)三不同的是在55~67行,是步驟1~8的循環(huán)操作。不再使用X寄存器作為循環(huán)計(jì)數(shù),而是直接使用步驟來(lái)指示8個(gè)循環(huán)操作。在55~67行,這樣的寫(xiě)法有一個(gè)好處,就是可以使得p的值輸出一致,因此可以減少8個(gè)時(shí)鐘。

仿真結(jié)果:

實(shí)驗(yàn)四所使用的.vt 文件和實(shí)驗(yàn)三的一樣。

從仿真結(jié)果看來(lái),一次的乘法操作只消耗8個(gè)時(shí)鐘而已(步驟0初始化,和步驟9~10完成信號(hào)產(chǎn)生除外)。現(xiàn)在我們把上面的仿真結(jié)果切成一塊一塊的來(lái)看。

?

?

?

00000000 10000001 0 值左邊上升沿開(kāi)始,即是第一個(gè)時(shí)間點(diǎn)i = 0,亦即步驟0。步驟0之后就是初始化的結(jié)果。S是取反過(guò)后的a值,并且填充在p空間的[8:1]。

?

?

00000000 10000001 0 值右邊的上升沿,亦即步驟1。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即00000000 + 10000001, 結(jié)果為10000001。Diff2 寄存過(guò)去的p[16:9] + s,亦即00000000 + 01111111, 結(jié)果為01111111。經(jīng)步驟1的“決定”,過(guò)去p[1:0]是

2'b10 ,所以p值的未來(lái)是{ Diff2[7] , Diff2 , p過(guò)去[8:1] }, 亦即

0 01111111 10000001。

?

?

00111111 11000000 1 值右邊的上升沿,亦即步驟2。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即00111111 + 10000001, 結(jié)果為11000000。Diff2 寄存過(guò)去的p[16:9] + s,亦即00111111 + 01111111, 結(jié)果為10111110。經(jīng)步驟2的“決定”,過(guò)去p[1:0]是

2'b01 ,所以p值的未來(lái)是{ Diff1[7] , Diff1 , p過(guò)去[8:1] }, 亦即

1 11000000 11000000。

?

?

11100000 01100000 0 值右邊的上升沿,亦即步驟3。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11100000 + 10000001, 結(jié)果為01100001。Diff2 寄存過(guò)去的p[16:9] + s,亦即11100000 + 01111111, 結(jié)果為01011111。經(jīng)步驟3的“決定”,過(guò)去p[1:0]是2'b00 ,所以p值的未來(lái)是{ p過(guò)去[16] , p過(guò)去[16:1] }, 亦即

1 11100000 01100000。


11110000 00110000 0 值右邊的上升沿,亦即步驟4。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11110000 + 10000001, 結(jié)果為01110001。Diff2 寄存過(guò)去的p[16:9] + s,亦即11110000 + 01111111, 結(jié)果為01101111。經(jīng)步驟4的“決定”,過(guò)去p[1:0]是2'b00 ,所以p值的未來(lái)是{ p過(guò)去[16] , p過(guò)去[16:1] }, 亦即

1 11110000 00110000。

?

?


11111000 00011000 0 值右邊的上升沿,亦即步驟5。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11111000 + 10000001, 結(jié)果為01111001。Diff2 寄存過(guò)去的p[16:9] + s,亦即11111000 + 01111111, 結(jié)果為01110111。經(jīng)步驟5的“決定”,過(guò)去p[1:0]是2'b00 ,所以p值的未來(lái)是{ p過(guò)去[16] , p過(guò)去[16:1] }, 亦即

1 11111000 00011000。

?

?


11111100 00001100 0 值右邊的上升沿,亦即步驟6。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11111100 + 10000001, 結(jié)果為01111101。Diff2 寄存過(guò)去的p[16:9] + s,亦即11111100 + 01111111, 結(jié)果為01111011。經(jīng)步驟6的“決定”,過(guò)去p[1:0]是2'b00 ,所以p值的未來(lái)是{ p過(guò)去[16] , p過(guò)去[16:1] }, 亦即

1 11111100 00001100。

?

?


11111110 000001100 0 值右邊的上升沿,亦即步驟7。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11111110 + 10000001, 結(jié)果為01111111。Diff2 寄存過(guò)去的p[16:9] + s,亦即11111110 + 01111111, 結(jié)果為01111101。經(jīng)步驟7的“決定”,過(guò)去p[1:0]是2'b00 ,所以p值的未來(lái)是{ p過(guò)去[16] , p過(guò)去[16:1] }, 亦即

1 11111110 00000110。

?

?


11111111 00000011 0 值右邊的上升沿,亦即步驟8。此時(shí):

Diff1 寄存過(guò)去的p[16:9] + a ,亦即11111111 + 10000001, 結(jié)果為10000000。Diff2 寄存過(guò)去的p[16:9] + s,亦即11111111 + 01111111, 結(jié)果為 01111110。經(jīng)步驟8的“決定”,過(guò)去p[1:0]是2'b10 ,所以p值的未來(lái)是{Diff2[7] , Diff2, p過(guò)去[8:1] }, 亦即

0 01111110 00000011。

?

?

最終結(jié)果取值未來(lái)p[16:1] ,00111111 00000001 亦即16129。

實(shí)驗(yàn)說(shuō)明:

如果以“大象放進(jìn)冰箱”這樣的概念去理解步驟i,在實(shí)驗(yàn)四中可能會(huì)產(chǎn)生許多思考邏輯上的矛盾。換一個(gè)想法,如果以“時(shí)間點(diǎn)”的概念去理解步驟i的話(huà),從仿真圖看來(lái)是絕對(duì)邏輯的。(再?lài)Z叨的補(bǔ)充一下,p空間的[ Width :1]是用來(lái)填入乘數(shù)B,然而p空間的[Width * 2 : Width + 1 ] 是用來(lái)執(zhí)行和被乘數(shù)A的操作)

實(shí)驗(yàn)結(jié)論:

這一章節(jié)筆記的重點(diǎn)不是要“如何如何實(shí)現(xiàn)一個(gè)算法”,而是“以不同概念的理解去完成乘法器的改進(jìn)”。

1.8 LUT乘法器

從1.8章節(jié)以前的乘法器都可以歸納為“慢速乘法器”,當(dāng)然它們不是真正意義上的慢,只不過(guò)它們無(wú)法達(dá)到急性一族人的任性而已。LUT乘法器,又成為查表乘法器。用傻瓜的話(huà)來(lái)說(shuō),就是先吧各種各樣的結(jié)果儲(chǔ)存在一個(gè)表中,然后將輸入資源以“查表”的方式,許對(duì)比“等于的結(jié)果”。

舉個(gè)例子,筆者先建立一個(gè)16 x 16 正值的查表:

?

?

?

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

1

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

2

0

2

4

6

8

10

12

14

16

18

20

22

24

26

28

30

3

0

3

6

9

12

15

18

21

24

27

30

33

36

39

42

45

4

0

4

8

12

16

20

24

28

32

36

40

44

48

52

56

60

5

0

5

10

15

20

25

30

35

40

45

50

55

60

65

70

75

6

0

6

12

18

24

30

36

42

48

54

60

66

72

78

84

90

7

0

7

14

21

28

35

42

49

56

63

70

77

84

91

98

105

8

0

8

16

24

32

40

48

56

64

72

80

88

96

104

112

120

9

0

9

18

27

36

45

54

63

72

81

90

99

108

117

126

135

10

0

10

20

30

40

50

60

70

80

90

100

110

120

130

140

150

11

0

11

22

33

44

55

66

77

88

99

110

121

132

143

154

165

12

0

12

24

36

48

60

72

84

96

108

120

132

144

156

168

180

13

0

13

26

39

52

65

78

91

104

117

130

143

156

169

182

195

14

0

14

28

42

56

70

84

98

112

126

140

154

168

182

196

210

15

0

15

30

45

60

75

90

105

120

135

150

165

180

195

210

225

假設(shè)A x B,它們均為4位,A為10,B為2,那么結(jié)果會(huì)是20。查表乘法器之所以被稱(chēng)為快速乘法器,就是上面的原因( 實(shí)際上許多硬件乘法器都是使用查表的方式)。

如果A x B ,它們均為8位,那么應(yīng)該如何呢?難道再建立一個(gè)256 x 256 乘法器!?這樣會(huì)死人的。

不知道讀者有沒(méi)有聽(tīng)過(guò)Quarter square 乘法查表呢?


上邊是該算法的公式,在公式的結(jié)束得到ab = ( ( a + b )2?)/4 - ( ( a - b )2?)/4 。

如果再進(jìn)一步細(xì)分的話(huà),無(wú)論是( a + b )2/4? 或者( a - b )2/4,經(jīng)過(guò)冪運(yùn)算后,得到的結(jié)果都是正值。

假設(shè)a 和b的位寬都是8 位的短整數(shù)話(huà)( 127 + 127 )2?/ 4 = ( -127 - 127 )2?/ 4。那么我們可以得到一個(gè)結(jié)論“( a + b )2/4? 或者( a - b )2/4? 使用同樣的(C)2/4 查表”。

那么我們建立一個(gè)C = 0 ~ 255 ,并且內(nèi)容是(C)2/4 的查表。




?

這個(gè)查表的尋址雖然是0~255,但是實(shí)際上下限是254而已。因?yàn)槲覀冎纼蓚€(gè)短整數(shù)最大值相加僅有-127 + -127 = -254 或者127 + 127 = 254 。

那么問(wèn)題來(lái)了, 短整數(shù)的最大取值范圍是-127 ~ 127 而已,何來(lái)寄存-254 ~ 254 呢?

這里我們就涉及了“不同容量空間的相互賦值”。假設(shè)C 是9位位寬的不正規(guī)整數(shù)

,然而A 和B 都是8位位寬的正規(guī)整數(shù),那么C = A + B ?

?

??? C = A + B

等價(jià)于

??? C = { A[7], A } + { B[7], B }

??? A = 127 (0111 1111)

??? B = 127 (0111 1111)

?

?A? ?? 0111 1111

?B? ? ?0111 1111? +

?C? ? 01111 1110

等價(jià)于

???

??? A = 127 (00111 1111)

??? B = 127 (00111 1111)

?

?A? ? 00111 1111

?B? ? 00111 1111? +

?C? ? 01111 1110

?

?

???

??? A = -127 (1000 0001)

??? B = -127 (1000 0001)

???

?A? ?? 1000 0001

?B? ?? 1000 0001? +

?C? ? 10000 0010

?

?

?

?

?

?

?

?

等價(jià)于

?

?

??? A = -127 (11000 0001)

??? B = -127 (11000 0001)

???

?A? ? 11000 0001

?B? ? 11000 0001? +

?C? ? 10000 0010

?

?

接下來(lái),我們來(lái)看一看下面的代碼:

reg [8:0]I1,I2;

case( i )

0:

begin

??? I1 <= { A[7], A } + { B[7], B };??????????? // C =A + B;

??? I2 <= { A[7], A } + { ~B[7], ( ~B + 1'b1 ) };? // C = A - B;

??? i <= i + 1'b1;

end

1:? // 取正值

begin

??? I1 <= I1[8] ? ( ~I1 + 1'b1 ) : I1;

??? I2 <= I2[8] ? ( ~I2 + 1'b1 ) : I2;

??? i <= i + 1'b1;

end

?

上面的I1 和I2 均為9位位寬。在步驟0,I1表示了C = A + B,相反的I2 表示了C = A - B。由于短整數(shù)的賦值采用補(bǔ)碼的表示方式,所以大大簡(jiǎn)化了正負(fù)轉(zhuǎn)換的操作。

假設(shè)A = -1 ( 1111 1111 ) , B = -3 ( 1111 1101 ), 經(jīng)過(guò)上面步驟0的操作:

I1 = { 1 11111111 } + { 1 1111 1101 } = 1 1111 1100 (-4) 等價(jià)于I1 = -1 + -3 = -4

I2 = { 1 11111111 } + { 0 0000 0011 } = 0 0000 0010 ( 2) 等價(jià)于I2 = -1 - (-3) = -1 + 3 = 2

步驟1是I1 和I2 從負(fù)值轉(zhuǎn)換為正值。

假設(shè)I1 = -4 (1 111 1100) ,I2 = 2 (0 0000 0010), 經(jīng)過(guò)步驟1的操作:

I1 = 0 0000 0011 + 1 = 0 0000 0100;

I2 = 0 0000 0010;

為什么在步驟1中,要特意將負(fù)值轉(zhuǎn)換為正值呢?筆者在前面已經(jīng)說(shuō)過(guò),無(wú)論是(-C)2?還是(C)2?取得的結(jié)果都是一至。為了兩者I1 和I2 共用相同的查表這是必須的步驟。

如果用I1和I2 來(lái)表達(dá)Quarter square 公式,那么:

?( | I1 |2?/ 4 ) - ( | I2 |2?/ 4 )

實(shí)驗(yàn)五:基于Quarter square 的查表乘法器

首先筆者手動(dòng)建立0~255 關(guān)于(C)2/4 結(jié)果的lut_module.v ,因?yàn)橛肣uartus II建立的rom 仿真不給力,很別扭。

?

lut_module.v







這是我目前,貼過(guò)最長(zhǎng)的.v 文件了...

lut_multiplier_module.v

這個(gè)模塊的功能很簡(jiǎn)單。首先取得I1 = A + B ,I2 = A - B,然后I1 和I2 都正值值,將I1 和I2 送至各自的查表,然后將得出的結(jié)果Q1_Sig (I1的結(jié)果) 和Q2_Sig

(I2的結(jié)果) , 執(zhí)行相減。實(shí)際上是補(bǔ)碼形式的相加,Q1_Sig + ( ~Q2_Sig + 1'b1 ) ,以致符合Quarter square的公式:

?( a + b )2/4? - ( a - b )2/4 = ( |I1| )2/4? + [ ( |I2| )2/4]補(bǔ)

???????????? ????????????????? = Q1_Sig + [Q2_Sig]補(bǔ)

?



?

第15~18行是仿真的輸出。第26~27行建立Q1_Sig 和Q2_Sig ,實(shí)際上這兩個(gè)線型數(shù)據(jù)是U1(81~87行)和U2(91~97行) 實(shí)例前申明的,可是modelsim 那么混蛋,偏偏就不給我通過(guò)。

從37~77行是該模塊的主功能。步驟0(49~54行)是取I1 和I2 的值。步驟1(56~61行)是I1和I2的正值化操作。步驟2(63~64行)是延遲一個(gè)時(shí)鐘,給予足夠的時(shí)間從lut_module.v讀出結(jié)果。步驟3(66~67行),是Quarter square公式操作的最后一步。

89~99行是lut_module.v 的實(shí)例化 ,U1是給I1使用 ,U2是給I2使用,它們的輸出連線分別是Q1_Sig 和Q2_Sig 。102行的Product 輸出信號(hào)由Data寄存器驅(qū)動(dòng)。然而106~109行是仿真輸出的驅(qū)動(dòng),分別有I1 , I2 ,Q1_Sig 和Q2_Sig 的仿真輸出。

?

lut_multiplier_module.vt


.vt 文件的寫(xiě)法和之前的實(shí)驗(yàn)都一樣,如果真的不知道筆者在寫(xiě)什么,就得好好看筆者之前寫(xiě)的筆記。

仿真結(jié)果:

看吧!一次的乘法操作僅需4個(gè)時(shí)鐘的而已。比起改進(jìn)的Booth算法減少了一半的時(shí)鐘消耗。真不愧是查表式的乘法器,佩服佩服。

實(shí)驗(yàn)結(jié)論:

說(shuō)實(shí)話(huà)查表式的乘法器是“以空間換時(shí)間”的乘法器,所以說(shuō)查表式的乘法器是很消耗空間。到底有什么乘法器“可以節(jié)約空間,又節(jié)省時(shí)鐘”呢?

你知道嗎?傳統(tǒng)查表的乘法器都有一個(gè)僵局,假設(shè)A(B),那么其中一個(gè)變量需要是“恒數(shù)”,否則建立查表的工作是非常的勞動(dòng)。但是Quarter square 公式的出現(xiàn)把這個(gè)僵局給打破。感謝前人的努力吧,我們后人才能乘涼......

1.9 Modified Booth 算法乘法器

事先聲明modified booth 算法 和 改進(jìn)的booth 算法乘法器(實(shí)驗(yàn)四)是沒(méi)有任何關(guān)系的。如字面上的意思modified booth 算法是booth 算法的升級(jí)版。我們稍微來(lái)回味一下booth 算法。

?

假設(shè)B是4位位寬的乘數(shù),那么booth 算法會(huì)對(duì)B[0: -1] , B[1:0], B[2:1], B[3:2] 加碼,而使得乘法運(yùn)算得到簡(jiǎn)化。booth 算法有典型數(shù)學(xué)做法,也有位操作的做法。Modified booth 算法比起booth 算法,對(duì)于4位位寬B乘數(shù)的加碼返回會(huì)更廣,而使得n/2 乘法運(yùn)算的優(yōu)化。再假設(shè)B是4微微款的倍數(shù),那么modified booth 算法會(huì)對(duì)B[1:-1] , B[3:1] 執(zhí)行加碼。

如果站在位操作的角度上:

?

B[1]

B[0]

B[-1]

操作結(jié)果

0

0

0

無(wú)操作,右移兩位

0

0

1

+被乘數(shù),右移兩位

0

1

0

+被乘數(shù),右移兩位

0

1

1

右移一位,+被乘數(shù),右移一位

1

0

0

右移一位,-被乘數(shù),右移一位

1

0

1

-被乘數(shù),右移兩位

1

1

0

-被乘數(shù),右移兩位

1

1

1

無(wú)操作,右移兩位

?

Modified booth 算法同樣也有使用p空間,假設(shè)乘數(shù)A,和被乘數(shù)B,均為4位,那么p空間的大小n x 2 + 1 ,亦即9位。乘數(shù)A為7 (0111),被乘數(shù)B為2 (0010)。

?

先求出+被乘數(shù) 和 -被乘數(shù),亦即A 和?A。

?? A = 0111 ,?A= 1001

P空間初始化為0,然后P空間的[4..1] 填入乘數(shù)

亦即B。

?? P = 0000 0000 0

?? P = 0000 0010 0

先判斷p[2:0],結(jié)果是3'b100

亦即“右移一位,-被乘數(shù),右移一位”。

?? P = 0000 0010 0

右移一位

?

?

?? P = 0000 0001 0

??

p[8:5] 加上?A

?? P = 0000 0001 0

???+? 1001?????

???P = 1001 0001 0

右移一位

?? p = 1100 1000 1

判斷p[2:0],結(jié)果是3'b001

亦即“+被乘數(shù),右移二位”。

?? p = 1100 1000 1

?

p[8:5] 加上 A

?? P = 1100 1000 1

???+? 0111?????

???P = 0011 1000 1

右移二位

?? P = 0000 1110 0

最終取出p[8:1] 就是最終答案8'b00001110

?,亦即14。

?? P =?0000 1110?0

?

關(guān)于4 位為位寬的乘數(shù)和被乘數(shù)操作流程圖如下:


說(shuō)實(shí)話(huà)modified booth 算法的位操作是很不規(guī)則,從上面的流程圖可以看到,不同的p[2:0]操作都有“不同的步驟次數(shù)”,這也使得它非常不適合作為運(yùn)用。

?

實(shí)驗(yàn)六:Modified Booth 乘法器

?

這個(gè)模塊大致的操作如上述的流程圖。

modified_booth_module.v




?

15~17行是仿真輸出。43~94行是該模塊的主功能。在步驟0(45~51行)取得被乘數(shù)A并且寄存在a寄存器,此外取得-1(被乘數(shù)A) 并且寄存在s寄存器。在初始化p空間的同時(shí),將乘數(shù)B填入p[8:1]。

(由于被乘數(shù)A和乘數(shù)B的位寬為8,所以p空間是n x 2 + 1 亦即9。我知道我很長(zhǎng)氣,但是還是容許筆者補(bǔ)充一下:p空間的[ Width :1]是用來(lái)填入乘數(shù)B,然而p空間的[Width * 2 : Width + 1 ] 是用來(lái)執(zhí)行和被乘數(shù)A的操作)。

步驟1和2(53~62行)是p[2:0] 等于3'b000 | 111 | 001 | 010 | 101 | 110 的操作。相反的,由于modified booth 算法當(dāng)p[2:0] 等于3'b011 和3'b100 所執(zhí)行的步驟次數(shù)是不一樣(56~57行)。

所以在步驟3~5(66~73行)針對(duì) p[2:0] 等于3'b011 的操作(56行)。反之步驟6~8 (77~84行)針對(duì)p[2:0] 3'b100 的操作(57行)。

?

步驟9~10產(chǎn)生完成信號(hào)。第102行的product輸出信號(hào)是由p[16:1]來(lái)驅(qū)動(dòng)。第106~109的仿真輸出信號(hào),分別由寄存器a ,s 和p來(lái)驅(qū)動(dòng)。

modified_booth_multiplier_module.v




?

這是激勵(lì)文件,在寫(xiě)這個(gè)文件的時(shí)候,筆者心情很糟糕,所以在步驟5加入了類(lèi)似for嵌套循環(huán)的東西。其他的和之前的.vt 文件都是大同小異~ 自己看著吧。

?

仿真結(jié)果:


在仿真結(jié)果中,可以很明顯的看到當(dāng)2(4) 和127(-127)有明顯的時(shí)鐘消耗差異。

實(shí)驗(yàn)結(jié)論:

如果Modified booth 算法用在“位操作”,雖然它是快速的乘法操作,但是很多時(shí)候它還是很別扭。換句話(huà)說(shuō),用它還要圖運(yùn)氣,因?yàn)椴煌某藬?shù)和被乘數(shù)都有不同的時(shí)鐘消耗......

?

1.10 Modified Booth 乘法器·改

如果要把Modified Booth 乘法器別扭的性格去掉,我們不得站在“數(shù)學(xué)的角度”去看modified booth 算法。下表是從數(shù)學(xué)的角度去看modified booth 針對(duì)乘數(shù)B的加碼。

?


B[1]

B[0]

B[n-1]

操作結(jié)果

0

0

0

無(wú)操作

0

0

1

+被乘數(shù)

0

1

0

+被乘數(shù)

0

1

1

+2(被乘數(shù))

1

0

0

-2(被乘數(shù))

1

0

1

-被乘數(shù)

1

1

0

-被乘數(shù)

1

1

1

無(wú)操作

?

我們假設(shè)A被乘數(shù)和乘數(shù)B均為4位位寬 :A=7(0111),B=2(0010)。

?

A = (7) 0000 0111;2A = (14) 0000 1110;-2A = (-14) 1111 0010。

?

在這里我們必須注意一下當(dāng)B[1:-1] 等于011 或者100 的時(shí)候,4位的被乘數(shù)A的取值范圍最大是-7 ~ 7 然而,+2(被乘數(shù)) 或者 -2(被乘數(shù)) 都會(huì)使得A的最大值突破取值范圍。所以需要從4位位寬的空間向更大的位位寬哦空間轉(zhuǎn)換。這里就選擇向8位位寬的空間轉(zhuǎn)換吧。

?

B乘數(shù)加碼為B[1:-1] = 3'b100?,亦即 -2(被乘數(shù)) 和B[3:1] = 3'b100 ,亦即 +被乘數(shù)。

?

??? A????? 0 1 1 1

?? ?B????? 0 0 1 0??0

??? ==============

?????????? +1? -2?????? B乘數(shù)加碼

??? ==============

? 1 1 1 1 0 0 1 0

?+ 0 0 0 0 0 1 1 1????????? << 2 左移兩位

?? ===============

??? 10 0 0 0 1 1 1 0????? 無(wú)視超過(guò)8位最高位的益處

?? ===============

?

還記得booth算法在數(shù)學(xué)角度上的運(yùn)算嗎?4位的乘數(shù)和被乘數(shù)相乘,乘數(shù)必須加碼n次,而且乘積也是n 位的次數(shù),亦即4次哦加碼操作,和4次的乘積操作。相反的modified booth 算法在數(shù)學(xué)的角度上運(yùn)算的話(huà),4位的乘數(shù)和被乘數(shù)相乘,乘數(shù)加碼為n位/ 2 次,而且乘積也是n位/2 的次數(shù),亦即2次加碼操作,和2次的乘積操作

實(shí)驗(yàn)七:Modified Booth 乘法器·改

modified_booth_multiplier_module_2.v



?

第29~27行是該模塊所使用的寄存器。a是用來(lái)寄存A,a2是用來(lái)寄存2A,s是用來(lái)寄存-A,s2是用來(lái)寄存-2A。M是用來(lái)表示每次乘積的偏移量。

由于這個(gè)實(shí)驗(yàn)不是站在位操作的角度上,所以P空間僅是作為累加空間的存在。作為補(bǔ)償寄存器N用來(lái)判別booth 加碼操作,所以寄存器N用于寄存乘數(shù)B的值。乘數(shù)B是8位位寬,所以N空間的大小是 “乘數(shù)B的大小+ 1”。多出來(lái)的1個(gè)空間是用來(lái)寄存B[-1]的值。”

在步驟0(54~65行),是用來(lái)初始化所有相關(guān)的寄存器。寄存器a,a2,s,s2 在初始化的同時(shí)也進(jìn)行8位 向16位 空間轉(zhuǎn)換。寄存器p和M都清零,至于寄存器N[8:1]是用來(lái)填充乘數(shù)B,N[0] 填入零值。

步驟1~4(67~79),也就是4次的乘積次數(shù),因?yàn)槭艿絥/2 的關(guān)系。每一次的乘積操作都是先判別N[2:0],然后累加相關(guān)的值。

我們知道傳統(tǒng)的乘法,每一次的乘積操作,都有偏移量 ,打個(gè)比方。

?? 123

?? 111

=====

?? 123? <= 十進(jìn)制的第一個(gè)乘積是 偏移0,沒(méi)有左移位操作。

? 123?? <= 十進(jìn)制的第二個(gè)乘積是 偏移10,也就是左移1位。

?123??? <= 十進(jìn)制的第三個(gè)乘積是 偏移100,也就是左移2位。

=====

???????? ?

同樣的道理寄存器M 是用于記錄二進(jìn)制的每一次乘積偏移量,但是modified booth乘法的乘積偏移量是普通2進(jìn)制乘法乘積偏移量的2被。所以每一次乘積操作結(jié)束都左移+2。

至于寄存器N它寄存了B[7:1] + B[-1] 的值。然而每一次用于的判別都是N[2:0],所以每一次的乘積之后,N都需要右移兩位。

假設(shè)B = 1101 0010 ,N 必然是1101 0010 0。

乘積1

?

?

B[1:-1] = 100

N = 1101 0010 0

乘積2

?

?

B[3:1] = 001

N = 0011 0100 1

乘積3

?

?

B[5:3] = 010

N = 0000 1101 0

乘積4

?

?

B[7:5] = 110

N = 0000 0011 0

為什么說(shuō)8 位位寬的數(shù)據(jù)相乘,乘積運(yùn)算次數(shù)是n / 2 ,亦即4。這是Modified booth算法的一個(gè)特點(diǎn)。如果站在數(shù)學(xué)的角度上,他可以節(jié)省“乘積次數(shù)/ 2”。

第92行的product 輸出是由寄存器p驅(qū)動(dòng)。前面筆者說(shuō)過(guò)了,如果站在數(shù)學(xué)的角度,p空間只是累加空間的作用而已。然而p空間的大小是“乘數(shù)和被乘數(shù)位寬大小的相加”。

第96~101行是仿真輸出信號(hào)的被驅(qū)動(dòng)。有一點(diǎn)很特別,除了寄存a, a2, s, s2 和N 以外,筆者還故意將該模塊的i 引出,這是為了觀察 “Modified booth 乘法使得乘積次數(shù)減半”這一事實(shí)。在仿真中,SQ_i 從1~4經(jīng)過(guò),如果輸出的結(jié)果是真確,那么可以證明Modified booth 算法確實(shí)何以減少一半的乘積。

modified_booth_multiplier_module_2.vt


?

仿真結(jié)果:

?

?

從仿真結(jié)果上,我們可以看到,每一個(gè)乘法操作都消耗同樣數(shù)目的時(shí)鐘。此外還有一點(diǎn), 當(dāng)SQ_i 等于4 之后,就會(huì)得到正確的答案。

實(shí)驗(yàn)結(jié)論:

實(shí)驗(yàn)七和實(shí)驗(yàn)六相比,不僅每一次乘法操作時(shí)鐘消耗都一致,而且這樣結(jié)果帶來(lái)一個(gè)好處,就是- 實(shí)驗(yàn)七和實(shí)驗(yàn)六相比比起乘法運(yùn)算更快。此外,從SQ_i信號(hào)等于4之后,product 就輸出正確的結(jié)果,所以我們可以證明modified booth算法是可以減半乘積的次數(shù)。

總結(jié):

從實(shí)驗(yàn)一到實(shí)驗(yàn)七當(dāng)中,筆者詳細(xì)描述出四種乘法器的各有千秋,其中還有幾種乘法器筆者還特意去優(yōu)化和提升它們。從四種乘法器之中,傳統(tǒng)乘法器,Booth 乘法器,LUT查表乘法器,和Modified Booth乘法器。LUT乘法器擁有最少的時(shí)鐘消耗(最快的運(yùn)算速度),但是LUT乘法器卻暴露出消耗資源的弱點(diǎn)。

如果將LUT乘法器排外,自然而然Modified Booth 乘法器成為第二候選人,但是要建立Modified Booth 乘法器需要很好的理論基礎(chǔ),故很多新手都很怕它。至于Booth乘法和是最受歡迎的,如果設(shè)計(jì)的要求不像DSP那么任性,估計(jì)會(huì)有很多人喜歡它,因?yàn)樗杏?#xff0c;簡(jiǎn)單,容易親近。

剩 下的傳統(tǒng)的乘法器,它什么都不比上后者,難道我們就要鄙視它嗎?這個(gè)不然,筆者接觸各種各樣的乘法,還是托它的副,不然我是不可能如此深入研究整數(shù)乘法 器。傳統(tǒng)的乘法器,最主要的功能是傳達(dá)“乘法運(yùn)算”的概念。正如筆者贊同的一句話(huà):“前人造路,后人走路”,前者們的辛苦應(yīng)該受到尊敬。

整數(shù)乘法器所涉及的知識(shí)可真不小,Verilog HDL語(yǔ)言掌握的成熟性姑且不說(shuō),而且還涉及諸如補(bǔ)碼,整數(shù)的表示方法,不同位空間的整數(shù)轉(zhuǎn)換等等... 都是一些非常基礎(chǔ)的知識(shí)。我們所使用的高級(jí)語(yǔ)言,如C語(yǔ)言:

int C;

short int A,B;

C = A * B;

假設(shè)筆者輸入如同上述的代碼,實(shí)際上我們是不知道和不被允許窺看它里邊是如何操作(有傳言說(shuō),C語(yǔ)言的乘法就是傳統(tǒng)的乘法概念... (-_-!))。

雖然這本只有短短50多頁(yè)的筆記,故事也只是圍繞著著“整數(shù)乘法器”發(fā)展,顯然還有很多地方都不給力。但是你知道嗎,關(guān)于網(wǎng)上“Verilog HDL 整數(shù)乘法器”的求救貼已經(jīng)達(dá)到很恐怖的數(shù)量,此外還有很多源碼和實(shí)例都非常不給力,真是非常蛋疼!故筆者才有編輯這本筆記的初衷,雖然這本筆記不是什么非常給力的東西,但是作為參考已經(jīng)切切有余。

不知道讀者們看完這本筆記后又會(huì)萌出什么奇怪的想法呢?

總結(jié)

以上是生活随笔為你收集整理的verilog乘法器以及booth编码改进的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产成人h | 欧美色图在线观看 | 免费看日韩 | a资源在线观看 | 亚洲麻豆视频 | 亚洲av无码乱码国产精品久久 | 久久影视大全 | 青青草视频在线观看 | 天天干天天爱天天操 | 九色porny视频 | 中文在线亚洲 | 不卡一区二区在线观看 | 奇米在线观看 | 精品动漫一区二区三区在线观看 | 黑人一区二区 | 狠狠夜夜 | 欧美性xxxxxx| 免费av网站在线观看 | 亚洲激情一区二区 | 久久九九久精品国产免费直播 | 色淫湿视频| 国产精品中文字幕在线 | 成人激情免费 | 日韩精品免费视频 | 国产一区二区麻豆 | 国产视频你懂的 | www.久久综合| 午夜少妇 | 一区二区在线不卡 | 人人妻一区二区三区 | 国产又猛又黄又爽 | 欧美久久久久久久久久久久 | 久久久久无码国产精品一区李宗瑞 | 四虎影成人精品a片 | www,xxx日本 | 末路1997全集免费观看完整版 | 三级网站在线 | 日本熟妇人妻中出 | 国产在线欧美在线 | 毛片毛片毛片毛片毛片毛片 | 超碰人人人人人人人 | 青青青手机在线视频 | julia一区二区中文久久97 | 欧美精品日韩在线 | 美梦视频大全在线观看高清 | 他揉捏她两乳不停呻吟动态图 | 欧美乱操| 天天摸天天舔 | 丝袜老师扒开让我了一夜漫画 | 青青青在线视频 | 小小姑娘电影大全免费播放 | 亚洲青涩网 | 麻豆免费av | 午夜精品在线视频 | 精品一区在线视频 | 123毛片 | 无码人妻一区二区三区av | 国产美女喷水视频 | 两个人看的www视频免费完整版 | wwwwww国产 | 国模杨依粉嫩蝴蝶150p | 狠狠一区 | 国产无遮挡aaa片爽爽 | 国产成人无码一区二区在线播放 | 国产精品欧美在线 | 亚洲第一成肉网 | babes性欧美69 | 最近最新mv字幕观看 | 猛男大粗猛爽h男人味 | 欧美色图在线播放 | 国产毛片a | 亚洲自拍偷拍精品 | 亚洲九九夜夜 | 青青青国产精品一区二区 | 97国产 | 欧美精品www | 中文字幕一区二区三区四区免费看 | 欧美熟妇精品久久久久久 | 女人18毛片水真多 | 九九热这里都是精品 | 国产调教一区 | 国产在线视频二区 | 在线成人免费 | 在线观看av一区二区 | 五月色婷 | 亚洲国产日韩一区二区 | 久在线观看视频 | 自拍偷拍欧美日韩 | 国产农村妇女精品 | 久久久久久久久久久久国产 | 国产成人精品综合久久久久99 | 国产一区二区免费在线观看 | jizz91| 黄色免费在线播放 | 成人在线观看免费爱爱 | 亚洲国产免费看 | 黄色污污视频软件 | 亚洲第一成网站 | 香蕉久久网站 |