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


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

今回の内容

前回の補足
LeadingZeros消去について

前回の補足

5.型の生成について

桁上がりを考慮してfloat型を生成する.

 //TIM5
reg [31:0] res;

always @(posedge clk) begin
    res[31] <= 1'b0;

    if (r[24]) begin
        res[30:23] <= vexp3 + 8'b1;
        res[22:0] <= r[23:1];
    end else begin
        res[30:23] <= vexp3;
        res[22:0] <= r[22:0];
    end
end

7行目の if 文で
2数の加算結果が繰り上がりを起こすか起こさないかを判定している.

01XX + 0XXX\\
= 01XX\ or\ 1XXX

繰り上がりを起こした際に 1bit シフトして調整を行う.
繰り上がりを起こさない場合は通常通り処理を行う.
(正規化というのかな)

LeadingZeros 消去について

LeadingZeros について

左の0を LeadingZeros というらしいよ.

8'd\ 8 = 8'b\ 0000\_1000

このときの上位 4bit の 0 のこと (らしい).

なぜ消去するのか

減算時にはどの位置に初めて 1 が出現するか予測できない.
float 型を生成するためには最上位の 1 を探す必要がある(?).

LeadingZeros 切り出しモジュール

leadingzero.sv
module lzsv(
    input wire clk,
    input wire [23:0] v,

    output wire [4:0] num,
    output wire [23:0] res
);

    // {num5, res24}
    reg [28:0] cnum;
    assign num = cnum[28:24];
    assign res = cnum[23:0];

always @(posedge clk) begin
    if (v[23]) cnum <= {5'd0, v};
    else if (v[22]) cnum <= {5'd1, v[22:0],  1'b0};
    else if (v[21]) cnum <= {5'd2, v[21:0],  2'b0};
    else if (v[20]) cnum <= {5'd3, v[20:0],  3'b0};
    else if (v[19]) cnum <= {5'd4, v[19:0],  4'b0};
    else if (v[18]) cnum <= {5'd5, v[18:0],  5'b0};
    else if (v[17]) cnum <= {5'd6, v[17:0],  6'b0};
    else if (v[16]) cnum <= {5'd7, v[16:0],  7'b0};
    else if (v[15]) cnum <= {5'd8, v[15:0],  8'b0};
    else if (v[14]) cnum <= {5'd9, v[14:0],  9'b0};
    else if (v[13]) cnum <= {5'd10, v[13:0], 10'b0};
    else if (v[12]) cnum <= {5'd11, v[12:0], 11'b0};
    else if (v[11]) cnum <= {5'd12, v[11:0], 12'b0};
    else if (v[10]) cnum <= {5'd13, v[10:0], 13'b0};
    else if (v[ 9]) cnum <= {5'd14, v[ 9:0], 14'b0};
    else if (v[ 8]) cnum <= {5'd15, v[ 8:0], 15'b0};
    else if (v[ 7]) cnum <= {5'd16, v[ 7:0], 16'b0};
    else if (v[ 6]) cnum <= {5'd17, v[ 6:0], 17'b0};
    else if (v[ 5]) cnum <= {5'd18, v[ 5:0], 18'b0};
    else if (v[ 4]) cnum <= {5'd19, v[ 4:0], 19'b0};
    else if (v[ 3]) cnum <= {5'd20, v[ 3:0], 20'b0};
    else if (v[ 2]) cnum <= {5'd21, v[ 2:0], 21'b0};
    else if (v[ 1]) cnum <= {5'd22, v[ 1:0], 22'b0};
    else if (v[ 0]) cnum <= {5'd23, 24'h800_000};
    else cnum <= {5'd24, 24'd0};
end

endmodule

この記述どうにかなりませんかね...

シミュレーション結果


カウントアップされる acnt が1クロック遅れで 0 を消去しシフトした値が res に得られていることが確認できる.


桁数の更新が指数関数的に長くなるのに対し、数値の更新が毎クロック行われていることが確認できる.