diff options
Diffstat (limited to 'fpga/usrp3/lib/vita_200/xxf_to_xxs.v')
-rw-r--r-- | fpga/usrp3/lib/vita_200/xxf_to_xxs.v | 77 |
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 |