summaryrefslogtreecommitdiff
path: root/rtl/fpu/float/fp_rnd.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-04-27 11:45:23 -0600
committerAlejandro Soto <alejandro@34project.org>2024-04-27 11:45:23 -0600
commit45b5eabe868ac2f8a755379bde07c102caf74afb (patch)
tree7b740cbc6b19b46d731e29ee145c2a8ad744e847 /rtl/fpu/float/fp_rnd.sv
parenta61ee4b16157f3c6501d958b8dcde7f57f41110d (diff)
rtl/fpu: initial commit
Imported from https://github.com/taneroksuz/fpu-sp
Diffstat (limited to '')
-rw-r--r--rtl/fpu/float/fp_rnd.sv194
1 files changed, 194 insertions, 0 deletions
diff --git a/rtl/fpu/float/fp_rnd.sv b/rtl/fpu/float/fp_rnd.sv
new file mode 100644
index 0000000..8f69e26
--- /dev/null
+++ b/rtl/fpu/float/fp_rnd.sv
@@ -0,0 +1,194 @@
+import fp_wire::*;
+
+module fp_rnd (
+ input fp_rnd_in_type fp_rnd_i,
+ output fp_rnd_out_type fp_rnd_o
+);
+
+ logic sig;
+ logic [13:0] expo;
+ logic [53:0] mant;
+ logic [1:0] rema;
+ logic [1:0] fmt;
+ logic [2:0] rm;
+ logic [2:0] grs;
+ logic snan;
+ logic qnan;
+ logic dbz;
+ logic infs;
+ logic zero;
+ logic diff;
+
+ logic odd;
+ logic rndup;
+ logic rnddn;
+ logic shift;
+ logic [63:0] result;
+ logic [4:0] flags;
+
+ always_comb begin
+
+ sig = fp_rnd_i.sig;
+ expo = fp_rnd_i.expo;
+ mant = fp_rnd_i.mant;
+ rema = fp_rnd_i.rema;
+ fmt = fp_rnd_i.fmt;
+ rm = fp_rnd_i.rm;
+ grs = fp_rnd_i.grs;
+ snan = fp_rnd_i.snan;
+ qnan = fp_rnd_i.qnan;
+ dbz = fp_rnd_i.dbz;
+ infs = fp_rnd_i.infs;
+ zero = fp_rnd_i.zero;
+ diff = fp_rnd_i.diff;
+
+ result = 0;
+ flags = 0;
+
+ odd = mant[0] | |grs[1:0] | (rema == 1);
+ flags[0] = (rema != 0) | |grs;
+
+ rndup = 0;
+ rnddn = 0;
+ if (rm == 0) begin //rne
+ if (grs[2] & odd) begin
+ rndup = 1;
+ end
+ end else if (rm == 1) begin //rtz
+ rnddn = 1;
+ end else if (rm == 2) begin //rdn
+ if (sig & flags[0]) begin
+ rndup = 1;
+ end else if (~sig & zero & diff) begin
+ sig = ~sig;
+ end else if (~sig) begin
+ rnddn = 1;
+ end
+ end else if (rm == 3) begin //rup
+ if (~sig & flags[0]) begin
+ rndup = 1;
+ end else if (sig) begin
+ rnddn = 1;
+ end
+ end else if (rm == 4) begin //rmm
+ if (grs[2] & flags[0]) begin
+ rndup = 1;
+ end
+ end
+
+ //if (expo == 0) begin
+ // flags[1] = flags[0];
+ //end
+
+ mant = mant + {53'h0, rndup};
+
+ if (rndup == 1) begin
+ if (fmt == 0) begin
+ if (expo == 0) begin
+ if (mant[23]) begin
+ expo = 1;
+ end
+ end
+ end else if (fmt == 1) begin
+ if (expo == 0) begin
+ if (mant[52]) begin
+ expo = 1;
+ end
+ end
+ end
+ end
+
+ if (rnddn == 1) begin
+ if (fmt == 0) begin
+ if (expo >= 255) begin
+ expo = 254;
+ mant = {31'b0, {23{1'b1}}};
+ flags = 5'b00101;
+ end
+ end else if (fmt == 1) begin
+ if (expo >= 2047) begin
+ expo = 2046;
+ mant = {2'b0, {52{1'b1}}};
+ flags = 5'b00101;
+ end
+ end
+ end
+
+ shift = 0;
+ if (fmt == 0) begin
+ if (mant[24]) begin
+ shift = 1;
+ end
+ end else if (fmt == 1) begin
+ if (mant[53]) begin
+ shift = 1;
+ end
+ end
+
+ expo = expo + {13'h0, shift};
+ mant = mant >> shift;
+
+ if (expo == 0) begin
+ flags[1] = flags[0];
+ end
+
+ if (rndup == 1) begin
+ if (expo == 1) begin
+ if (fmt == 0 && |mant[22:0] == 0) begin
+ flags[1] = rm == 2 || rm == 3 ? ((grs == 1) | (grs == 2) | (grs == 3) | (grs == 4)) : ((grs == 4) | (grs == 5));
+ end else if (fmt == 1 && |mant[51:0] == 0) begin
+ flags[1] = rm == 2 || rm == 3 ? ((grs == 1) | (grs == 2) | (grs == 3) | (grs == 4)) : ((grs == 4) | (grs == 5));
+ end
+ end
+ end
+
+ if (snan) begin
+ flags = 5'b10000;
+ end else if (qnan) begin
+ flags = 5'b00000;
+ end else if (dbz) begin
+ flags = 5'b01000;
+ end else if (infs) begin
+ flags = 5'b00000;
+ end else if (zero) begin
+ flags = 5'b00000;
+ end
+
+ if (fmt == 0) begin
+ if (snan | qnan) begin
+ result = {32'h00000000, 1'h0, 8'hFF, 23'h400000};
+ end else if (dbz | infs) begin
+ result = {32'h00000000, sig, 8'hFF, 23'h000000};
+ end else if (zero) begin
+ result = {32'h00000000, sig, 8'h00, 23'h000000};
+ end else if (expo == 0) begin
+ result = {32'h00000000, sig, 8'h00, mant[22:0]};
+ end else if ($signed(expo) > 254) begin
+ flags = 5'b00101;
+ result = {32'h00000000, sig, 8'hFF, 23'h000000};
+ end else begin
+ result = {32'h00000000, sig, expo[7:0], mant[22:0]};
+ end
+ end else if (fmt == 1) begin
+ if (snan | qnan) begin
+ result = {1'h0, 11'h7FF, 52'h8000000000000};
+ end else if (dbz | infs) begin
+ result = {sig, 11'h7FF, 52'h0000000000000};
+ end else if (zero) begin
+ result = {sig, 11'h000, 52'h0000000000000};
+ end else if (expo == 0) begin
+ result = {sig, 11'h000, mant[51:0]};
+ end else if ($signed(expo) > 2046) begin
+ flags = 5'b00101;
+ result = {sig, 11'h7FF, 52'h0000000000000};
+ end else begin
+ result = {sig, expo[10:0], mant[51:0]};
+ end
+ end
+
+ fp_rnd_o.result = result;
+ fp_rnd_o.flags = flags;
+
+ end
+
+endmodule