攜程特牌 的同時(shí)做別的網(wǎng)站自己如何制作一個(gè)網(wǎng)站
1、前言
在邏輯設(shè)計(jì)中,為了保證運(yùn)算結(jié)果的正確性,常常需要對(duì)結(jié)果的位寬進(jìn)行擴(kuò)展。比如2個(gè)3bits的無(wú)符號(hào)數(shù)相加,只有將結(jié)果設(shè)定為4bits,才能保證結(jié)果一定是正確的。不然,某些情況如7+7 = 14(1110),如果結(jié)果只用3bits表示那么就成了110(6)了,這樣運(yùn)算的結(jié)果就是錯(cuò)的。同理,乘法操作需要擴(kuò)展的位寬更大,是兩個(gè)乘數(shù)的位寬之和,比如2個(gè)3bits的無(wú)符號(hào)數(shù)做乘法,結(jié)果需要設(shè)定為6bits。
如果在后續(xù)數(shù)據(jù)處理的過(guò)程中,一直都這樣對(duì)結(jié)果的位寬進(jìn)行擴(kuò)展,那么在算法鏈很長(zhǎng)的情況下,將會(huì)消耗大量的邏輯資源。因此在設(shè)計(jì)中,常常需要對(duì)數(shù)據(jù)進(jìn)行的位寬進(jìn)行處理。
數(shù)據(jù)的位寬處理分為兩個(gè)部分:
- 對(duì)整數(shù)的處理:例如原本用6bits表示的結(jié)果,下級(jí)模塊規(guī)定只能用到4bits輸入。因?yàn)?bits的表示范圍大于4bits,就有可能出現(xiàn)4bits無(wú)法表示的情況(即溢出)
- 對(duì)小數(shù)的處理:原理同上。四舍五入就是一種經(jīng)典的對(duì)小數(shù)截位的方式,類(lèi)似的方法還有ceili,floor,nearest等等。
本文只討論整數(shù)部分的溢出截位處理,小數(shù)部分的處理下篇文章再說(shuō)。對(duì)整數(shù)的截位處理,實(shí)際上就是對(duì)溢出的處理,其決定了當(dāng)運(yùn)算結(jié)果大于該數(shù)位寬所能表示的最大值時(shí),如果對(duì)溢出部分處理。通常有兩種對(duì)溢出的處理方式:
- Saturate(飽和):一旦數(shù)據(jù)溢出,那么就將結(jié)果飽和處理為最大值或最小值(取決于正向溢出還是負(fù)向溢出)
- Wrap(繞回/截?cái)?#xff09;:一旦數(shù)據(jù)溢出,那么就直接將溢出的高位截?cái)?/li>
將6bits的整數(shù)41截位到4bits,兩種溢出模式的處理結(jié)果如下:
2、Saturate
因?yàn)橛蟹?hào)數(shù)和無(wú)符號(hào)存在表示范圍的區(qū)別,所以二者的溢出處理也存在一定的區(qū)別,接下來(lái)對(duì)兩種情況分別進(jìn)行討論。
2.1、無(wú)符號(hào)數(shù)的Saturate
Saturate是當(dāng)數(shù)據(jù)溢出時(shí),就直接用最大值或最小值來(lái)表示。因?yàn)闊o(wú)符號(hào)數(shù)不能表示負(fù)數(shù),因此不存在對(duì)于負(fù)數(shù)的飽和處理,只存在正向的飽和。例如要將1個(gè)6bits的數(shù)截?cái)嗟?bits,因?yàn)?bits能表示的最大值是15,那么所有大于15的數(shù),都直接用15來(lái)表示,示意圖如下:
將1個(gè)6bits的輸入Saturate為4bits的輸出,用Verilog可以這么寫(xiě):
module test(input [5:0] data_6bits,output reg [3:0] data_4bits
);always@(*)
beginif(data_6bits > 4'd15) //溢出了data_4bits = 4'd15; //飽和到最大值else data_4bits = data_6bits; //沒(méi)溢出則直接賦值
endendmodule
除了直接用大于符號(hào)(data_6bits > 4’d15)來(lái)判斷是否溢出外,也可以這樣判斷:
if(|data_6bits[5:4]) //判斷高2位是否存在1,若存在則該數(shù)的值必定大于15
再寫(xiě)個(gè)TB測(cè)試一下:因?yàn)檩斎氡容^少,所以可以用窮舉法來(lái)測(cè)試,把輸入從最小值0開(kāi)始累加最大值63,觀(guān)察輸出是否會(huì)被Saturate。
`timescale 1ns/1ns
module test_tb();reg [5:0] data_6bits;
wire [3:0] data_4bits;//例化被測(cè)試模塊
test test_inst(.data_6bits (data_6bits),.data_4bits (data_4bits)
);initial begindata_6bits = 0;while(~(&data_6bits))begin //當(dāng)輸入不全為1,即非最大值data_6bits = data_6bits + 1; //從0開(kāi)始累加1#5;end#20 $stop();
endendmodule
仿真結(jié)果是這樣的:
當(dāng)輸入超過(guò)4bits位寬能表示的最大值15時(shí),就會(huì)都飽和處理,即輸出為最大值15。
2.2、有符號(hào)數(shù)Saturate
對(duì)于有符號(hào)數(shù)的Saturate處理有兩種情況:
- 正數(shù)太大無(wú)法表示,只能飽和到最大值。例如4bits有符號(hào)數(shù)最大只能表示 7,那么大于7的數(shù)就只能飽和處理為 7。
- 負(fù)數(shù)太小無(wú)法表示,只能飽和到最小值。例如4bits有符號(hào)數(shù)最小只能表示 -8,那么小于-8的數(shù)就只能飽和處理為 -8。
當(dāng)數(shù)據(jù)溢出時(shí),就直接用最大值或最小值來(lái)表示。因?yàn)闊o(wú)符號(hào)數(shù)不能表示負(fù)數(shù),因此不存在對(duì)于負(fù)數(shù)的飽和處理,只存在正向的飽和。例如要將1個(gè)6bits的數(shù)截?cái)嗟?bits,因?yàn)?bits能表示的最大值是15,那么所有大于15的數(shù),都直接用15來(lái)表示,示意圖如下:
例如,將1個(gè)6bits的有符號(hào)數(shù)Saturate為4bits,對(duì)于數(shù)據(jù)的正向溢出判斷和無(wú)符號(hào)數(shù)的Saturate是類(lèi)似的,只要判斷除了符號(hào)位的多出來(lái)的高位是否有1即可。
對(duì)于數(shù)據(jù)的負(fù)數(shù)方向溢出判斷要麻煩一點(diǎn),首先我們要知道,對(duì)于一個(gè)有符號(hào)的負(fù)數(shù),在其高位擴(kuò)展符號(hào)位,其數(shù)值是不會(huì)改變的。例如:
10\110\1110\11110,它們表示的都是 -2。
把6bits截位到4bits,只要判斷它的高三位(因?yàn)橛懻摰氖秦?fù)數(shù),所以最高位肯定是1)是否都為1就行了,如果是的話(huà),說(shuō)明高3位可是視為是1位符號(hào)位的擴(kuò)展,數(shù)據(jù)的表示范圍等價(jià)于4bits的表示范圍。如果不為全1,則說(shuō)明比4bits的表示范圍要大,即數(shù)據(jù)產(chǎn)生了溢出。
綜上,用Verilog可以這么寫(xiě):
module test(input [5:0] data_6bits,output reg [3:0] data_4bits
);always@(*)
beginif(~data_6bits[5] && (|data_6bits[4:3])) //判斷條件(正數(shù) && 溢出),即正向溢出了data_4bits = 4'b0111; //飽和到最大值7else if(data_6bits[5] && ~(&data_6bits[4:3])) //判斷條件(負(fù)數(shù) && 溢出),即負(fù)向溢出了 data_4bits = 4'b1000; //飽和到最小值-8else data_4bits = data_6bits; //沒(méi)溢出則直接賦值
endendmodule
仍然用上面的TB,仿真結(jié)果如下:
3、Wrap
Wrap從字面上理解是繞回,什么是繞回呢?比如一塊手表,它只能表示0點(diǎn)~12點(diǎn),超出了12點(diǎn)的話(huà),它就會(huì)繞回到0點(diǎn)再重新開(kāi)始。比如13點(diǎn)的表示就是到了12點(diǎn)后,再走到了1點(diǎn)。
對(duì)數(shù)據(jù)的Wrap處理也是類(lèi)似的,比如4bits的無(wú)符號(hào)數(shù)最多只能表示1111(15),這個(gè)時(shí)候如果再加1就是16了,16是表示不了的。Saturate是直接表示最大值15,而Wrap則是重新回到開(kāi)始表示0。類(lèi)似的,17就Wrap到1,18就Wrap到2,19就Wrap到3,依此類(lèi)推。示意圖如下:
對(duì)于有符號(hào)數(shù)的Wrap處理也是一樣的截掉高位,但是因?yàn)橛蟹?hào)數(shù)可以表示負(fù)數(shù),所以它的繞回是從最小的負(fù)數(shù)開(kāi)始的,例如最大的4bits有符號(hào)數(shù)是0111即7,溢出后是1000即-8,示意圖如下:
Wrap處理用Verilog是很好實(shí)現(xiàn)的,因?yàn)樗举|(zhì)上相當(dāng)于截掉高位,而截掉高位這個(gè)操作是可以被綜合工具自動(dòng)實(shí)現(xiàn)的,它甚至都不需要消耗任何邏輯資源。比如,將1個(gè)6bits的輸入Wrap為4bits的輸出,用Verilog可以這么寫(xiě):
module test(input [5:0] data_6bits,output [3:0] data_4bits
);assign data_4bits = data_6bits; //直接賦值即可,工具會(huì)自動(dòng)截位
//等價(jià)于下面的語(yǔ)句
//assign data_4bits = data_6bits[3:0];endmodule
用上面的TB測(cè)試就行,無(wú)符號(hào)數(shù)的測(cè)試結(jié)果如下:
有符號(hào)數(shù)的測(cè)試結(jié)果如下:
可以看到當(dāng)輸入大于4bits能表示的最大值后,就會(huì)回到最小值重新開(kāi)始,相當(dāng)于截掉了高位。
4、總結(jié)
- Saturate相當(dāng)于溢出時(shí),將結(jié)果保留在最大值或最小值;而Wrap則是溢出時(shí)重新繞回到起點(diǎn)。
- 相對(duì)來(lái)說(shuō)Saturate損失的精度比較小,結(jié)果較為準(zhǔn)確,但是消耗的硬件資源比Wrap方式要多;Wrap不需要消耗硬件資源,因?yàn)樗鼘?shí)際上相當(dāng)于截掉高位,等于是沒(méi)有什么處理,精度損失大,結(jié)果不太準(zhǔn)確(尤其是有符號(hào)數(shù)的Wrap),只適用于特定場(chǎng)合。