Ehh, I dont think that's an accurate description of what's going on... Take a look at the 32-bit floating point definition: https://en.wikipedia.org/wiki/Single-precision_floating-point_format The wikipedia definition seems to be essentially what's going on here, with the added twist that the output is 16-bit fixed point, so there's some shortcuts to get the datatypes to match.
Some quick thoughts... The sign bit specifies the sign of the value. The 8-bits pulled out into "shift_val" represents the exponent, while the remaining 24-bits are the mantissa (captured in "shift" -- you can see the "shift" variable takes the round_fraction and right-shifts by the shift_val). I expect the magic numbers in round_fraction and shift are due to the 16-bit fixed point output, and you'd want to confirm the Q-style format (# integer bits, # fractional bits) is correct on the output. You might be able to use this block to read convert a 32-bit floating point register in the FPGA to your desired 16-bit fixed point, which could be a fine solution. But if you're already programming taps, you definitely need a C++ controller anyway, so I'd suggest doing the conversion there. EJ On Mon, Aug 14, 2017 at 4:06 PM, Andrew Lanez <[email protected]> wrote: > Hi EJ, > > Thanks for the pointers. Ok, I think I see now that float_to_iq module is > fixed point. Am I interpreting these lines of code correctly that put an > 8-bit bound on the mantissa with a 2's complement sign bit, leaving the > remaining 8-bits for radix: > > > assign shift_val = (in[30:23] > 127)? (in[30:23] - 127): (127 - in[30:23]); > > ... > > wire [15:0] final_val = (in[31] == 1)?(~shift + 1'b1):shift; > > > I've been pursuing this conversion from within my noc block but doing it > in the block controller instead is looking more attractive. > > Thanks, > Andrew > > > > > On Mon, Aug 14, 2017 at 4:49 AM, EJ Kreinar <[email protected]> wrote: > >> Hi Andrew, >> >> As far as I can tell, that particular verilog block implements a 32-bit >> floating point to 16-bit fixed point conversion. The name may be a misnomer >> because it does not actually break the input into I/Q channels. >> >> For floating to fixed conversion in software, I usually refer to this >> wikipedia page, which includes notation information and provides a >> quick/easy conversion: https://en.wikipedia.org/wiki/Q_(number_format) >> >> Usually my rule of thumb is that if there's a plausible way to do >> something in software, it's better to do it in software :D The C++ control >> block driver is a good place to wrap some helper code (e.g., converting >> taps, calculating magic numbers, etc etc) around your time-critical and >> performance-intensive FPGA operations. >> >> EJ >> >> On Sun, Aug 13, 2017 at 7:30 AM, Andrew Lanez <[email protected]> >> wrote: >> >>> EJ, >>> >>> I spent some time wrestling with the 32-bit to 16-bit conversion in my >>> verilog noc block then realized doing the conversion in the C++ control >>> block driver might be more straightforward. I'm trying to digest the >>> following: >>> >>> https://raw.githubusercontent.com/EttusResearch/fpga/b108e88 >>> 865ee0fa68e685461681d8ca6a320b937/usrp3/lib/vita/float_to_iq.v >>> >>> I can't tell if that converter is fixed-point. I'm inclined to believe >>> it's 16-bit compressed floating point. Do you or anyone have references to >>> do an equivalent conversion in C++? >>> >>> Andrew >>> >>> On Thu, Aug 10, 2017 at 8:51 AM, EJ Kreinar <[email protected]> wrote: >>> >>>> Hi Andrew, >>>> >>>> The OOT module .xml file definition currently only supports writing >>>> scalar registers, so you need a custom C++ driver. The int_vector option >>>> has not been implemented, and honestly I'm not sure if it would even make >>>> sense because there's many different ways the HDL could implement a >>>> "vector" of taps... it's not really a one-size-fits-all problem. >>>> >>>> My recommendation would be to model your hf_chlizer's C++ driver on the >>>> in-tree fir_block_ctrl_impl. Use the sr_write functions to program your >>>> taps as your HDL code requires. >>>> >>>> You'll notice fir_block_ctrl_impl uses integer taps. This ends up being >>>> a little clumsy when developing flowgraphs, since your flowgraph >>>> application needs to handle the floating point / fixed point conversion. In >>>> the past, I've created a C++ driver that accepts floating point inputs and >>>> converts to fixed point before programming to FPGA registers. Your >>>> preference. >>>> >>>> Hope this helps, >>>> EJ >>>> >>>> >>>> >>>> On Tue, Aug 8, 2017 at 6:00 AM, Andrew Lanez via USRP-users < >>>> [email protected]> wrote: >>>> >>>>> Typo, the 3rd to last paragraph should read: >>>>> >>>>> Or I could hack *rfnoc_fir_cci()*. I started this by replacing int >>>>> vectors with std::complex vectors everywhere FIR taps were referenced in >>>>> the in-tree module's C++ library but I stopped when it traced up to >>>>> block.h >>>>> because that may affect other modules. >>>>> >>>>> On Tue, Aug 8, 2017 at 2:56 AM, Andrew Lanez <[email protected]> >>>>> wrote: >>>>> >>>>>> Hi, >>>>>> >>>>>> I am developing a FIR filter that will eventually accepts complex >>>>>> taps reprogrammable during runtime. As a first iteration, I want to >>>>>> verify >>>>>> it works like the in-tree module with int_vector real taps. So I >>>>>> configure >>>>>> the settings register in OOT module's .xml file to take int_vector taps >>>>>> but >>>>>> running it returns: >>>>>> RuntimeError: RuntimeError: not yet implemented: int_vector >>>>>> >>>>>> I guess it's because the in-tree module's ettus.rfnoc_fir_cci() make >>>>>> function supports int_vector whereas my rfnocmodtool generated make >>>>>> function hf_chlizer.fir() does not. >>>>>> >>>>>> So I changed my OOT module's .xml to use ettus.rfnoc_fir_cci() >>>>>> instead of hf_chlizer.fir() and output shows both I and Q samples are >>>>>> filtered identically by real taps. >>>>>> >>>>>> But ettus.rfnoc_fir_cci() does not seem to support complex_vector >>>>>> taps. So I must revert to hf_chlizer.fir() in which case I get: >>>>>> RuntimeError: RuntimeError: Invalid block definition in >>>>>> /home/switchlanez/rfnoc/share/uhd/rfnoc/blocks/fir.xml: >>>>>> RuntimeError: Found invalid arguments for block fir. >>>>>> >>>>>> Or I could hack hf_chlizer.fir(). I started this by replacing int >>>>>> vectors with std::complex vectors everywhere FIR taps were referenced in >>>>>> the in-tree module's C++ library but I stopped when it traced up to >>>>>> block.h >>>>>> because that may affect other modules. >>>>>> >>>>>> 1) What's the best approach to implement a vector of complex taps >>>>>> reprogrammable during runtime? >>>>>> >>>>>> 2) My verilog code assumes one complex tap is 32 bits (leftmost 16 >>>>>> bits for I, rightmost 16 bits for Q) and formats complex samples the same >>>>>> (in-tree module also handles complex sample this way). Will UHD >>>>>> automatically convert complex floats incoming from the host to sc16 for >>>>>> the >>>>>> embedded settings registers? >>>>>> >>>>>> Thanks, >>>>>> Andrew >>>>>> >>>>> >>>>> >>>>> _______________________________________________ >>>>> USRP-users mailing list >>>>> [email protected] >>>>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com >>>>> >>>>> >>>> >>> >> >
_______________________________________________ USRP-users mailing list [email protected] http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
