0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

verilog中數(shù)據(jù)的符號(hào)屬性(有符號(hào)數(shù)和無(wú)符號(hào)數(shù))探究根源

FPGA開(kāi)源工坊 ? 來(lái)源:FPGA開(kāi)源工坊 ? 2023-12-10 10:50 ? 次閱讀

不知道有沒(méi)有人像我一樣,長(zhǎng)久以來(lái)將verilog中的有符號(hào)數(shù)視為不敢觸碰的禁區(qū)。不過(guò)俗話說(shuō)啊解決恐懼的最好辦法就是直面恐懼,又有俗話說(shuō)要想工其事必先利其器,還有俗話說(shuō)磨刀不誤砍柴工,也有俗話說(shuō)The only thing we have to fear is fear itself,所以今天咱們就嘗試對(duì)verilog中數(shù)據(jù)的符號(hào)屬性(有符號(hào)數(shù)和無(wú)符號(hào)數(shù))探究根源。

本文的驗(yàn)證環(huán)境基于VCS通過(guò)auto_testbench生成,相關(guān)的vcs命令行細(xì)節(jié)請(qǐng)?jiān)赼uto_testbench工程目錄下查詢。

先說(shuō)明一個(gè)大前提,有符號(hào)數(shù)即補(bǔ)碼表示,無(wú)符號(hào)數(shù)即原碼表示或者說(shuō)必然是整數(shù)的補(bǔ)碼表示,因此有符號(hào)數(shù)和無(wú)符號(hào)數(shù)均可以認(rèn)為是數(shù)值的補(bǔ)碼。

為了省流,還是先甩結(jié)論。有符號(hào)數(shù)和無(wú)符號(hào)數(shù)的最本質(zhì)區(qū)別就是:符號(hào)位的識(shí)別和高位拓展。除此之外,另一個(gè)區(qū)別就是從人的角度如何如何讀這個(gè)數(shù),或者說(shuō)$display(%d)打印時(shí)打印的值是什么(而從機(jī)器的角度它壓根就不區(qū)分signed和unsigned)。也就是說(shuō),如果不涉及到位寬拓展的事,有符號(hào)數(shù)和無(wú)符號(hào)數(shù)在verilog運(yùn)算中可以說(shuō)毫無(wú)差別。

所以先給出兩個(gè)結(jié)論,verilog中數(shù)據(jù)的符號(hào)屬性會(huì)影響兩件事:

1.符號(hào)位的識(shí)別和位寬拓展,有符號(hào)數(shù)最高位被識(shí)別為符號(hào)位,高位拓展時(shí)拓展符號(hào)位,無(wú)符號(hào)數(shù)高位拓展0;

2.數(shù)據(jù)的實(shí)際值(人的角度如何如何讀這個(gè)數(shù));

顯然,這個(gè)這個(gè)結(jié)論和固有的認(rèn)知出入有點(diǎn)大,不急咱們先看一個(gè)實(shí)驗(yàn)。下面的代碼是一段不涉及到位寬拓展的運(yùn)算,t0_va0為有符號(hào)數(shù)-1,也就是16'hffff:


	

	
logic signed[15:0]t0_va0 = -1;//16'hffff wire signed[15:0]t0_en0 = t0_va0 + 16'hffff; wire [15:0]t0_en1 = t0_va0 + 16'hffff; wire signed[15:0]t0_en2 = t0_va0 + $signed(16'hffff); wire [15:0]t0_en3 = t0_va0 + $signed(16'hffff); wire signed[15:0]t0_en4 = t0_va0 - 16'h1; wire signed[15:0]t0_en5 = t0_va0 - $unsigned(16'h1); wire [15:0]t0_en6 = t0_va0 - 16'h1; wire [15:0]t0_en7 = t0_va0 - $unsigned(16'h1);

仿真的結(jié)果如下:

0a9fb1d4-9699-11ee-8b88-92fbcf53809c.png

可以看到所有的結(jié)果都是一致的。而如果將va0信號(hào)改成無(wú)符號(hào)數(shù):


	

	
logic [15:0]t1_va0 = 16'hffff; wire signed[15:0]t1_en0 = t1_va0 + 16'hffff; wire [15:0]t1_en1 = t1_va0 + 16'hffff; wire signed[15:0]t1_en2 = t1_va0 + $signed(16'hffff); wire [15:0]t1_en3 = t1_va0 + $signed(16'hffff); wire signed[15:0]t1_en4 = t1_va0 - 16'h1; wire signed[15:0]t1_en5 = t1_va0 - $unsigned(16'h1); wire [15:0]t1_en6 = t1_va0 - 16'h1; wire [15:0]t1_en7 = t1_va0 - $unsigned(16'h1);

其仿真結(jié)果也是一致的:

0ab7e54c-9699-11ee-8b88-92fbcf53809c.png

而一旦涉及到運(yùn)算結(jié)果位寬拓展結(jié)果就有所差別了,比如將結(jié)果的位寬都改成18bit:


	

	
logic signed[15:0]t2_va0 = -1; wire signed[17:0]t2_en0 = t2_va0 + 16'hffff; wire [17:0]t2_en1 = t2_va0 + 16'hffff; wire signed[17:0]t2_en2 = t2_va0 + $signed(16'hffff); wire [17:0]t2_en3 = t2_va0 + $signed(16'hffff); wire signed[17:0]t2_en4 = t2_va0 - 16'h1; wire signed[17:0]t2_en5 = t2_va0 - $unsigned(16'h1); wire [17:0]t2_en6 = t2_va0 - 16'h1; wire [17:0]t2_en7 = t2_va0 - $unsigned(16'h1);

看到的波形就是這樣:

0ac61630-9699-11ee-8b88-92fbcf53809c.png

這個(gè)事就有些神奇了,所以后面就是說(shuō)明下這里面的區(qū)別,或者說(shuō)在完成運(yùn)算后工具是如何識(shí)別這個(gè)數(shù)的符號(hào)性以決定位寬拓展的結(jié)果的。在開(kāi)始之前必須明確下一個(gè)有符號(hào)數(shù)(補(bǔ)碼),'h1fffe和'hfffe對(duì)于機(jī)器是沒(méi)有區(qū)別的,都是-2。

仿真工具在對(duì)一個(gè)運(yùn)算結(jié)果進(jìn)行位寬拓展時(shí),會(huì)先識(shí)別這個(gè)數(shù)的符號(hào)屬性,那么具體是怎么識(shí)別的呢?

1.有符號(hào)數(shù)和有符號(hào)數(shù)運(yùn)算,結(jié)果為有符號(hào)數(shù);

2.有符號(hào)數(shù)和無(wú)符號(hào)數(shù)運(yùn)算,結(jié)果為無(wú)符號(hào)數(shù);

3.無(wú)符號(hào)數(shù)和無(wú)符號(hào)數(shù)運(yùn)算,結(jié)果為無(wú)符號(hào)數(shù);

4.運(yùn)算結(jié)果外又通過(guò)$signed和$unsigned定向指定時(shí),最終的符號(hào)屬性遵照指定結(jié)果;

5.等號(hào)左側(cè)信號(hào)聲明中的signed/unsigned不影響右側(cè)運(yùn)算結(jié)果的符號(hào)數(shù)屬性;

好,咱們一個(gè)一個(gè)看。

有符號(hào)數(shù)和有符號(hào)數(shù)運(yùn)算,結(jié)果為有符號(hào)數(shù)。


	

	
logic signed[15:0]t3_va0 = -1; wire signed[17:0]t3_en0 = t3_va0 - $signed(16'h1); wire signed[17:0]t3_en1 = t3_va0 + $signed(16'hffff); wire [17:0]t3_en2 = t3_va0 - $signed(16'h1); wire [17:0]t3_en3 = t3_va0 + $signed(16'hffff);

0ad7a044-9699-11ee-8b88-92fbcf53809c.png

很顯然,兩個(gè)有符號(hào)數(shù)進(jìn)行操作結(jié)果是有符號(hào)數(shù),位寬拓展時(shí)拓展符號(hào)位。同時(shí)這個(gè)波形還說(shuō)明了等號(hào)左側(cè)信號(hào)聲明中的signed/unsigned不影響右側(cè)運(yùn)算結(jié)果的符號(hào)數(shù)屬性。

有符號(hào)數(shù)和無(wú)符號(hào)數(shù)運(yùn)算,結(jié)果為無(wú)符號(hào)數(shù)。


	

	
wire signed[17:0]t3_en4 = t3_va0 - 16'h1; wire signed[17:0]t3_en5 = t3_va0 + 16'hffff; wire [17:0]t3_en6 = t3_va0 - 16'h1; wire [17:0]t3_en7 = t3_va0 + 16'hffff;
0aeab6de-9699-11ee-8b88-92fbcf53809c.png顯然結(jié)果是無(wú)符號(hào)數(shù),高位拓展時(shí)拓展的都是0。

無(wú)符號(hào)數(shù)和無(wú)符號(hào)數(shù)運(yùn)算,結(jié)果為無(wú)符號(hào)數(shù)。這個(gè)不說(shuō)了,顯而易見(jiàn)的事情。

運(yùn)算結(jié)果外又通過(guò)$signed和$unsigned定向指定時(shí),最終的符號(hào)屬性遵照指定結(jié)果。


	

	
wire signed[17:0]t3_en8 = $unsigned(t3_va0 - $signed(16'h1)); wire signed[17:0]t3_en9 = $unsigned(t3_va0 + $signed(16'hffff)); wire [17:0]t3_en10 = $signed(t3_va0 - 16'h1); wire [17:0]t3_en11 = $signed(t3_va0 + 16'hffff);
0afc075e-9699-11ee-8b88-92fbcf53809c.png因?yàn)樵谶\(yùn)算之后又通過(guò)$signed和$unsigned指定了符號(hào)屬性,所以后面的位寬拓展就按照對(duì)應(yīng)的屬性來(lái)了。再次進(jìn)一步的佐證,等號(hào)左側(cè)信號(hào)聲明中的signed/unsigned不影響右側(cè)運(yùn)算結(jié)果的符號(hào)數(shù)屬性。

好了現(xiàn)在我們?cè)侔亚拔牡慕Y(jié)論翻出來(lái),verilog中的符號(hào)屬性會(huì)影響兩件事情:

1.符號(hào)位的識(shí)別和位寬拓展,有符號(hào)數(shù)最高位被識(shí)別為符號(hào)位,高位拓展時(shí)拓展符號(hào)位,無(wú)符號(hào)數(shù)高位拓展0;

2.數(shù)據(jù)的實(shí)際值(人的角度如何如何讀這個(gè)數(shù));

再看這個(gè)測(cè)試就很好解釋了:


	

	
logic signed[15:0]t2_va0 = -1; wire signed[17:0]t2_en0 = t2_va0 + 16'hffff; //就是'hffff+'hffff = 'h1fffe wire [17:0]t2_en1 = t2_va0 + 16'hffff; //同上 wire signed[17:0]t2_en2 = t2_va0 + $signed(16'hffff); //本質(zhì)還是'hffff+'hffff = 'h1fffe,不過(guò)因?yàn)榻Y(jié)果是有符號(hào)數(shù),拓展位寬為18bit時(shí)拓展為18'h3fffe wire [17:0]t2_en3 = t2_va0 + $signed(16'hffff); //同上 wire signed[17:0]t2_en4 = t2_va0 - 16'h1; //本質(zhì)是'hffff-'h1,或者理解成'hffff+'hffff,加上一個(gè)負(fù)數(shù)位寬一定不需要高位拓展,所以結(jié)果是'hfffe //再根據(jù)等號(hào)左側(cè)的需求拓展為18bit,無(wú)符號(hào)數(shù)拓展0,結(jié)果為18'fffe wire signed[17:0]t2_en5 = t2_va0 - $unsigned(16'h1); //同上 wire [17:0]t2_en6 = t2_va0 - 16'h1; //同上 wire [17:0]t2_en7 = t2_va0 - $unsigned(16'h1); //同上

0b10ff92-9699-11ee-8b88-92fbcf53809c.png

再來(lái)補(bǔ)充一個(gè),大家看看結(jié)果應(yīng)該是啥:


	

	
wire [17:0]t2_en8 = t2_va0 - $signed(16'h1);

顯然結(jié)果應(yīng)該是18'h3fffe,因?yàn)樽髠?cè)的運(yùn)算結(jié)果是有符號(hào)數(shù)的16'hfffe,拓展成18bit時(shí)拓展符號(hào)位1:

0b254614-9699-11ee-8b88-92fbcf53809c.png

最后呢再看一組額外的實(shí)驗(yàn),感興趣的可以分析一下結(jié)果:

	

	
//test logic [1:0]va_u; logic signed[1:0]va_s; logic [2:0]vb_u; logic [2:0]vb_s; logic [31:0]vc_u; logic [31:0]vc_s; initial begin va_u = -1; va_s = -1;//signed $display("va_u='b%0b, va_s='b%0b", va_u, va_s); $display("va_u=%0d, va_s=%0d", va_u, va_s); vb_u = -va_u; vb_s = -va_s; $display("vb_u='b%0b, vb_s='b%0b", vb_u, vb_s); $display("vb_u=%0d, vb_s=%0d", vb_u, vb_s); vc_u = va_u; vc_s = va_s; $display("vc_u='b%0b, vc_s='b%0b", vc_u, vc_s); end

仿真的結(jié)果為:


	

	
va_u='b11, va_s='b11 va_u=3, va_s=-1 vb_u='b101, vb_s='b1 vb_u=5, vb_s=1 vc_u='b11, vc_s='b11111111111111111111111111111111



聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1333

    瀏覽量

    109713
  • 運(yùn)算
    +關(guān)注

    關(guān)注

    0

    文章

    127

    瀏覽量

    25738
  • 符號(hào)
    +關(guān)注

    關(guān)注

    0

    文章

    55

    瀏覽量

    4283

原文標(biāo)題:【芯片設(shè)計(jì)】verilog中有符號(hào)數(shù)和無(wú)符號(hào)數(shù)的本質(zhì)探究

文章出處:【微信號(hào):FPGA開(kāi)源工坊,微信公眾號(hào):FPGA開(kāi)源工坊】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    關(guān)于verilog無(wú)符號(hào)數(shù)符號(hào)數(shù)

    在數(shù)字電路,出于應(yīng)用的需要,我們可以使用無(wú)符號(hào)數(shù),即包括0及整數(shù)的集合;也可以使用符號(hào)數(shù),即包括0和正負(fù)數(shù)的集合。在更加復(fù)雜的系統(tǒng)
    的頭像 發(fā)表于 11-18 17:46 ?1.7w次閱讀

    verilog中有符號(hào)數(shù)無(wú)符號(hào)數(shù)的本質(zhì)探究

    不知道有沒(méi)有人像我一樣,長(zhǎng)久以來(lái)將verilog符號(hào)數(shù)視為不敢觸碰的禁區(qū)。
    的頭像 發(fā)表于 12-04 16:13 ?772次閱讀
    <b class='flag-5'>verilog</b>中有<b class='flag-5'>符號(hào)數(shù)</b>和<b class='flag-5'>無(wú)</b><b class='flag-5'>符號(hào)數(shù)</b>的本質(zhì)<b class='flag-5'>探究</b>

    采集的數(shù)據(jù)轉(zhuǎn)換成符號(hào)數(shù)的問(wèn)題

    的時(shí)候怎么都不正確,具體原因如下,字符串轉(zhuǎn)數(shù)值的時(shí)候只發(fā)現(xiàn)可以轉(zhuǎn)換成無(wú)符號(hào)數(shù),而采集下來(lái)的數(shù)據(jù)符號(hào)數(shù),轉(zhuǎn)換成
    發(fā)表于 05-02 11:55

    原碼、補(bǔ)碼、反碼、符號(hào)數(shù)、無(wú)符號(hào)數(shù)概念.pdf

    原碼、補(bǔ)碼、反碼、符號(hào)數(shù)、無(wú)符號(hào)數(shù)概念.pdf
    發(fā)表于 11-15 08:44

    符號(hào)數(shù)無(wú)符號(hào)數(shù),浮點(diǎn)數(shù)探討

    本帖最后由 hq1987 于 2015-4-29 11:52 編輯 對(duì)于無(wú)符號(hào)數(shù)大家都基本理解,我主要說(shuō)說(shuō)符號(hào)數(shù),浮點(diǎn)數(shù)在機(jī)器世界里到底是怎么表示的。1、
    發(fā)表于 04-29 10:15

    關(guān)于無(wú)符號(hào)數(shù)符號(hào)數(shù)的困惑

    ,存儲(chǔ)無(wú)符號(hào)數(shù))Tab = -4'd12;//整數(shù)Tab的十進(jìn)制數(shù)為-12,位形式為110100.(因?yàn)門(mén)ab是整數(shù)寄存器變量,存儲(chǔ)符號(hào)數(shù))我的困惑是,-12的二進(jìn)制補(bǔ)碼應(yīng)該是101
    發(fā)表于 11-02 14:13

    請(qǐng)問(wèn)AFE5801 AD轉(zhuǎn)換后數(shù)字信號(hào)是用符號(hào)數(shù)還是無(wú)符號(hào)數(shù)表示?

    請(qǐng)問(wèn)AFE5801 AD轉(zhuǎn)換后數(shù)字信號(hào)是用符號(hào)數(shù)還是無(wú)符號(hào)數(shù)表示的啊?
    發(fā)表于 05-24 08:04

    雙狀態(tài)無(wú)符號(hào)/符號(hào)數(shù)據(jù)類型

    雙狀態(tài)無(wú)符號(hào)數(shù)據(jù)類型雙狀態(tài)符號(hào)數(shù)據(jù)類型四狀態(tài)數(shù)據(jù)類型
    發(fā)表于 01-18 06:03

    單字節(jié)無(wú)符號(hào)數(shù)據(jù)塊排序(增序)

    單字節(jié)無(wú)符號(hào)數(shù)據(jù)塊排序(增序)   入口條件:數(shù)據(jù)塊的首址在R0,字節(jié)數(shù)在R7。出口信息:完成排序(增序)影響資
    發(fā)表于 01-19 22:58 ?1073次閱讀

    fpga 符號(hào)數(shù)無(wú)符號(hào)數(shù)

    ?在設(shè)計(jì),所有的算數(shù)運(yùn)算符都是按照無(wú)符號(hào)數(shù)進(jìn)行的。如果要完成符號(hào)數(shù)計(jì)算,對(duì)于加、減操作通過(guò)補(bǔ)碼處理即可用
    的頭像 發(fā)表于 10-09 15:22 ?5922次閱讀
    fpga <b class='flag-5'>有</b><b class='flag-5'>符號(hào)數(shù)</b>、<b class='flag-5'>無(wú)</b><b class='flag-5'>符號(hào)數(shù)</b>

    FPGA符號(hào)數(shù)乘法操作指南

    FPGA乘法器是很稀缺的資源,但也是我們做算法必不可少的資源。7系列及之前的FPGA都是25x18的DSP,UltraScale是27x18,我們可以通過(guò)調(diào)IP Core的方式或者原語(yǔ)的方式來(lái)進(jìn)行乘法操作。在里面可以設(shè)置
    的頭像 發(fā)表于 03-08 17:14 ?6521次閱讀
    FPGA<b class='flag-5'>有</b><b class='flag-5'>符號(hào)數(shù)</b>乘法操作指南

    詳細(xì)分析Verilog編寫(xiě)程序測(cè)試無(wú)符號(hào)數(shù)符號(hào)數(shù)的乘法

    符號(hào)數(shù)的計(jì)算在 Verilog 是一個(gè)很重要的問(wèn)題(也很容易會(huì)被忽視),在使用 Verilog 語(yǔ)言編寫(xiě) FIR 濾波器時(shí),需要涉及到
    的頭像 發(fā)表于 05-02 10:48 ?7124次閱讀
    詳細(xì)分析<b class='flag-5'>Verilog</b>編寫(xiě)程序測(cè)試<b class='flag-5'>無(wú)</b><b class='flag-5'>符號(hào)數(shù)</b>和<b class='flag-5'>有</b><b class='flag-5'>符號(hào)數(shù)</b>的乘法

    C語(yǔ)言中無(wú)符號(hào)數(shù)符號(hào)數(shù)的左移和右移

    。那么對(duì)于無(wú)符號(hào)數(shù)符號(hào)數(shù),對(duì)于左移和右移的操作分別是如何呢?下面通過(guò)實(shí)驗(yàn)來(lái)進(jìn)行驗(yàn)證:對(duì)于無(wú)符號(hào)數(shù)
    發(fā)表于 01-13 13:17 ?2次下載
    C語(yǔ)言中<b class='flag-5'>無(wú)</b><b class='flag-5'>符號(hào)數(shù)</b>和<b class='flag-5'>有</b><b class='flag-5'>符號(hào)數(shù)</b>的左移和右移

    FPGA符號(hào)數(shù)乘法說(shuō)明

    FPGA乘法器是很稀缺的資源,但也是我們做算法必不可少的資源。7系列及之前的FPGA都是25x18的DSP,UltraScale是27x18,我們可以通過(guò)調(diào)IP Core的方式或者原語(yǔ)的方式來(lái)進(jìn)行乘法操作。在里面可以設(shè)置
    的頭像 發(fā)表于 02-16 16:21 ?4649次閱讀
    FPGA<b class='flag-5'>中</b>的<b class='flag-5'>有</b><b class='flag-5'>符號(hào)數(shù)</b>乘法說(shuō)明

    關(guān)于符號(hào)數(shù)據(jù)類型的示例

    我們學(xué)習(xí)一下Systemverilog符號(hào)數(shù)據(jù)類型的賦值。
    的頭像 發(fā)表于 10-17 14:40 ?884次閱讀