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

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

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

怎么設(shè)計(jì)一個(gè)32bit浮點(diǎn)的加法器呢?

冬至子 ? 來源:FPGA and ICer ? 作者:Vuko ? 2023-06-02 16:13 ? 次閱讀

設(shè)計(jì)需求

設(shè)計(jì)一個(gè)32bit浮點(diǎn)的加法器,out = A + B,假設(shè)AB均為無符號(hào)位,或者換個(gè)說法都為正數(shù)。

clk為系統(tǒng)時(shí)鐘rst_n為系統(tǒng)復(fù)位,低有效;en信號(hào)控制數(shù)據(jù)輸入;busy指示模塊工作狀態(tài),busy拉高時(shí),輸入無效;aIn和bIn是數(shù)據(jù)輸入,out_vld,指示輸出數(shù)據(jù)有效。

設(shè)計(jì)的信號(hào)列表如下:

module float_adder(
  input                clk,
  input              rst_n,
  input                 en, 
  input      [31:0]    aIn,
  input      [31:0]    bIn,
  output reg          busy,
  output reg       out_vld,   
  output reg [31:0]    out
);

32bit的浮點(diǎn)格式

EE標(biāo)準(zhǔn)754規(guī)定了三種浮點(diǎn)數(shù)格式:單精度、雙精度、擴(kuò)展精度。前兩者正好對(duì)應(yīng)C語言里頭的float、double或者FORTRAN里頭的real、double精度類型。本文設(shè)計(jì)實(shí)現(xiàn)的為單精度。

圖片

單精度格式

單精度:N共32位,其中S占1位,E占8位,M占23位。

圖片

雙精度格式

雙精度:N共64位,其中S占1位,E占11位,M占52位。

浮點(diǎn)數(shù)的加法過程

運(yùn)算過程:對(duì)階、尾數(shù)求和、規(guī)格化、舍入、溢出判斷

對(duì)階:

和定點(diǎn)數(shù)不相同的是,浮點(diǎn)數(shù)的指數(shù)量級(jí)不一定是一樣的,所以這也就意味著,尾數(shù)直接進(jìn)行加法運(yùn)算時(shí)會(huì)存在問題,也就需要首先對(duì)階數(shù)進(jìn)行處理。該過程有點(diǎn)像科學(xué)計(jì)數(shù)法的加法處理,把科學(xué)計(jì)數(shù)法的指數(shù)化為一致,求出來指數(shù)相差多少,然后移位處理后再進(jìn)行加法減法。所以這里處理也要先求階差。

如果把階碼大的向階碼小的看齊,就要把階碼大的數(shù)的尾數(shù)部分左移,階碼減小。這個(gè)操作有可能在移位過程中把尾數(shù)的高位部分移掉,這樣就引發(fā)了數(shù)據(jù)的錯(cuò)誤,所以,尾數(shù)左移在計(jì)算機(jī)運(yùn)算中不可取。

如果把階碼小的向階碼大的看齊,在移位過程中如果發(fā)生數(shù)據(jù)丟失,也是最右邊的數(shù)據(jù)位發(fā)生丟失,最右邊的數(shù)據(jù)位丟失,只會(huì)影響數(shù)據(jù)的精度,不會(huì)影響數(shù)據(jù)的大小。

尾數(shù)求和

這里就是常規(guī)的補(bǔ)碼加法。

規(guī)格化:

右規(guī)(尾數(shù)的絕對(duì)值太大時(shí),右規(guī)) 尾數(shù)右移一位,階碼加1。 當(dāng)尾數(shù)溢出( >1 )時(shí),需要右規(guī) 。是否溢出,可以通過兩位的符號(hào)位得出:即尾數(shù)出現(xiàn)01.xx…xx或10.xx…xx(兩位符號(hào)位不同)

提高浮點(diǎn)數(shù)的表示精度,這里設(shè)計(jì)考慮比較簡單,我只考慮了同號(hào)數(shù)據(jù)相加的情況,所以這里只設(shè)計(jì)了右規(guī)的情況,不考慮符號(hào)位。

舍入判斷:

這里直接用截?cái)嗵幚淼姆绞?,針?duì)數(shù)據(jù)相加上溢的情況,規(guī)定了運(yùn)算后上溢后將數(shù)據(jù)規(guī)定為最大值。

實(shí)現(xiàn)代碼

module float_adder(
  input                clk,
  input              rst_n,
  input                 en, 
  input      [31:0]    aIn,
  input      [31:0]    bIn,
  output reg          busy,
  output reg       out_vld,   
  output reg [31:0]    out
);
//運(yùn)算過程:對(duì)階、尾數(shù)求和、規(guī)格化、舍入、溢出判斷
//分離階數(shù)、尾數(shù)
wire signal_bit = aIn[31];
wire [7:0] pow_a = aIn[30:23];
wire [7:0] pow_b = bIn[30:23];


wire [22:0] val_a = aIn[22:0];
wire [22:0] val_b = bIn[22:0];


//找到輸入指數(shù)階數(shù)較大,和階數(shù)差
//對(duì)階:在計(jì)算機(jī)中,采用小階向大階看齊的方法,實(shí)現(xiàn)對(duì)階。即右移
reg [22:0] pow_max ;
reg [23:0] pow_dif ;
reg [22:0] val_max ;
reg [22:0] val_min ;
reg en_dly0;
always @(posedge clk or negedge rst_n) begin
  if(rst_n==0)begin
    pow_max <= 'd0;
    val_max <= 'd0;
    val_min <= 'd0;
    pow_dif <= 'd0;
    en_dly0 <= 'd0;
  end
  else if( en == 1 && busy == 0)begin
    if(pow_a >= pow_b)begin
      pow_max <= pow_a;
      val_max <= val_a;
      val_min <= val_b;
      en_dly0 <= 'd1;
      if ( pow_a - pow_b > 'd23) begin
        pow_dif <= 'd23;
      end 
      else begin
        pow_dif <= pow_a - pow_b;
      end
    end
    else begin
      pow_max <= pow_b;
      val_max <= val_b;
      val_min <= val_a;
      en_dly0 <= 'd1;
      if ( pow_b - pow_a > 'd23) begin
        pow_dif <= 'd23;
      end 
      else begin
        pow_dif <= pow_b - pow_a;
      end
    end
  end
  else begin
    pow_max <= pow_max;
    val_max <= val_max;
    val_min <= val_min;
    pow_dif <= pow_dif;
    en_dly0 <= 'd0;
  end
end


//移位忙指示信號(hào)
reg shift_busy;
reg [4:0] shift_cnt;
always @(posedge clk or negedge rst_n) begin
  if (rst_n==0) begin
    shift_busy<='d0;
  end
  else if(en_dly0 == 1 )begin
    shift_busy <='d1;
  end
  else if(shift_cnt == pow_dif)begin
    shift_busy <=  0;
  end
end


//移位計(jì)數(shù)


always @(posedge clk or negedge rst_n) begin
  if(rst_n == 0)begin
    shift_cnt <= 'd0;
  end
  else if (shift_busy ==1) begin
    if (shift_cnt == pow_dif) begin
      shift_cnt <= shift_cnt;
    end
    else begin
      shift_cnt <= shift_cnt + 1'b1;
    end
  end
  else begin
    shift_cnt <= 'd0;
  end
end
reg [22:0] val_shift;
always @(posedge clk or negedge rst_n) begin
  if(rst_n == 0)begin
    val_shift <= 'd0;
  end
  else if (en_dly0==1'b1) begin
    val_shift <= val_min;
  end
  else if (shift_busy == 1) begin
    val_shift <= {1'b0,val_shift[22:1]};
  end
  else begin
    val_shift <= val_shift;
  end
end


//尾數(shù)求和
wire val_add_flag = (shift_cnt == pow_dif)&&(shift_busy ==1);
reg [23:0] val_sum;
reg val_sum_vld;
always @(posedge clk or negedge rst_n) begin
  if (rst_n==0) begin
    val_sum<='d0;
    val_sum_vld<='d0;
  end
  else if(val_add_flag == 1)begin
    val_sum <= val_max + val_shift;
    val_sum_vld<='d1;
  end
  else begin
    val_sum <= val_sum;
    val_sum_vld<='d0;
  end
end


//規(guī)范
always @(posedge clk or negedge rst_n) begin
  if (rst_n==0) begin
    out<='d0;
    out_vld<='d0;
  end
  else if(val_sum_vld == 1)begin
    //尾數(shù)求和有溢出
    out_vld<='d1;
    out[31]<= signal_bit;
    if(val_sum[23] == 1 && out[30:23] == 8'hFF)begin
      out[30:23]<= 8'hFF;
      out[22:0] <= 23'h7F_FFFF;
    end
    else if(val_sum[23] == 1)begin
      out[30:23]<= pow_max + 1;
      out[22:0] <= val_sum[23:1];
    end
    else begin
      out[30:23]<= pow_max;
      out[22:0] <= val_sum[22:0];
  end 
  end
  else begin
    out <= out;
    out_vld<='d0;
  end
end


//運(yùn)算忙指示
always @(posedge clk or negedge rst_n) begin
  if (rst_n==0) begin
    busy<='d0;
  end
  else if(en == 1 && busy == 0)begin
    busy<='d1;
  end
  else if(out_vld == 1 )begin
    busy<='d0;
  end
  else begin
    busy <= busy;
  end
end


endmodule

仿真代碼

這里簡單測(cè)試了下代碼的功能,模擬了連續(xù)輸入多個(gè)數(shù)據(jù),核查是否數(shù)據(jù)會(huì)影響正常計(jì)算過程。

`timescale 1ns/1ps
module float_adder_tb;


  // Parameters


  // Ports
  reg clk = 1;
  reg rst_n = 0;
  reg en = 0;
  reg [31:0] aIn;
  reg [31:0] bIn;
  wire busy;
  wire out_vld;
  wire [31:0] out;


  float_adder float_adder_dut (
    .clk (clk ),
    .rst_n (rst_n ),
    .en (en ),
    .aIn (aIn ),
    .bIn (bIn ),
    .busy (busy ),
    .out_vld (out_vld ),
    .out  ( out)
  );
  always
    #5  clk = ! clk ;
  initial begin
    rst_n = 0;
    #100;
    rst_n = 1;
    #100;
    aIn = {1'b0,8'd2,23'd7};
    bIn = {1'b0,8'd2,23'd8};
    en  = 1 ;
    #10;
    aIn = {1'b0,8'd0,23'd7};
    bIn = {1'b0,8'd2,23'd8};
    en  = 1 ;
    #1000;
    $finish;
  end


endmodule

仿真測(cè)試

從仿真測(cè)試中可以看出,當(dāng)輸入信號(hào)連續(xù)輸入兩個(gè)浮點(diǎn)數(shù)時(shí),在busy拉高狀態(tài)下,第二次輸入的數(shù)據(jù)無效,數(shù)據(jù)使能信號(hào)常為1,也不會(huì)影響正常模塊運(yùn)算過程,只有在該次運(yùn)算完成busy拉低后數(shù)據(jù)可重新加載。

圖片

仿真截圖

小結(jié)

本文的設(shè)計(jì)方法對(duì)于對(duì)階移位的操作需要循環(huán)操作,也即當(dāng)階數(shù)相差較小時(shí),結(jié)果輸出延遲較小,在極端情況下,比如階數(shù)差大于10,輸出延時(shí)會(huì)比階數(shù)差為0時(shí),多10個(gè)周期,上限為23。如在實(shí)際使用時(shí),對(duì)延時(shí)要求較小的情況,可針對(duì)移位操作部分,使用更多的資源來換取性能的提升??墒褂胏ase語句對(duì)具體情況進(jìn)行遍歷。

針對(duì)原始題目中的累加操作,可將任意一個(gè)輸入和輸出相接,即可實(shí)現(xiàn)累加操作。此外,如果要實(shí)現(xiàn)異號(hào)加法情況,則需要仔細(xì)考慮對(duì)階,規(guī)格化等情況進(jìn)行進(jìn)一步設(shè)計(jì)。

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

    關(guān)注

    180

    文章

    7605

    瀏覽量

    136930
  • 加法器
    +關(guān)注

    關(guān)注

    6

    文章

    183

    瀏覽量

    30131
  • CLK
    CLK
    +關(guān)注

    關(guān)注

    0

    文章

    127

    瀏覽量

    17175
  • 累加器
    +關(guān)注

    關(guān)注

    0

    文章

    50

    瀏覽量

    9462
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    運(yùn)算放大器的同相加法器和反相加法器

      運(yùn)算放大器構(gòu)成加法器 可以分為同相加法器和反相加法器
    發(fā)表于 08-05 17:17 ?3.1w次閱讀
    運(yùn)算放大器的同相<b class='flag-5'>加法器</b>和反相<b class='flag-5'>加法器</b>

    32位浮點(diǎn)加法器設(shè)計(jì)

    求助誰幫我設(shè)計(jì)個(gè)32位浮點(diǎn)加法器,求助啊,謝謝啊 新搜剛學(xué)verilog,不會(huì)做{:4_106:}
    發(fā)表于 10-20 20:07

    加法器

    請(qǐng)問下大家,,進(jìn)位選擇加法器和進(jìn)位跳躍加法器的區(qū)別是啥???我用Verilog實(shí)現(xiàn)16位他們的加法器有什么樣的不同???還請(qǐng)知道的大神告訴我下。。
    發(fā)表于 10-20 20:23

    什么是加法器加法器的原理是什么 ?

    什么是加法器加法器的原理是什么 反相加法器等效原理圖解析
    發(fā)表于 03-11 06:30

    加法器,加法器是什么意思

    加法器,加法器是什么意思 加法器 :  加法器是為了實(shí)現(xiàn)加法的。  即是產(chǎn)生數(shù)的和的裝置。加數(shù)和被加數(shù)為輸入,和數(shù)與
    發(fā)表于 03-08 16:48 ?5560次閱讀

    十進(jìn)制加法器,十進(jìn)制加法器工作原理是什么?

    十進(jìn)制加法器,十進(jìn)制加法器工作原理是什么?   十進(jìn)制加法器可由BCD碼(二-十進(jìn)制碼)來設(shè)計(jì),它可以在二進(jìn)制加法器的基礎(chǔ)上加上適當(dāng)?shù)摹靶U边壿媮韺?shí)現(xiàn),該校正邏
    發(fā)表于 04-13 10:58 ?1.4w次閱讀

    FPU加法器的設(shè)計(jì)與實(shí)現(xiàn)

    浮點(diǎn)運(yùn)算器的核心運(yùn)算部件是浮點(diǎn)加法器,它是實(shí)現(xiàn)浮點(diǎn)指令各種運(yùn)算的基礎(chǔ),其設(shè)計(jì)優(yōu)化對(duì)于提高浮點(diǎn)運(yùn)算的速度和精度相當(dāng)關(guān)鍵。文章從
    發(fā)表于 07-06 15:05 ?47次下載
    FPU<b class='flag-5'>加法器</b>的設(shè)計(jì)與實(shí)現(xiàn)

    同相加法器電路原理與同相加法器計(jì)算

    同相加法器輸入阻抗高,輸出阻抗低 反相加法器輸入阻抗低,輸出阻抗高.加法器種數(shù)位電路,其可進(jìn)行數(shù)字的加法計(jì)算。當(dāng)選用同相
    發(fā)表于 09-13 17:23 ?5.8w次閱讀
    同相<b class='flag-5'>加法器</b>電路原理與同相<b class='flag-5'>加法器</b>計(jì)算

    怎么設(shè)計(jì)個(gè)32位超前進(jìn)位加法器?

    ,影響整個(gè)CPU的性能,為了減小這種延遲,遂采用超前進(jìn)位加法器(也叫先行進(jìn)位加法器),下面來介紹下設(shè)計(jì)的原理。
    發(fā)表于 07-09 10:42 ?2.1w次閱讀
    怎么設(shè)計(jì)<b class='flag-5'>一</b><b class='flag-5'>個(gè)</b>32位超前進(jìn)位<b class='flag-5'>加法器</b>?

    加法器設(shè)計(jì)代碼參考

    介紹各種加法器的Verilog代碼和testbench。
    發(fā)表于 05-31 09:23 ?19次下載

    超前進(jìn)位加法器是如何實(shí)現(xiàn)記憶的

    行波進(jìn)位加法器和超前進(jìn)位加法器都是加法器,都是在邏輯電路中用作兩個(gè)數(shù)相加的電路。我們?cè)賮砘仡?b class='flag-5'>一下行波進(jìn)位加法器。
    發(fā)表于 08-05 16:45 ?1570次閱讀
    超前進(jìn)位<b class='flag-5'>加法器</b>是如何實(shí)現(xiàn)記憶的<b class='flag-5'>呢</b>

    加法器的原理及采用加法器的原因

    有關(guān)加法器的知識(shí),加法器是用來做什么的,故名思義,加法器是為了實(shí)現(xiàn)加法的,它是種產(chǎn)生數(shù)的和的裝置,那么
    的頭像 發(fā)表于 06-09 18:04 ?5181次閱讀

    鏡像加法器的電路結(jié)構(gòu)及仿真設(shè)計(jì)

    鏡像加法器個(gè)經(jīng)過改進(jìn)的加法器電路,首先,它取消了進(jìn)位反相門;
    的頭像 發(fā)表于 07-07 14:20 ?2880次閱讀
    鏡像<b class='flag-5'>加法器</b>的電路結(jié)構(gòu)及仿真設(shè)計(jì)

    加法器的原理是什么 加法器有什么作用

    加法器是數(shù)字電路中的基本組件之,用于執(zhí)行數(shù)值的加法運(yùn)算。加法器的基本原理和作用可以從以下幾個(gè)方面進(jìn)行詳細(xì)闡述。
    的頭像 發(fā)表于 05-23 15:01 ?3071次閱讀
    <b class='flag-5'>加法器</b>的原理是什么 <b class='flag-5'>加法器</b>有什么作用

    串行加法器和并行加法器的區(qū)別?

    串行加法器和并行加法器是兩種基本的數(shù)字電路設(shè)計(jì),用于執(zhí)行二進(jìn)制數(shù)的加法運(yùn)算。它們?cè)谠O(shè)計(jì)哲學(xué)、性能特點(diǎn)以及應(yīng)用場景上有著明顯的區(qū)別。
    的頭像 發(fā)表于 05-23 15:06 ?2618次閱讀