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

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

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

詳細分析Verilog編寫程序測試無符號數(shù)和有符號數(shù)的乘法

FPGA之家 ? 來源:CSDN技術(shù)社區(qū) ? 作者: DengFengLai123 ? 2021-05-02 10:48 ? 次閱讀

有符號數(shù)的計算在 Verilog 中是一個很重要的問題(也很容易會被忽視),在使用 Verilog 語言編寫 FIR 濾波器時,需要涉及到有符號數(shù)的加法和乘法,在之前的程序中我把所有的輸入輸出和中間信號都定義成有符號數(shù),這樣在計算時沒有出現(xiàn)問題(實際在之前的程序中遇到了問題,最后濾波結(jié)果不對,博客的程序是已經(jīng)改正過的),下面實際試驗一下 Verilog 的乘法問題;

1. 編寫程序測試無符號數(shù)和有符號數(shù)的乘法

編寫程序如下,其中,乘法的兩個乘數(shù)分別是無符號、有符號的四種組合,輸出的積也是分為無符號和有符號,共計 8 種可能;

module signed_test( input [7:0] data_in_unsigned_1, input [7:0] data_in_unsigned_2,

input signed [7:0] data_in_signed_1, input signed [7:0] data_in_signed_2,

output [15:0] data_out_000, output [15:0] data_out_001, output [15:0] data_out_010, output [15:0] data_out_011,

output signed [15:0] data_out_100, output signed [15:0] data_out_101, output signed [15:0] data_out_110, output signed [15:0] data_out_111 );

//無符號 = 無符號 * 無符號assign data_out_000 = data_in_unsigned_1 * data_in_unsigned_2;//無符號 = 無符號 * 有符號assign data_out_001 = data_in_unsigned_1 * data_in_signed_2;//無符號 = 有符號 * 無符號assign data_out_010 = data_in_signed_1 * data_in_unsigned_2;//無符號 = 有符號 * 有符號assign data_out_011 = data_in_signed_1 * data_in_signed_2;

//有符號 = 無符號 * 無符號assign data_out_100 = data_in_unsigned_1 * data_in_unsigned_2;//有符號 = 無符號 * 有符號assign data_out_101 = data_in_unsigned_1 * data_in_signed_2;//有符號 = 有符號 * 無符號assign data_out_110 = data_in_signed_1 * data_in_unsigned_2;//有符號 = 有符號 * 有符號assign data_out_111 = data_in_signed_1 * data_in_signed_2;

endmodule

生成的 RTL 圖如下:

可以看到,輸出的積和符號無關(guān),有符號數(shù)和無符號數(shù)實際上是同一個數(shù),只看我們怎么定義它,比如乘積是 16 位的二進制 16’b1100_0000_0000_0011,當(dāng)我們認為它是無符號數(shù)是,最高位的 1 就不是符號位,而是 2^15(2的15次方),這樣這個數(shù)代表的十進制是 2^15 + 2^14 + 2^1 + 2^0 = 49155;

4e28e056-9d13-11eb-8b86-12bb97331649.png

如果把 16 位的二進制 16’b1100_0000_0000_0011 當(dāng)成是一個有符號數(shù)來看,那么最高位是符號位,且剩下的數(shù)據(jù)時原來的數(shù)據(jù)二進制表示后取反再加1(補碼表示),要計算它對應(yīng)的十進制數(shù)

(1) 先去掉符號位,保留剩下的 15-bit 的 100_0000_0000_0011;

(2) 把 100_0000_0000_0011 取反,得到 011_1111_1111_1100;

(3) 把 011_1111_1111_1100 的最低位 + 1,得到 011_1111_1111_1101;

(4) 011_1111_1111_1101 按照無符號數(shù)換算成十進制是 16381;

(5) 把最高位符號位加上,0代表正數(shù),1代表負數(shù),所以最后換算是 -16831;

Windows 計算器默認最高位是符號位;

4e3eb69c-9d13-11eb-8b86-12bb97331649.png

測試數(shù)據(jù)如下:

initial begin data_in_unsigned_1 = 8‘hff; //255 data_in_unsigned_2 = 8’hf0; //240 data_in_signed_1 = 8‘hff; //-1 data_in_signed_2 = 8’hf0; //-16 #200; data_in_unsigned_1 = 8‘hff; //255 data_in_unsigned_2 = 8’h0f; //15 data_in_signed_1 = 8‘hff; //-1 data_in_signed_2 = 8’h0f; //15 #200; data_in_unsigned_1 = 8‘d127; //127 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = -8‘sd127; //-127,十進制有符號數(shù)賦值,必須要用 sd 表示 data_in_signed_2 = -8’sd15; //-15 #200; data_in_unsigned_1 = 8‘d128; //128 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = -8‘sd128; //-128 data_in_signed_2 = -8’sd15; //-15 #200; data_in_unsigned_1 = 8‘d127; //127 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = -8‘sd127; //-127 data_in_signed_2 = 8’sd15; //15 #200; data_in_unsigned_1 = 8‘d128; //128 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = -8‘sd128; //-128 data_in_signed_2 = 8’sd15; //15 #200; data_in_unsigned_1 = 8‘d127; //127 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = 8‘sd127; //127 data_in_signed_2 = -8’sd15; //-15 #200; data_in_unsigned_1 = 8‘d127; //127 data_in_unsigned_2 = 8’d15; //15 data_in_signed_1 = 8‘sd127; //127 data_in_signed_2 = 8’sd15; //15 #200; $stop;end

2. 仿真分析

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

4e6ffb26-9d13-11eb-8b86-12bb97331649.png

對上圖分析:

(1) 在 0 ~ 400 ns,仿真中使用十六進制賦值相同的十六進制數(shù)據(jù)給乘數(shù),讓乘數(shù)分別以無符號數(shù)和有符號數(shù)進行讀取,可以看到對 8’hff(對應(yīng)二進制 8’b1111_1111)以無符號數(shù)讀取時是按照 原碼 讀取,對應(yīng)十進制 255,以有符號數(shù)讀取時是按照補碼讀取,按照上文所說的去掉符號位后取反、加1再計算十進制得 -1;

(2) 直接賦值十進制數(shù)據(jù),乘數(shù)在以無符號數(shù)讀取時時按照原碼讀取,127就對應(yīng) 8 位二進制數(shù) 8’b0111_1111,十進制 128 就對應(yīng) 8 位二進制 8’b1000_0000;而以有符號數(shù)讀取的時候是會直接轉(zhuǎn)換為補碼形式,如 -127,先去掉符號位是 127,對應(yīng) 7 位二進制數(shù) 7’b111_1111,取反為 7’b000_0000,加 1 為 7’b000_0001,將符號位補回到最高位為 8’b1000_0001;對于 -128 的表示比較特殊,8-bit的二進制數(shù)最高位是符號位,表示正負,剩下的 7-bit 能夠表示的數(shù)的范圍是 0 ~ 127,前面加上 ± 就能表示 -127 ~ 127,其中有 2 個數(shù)很特殊就是 8’b0000_0000 和 8’b1000_0000,按照上面會出現(xiàn) +0 和 -0,為了區(qū)分出這兩個數(shù),前人定義 8’b0000_0000 表示 0,而 8’b1000_0000 表示 -128,這樣不僅能區(qū)分開兩個數(shù),還多表示了一個數(shù) -128(整個計算機體系通用,其他位數(shù)時類似表示一個負數(shù));

4e7a71dc-9d13-11eb-8b86-12bb97331649.png

(3) 實際上,觀察下圖數(shù)據(jù)可以發(fā)現(xiàn),只有data_out_000 和 data_out_111 的數(shù)據(jù)時全部計算正確的,這也符合常理:

無符號 * 無符號 = 無符號;

有符號 * 有符號 = 有符號;

其它的計算為什么會出錯呢?實際上這里遵循一個原則:

如果表達式中有一個無符號數(shù),則所有的操作數(shù)都會被強行轉(zhuǎn)換為無符號數(shù);

這樣也就解釋了 0 ~ 400 ns 時的 data_out_001 和 data_out_010 的計算結(jié)果和 data_out_000 完全一致,它們都是把賦值的 8 位十六進制數(shù)當(dāng)做無符號數(shù)計算的(這里不存在十進制到二進制原碼、補碼換算的問題,因為給的是十六進制);

當(dāng)后面設(shè)計輸入輸出時,如果是有符號,那么將相關(guān)計算的輸入/輸出和中間量都顯式的用 signed 定義;

4ea872a8-9d13-11eb-8b86-12bb97331649.png

3. 有符號數(shù)乘法的另一種計算

前面說的計算時將涉及到的相關(guān)量全部定義為有符號數(shù)是一種計算方法,此外,通常情況下可能會定義的無符號數(shù),但是實際傳入的是有符號數(shù),比如下面的輸入和輸出都沒有指定成 signed 有符號數(shù),計算時默認是按照無符號數(shù)計算(實際上我感覺是把讀取到的 8 位二進制數(shù)當(dāng)做原碼去算),此時若外部傳入的數(shù)據(jù)實際上是有符號數(shù)(比如 FIR 濾波器傳入了正負均有的待濾波信號),那么需要對符號位進行擴展來計算乘法和加法;

module signed_test_2( input [7:0] data_in_1, input [7:0] data_in_2, output [15:0] data_out_1, output [15:0] data_out_2);

對于乘法,需要擴展符號位 到 和積的位數(shù)相等,比如乘數(shù)a為 N-bit,乘數(shù) b 為M-bit,兩個相乘得到 N+M 位數(shù)據(jù),此時需要對 a 擴展 M-bit 到 N+M 位,對 b 擴展 N-bit 到 N+M 位;

下面,使用 位拼接符 { } 來做演示,位拼接符可以按照二進制的位來進行高低位的拼接,假設(shè) data_in_1= 8’b1000_0011,對于 {{8{data_in_1[7]}},data_in_1} 可以這樣理解:

(1) 先看 8{data_in_1[7]},表示取出 8-bit 數(shù)據(jù) data_in_1 的最高位 data_in_1[7],重復(fù) 8 次,相當(dāng)于 { data_in_1[7], data_in_1[7], data_in_1[7], data_in_1[7], data_in_1[7], data_in_1[7], data_in_1[7], data_in_1[7] },即高位擴展 8-bit 的 1

(2) {{8{data_in_1[7]}},data_in_1} 相當(dāng)于在 data_in_1 的前面補上 8 個 data_in_1[7],即 結(jié)果為 16-bit 的 16’b1111_1111_1000_0011;

//不做符號位擴展,直接相乘assign data_out_1 = data_in_1 * data_in_2;//做符號位擴展,再相乘assign data_out_2 = {{8{data_in_1[7]}},data_in_1} * {{8{data_in_2[7]}},data_in_2};

仿真測試數(shù)據(jù)如下,1 處用十六進制給出數(shù)據(jù),2 處用有符號的十進制賦值,3 處是為了和 2 處對比,看最后賦值是否一樣(看到有博客說 3 的賦值是錯的,所以測試一下);

4eb7e68e-9d13-11eb-8b86-12bb97331649.png

仿真結(jié)果如下,可以看到上圖 2 處和 3 處的賦值在仿真時是同樣的數(shù)據(jù),把所有數(shù)據(jù)都用有符號的十進制數(shù)顯示(右鍵數(shù)據(jù) Radix -》 Signed Decimal);

4ec3fa3c-9d13-11eb-8b86-12bb97331649.png

可以看到,data_out_1的結(jié)果是錯的(沒有補符號位),data_out_2的結(jié)果是對的(補符號位);

4ecead7e-9d13-11eb-8b86-12bb97331649.png

對有符號數(shù)的加法,同樣的,要么相關(guān)的運算全部定義成有符號數(shù),要么進行符號位的擴展,對于加法操作,只需要每個被加數(shù)擴展 1 位符號位即可;

除此之外,還可以調(diào)用乘法器的 IP 來代替 乘法符號 *,或者加法器的 IP 來代替 加法符號 +,在 IP 核中配置輸入輸出為有符號數(shù)即可。
編輯:lyn

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

    關(guān)注

    159

    文章

    7664

    瀏覽量

    177194
  • Verilog
    +關(guān)注

    關(guān)注

    28

    文章

    1335

    瀏覽量

    109857
  • RTL
    RTL
    +關(guān)注

    關(guān)注

    1

    文章

    385

    瀏覽量

    59625
  • Vivado
    +關(guān)注

    關(guān)注

    19

    文章

    799

    瀏覽量

    66134

原文標(biāo)題:Verilog學(xué)習(xí)筆記——有符號數(shù)的乘法和加法

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    LM70 SPI/MICROWIRE 10位帶符號數(shù)字溫度傳感器數(shù)據(jù)表

    電子發(fā)燒友網(wǎng)站提供《LM70 SPI/MICROWIRE 10位帶符號數(shù)字溫度傳感器數(shù)據(jù)表.pdf》資料免費下載
    發(fā)表于 08-14 09:28 ?0次下載
    LM70 SPI/MICROWIRE 10位帶<b class='flag-5'>符號數(shù)</b>字溫度傳感器數(shù)據(jù)表

    LM12454/LM12458/LM12H458 12位符號數(shù)據(jù)采集系統(tǒng)數(shù)據(jù)表

    電子發(fā)燒友網(wǎng)站提供《LM12454/LM12458/LM12H458 12位符號數(shù)據(jù)采集系統(tǒng)數(shù)據(jù)表.pdf》資料免費下載
    發(fā)表于 07-22 09:25 ?0次下載
    LM12454/LM12458/LM12H458 12位<b class='flag-5'>符號數(shù)</b>據(jù)采集系統(tǒng)數(shù)據(jù)表

    verilog系統(tǒng)函數(shù)

    (1)fwrite是需要觸發(fā)條件的,需要手動添加換行。 (2)如果寫放文件的格式為%d,則認為是符號數(shù),
    的頭像 發(fā)表于 07-05 11:48 ?608次閱讀
    <b class='flag-5'>verilog</b>系統(tǒng)函數(shù)

    時間繼電器的電磁符號和字母符號是什么

    時間繼電器,作為電氣控制系統(tǒng)中不可或缺的元件,其精確的延時功能對于整個系統(tǒng)的穩(wěn)定運行至關(guān)重要。為了更好地理解和使用時間繼電器,了解其電磁符號和字母符號顯得尤為重要。本文將詳細闡述時間繼電器的電磁
    的頭像 發(fā)表于 06-29 11:48 ?939次閱讀

    電壓繼電器的圖形符號和文字符號是什么

    電壓繼電器是一種電氣設(shè)備,用于在電路中檢測電壓水平,并在達到特定閾值時觸發(fā)開關(guān)或其他控制設(shè)備。在本文中,我們將詳細討論電壓繼電器的圖形符號和文字符號,以及它們的應(yīng)用和工作原理。 電壓繼電器的圖形
    的頭像 發(fā)表于 06-24 09:51 ?1391次閱讀

    matlab與FPGA數(shù)字信號處理系列 Verilog 實現(xiàn)并行 FIR 濾波器

    ; 量化后導(dǎo)出參數(shù),可以直接用 .coe 文件導(dǎo)出備用,導(dǎo)出后 matlab 也會自動打開系數(shù)文件,用 Verilog 語言的常數(shù)定義參數(shù) h0 ~ h7(注意指定為符號數(shù)); 此外,除了將量化后
    發(fā)表于 05-24 07:48

    verilog實現(xiàn)卷積運算

    Verilog中實現(xiàn)卷積運算,你可以使用以下示例代碼。這里假設(shè)輸入數(shù)據(jù)是符號8位數(shù),輸出數(shù)據(jù)也是符號8位數(shù)。卷積在數(shù)字信號處理中通常指
    發(fā)表于 03-26 07:51

    char是符號類型還是符號類型?

    看一個C語言的筆試題,題目很簡單,問char是符號類型還是符號類型?
    的頭像 發(fā)表于 03-17 10:15 ?1071次閱讀

    labview編寫程序的一般步驟

    LabVIEW是一種非常強大的圖形化編程工具,它可用于控制、測量、測試和監(jiān)控應(yīng)用。編寫LabVIEW程序的一般步驟包括以下幾個方面: 程序需求分析
    的頭像 發(fā)表于 12-29 10:06 ?1764次閱讀

    verilog中數(shù)據(jù)的符號屬性(符號數(shù)符號數(shù))探究根源

    為了省流,還是先甩結(jié)論。符號數(shù)符號數(shù)的最本質(zhì)區(qū)別就是:符號位的識別和高位拓展。除此之外,另一個區(qū)別就是從人的角度如何如何讀這個數(shù),或者
    的頭像 發(fā)表于 12-10 10:50 ?1287次閱讀
    <b class='flag-5'>verilog</b>中數(shù)據(jù)的<b class='flag-5'>符號</b>屬性(<b class='flag-5'>有</b><b class='flag-5'>符號數(shù)</b>和<b class='flag-5'>無</b><b class='flag-5'>符號數(shù)</b>)探究根源

    verilog中有符號數(shù)符號數(shù)的本質(zhì)探究

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

    codeblocks怎么編寫程序

    ::Blocks編寫程序的過程,以使您對其操作更深入的了解。 首先,我們需要下載并安裝Code::Blocks。您可以在官方網(wǎng)站https://www.codeblocks.org/上找到適用于您的操作系統(tǒng)的安裝程序。安裝過程
    的頭像 發(fā)表于 11-26 10:28 ?1268次閱讀

    怎樣在codeblocks上編寫程序

    在CodeBlocks上編寫程序是一項相對簡單而又重要的任務(wù)。CodeBlocks是一個廣泛使用的集成開發(fā)環(huán)境(IDE),它能夠幫助程序編寫、編譯和運行他們的代碼。在本篇文章中,我們將詳細
    的頭像 發(fā)表于 11-26 09:26 ?1344次閱讀

    虛擬機linux怎么編寫程序

    在虛擬機Linux上編寫程序是一項非常常見且有用的任務(wù)。無論是開發(fā)一個簡單的腳本、一個Web應(yīng)用程序還是一個復(fù)雜的軟件項目,Linux提供了強大的工具和環(huán)境來幫助你進行編程。本文將詳細介紹如何在
    的頭像 發(fā)表于 11-17 10:08 ?1507次閱讀

    符號整型能產(chǎn)生哪些bug?

    為什么不建議使用符號整型,符號整型能產(chǎn)生哪些bug?
    的頭像 發(fā)表于 11-09 17:09 ?442次閱讀
    <b class='flag-5'>無</b><b class='flag-5'>符號</b>整型能產(chǎn)生哪些bug?