aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/vita_200/xxf_to_xxs.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/vita_200/xxf_to_xxs.v')
-rw-r--r--fpga/usrp3/lib/vita_200/xxf_to_xxs.v77
1 files changed, 77 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/vita_200/xxf_to_xxs.v b/fpga/usrp3/lib/vita_200/xxf_to_xxs.v
new file mode 100644
index 000000000..a64b612c9
--- /dev/null
+++ b/fpga/usrp3/lib/vita_200/xxf_to_xxs.v
@@ -0,0 +1,77 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+module xxf_to_xxs
+#(
+ parameter FBITS = 32, // # of bits for the float
+ parameter integer QWIDTH = 16 // # of bits in total, e.g. 16 for a Q15
+)
+(
+ input [FBITS-1:0] i_float,
+ output reg [QWIDTH-1:0] o_fixed
+);
+
+ // # of bits for the mantissa
+ parameter MBITS = 23;
+
+ // # of bits for the exponent
+ parameter integer EBITS = 8;
+
+ // # of fractional bits, e.g. 15 for Q15
+ parameter integer RADIX = 15;
+
+ // the bias for the exponent
+ parameter integer BIAS = (1 << EBITS -1) - 1;
+
+ // the min/max values displayable in Qx.x format
+ parameter integer MIN = 1 << RADIX;
+ parameter integer MAX = (1 << RADIX) - 1;
+
+ parameter integer SDIFF = RADIX - MBITS - BIAS;
+
+ // Dissect the IEEE 754 float
+ wire is_neg = i_float[FBITS-1];
+ wire [EBITS-1:0] exponent = i_float[MBITS+EBITS-1:MBITS];
+ wire [MBITS-1:0] mantissa = i_float[MBITS-1:0];
+
+ // check for +/- zero
+ wire is_zero = (exponent == 'h0) && (mantissa == 'h0);
+
+ // check for normal / denormalized
+ wire is_denorm = (exponent == 'h0) && (mantissa != 'h0);
+ wire is_norm = !is_denorm;
+
+ // check for infty TODO: parametrize!
+ wire is_inf = (exponent == 'hff) && (mantissa == 'h0);
+
+ // check for NaN TODO: parametrize!
+ wire is_nan = (exponent == 'hff) && (mantissa != 'h0);
+
+ // calculate shift
+ wire signed [EBITS-1:0] shift = $signed(SDIFF[EBITS-1:0])
+ + $signed(exponent);
+
+ wire [FBITS-1:0] shifted_mant = (shift < 0) ?
+ {1'b1, mantissa} >> -shift
+ : {1'b1, mantissa} >> -shift;
+
+ // if shifted value cannot be displayed by Q15 numbers, truncate to MAX/MIN
+ wire [QWIDTH-1:0] sat_mant = (shifted_mant > 16'h8000 && is_neg) ?
+ MIN
+ : (shifted_mant > 16'h7fff && !is_neg) ?
+ MAX : shifted_mant;
+
+ always @(*) begin
+ if (is_inf)
+ o_fixed = (is_neg) ? MIN : MAX;
+ else if (is_denorm || is_zero)
+ o_fixed = 16'h0;
+ else begin
+ o_fixed = (is_neg) ? ~sat_mant + 1 : sat_mant;
+ end
+ end
+endmodule