減算型でいく。基数 4 の SRT でいってみたいのだが、とりあえず基数 2 で。
サイクル数は 1 + 18 ( iteration ) + 2 = 21 サイクルを目標に。
ゲートは 10000 くらいでやりたいところ。
Weitek 3364 は 4 進 SRT で 165,000 ゲートの 3.9 % を、
TI 8847は 8b seed Goldschmidt 法で 180,000 ゲートの 5.0 % を使用している。
乗算型除算器の方が、ゲートを食う分だけ速いらしい。
基数 2 の SRT 法は、適当に修正された被除数から出発して、部分剰余の絶対 値を常に 0.25 以上にするようなアルゴリズムである。 これによって、除数と被除数のビット数に関わらず、常に一定のビットを参照 するだけで商を求めることができる。 とりあえず 通常の SRT で作ってみることにする。
単精度も標的にしつつ設計してみよう。
module fdiv_split(in,isdouble,s,e,upf);
input [63:0] in;
input isdouble;
output s; // sign
output [10:0] e; // biased exp ( zero adjusted )
output [52:0] upf; // unpacked mantissa
単精度か倍精度かで主に判断する、が、ただ分割するだけではなく
という作業を行う。
module fdiv_encode(upf,enc,isfzero);
input [52:0] upf;
output [5:0] enc;
output isfzero;
module fdiv_presft(upf,enc,n);
input [52:0] upf;
input [5:0] enc;
output [53:0] n;
module fdiv_qselect_top(nb,na,po,mo,zpo,zno);
input [53:0] nb,na;
// divisor , dividend (initial partial remainder)
output [53:0] po,mo; // partial remainder
output [54:0] zpo,zno;
// on the fly conversion
但し、最初、商は 1 で固定である。
module fdiv_premux(in0,in1,start,out);
input [380:0] in0,in1;
input start;
output [380:0] out;
実行時間の大部分は商を求める繰り返し部分だが、そこに投入する入力を選択する。
module fdiv_qselect(nb,pi,mi,zpi,zni,po,mo,zpo,zno);
input [53:0] nb; // divisor
input [53:0] pi,mi; // plusone , minusone
input [54:0] zpi,zni; // zpi[54],zni[54] is dummy
output [53:0] po,mo; // partial remainder , output
output [54:0] zpo,zno; // on-the-fly conversion
module fdiv_exception(a,b,isdouble,out,flags,istrue);
input [63:0] a,b;
input isdouble;
output [63:0] out;
output [4:0] flags; // V,O,Z,U,I
output istrue; // output is TRUE or Don't care
module fdiv_resultinf(rmode,sc,ovi);
input [1:0] rmode; // roundmode
input sc; // sign of result
output ovi;
module fdiv_adjq(p54,m54,zp54,zn54,cancel,adjq);
input [53:0] p54,m54;
input [54:0] zp54,zn54;
output cancel;
// 1bit cancellation of quotient digit
output [54:0] adjq; // with roundbit and stickybit
module fdiv_adje(ea,eb,enca,encb,cancel,isdouble,adje,sftbit);
input [10:0] ea,eb;
input [5:0] enca,encb;
input cancel;
input isdouble;
output [12:0] adje;
output [12:0] sftbit;
module fdiv_postsft(adjq,sftbit,sft);
input [54:0] adjq; // 53b + r + s
input [12:0] sftbit;
output [54:0] sft;
ここでは精度については気にせず、単に右シフトを行って 55 ビットのフォー マットに収まるようにしている。
module fdiv_round(sftq,s,isdouble,rmode,roundq,carry,iex);
input [54:0] sftq;
input s; // sign
input isdouble;
input [1:0] rmode;
output [52:0] roundq;
output carry;
output iex; // inexact exception flag
但し、このモジュールは内部に丸めの純粋なロジックモジュール ( fdiv_roundlogic ) を持っている。
module fdiv_roundlogic(sib,lsb,rob,stb,rmode,pone,iex);
input sib,lsb,rob,stb;
input [1:0] rmode; // 00:RN , 01:RZ , 10:RP , 11:RM
output pone;
output iex; // to inexact exception flag
module fdiv_adjall(adje,roundq,carry,isdouble,ovi,oute,outf,flags);
input [12:0] adje;
input [52:0] roundq; // roundq[52] is dummy
// rounded , but uneconomized quotient
input carry; // carry by rounding
input isdouble;
input ovi; // overflow-infinity
output [10:0] oute;
output [52:0] outf; // uneconomized format
output [4:0] flags;
module fdiv_rflush(s,adje,roundq,isdouble,rflush);
input s; // sign
input [10:0] adje; // exp
input [52:0] roundq; // roundq [52] is dummy
input isdouble;
output [63:0] rflush;
module fdiv_mux(normsef,normflags,excesef,exceflags,isexcetrue,mux,muxflags);
input [63:0] normsef,excesef; // sign , exp , mantissa
input [4:0] normflags,exceflags;
input isexcetrue;
output [63:0] mux;
output [4:0] muxflags;
| モジュール名 | cost prim. | 時間 (ns) | 必要 数 | 小計 prim. |
|---|---|---|---|---|
| fdiv_split | 198 | 1.866 | 2 | 396 |
| fdiv_encode | 365 | 6.988 | 2 | 730 |
| fdiv_presft | 842 | 4.368 | 2 | 1684 |
| fdiv_qselect_top | 268 | 0.739 | 1 | 268 |
| fdiv_exception | 716 | 6.755 | 1 | 716 |
| fdiv_premux | 1183 | 2.426 | 1 | 1183 |
| fdiv_qselect | 1894 | 5.284 | 1 | 1894 |
| fdiv_resultinf | 4 | 0.733 | 1 | 4 |
| fdiv_adjq | 1103 | 10.406 | 1 | 1103 |
| fdiv_adje | 831 | 9.367 | 1 | 831 |
| fdiv_postsft | 2345 | 5.135 | 1 | 2345 |
| fdiv_round | 464 | 8.860 | 1 | 464 |
| fdiv_adjall | 283 | 6.981 | 1 | 283 |
| fdiv_rflush | 170 | 1.882 | 1 | 170 |
| fdiv_mux | 217 | 2.535 | 1 | 217 |
ここで特殊数とは、SNaN と QNaN と Inf と 0 を指し、入力に対してこれら を排他的にアサートされる 4 ビットで入力の状態を決定する。全てのビット が立っていなければ、それは通常の有限数を意味する。以下の仕様に基づいて 作る。
| 演算種類 | 結果 | 例外 |
|---|---|---|
| SNaN / SNaN SNaN / QNaN と QNaN / SNaN SNaN / 0 と 0 / SNaN SNaN / Inf と Inf / SNaN SNaN / W と W / SNaN Inf / Inf と 0 / 0 | QNaN | V |
| QNaN / QNaN QNaN / 0 と 0 / QNaN QNaN / Inf と Inf / QNaN QNaN / W と W / QNaN | QNaN | - |
| 0 / Inf と W / Inf 0 / W | 符号付き 0 | - |
| Inf / 0 と Inf / W | 符号付き Inf | - |
| W / 0 | 符号付き Inf | Z |
| W / W | ?(W,Inf,0) | ?(O,U,I) |
各ステージに分割したモジュールのインターフェースは以下の通り。
module fdiv_1(CLK,a,b,isdouble,rmode,start,
fp,fm,fzp,fzn,fnb,fovi,frmode,fs,fea,feb,fenca,fencb,
fisdouble,fexception,fexceflags,fisexcetrue,fstart);
input CLK;
input [63:0] a,b;
input isdouble;
input [1:0] rmode;
input start;
output [53:0] fp,fm;
output [54:0] fzp,fzn;
output [53:0] fnb;
output fovi;
output [1:0] frmode;
output fs;
output [10:0] fea,feb;
output [5:0] fenca,fencb;
output fisdouble;
output [63:0] fexception;
output [4:0] fexceflags;
output fisexcetrue;
output fstart;
module fdiv_2(CLK,fstart, fp,fm,fzp,fzn,fnb,fovi,frmode,fs,fea,feb,fenca,fencb, fisdouble,fexception,fexceflags,fisexcetrue, sp,sm,szp,szn,snb,sovi,srmode,ss,sea,seb,senca,sencb, sisdouble,sexception,sexceflags,sisexcetrue, dp,dm,dzp,dzn,dnb,dovi,drmode,ds,dea,deb,denca,dencb, disdouble,dexception,dexceflags,disexcetrue); input CLK; input fstart; input [53:0] fp,fm; input [54:0] fzp,fzn; input [53:0] fnb; input fovi; input [1:0] frmode; input fs; input [10:0] fea,feb; input [5:0] fenca,fencb; input fisdouble; input [63:0] fexception; input [4:0] fexceflags; input fisexcetrue; input [53:0] sp,sm; input [54:0] szp,szn; input [53:0] snb; input sovi; input [1:0] srmode; input ss; input [10:0] sea,seb; input [5:0] senca,sencb; input sisdouble; input [63:0] sexception; input [4:0] sexceflags; input sisexcetrue; output [53:0] dp,dm; output [54:0] dzp,dzn; output [53:0] dnb; output dovi; output [1:0] drmode; output ds; output [10:0] dea,deb; output [5:0] denca,dencb; output disdouble; output [63:0] dexception; output [4:0] dexceflags; output disexcetrue;
module fdiv_3(CLK, p,m,zp,zn,ovi,rmode,s,ea,eb,enca,encb, isdouble,exception,exceflags,isexcetrue, disdouble,ds,dadje,dsftq,dovi,drmode,dexception,dexceflags,disexcetrue); input CLK; input [53:0] p,m; input [54:0] zp,zn; /* input [53:0] nb; */ input ovi; input [1:0] rmode; input s; input [10:0] ea,eb; input [5:0] enca,encb; input isdouble; input [63:0] exception; input [4:0] exceflags; input isexcetrue; output disdouble; output ds; output [12:0] dadje; output [54:0] dsftq; output dovi; output [1:0] drmode; output [63:0] dexception; output [4:0] dexceflags; output disexcetrue; reg disdouble; reg ds; reg [12:0] dadje; reg [54:0] dsftq; reg dovi; reg [1:0] drmode; reg [63:0] dexception; reg [4:0] dexceflags; reg disexcetrue;
module fdiv_4( isdouble,s,adje,sftq,ovi,rmode,exception,exceflags,isexcetrue); out,flags); input isdouble; input s; input [12:0] adje; input [54:0] sftq; input ovi; input [1:0] rmode; input [63:0] exception; input [4:0] exceflags; input isexcetrue; output [63:0] out; output [4:0] flags;
| モジュール名 | cost prim. | 時間 (ns) | 必要 数 | 小計 prim. |
|---|---|---|---|---|
| fdiv_1 | 6245 | 12.252 | 1 | 6245 |
| fdiv_2 | 1 | |||
| fdiv_3 | 5236 | 15.357 | 1 | 5236 |
| fdiv_4 | 1139 | 17.443 | 1 | 1139 |
最終ステージが少し時間がかかりすぎているので、除算前の処理を重くして、 負荷分散させてやることが必要である ( 19971225 )
module div_qselect(b,rsi,rci,zpi,zni,rso,rco,zpo,zno);
input [31:0] b; // divisor
input [31:0] rsi,rci; // sum/carry of partial remainder , input
input [30:0] zpi,zni; // on-the-fly conversion
output [31:0] rso,rco; // sum/carry of partial remainder , output
output [31:0] zpo,zno;
キャリーセーブ表現の部分剰余 rsi , rci から商を判定して
を返す。
商の選択が少し変形していびつだが、範囲にちゃんと入るようになっている。
| 部分剰余 | 対応ビット列 | 商 | 対応ビッ ト列 |
|---|---|---|---|
| 0 以上 | 0.11 0.10 0.01 0.00 | +1 | 01 |
| -0.5 以上 0 未満 | 1.11 | 0 | 10 |
| -0.5 未満 | 1.10 1.01 1.00 | -1 | 00 |
部分剰余のアルゴリズムは
これを表にすると
| qi | 減数 B2 | LSBofCarry |
|---|---|---|
| +1 | ~B | 1 |
| 0 | 0 | 0 |
| -1 | B | 0 |
となる。
また、on - the - fly 変換は具体的に以下の通り。
| qi | ZPi | ZNi |
|---|---|---|
| +1 | { ZPi - 1 , 1 } | { ZPi - 1 , 0 } |
| 0 | { ZPi - 1 , 0 } | { ZNi - 1 , 1 } |
| -1 | { ZNi - 1 , 1 } | { ZNi - 1 , 0 } |
| モジュール名 | cost prim. | 時間 (ns) | 必要 数 | 小計 prim. |
|---|---|---|---|---|
| div_encode | 149 | 3.343 | 2 | 358 |
| div_presft | 420 | 3.920 | 1 | 618 |
| div_qselect_top | 163 | 0.739 | 1 | 163 |
| div_qselect | 1141 | 5.373 | 1 | 1141 |
| div_postsft | 491 | 3.732 | 1 | 491 |