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 <switchla...@gmail.com> 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 <ejkrei...@gmail.com> 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 <switchla...@gmail.com>
>> 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 <ejkrei...@gmail.com> 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 <
>>>> usrp-users@lists.ettus.com> 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 <switchla...@gmail.com>
>>>>> 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
>>>>> USRP-users@lists.ettus.com
>>>>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
>>>>>
>>>>>
>>>>
>>>
>>
>
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com

Reply via email to