FPU 拡張を追加したい (FADD)

まずは FADD を作ってみます。回路構造をあまり意識しない、Verilog 動作モデルから作ってみることにしました。Veriloator を使ってランダム(指数差に制限あり)の入力データを作って力尽くで検証します。回路構造は FMADD までの動作モデルがそろってから考えることにします。
RISC-V アーキテクチャで面倒くさいのは、サブノーマル数を扱わなくてはならないことです。入力側は特に難しいことはないし、レジスタ読み出し後に多少の時間の余裕があるので、あまり気にすることはありません。出力側はちょっと難しくて、正規化シフトを途中で止めなくてはなりません。正規化前指数を正規化シフト量が超えては駄目なんです。こんな感じでシフト量をマスクする実装が無駄が少なくて良いのかな?
wire [4:0] nrmsft; // expr >= nrmsft : subnormal output
assign nrmsft[4] = (sft[4])& (expr[7:4]!=4'h0);
assign nrmsft[3] = (sft[3])&((expr[7:3]&{3'h7, ~nrmsft[4], 1'b1})!=5'h00);
assign nrmsft[2] = (sft[2])&((expr[7:2]&{4'hf, ~nrmsft[4:3],1'b1})!=6'h00);
assign nrmsft[1] = (sft[1])&((expr[7:1]&{5'h1f,~nrmsft[4:2],1'b1})!=7'h00);
assign nrmsft[0] = (sft[0])&((expr[7:0]&{6'h3f,~nrmsft[4:1],1'b1})!=8'h00);

そして丸めですが、加算(減算)後の仮数が負になってしまった場合の処理が特殊です。正に戻してから丸め判定なんてのんびりした事はせず、反転前のデータを使って丸め判定します。
まずは LSB よりも下位が全部0の場合は、丸めとは関係なしに LSB に 1 を足します(×-1のため)。
sticky は×-1しても変わりません。
つぎに、round は sticky = 0 の時に、反転した後にまた元に戻ります。sticky = 1 の時は反転のままです。LSB も同様に考えます。
すると、反転した仮数部に 1 を足すか否かの判定は以下のようになります。
assign rnd = ((grs[1:0]==2'b00)| // inc
((grs[1]^grs[0]) &(grs[0]))| // rs=11
((grs[2]^(|grs[1:0]))&(grs[1]^grs[0]))); // gr=11

FADD 全体を Veriloator 用のテストベンチと共に Github に置いておきます。
あ、近傍丸め以外の事とか全然考えてないや。

[PR]
トラックバックURL : http://tom01h.exblog.jp/tb/27461448
トラックバックする(会員専用) [ヘルプ]
※このブログはトラックバック承認制を適用しています。 ブログの持ち主が承認するまでトラックバックは表示されません。
by tom01h | 2017-01-19 23:21 | PCとか | Trackback | Comments(0)