1. 程式人生 > 其它 >FPGA定點數轉換成雙精度浮點數(IEEE754)

FPGA定點數轉換成雙精度浮點數(IEEE754)

技術標籤:FPGAfpga

本文利用一個例子,簡單的介紹了,FPGA定點數轉換成雙精度浮點數(IEEE754協議),文章後,貼有實現程式碼和模擬檔案,我用的是quartus II 13.1。
一:雙精度浮點數格式
在這裡插入圖片描述
雙精度的指數部分(E)採用的偏置碼為1023
假設待轉換的資料是11(二進位制)
第一步:將其擴充套件成64位2進位制數
0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0011
第二步:計算首1是第幾位
2
第三步:計算階碼
偏移值是1023
Code=1023+2-1=1024
第四步:計算尾數
4.1:因為首1是第2位,所以資料往左移52-2=50位
Pre_尾數=1100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
4.2:將首1隱藏 Pre_尾數,往左移動一位

尾數=1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
第五步:組合成新的浮點數
Double_Float=0100_0000_0000_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
0x4008000000000000

在這裡插入程式碼片
module  int_to_double_float
(
     input              clk,
     input              rst_n,
     input  signed      [31:0]int_number,                   //輸入進來的是32位整型資料,能表示到浮點數21474836648
     output reg   [63:0]double_float
);


//變數宣告
reg [63:0]int_number_64; //輸入的整型變數 reg [9:0]cnt; //計數器,進行時序約束 reg [5:0]first_one; //首1,所在的位置 reg [10:0]code; //11位的階碼 reg [31:0]pre_mantissa; //擴充套件後的資料,其中有效資料部分的首1,移位到第53位時的尾數
reg sign; //資料的符號位 //建立一個計數器,進行時序約束 always @(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 10'd0; else begin if(cnt < 6) cnt<= cnt + 1'b1; else cnt<= 10'd0; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) sign<= 1'd0; else begin sign<=int_number[31]; end end //第一步取符號位 //第一步擴寬輸出的整型,先將其擴充套件成64位數 always @(posedge clk or negedge rst_n ) begin if(!rst_n) begin int_number_64<=64'd0; end else begin int_number_64<={32'd0,int_number}; end end //第一步計算首1在那個位置 always @(posedge clk or negedge rst_n ) begin if(!rst_n) begin first_one<=6'd0; end else if(int_number>=32'd1073741824) begin first_one=31; end else if(int_number>=32'd536870912) begin first_one=30; end else if(int_number>=32'd268435456) begin first_one=29; end else if(int_number>=32'd134217728) begin first_one=28; end else if(int_number>=32'd67108864) begin first_one=27; end else if(int_number>=32'd33554432) begin first_one=26; end else if(int_number>=32'd16777216) begin first_one=25; end else if(int_number>=32'd8388608) begin first_one=24; end else if(int_number>=32'd4194304) begin first_one=23; end else if(int_number>=32'd2097152) begin first_one=22; end else if(int_number>=32'd1048576) begin first_one=21; end else if(int_number>=32'd524288) begin first_one=20; end else if(int_number>=32'd262144) begin first_one=19; end else if(int_number>=32'd131072) begin first_one=18; end else if(int_number>=32'd65536) begin first_one=17; end else if(int_number>=32'd32768) begin first_one=16; end else if(int_number>=32'd32768) begin first_one=15; end else if(int_number>=32'd8192) begin first_one=14; end else if(int_number>=32'd4096) begin first_one=13; end else if(int_number>=32'd2048) begin first_one=12; end else if(int_number>=32'd1024) begin first_one=11; end else if(int_number>=32'd512) begin first_one=10; end else if(int_number>=32'd256) begin first_one=9; end else if(int_number>=32'd128) begin first_one=8; end else if(int_number>=32'd64) begin first_one=7; end else if(int_number>=32'd32) begin first_one=6; end else if(int_number>=32'd16) begin first_one=5; end else if(int_number>=32'd8) begin first_one=4; end else if(int_number>=32'd4) begin first_one=3; end else if(int_number>=32'd2) begin first_one<=6'd2; end else if(int_number>=32'd1) begin first_one=1; end else begin first_one=0; end end //第二步計算階碼 always @(posedge clk or negedge rst_n ) begin if(!rst_n) begin code<=11'b0; end else if(cnt==3) begin code<=1022+first_one; end else code<=code; end //第二步計算尾數 always @(posedge clk or negedge rst_n ) begin if(!rst_n) begin pre_mantissa<=32'd0; end else if(cnt==3) begin pre_mantissa<= int_number<<(33-first_one); //要將首1隱藏,取剩下的部分 end else pre_mantissa<= pre_mantissa; end //第三步計算結果 always @(posedge clk or negedge rst_n ) begin if(!rst_n) begin double_float<=64'd0; end else if(cnt==4) begin double_float<= {sign,code,pre_mantissa,20'd0} ; //要將首1隱藏,取剩下的部分 end else double_float<=double_float; end endmodule

模擬檔案

`timescale   1ns/1ns
`define    time_period 20


module int_to_double_float_tb;

reg clk;
reg rst_n;
reg [31:0]int_number;

always #(`time_period/2)clk=~clk;


initial begin
      clk=1'b0;
      rst_n=1'b0;
      #(`time_period/2) 
      rst_n =1'b1;
      int_number<=32'd536870912;
      #((`time_period/2)*100000 );
      $stop;


end
  int_to_double_float   int_to_double_float_u1(
       .clk(clk),
       .rst_n(rst_n),
       .int_number(int_number),                   //能表示到無浮點數4294967296
       .double_float(double_float)
);


endmodule