Verilog 實數(shù)整數(shù)轉(zhuǎn)換

2022-05-20 14:38 更新

關鍵詞 :定點數(shù), 浮點數(shù), $realtobits, $bitstoreal

本節(jié)主要介紹實數(shù)與整數(shù)間相互轉(zhuǎn)換的函數(shù):?$realtobits?, ?$bitstoreal?,同時說明下 real 型 (同 C 語言中的 double float)變量是怎么用多位寬的二進制碼表示的。

二進制表示方法

二進制表示小數(shù)

十進制整數(shù)用二進制來表示時,需要進行數(shù)據(jù)除以 2 然后取余的操作。

小數(shù)部分用二進制來表示時恰好相反,需要進行數(shù)據(jù)乘以 2 然后判斷整數(shù)部分是否大于 1 的操作。

得到 2.3125 小數(shù)部分 0.3125 的二進制表示的過程如下:

計算過程 判斷 二進制位
0.3125 x 2 = 0.625 < 1 0
0.625 x 2 = 1.25 ≥ 1 1
(1.25 - 1) x 2 = 0.5 < 1 0
0.5 x 2 = 1 ≥ 1 1
結果:用 4 位二進制數(shù)表示小數(shù) stop 0101

所以 2.3125 的二進制表示為 dec2bin(2.3125) = bin(10.0101)。這里小數(shù)點只是用于區(qū)分小數(shù)部分的位置,即小數(shù)部分用 4bit 二進制碼來表示。實際中小數(shù)點標識是不存在的。

二進制表示小數(shù)時,還有一種快捷的方法。假如小數(shù)部分用 N bit 來表示,則一個小數(shù) num 的二進制表示數(shù)值大小為:

dec2bin(num) = bin(num x 2^N )

例如小數(shù) 2.3125 轉(zhuǎn)換過程如下:

2.3125 x 2 ^ 4 = 37 = bin(100101)

小數(shù)部分位寬為 4, 則 dec2bin(2.3125) = bin(10.0101)。

二進制轉(zhuǎn)為小數(shù)

二進制整數(shù)轉(zhuǎn)換為十進制時,需要按位進行以 2 為低的指數(shù)相乘并累加的運算。

二進制小數(shù)轉(zhuǎn)換為十進制時,需要按位進行以 1/2 為低的指數(shù)相乘并累加的運算。

例如小數(shù)位寬為 4 時,則 bin(11.1001) 小數(shù)部分表示的十進制小數(shù)為:

bin2dec(1001) = 1 x 2^(-1) + 0 x 2^(-2) + 0 x 2^(-3) + 1 x 2^(-4) = 0. 5625

則小數(shù)部分位寬為 4 的二進制小數(shù) bin(11.1001) 表示的十進制小數(shù)為 3.5626 。

N 位寬小數(shù)部分的二進制小數(shù) num 轉(zhuǎn)為十進制時的快速方法為:

bin2dec(num) = num / 2^N 

例如 bin(11.1001) 表示的小數(shù)計算過程為:

bin(11.1001) = bin(111001) / (2^4) = 57/16 = 3.5625 。

其實多位寬的一個變量表示整數(shù)還是小數(shù),Verilog 編譯器是不區(qū)分的,都只是人為的在小數(shù)層面上進行運算。

浮點數(shù)表示方法

定點數(shù)是指小數(shù)點位置固定不變的數(shù)。整數(shù)就是一種定點數(shù),因為小數(shù)點總是在最后一位。

浮點數(shù)是指小數(shù)點的位置不是固定的數(shù)。例如 1.2 x 1.3 =1.56,小數(shù)點的位置一直在浮動,此謂浮點數(shù)。

當然也可以將小數(shù)的小數(shù)點位置固定,此謂定點小數(shù)。但該表示方法會降低小數(shù)的精度。例如固定小數(shù)點后面只有一位數(shù)據(jù)表示小數(shù),則 1.2 x 1.3 = 1.5,丟失了部分數(shù)據(jù)。

十進制浮點數(shù)一般表示方法:

dec(num) = (-1) ^ S x M x (10^E );

S 為符號位,為 1 時表示負數(shù),為 0 時表示正數(shù)。

E 為比例因子的指數(shù)部分,用整數(shù)表示,稱為階碼。階碼指明了小數(shù)點在碼字中的位置,因而決定了浮點數(shù)的表示范圍。

M 為小數(shù)部分,稱為尾數(shù)。尾數(shù)位寬決定了浮點數(shù)的表示精度。

例如數(shù)字 100.0344 可以表示為:

1995.0907 = (-1) ^ 0 x 199.50907 x 10^1 (正數(shù),尾數(shù)為199.50907,  階碼為1)
= (-1) ^ 0 x 1.9950907 x 10^3 
= (-1) ^ 0 x 0.19950907 x 10^ 4

同理,二進制浮點數(shù)一般表示方法:

dec(num) = (-1) ^ S x M x (2^E ) 

例如:

dec(2.3125) (十進制)  =  bin(10.0101) 
              = bin(10.0101) x 2^0
              = bin(1.00101) x 2^1 (正數(shù),尾數(shù)為 1.00101,階碼為 1)
              = bin(0.100101) x 2^2

由上可知,同一個浮點數(shù)不同的表示方法,尾數(shù)和階碼均是不同的。為了便于移植,1985年 IEEE (Institute of Electrical and Electronics Engineers, 美國電氣與電子工程協(xié)會) 提出了 IEEE-754 標準,以此作為浮點數(shù)表示格式的統(tǒng)一標準。

IEEE-754 標準從邏輯上采用一個三元組 {S, E, M} 來表示浮點數(shù) Num。

S 代表符號位,0 和 1 分布代表正數(shù)和負數(shù)。

E 代表指數(shù)部分,稱為移碼。為避免出現(xiàn)正負指數(shù),移碼是由階碼加上固定的偏移量得到的。所以階碼可由移碼得到:E - 2^(W-1) +1 。W 為移碼位寬。指數(shù)基底為 2。

M 代表尾數(shù),尾數(shù)的最高位總是為1,但是尾數(shù)部分不存儲該位數(shù)據(jù),只存儲小數(shù)部分。所以,尾數(shù)代表的數(shù)值大小實際是 1.M 。

規(guī)定單精度浮點數(shù)用 4 字節(jié)存儲,雙精度浮點數(shù)用 8 字節(jié)存儲,示意圖如下。


單精度格式 (32 位):S 符號位 1 位寬;E 階碼 8 位寬,階碼的偏移量為 127 (7'h7F);M 尾數(shù) 23 位寬,表示小數(shù),小數(shù)點放在尾數(shù)域的最前面。

雙精度格式 (64 位):S 符號位 1 位寬;E 階碼 11 位寬,階碼的偏移量為 1023 (10'h3FF);M 尾數(shù) 52 位寬,表示小數(shù),小數(shù)點放在尾數(shù)域的最前面。

32 位浮點數(shù) N 的真值可表示為:

Num = (-1)^S × (1.M) × 2 ^(E-127)

64 位浮點數(shù) N 的真值可表示為:

Num = (-1)^S × (1.M) × 2 ^(E-1023)

例如雙精度浮點數(shù)對應的二進制碼 64'h4002_8000_0000_0000 表示的小數(shù)為:

Num = (-1)^0 x  (1+ 8'h28/2**8) x 2^((12'h400 & 11'h7FF)-1023) = 2.3125

上述尾數(shù)計算過程省略了后面一連串的"0",只取前 8bit 有效位。

例如雙精度浮點數(shù) -13.14 的二進制表示過程為:

需要 1bit 表示符號位 S = 1
需要 4bit 表示整數(shù) 13 = bin(1101) = bin(1.101) x 2^3
需要 11bit 表示階數(shù) E = 3 + 1023 = 11'h402
需要 (52-3)bit 表示小數(shù) 0.14 * 2^(52-3) = 78812993478983.688
≈ 78812993478984 = 49'h47ae147ae148
需要52bit表示尾數(shù):整合兩部分小數(shù) M = (bin(101)<<49) + 49'h47ae147ae148
= 52'ha47ae147ae148
浮點數(shù)二進制碼 {S, E, M} = 32'hc02a_47ae_147a_e148

而 Verilog 中的 real 型變量,正是 IEEE-754 標準的 64bit 位寬的雙精度浮點型變量。

轉(zhuǎn)換函數(shù)

調(diào)用系統(tǒng)任務 任務描述
int_val = $rtoi( real_val ) ; 實數(shù) real_val 轉(zhuǎn)換為整數(shù) int_val
例如 3.14 -> 3
real_val = $itor( int_val ) ; 整數(shù) int_vla 轉(zhuǎn)換為實數(shù) real_val
例如 3 -> 3.0
vec_val = $realtobits( real_val ) ; 實數(shù)轉(zhuǎn)換為多位寬的寄存器向量
寄存器內(nèi)按照 IEEE-754 標準存儲雙精度浮點型數(shù)據(jù)
real_val = $bitstoreal( vec_val ) ; 多位寬的寄存器向量轉(zhuǎn)換為實數(shù)

real 型變量的產(chǎn)生或轉(zhuǎn)換過程,都應該遵循 IEEE Std 754-1985 [B1] 標準。

利用 ?$realtobits? 與 ?$bitstoreal? 對數(shù)據(jù)進行轉(zhuǎn)換:

   //real, bits
   reg [63:0]   num_bits ;
   initial begin
      num_bits  = 64'h4002_8000_0000_0000 ;
      $display("-14.13 -> hex: %h", $realtobits(-13.14));
      $display("64'h4002_8000_0000_0000 -> real: %f", $bitstoreal(num_bits));
   end

仿真 log 如下,可知轉(zhuǎn)換正確。


利用 ?$itor? 與 ?$rtoi? 對數(shù)據(jù)進行格式轉(zhuǎn)換:

   //$itor, $rtoi
   initial begin
      $display();
      $display("Real to integer: %h", $rtoi(13.14));
      $display("Display integer in float: %f", 1001);
      $display("Integer to real: %f", $itor(1001));
   end

由以下仿真 log 可知,?$rtoi? 做實數(shù)(13.14)向整數(shù)(4'hd)的轉(zhuǎn)換時,只截了取整數(shù)部分。$itor 做整數(shù) (1001) 向?qū)崝?shù)(1001.000000)的轉(zhuǎn)換時,似乎沒有什么變化。


其實,?$rtoi? 與 ?$itor? 的功能是改變變量的存儲方式。

例如 14 以整數(shù)型變量儲存時,表示方法為 32'h1110,而如果以實數(shù)型變量存儲,則表示方法為 64h402c_0000_0000_0000。

點擊這里下載源碼


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號