Float計算回路のVerilog-HDL実装について -その2(減算編)


Float計算回路のVerilog実装

~ FPGA に載せたい ~
オレオレ実装なので間違っていても知りません

加算回路編
Float計算回路のVerilog-HDL実装について -その1

デバッグツール作成編
Float計算回路の(ry-その1.1(float値の16進数表記)

補足とLeadingZeros編
Float計算回路のVerilog-HDL実装について -その1.5 (LeadingZeros)

(基本的な)減算だけ
正の数1 - 正の数2
かつ 数1 > 数2

大体前回と一緒.

目的

floatの勉強
float32のハードウェア実装

浮動小数点数の減算

オレオレ浮動小数点加算回路のタイミングは下の図のように設計した.

以下詳細

1. 値の比較

数値比較を行い, 大きい方を vb(value big), 小さい方を vs(value small)へ格納する.
加算回路と異なり、符号の話が関係するので完全に大小を分離したい.

//TIM1
reg [31:0] vb;
reg [31:0] vs;

always @(posedge clk) begin
    // TIM1 //
    if (v2[30:23] < v1[30:23]) begin
        vb <= v1;
        vs <= v2;
    end else if (v1[30:23] < v2[30:23]) begin
        vb <= v2;
        vs <= v1;
    end else if (v2[22:0] < v1[22:0]) begin
        vb <= v1;
        vs <= v2;
    end else begin
        vb <= v2;
        vs <= v1;
    end
end  

指数部で大小比較
指数部が同値ならば仮数部で大小比較

2. 指数部距離の計算

シフト量を把握するために, 各数値の指数部距離を計算する.
他はパイプライン時に潰されないように保護する.

//TIM2
reg [7:0] dexp;
reg [7:0] vexp;
reg [22:0] vb2;
reg [22:0] vs2;

always @(posedge clk) begin
    dexp <= vb[30:23] - vs[30:23];
    vexp <= vb[30:23];

    vb2 <= vb[22:0];
    vs2 <= vs[22:0];                                                                                     
end

3. 値のシフト, 減算の準備

減算のために1を付け加えたり, 値をシフトして桁を合わせておく.
この際小さい方の数値はシフト時に切り捨てる(正しいかどうかは知らない).

//TIM3
reg [7:0] vexp2;
reg [24:0] vb3;
reg [24:0] vs3;

always @(posedge clk) begin
    vexp2 <= vexp;

    vb3 <= {2'b1, vb2};
    vs3 <= {1'b0, vssf({1'b1, vs2}, dexp)};
end

シフト方法は頭いい方法がまだわからないで前回のを使います.

4. 減算

桁は合わせているため,減算を行うのみ.

//TIM4
reg [7:0] vexp3;
reg [24:0] r;

always @(posedge clk) begin
    vexp3 <= vexp2;

    r <= vb3 - vs3;                                                                                
end

5. LeadingZeros処理

LeadingZeros を処理し
指数部をいじる.
LeadingZerosモジュール lzsv にて
1クロック消化される為

//TIM5, 6
reg [7:0] vexp4;
reg [7:0] vexp5;
reg [23:0] lzr;
wire [4:0] lznum;
wire [23:0] lzres;

lzsv lzm(
    .clk(clk),
    .v(r),
    .num(lznum),
    .res(lzres)
);

always @(posedge clk) begin
    vexp4 <= vexp3;
    vexp5 <= vexp4 - {3'b0, lznum};

    lzr <= lzres;
end

6. 型の生成

//TIM7
reg [31:0] res;

always @(posedge clk) begin
    res[31] <= 1'b0;
    res[30:23] <= vexp5;
    res[22:0] <= lzr[22:0];
end

float 型を生成する.

シミュレーション結果

123.4\ -\ 7.25 = 116.15\\
42F6\_CCCD\ -\ 40E8\_0000 = 42E8\_4CCD

まぁあっているのではないでしょうか.

桁数ブレッブレなのはご愛嬌