Author Topic: 48-bit unsigned integer to 32-bit IEEE-754 float for Xilinx 7-series (VHDL)  (Read 1099 times)

0 Members and 2 Guests are viewing this topic.

Offline JohnnyMalariaTopic starter

  • Super Contributor
  • ***
  • Posts: 1154
  • Country: us
    • Enlighten Scientific LLC
Hi,

I need to converted 48-bit unsigned integers to 32-bit IEEE-754 floating point format on a Zynq-based FPGA.

The integers come from calculating the magnitude (hence unsigned) of a complex FFT using the Xilinx FFT IP. I want to transfer them to the PS via block RAM to do further numerical processing. Conversion to 32-bit float obviously reduces the RAM required by a third and saves the int-to-float conversion on the ARM processor.

I am aware of the Xilinx Floating Point IP and that it can do conversion but, since I don't need to do any floating point arithmetic on the PL side, I was wondering if there is a simpler, more lightweight way in VHDL (not 2008).

Thanks.
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2812
  • Country: nz
Haven't looked at floating point for a long time, but you have two paths...

x == zero:  maps to floating point zero

x > 0: shift left until a 1 drops off the end, and adjust the mantissa, might need to investigate rounding and corner cases too. The shifter might be a bit resource hungry.

Maybe I'll write a little code to see if it works as I expect....
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 
The following users thanked this post: JohnnyMalaria

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2812
  • Country: nz
Code checks out...

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void u_to_f(uint64_t u, float *d) {
   int m = 128+48-1;
   uint32_t *p = (uint32_t *)d;
   if(u == 0) {
     *p = 0;
     return;
   }

   if((u>>(49-24)) == 0) {
      u <<= 24;
      m -= 24;
   }

   if((u>>(49-12)) == 0) {
      u <<= 12;
      m -= 12;
   }

   if((u>>(49-6)) == 0) {
      u <<= 6;
      m -= 6;
   }

   if((u>>(49-4)) == 0) {
      u <<= 4;
      m -= 4;
   }

   if((u>>(49-2)) == 0) {
      u <<= 2;
      m -= 2;
   }

   if((u>>(49-1)) == 0) {
      u <<= 1;
      m -= 1;
   }

   *p = (m<<23) + ((u >> 25)&0x7FFFFF);
}

int main(int argc, char *argv[]) {
   uint64_t u;
   for(int i = 0; i < 1000; i++) {
      u = rand() % 100000;
      float f = u;
      u_to_f(u, &f);
      printf("%10lu  %10.1f %10.1f\n",u,(float)u, f);
   }
}

How to implement it in VHDL depends on your needs for throughput, latency, and so on.

(and of course code is broken on machines with different endian).
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 
The following users thanked this post: JohnnyMalaria

Offline JohnnyMalariaTopic starter

  • Super Contributor
  • ***
  • Posts: 1154
  • Country: us
    • Enlighten Scientific LLC
Code checks out...

Code: [Select]
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void u_to_f(uint64_t u, float *d) {
   int m = 128+48-1;
   uint32_t *p = (uint32_t *)d;
   if(u == 0) {
     *p = 0;
     return;
   }

   if((u>>(49-24)) == 0) {
      u <<= 24;
      m -= 24;
   }

   if((u>>(49-12)) == 0) {
      u <<= 12;
      m -= 12;
   }

   if((u>>(49-6)) == 0) {
      u <<= 6;
      m -= 6;
   }

   if((u>>(49-4)) == 0) {
      u <<= 4;
      m -= 4;
   }

   if((u>>(49-2)) == 0) {
      u <<= 2;
      m -= 2;
   }

   if((u>>(49-1)) == 0) {
      u <<= 1;
      m -= 1;
   }

   *p = (m<<23) + ((u >> 25)&0x7FFFFF);
}

int main(int argc, char *argv[]) {
   uint64_t u;
   for(int i = 0; i < 1000; i++) {
      u = rand() % 100000;
      float f = u;
      u_to_f(u, &f);
      printf("%10lu  %10.1f %10.1f\n",u,(float)u, f);
   }
}

How to implement it in VHDL depends on your needs for throughput, latency, and so on.

(and of course code is broken on machines with different endian).

Thank you very much - it looks like I have a homework assignment for the weekend.  :-+
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf