#Float計算回路のVerilog実装
~ FPGA に載せたい ~
オレオレ実装なので間違っていても知りません
加算回路編
Float計算回路のVerilog-HDL実装について -その1
デバッグツール作成編
Float計算回路の(ry-その1.1(float値の16進数表記)
補足とLeadingZeros編
Float計算回路のVerilog-HDL実装について -その1.5 (LeadingZeros)
減算回路編
Float計算回路のVerilog-HDL実装について -その2(減算編)
目的
floatの勉強
float32のハードウェア実装
その1で作成した加算回路とその2で作成した減算回路を共通化するため、
加算回路(のタイミングなどを)を調整する。
仕様はその1に準拠
仕様
下図右が前回作成した減算回路
下図左が今回作成した加算回路
4クロック目の符号のみ異なる
略コード
module float_add(
input wire clk,
input wire [31:0] v1,
input wire [31:0] v2,
output wire [31:0] vres
);
assign vres = res;
//TIM1
reg [31:0] vb;
reg [31:0] vs;
//TIM2
reg [7:0] dexp;
reg [7:0] vexp;
reg [22:0] vb2;
reg [22:0] vs2;
//TIM3
reg [7:0] vexp2;
reg [24:0] vb3;
reg [24:0] vs3;
//TIM4
reg [7:0] vexp3;
reg [24:0] r;
//TIM5,6
reg [7:0] vexp4;
reg [7:0] vexp5;
reg [23:0] lzr;
wire [7:0] lznum;
wire [23:0] lzres;
lzsv lzm(
.clk(clk),
.v(r),
.num(lznum),
.res(lzres)
);
//TIM7
reg [31:0] res;
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
// TIM2 //
dexp <= vb[30:23] - vs[30:23];
vexp <= vb[30:23];
vb2 <= vb;
vs2 <= vs;
// TIM3 //
vexp2 <= vexp;
vb3 <= {2'b1, vb2};
vs3 <= {1'b0, vssf({1'b1, vs2}, dexp)};
// TIM4 //
vexp3 <= vexp2;
r <= vb3 + vs3;
// r <= vb3 - vs3;
// TIM5 //
vexp4 <= vexp3;
vexp5 <= vexp4 - lznum;
lzr <= lzres;
// TIM6 //
res[31] <= 1'b0;
res[30:23] <= vexp5;
res[22:0] <= lzr[22:0];
end
//Value Small Shift Function
function [23:0] vssf(input [23:0] v, input [7:0] num);
(略)
endfunction
endmodule
TIM4 のコメントアウトを逆にすることで、減算できることも確認できている
新しい LeadingZeros 用モジュール
加算回路でもLeadingZerosモジュールを使用するため、
桁下がりだけでなく、桁上がりにもこのLeadingZerosモジュールを対応させる必要がある
module lzsv(
input wire clk,
input wire [24:0] v,
output wire [7:0] num,
output wire [23:0] res
);
// {num8, res24}
reg [31:0] cnum;
assign num = cnum[31:24];
assign res = cnum[23:0];
always @(posedge clk) begin
if (v[24]) cnum <= {8'hFF, v[24:1]};
else if (v[23]) cnum <= {8'd0, v[23:0]};
else if (v[22]) cnum <= {8'd1, v[22:0], 1'b0};
else if (v[21]) cnum <= {8'd2, v[21:0], 2'b0};
else if (v[20]) cnum <= {8'd3, v[20:0], 3'b0};
else if (v[19]) cnum <= {8'd4, v[19:0], 4'b0};
(略)
else if (v[ 1]) cnum <= {8'd22, v[ 1:0], 22'b0};
else if (v[ 0]) cnum <= {8'd23, 24'h800_000};
else cnum <= {8'd24, 24'd0};
end
endmodule
桁計算時に-1を引くように仕向けるべく 24bit 目が 1 のとき FF(-1) を返す
シミュレーション結果
123.4 + 7.25 = 130.65\\
=> 42F6\_CCCD + 40E8\_0000 = 4302\_A666
123.4 - 7.25 = 116.15\\
=> 42F6\_CCCD - 40E8\_0000 = 42E8\_4CCD