155 lines
7.6 KiB
Systemverilog
155 lines
7.6 KiB
Systemverilog
//////
|
|
// Please consider this function a black box. DO NOT try to copy any part of this function in your code.
|
|
//////
|
|
|
|
function [31:0] multiplication (string round, logic [31:0] a, logic [31:0] b);
|
|
bit [31:0] result;
|
|
// Convert every denormal in zero
|
|
if(a[30:23] == '0) a[22:0] = '0;
|
|
if(b[30:23] == '0) b[22:0] = '0;
|
|
if(a[30:23] == '1) a[22:0] = '0;
|
|
if(b[30:23] == '1) b[22:0] = '0;
|
|
|
|
// If (a is inf or NaN) or (b is inf or NaN) => Result Inf
|
|
if((a[30:23] == '1 && b[30:23] == '0) || (a[30:23] == '0 && b[30:23] == '1)) result = {1'b0, {8{1'b1}}, {23{1'b0}}};
|
|
else begin
|
|
result = $shortrealtobits($bitstoshortreal(a) * $bitstoshortreal(b));
|
|
case (round)
|
|
//IEEE_NEAR ROUNDING
|
|
"IEEE_near": begin
|
|
if(result[30:23] == '1) result[22:0] = '0;
|
|
if(result[30:23] == '0) result[22:0] = '0;
|
|
end
|
|
//IEEE_ZERO ROUNDING
|
|
"IEEE_zero": begin
|
|
//Round towards zero instead if rounded up and positive
|
|
if($bitstoshortreal(result) > ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) > 0)
|
|
begin
|
|
result = result - 1;
|
|
end
|
|
end
|
|
//Round towards zero instead if rounded down and negative
|
|
if($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) < 0)
|
|
begin
|
|
result = result - 1;
|
|
end
|
|
end
|
|
if(result[30:23] == '0) result[22:0] = '0;
|
|
end
|
|
//AWAY_ZERO ROUNDING
|
|
"away_zero": begin
|
|
//Check if the result is denormal and round to minNormal
|
|
if((result[30:23] == '0 && result[22:0] != '0) || (a[30:23] != '0 && b[30:23] != '0 && result[30:23] == '0 && result[22:0] == '0)) begin
|
|
result = {result[31], {7{1'b0}}, 1'b1, {23{1'b0}}};
|
|
end
|
|
else begin
|
|
//Round away from zero instead if rounded up and negative
|
|
if($bitstoshortreal(result) > ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) < 0)
|
|
begin
|
|
result = result + 1;
|
|
end
|
|
end
|
|
//Round away from zero instead if rounded down and positive
|
|
if($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) > 0)
|
|
begin
|
|
result = result + 1;
|
|
end
|
|
end
|
|
end
|
|
if(result[30:23] == '1) result[22:0] = '0;
|
|
end
|
|
//IEEE_PINF ROUNDING
|
|
"IEEE_pinf": begin
|
|
//Check if the result is denormal and round to minNormal, but only for positives
|
|
if((result[31] == 0 && result[30:23] == '0 && result[22:0] != '0) || (result[31] == 0 && a[30:23] != '0 && b[30:23] != '0 && result[30:23] == '0 && result[22:0] == '0)) begin
|
|
result = {{8{1'b0}}, 1'b1, {23{1'b0}}};
|
|
end
|
|
else begin
|
|
//Round towards positive infinity instead if rounded down and positive
|
|
if($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) > 0)
|
|
begin
|
|
result = result + 1;
|
|
end
|
|
end
|
|
//Round towards positive infinity instead if rounded down and negative
|
|
if($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) < 0)
|
|
begin
|
|
result = result - 1;
|
|
end
|
|
end
|
|
end
|
|
if(result[30:23] == '0) result[22:0] = '0;
|
|
end
|
|
//IEEE_NINF ROUNDING
|
|
"IEEE_ninf": begin
|
|
//Check if the result is denormal and round to minNormal, but only for negatives
|
|
if((result[31] == 1 && result[30:23] == '0 && result[22:0] != '0) || (result[31] == 1 && a[30:23] != '0 && b[30:23] != '0 && result[30:23] == '0 && result[22:0] == '0)) begin
|
|
result = {1'b1, {7{1'b0}}, 1'b1, {23{1'b0}}};
|
|
end
|
|
else begin
|
|
//Round towards negative infinity instead if rounded up and positive
|
|
if($bitstoshortreal(result) > ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) > 0)
|
|
begin
|
|
result = result - 1;
|
|
end
|
|
end
|
|
//Round towards negative infinity instead if rounded up and negative
|
|
if($bitstoshortreal(result) > ($bitstoshortreal(a) * $bitstoshortreal(b)))
|
|
begin
|
|
if($bitstoshortreal(result) < 0)
|
|
begin
|
|
result = result + 1;
|
|
end
|
|
end
|
|
end
|
|
if(result[30:23] == '0) result[22:0] = '0;
|
|
end
|
|
//NEAR_UP ROUNDING
|
|
"near_up": begin
|
|
//Round towards positive infinity if rounded down, negative and in the middle
|
|
if(($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b))))
|
|
begin
|
|
if(($bitstoshortreal(result) - ($bitstoshortreal(a) * $bitstoshortreal(b))) == (($bitstoshortreal(a) * $bitstoshortreal(b)) - $bitstoshortreal(result-1)))
|
|
begin
|
|
if($bitstoshortreal(result) < 0)
|
|
begin
|
|
result = result - 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
//Round towards positive infinity if rounded down, positive and in the middle
|
|
if(($bitstoshortreal(result) < ($bitstoshortreal(a) * $bitstoshortreal(b))))
|
|
begin
|
|
if(($bitstoshortreal(result+1) - ($bitstoshortreal(a) * $bitstoshortreal(b))) == (($bitstoshortreal(a) * $bitstoshortreal(b)) - $bitstoshortreal(result)))
|
|
begin
|
|
if($bitstoshortreal(result) > 0)
|
|
begin
|
|
result = result + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
if(result[30:23] == '1) result[22:0] = '0;
|
|
if(result[30:23] == '0) result[22:0] = '0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
return result;
|
|
endfunction
|
|
|