1

I'm sqauring a 16.16 fixed point binary number and then compare the result with an integer. The 16.16 number becomes a 64 Bit binary number after squaring. I don't know exactly if my code is correct and every square of a 16.16 fixed point number is within range. Also I cannot setup the right statement to represent the 32.32 fixed point result.

Pseudo code

  reg [31:0] n;      //the 32 Bit number we want to square
  reg [63:0] res;    //out result register after squaring n
  integer i;         

  ...
  res = n * n;      // squaring n
  i   = 1;
   /* compare with some integer - bigger than i */
  if( res[63:32] >= i && res[31:0] > 0)
     begin ...do something ... end

   /* compare with some integer - less/equal than i */
 if( (res[63:32] < i && res[31:0] >= 0) || (res[63:32] <= i && res[31:0] == 0))
     begin ...do something... end
 ...

In the testbench I'm trying to represent the result as a 32.32 fixed point binary number - but this representation won't give me the right float value when displaying:

    res[63:32] + $bitstoreal({1'b0,15'b011111111111111,{fer3[31:0],{81{1'b0}} }) -1;
k t
  • 343
  • 5
  • 15

1 Answers1

3

There is a similar question which discusses fixed point widths, ... multiply a 32 bit by 32 bit the answer would fit into 64bits. Your correct with 16.16 x 16.16 is 32.32.

verilog conversion to reals can be automatic, if done correctly, to scale a number for display n * 2**-16 does not work. n * 2.0**-16 Does because we used 2.0 the calculation is done using floating point instead of integer.

NB: 2**n is 2 to the power of n. 2^n in some languages but ^ is XOR in verilog.

A quick example of scaling for comparison using a real:

reg [31:0] n;    //16.16
reg [63:0] n_sq; //32.32
real n_sq_real;  // Floating Point

always @* begin
  n_sq = n * n;
end

initial begin
  #1ps;
  n = { 16'd2, 16'b1000_0000_0000_0000}; //2.5
  #1ns;

  $display("n %f, n squared %f", (n * 2.0**-16), n_sq * 2.0**-32);

  n_sq_real = n_sq * 2.0**-32 ;

  $display("n_sq_real %f", n_sq_real);
end

Returns:

# n 2.500000, n squared 6.250000
# n_sq_real 6.250000

The example on EDA Playground.

If it is just for comparison to an integer you can just truncate your number by shifting out the fractional bits ie n_sq * 2.0**-32 becomes n_sq >> 32

Or you could scale the integer by the number of fractional bits.

n_sq >= i<<32 ;

At the end of the day fixed point numbers in verilog are just integers scaled by a power of 2 to thats some bits can represent fractional information.

Community
  • 1
  • 1
Morgan
  • 19,934
  • 8
  • 58
  • 84
  • yes, this works great. You helped a lot; My mistake was more fundamental. I did the actual squaring at the wrong position in the code. It was done in the sequential part in my code. What followed, was that the squaring of the number didn't changed for two clock cycles, though the number to be squared should have been changing. Thanks a lot! – k t Jan 06 '15 at 22:15