0
votes

Here is my code for the square root in floating point format in Verilog:

module fp_sqrt (x,y);
input [31:0]x;
output [31:0]y;
reg [31:0]y;
integer i;

function [63:0]bit2bit_sq;
input [31:0]x;
reg[63:0]y;

begin 
for (i =31; i > 0; i=i-1)
y [2*i] = x[i]; 
y [(2*i)+1] = 1'b0;
    bit2bit_sq=y;
end
endfunction

   always@(x)
begin
reg[22:0]x_mantissa;
reg[7:0]x_exponent;
reg x_sign;
reg[22:0]y_mantissa;
reg[7:0]y_exponent;
reg y_sign;
reg[25:0]ix;

reg[51:0]a;

reg[25:0]biti;

    reg[51:0]r;
    reg[52:0]rt;

    x_mantissa=x[22:0];
    x_exponent=x[30:23];
    x_sign=x[31];
    y_sign=1'b0;

if(x_exponent==8'b00000000)
begin
    y_exponent=8'b0;
    y_mantissa=23'b0;
end
else if (x_exponent==8'b11111111)
begin
    y_exponent=8'b1;
    y_mantissa=23'b0;
end
else
begin
    if(x_exponent[0]==1'b1)
    begin
        y_exponent={1'b0,x_exponent[7:1]}+64;
        ix={2'b01,x_mantissa,1'b0};
    end
    else
    begin
        y_exponent={1'b0,x_exponent[7:1]}+63;
        ix={1'b1,x_mantissa,2'b00};
    end
a=52'b0;
biti={2'b10,x<=000000};
r[51:26]=ix;
r[25:0]=26'b0;
begin
    for(i=25;i>=0;i=i-1)
    begin
        rt={{1'b0,r}-{{1'b0,{a|bit2bit_sq(biti)}}}};
        a={a[51:1],1'b0};
        if(rt[52]==1'b0)
        begin
            r=rt[51:0];
            a=a|bit2bit_sq;
        end
            biti={biti[25:1],1'b0};
        end
    end
    a[24:2]=a[24:2]+a[1];
    y_mantissa=a[24:2];
end

y[22:0]=y_mantissa;
y[30:23]=y_exponent;
y[31]=y_sign;
end
endmodule

Why does it show the following error?

Error (10833): SystemVerilog error at fp_sqrt.v(8): argument "x"associated with empty expression must have a default value

this is the message after i done compilation

⚠️ 10036 Verilog HDL or VHDL warting at fp_sqrt.v(93) : object "x_sign" assigned a value but never read
⚠️ 10230 Verilog HDL assignment warning at fp_sqrt.v(122) : truncated value with size 32 to match size of target (8)
⚠️ 10230 Verilog HDL assignment warning at fp_sqrt.v(127) : truncated value with size 32 to match size of target (8)
⚠️ 10242 Verilog HDL Function Declaration warning at fp_seqrt.v(14) : variable "y" may have a Don't Care value because it may not be assigned a value in every possible ...
⚠️ 10230 Verilog HDL assignment warning at fp_sqrt.v(127) : truncated value with size 65 to match size of targe (53)
❌ 10833 SystemVerilog error at fp_sqrt.v(7) : argument "x" associated with empty expression must have a default value
⚠️ 10230 Verilog HDL assignment warning at fp_sqrt.v(142) : truncated value with size 64 to match size of target (52)
⚠️ 10240 Verilog HDL Always Construct warning at fp_sqrt.v(89) : inferring latch(es) for variable "i", which holds its previous value in one or more paths ...
❌ 12153 Can't elaborate top-level user hierarchy
❌ Quartus II 64-Bit Analysis & Synthesis was unsucessful. 2 errors and 8 warnings

this is code that i convert from this original VHDL code I have try to understand then i try to edit into verilog code. while when i compile the code below which is VHDL implementation of a 32 bit floating point square root. there is no error and function well. while i convert to verilog code there is error. please help me.

  -- Description: VHDL implementation of a 32 bit floating point square root.
--          Float format: sign | 8 bits exponent + 127 | 23 bits normalized mantissa.
--      Uses IEEE 754-1985, with the following exceptions.
--          NaN is not implemented. Operations that would result in NaN 
--          have a non definied result.
--          An exponent of all zeros will always mean zero, and an
--          exponent of all ones will always mean infinity.
--          Rounding is round nearest ties away from zero.
--          Non normalized numbers are not implemented.
--
-- Dependencies: 
--
-- Revision: 1.0
-- Additional Comments: 
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- use STD.textio.all;                     -- basic I/O
-- use IEEE.std_logic_textio.all;          -- I/O for logic types

entity sqrt is
    Port ( x : in  STD_LOGIC_VECTOR (31 downto 0);
           y : out  STD_LOGIC_VECTOR (31 downto 0));
end sqrt;

architecture Behavioral of sqrt is

    function bit2bit_sq(x: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
        variable y : STD_LOGIC_VECTOR(2*x'left+1 downto 0);
    -- Returns x^2 by intercalating zeros in the argument,
    -- were x has only one bit different from zero.
    begin
        for i in x'left downto 0 loop
            -- x'right must be zero
            y(2*i):=x(i);
            y(2*i+1):='0';
        end loop;
        return y;
    end;

begin
    process(x)
        variable x_mantissa : STD_LOGIC_VECTOR (22 downto 0);
        variable x_exponent : STD_LOGIC_VECTOR (7 downto 0);
        variable x_sign : STD_LOGIC;
        variable y_mantissa : STD_LOGIC_VECTOR (22 downto 0);
        variable y_exponent : STD_LOGIC_VECTOR (7 downto 0);
        variable y_sign : STD_LOGIC;

        variable ix: STD_LOGIC_VECTOR (25 downto 0);
        variable a : STD_LOGIC_VECTOR (51 downto 0);
        variable biti : STD_LOGIC_VECTOR (25 downto 0);
        variable r : STD_LOGIC_VECTOR (51 downto 0);
        variable rt : STD_LOGIC_VECTOR (52 downto 0);

        -- variable my_line : line;  -- type 'line' comes from textio
   begin
        x_mantissa := x(22 downto 0);
        x_exponent := x(30 downto 23);
        x_sign := x(31);

        y_sign := '0';

        if (x_exponent="00000000") then -- zero
            y_exponent := (others=>'0');
            y_mantissa := (others=>'0');
        elsif (x_exponent="11111111") then -- infinity
            y_exponent := (others=>'1');
            y_mantissa := (others=>'0');
        else

            if (x_exponent(0)='1') then -- exponent-127 is even
                y_exponent := '0' & x_exponent(7 downto 1) + 64;
                ix := "01" & x_mantissa & '0'; 
            else -- exponent-127 is odd
                -- shift mantissa one to the left and subtract one from x_exponent
                y_exponent := '0' & x_exponent(7 downto 1) + 63;
                ix := '1' & x_mantissa & "00";
            end if;
            -- mantissa is m=ix/2^24 
            -- (one zero was added to the right to make the power even)
            -- let the result of the integer square root algorithm be iy (26 bits)
            -- iy = sqtr(ix)*2^13
            -- resulting that sqrt(m)=iy/2^25

            -- Integer input N bits square root algorithm:
            -- r is be the reminder, r=ix-z^2, and z(N+1) the result, 
            --  with bit(N)=1/2^(N/2), and bit(n)=2^(N/2-n)
            -- Test each bit in the result, from the most significative to the least
            -- significative: n goes from zero no N.
            -- if bit is one: r(n+1) = ix - (z(n)+bit(n))^2 = 
            --                              r(n) - 2z(n)bit(n) - bit(n)^2
            -- else           r(n+1) = r(n)
            -- bit will be one if the resulting remainder is positive.
            -- making a(n) = 2z(n)bit(n), one has, 
            -- if bit is one: a(n+1) = 2(z(n)+bit(n))bit(n)/2 = 
            --                                  a(n)/2+bit(n)^2
            -- else           a(n+1) = a(n)/2
            -- and a(N+1) = 2z(N+1)/2^(N/2+1) = z(N+1)/2^(N/2)

            -- VHDL Implementation

            a := (others=>'0');

            biti := "10" & x"000000"; -- 2^(25)
            -- biti has the bit being evaluated equal to one
            r(51 downto 26):= ix; -- r is in Q26
            r(25 downto 0):=(others=>'0');

            for i in 25 downto 0 loop
                rt := ('0' & r) - ('0' & (a or bit2bit_sq(biti))); 
                -- trial for the new value for the reminder
                a := '0' & a(51 downto 1); -- srl
                if (rt(52)='0') then -- rt>=0
                    r := rt(51 downto 0);
                    a := a or bit2bit_sq(biti); -- the adder is safelly replaced by an or
                end if;
                biti := '0' & biti(25 downto 1); -- srl 1
            end loop;

            a(24 downto 2) := a(24 downto 2)+a(1); -- round
            -- even for ix = all '1' a will not oveflow

            -- a is the result
            y_mantissa := a(24 downto 2);

        end if;

        y(22 downto 0) <= y_mantissa;
        y(30 downto 23) <= y_exponent;
        y(31) <= y_sign;
   end process;
end Behavioral;
3
Where does your `'i' come from? - Oldfart
i already add all my code there - Ho Jin Ling
The VHDL code appears to be by Paulo A. C. Lopes and gives the same answer as the sqrt function in the IEEE package float_pkg.vhdl (-2008). - user1155120
Yea. I copied the code from Paulo A. C. Lopes. what is that mean? - Ho Jin Ling
All the errors and warnings are significant here. Please don't provide text as pictures. - user1155120

3 Answers

0
votes

in this example you have at least 2 errors. I think you did not show all error messages and the one you showed is the result of previous errors.

  1. you have not declared i. most likely your the error is the result of it, and x[i] probably contributes to the message.

  2. it seems that begin/end statements are not in the correct place.

Here i added indentations to show how the compiler interprets your loop:

begin 
   for (i =31; i > 0; i=i-1)
      y [2*i] = x[i]; // << part of the loop 

   y [(2*i)+1] = 1'b0; // << not a part of the loop

   bit2bit_sq=y;
end

So, most likely the begin should be moved down as int the Dave's example and the end should be moved up. Otherwise it makes no sense.

for (i =31; i > 0; i=i-1)
begin 
   y [2*i] = x[i];     
   y [(2*i)+1] = 1'b0; 
end
bit2bit_sq=y;
  1. and finally, this code does not look as a square root caculation. Check this: https://verilogcodes.blogspot.com/2017/11/a-verilog-function-for-finding-square-root.html
0
votes

The Verilog warning and error line numbers can't easily be discerned without an identical source file being presented here.

There's also one warning unaccounted for in the reference image (and images of text shouldn't be provided in questions).

There are two classes of errors/warnings. Those to do with the function declaration and the assignment to biti in the always block.

function [63:0]bit2bit_sq;  // TRANSCRIPTION ERROR WARNING Line (7)
// vector type range wrong SHOULD BE [51:0] NOT [63:0]
input [31:0]x;              // TRANSCRIPTION ERROR WARNINGS LINE (8)
// vector type range wrong SHOULD BE [25:0] NOT [31:0]
reg[63:0]y;                 // TRANSCRIPTION ERROR

begin                       // TRANSCRIPTION ERROR
for (i =31; i > 0; i=i-1)   // TRANSCRIPTION ERROR
// MOVE begin AFTER for loop variable assignment and closing parenthese
// variable i initialization wrong SHOULD be i = 25 NOT i = 30
y [2*i] = x[i]; 
y [(2*i)+1] = 1'b0;
    bit2bit_sq=y;          // WARNING Line (14)
end
endfunction

The confusion over the size of vector type of the return value and size of the vector type of the input x comes from not understanding the semantics of VHDL in the original VHDL:

    function bit2bit_sq(x: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
        variable y : STD_LOGIC_VECTOR(2*x'left+1 downto 0);
    -- Returns x^2 by intercalating zeros in the argument,
    -- where x has only one bit different from zero.
    begin
        for i in x'left downto 0 loop
            -- x'right must be zero
            y(2*i):=x(i);
            y(2*i+1):='0';
        end loop;
        return y;
    end;

The subtype of the return value is determined by the expression (y) that's returned. VHDL is strongly typed and every object declaration defines a subtype as well as the base type. A subtype is a type and a constraint.

A function call to a function can convey subtype (and here the undeclared subtype in the parameter x declaration comes from the actual expression in the function call:

            for i in 25 downto 0 loop
                rt := ('0' & r) - ('0' & (a or bit2bit_sq(biti))); 

There are several things known about the return value of bit2bit_sq. From it's declaration the type mark is std_logic_vector. The number of elements in the return value has to be the same as a:

        variable a : STD_LOGIC_VECTOR (51 downto 0);

because the logical operator or requires a matching element between it's left and right operands.

The index range of the passed parameter biti is known:

        variable biti : STD_LOGIC_VECTOR (25 downto 0);

Associations between formals (declared parameters here) and actuals (the passed expression, here biti) requires matching elements and not identical index ranges.

That's all the information needed to correct the Verilog function declaration:

function [63:0]bit2bit_sq;  // TRANSCRIPTION ERROR WARNING Line (7)
// vector type range wrong SHOULD BE [51:0] NOT [63:0]
input [31:0]x;              // TRANSCRIPTION ERROR WARNINGS LINE (8)
// vector type range wrong SHOULD BE [25:0] NOT [31:0]
reg[63:0]y;                 // TRANSCRIPTION ERROR

begin                       // TRANSCRIPTION ERROR
for (i =31; i > 0; i=i-1)   // TRANSCRIPTION ERROR
// MOVE begin AFTER for loop variable assignment and closing parenthese
// variable i initialization wrong SHOULD be i = 25 NOT i = 30
y [2*i] = x[i]; 
y [(2*i)+1] = 1'b0;
end
    bit2bit_sq=y;          // WARNING Line (14)
// end                     // MOVED as per 
endfunction

The Verilog assignment to biti has an insufficient number of elements (bits) assigned initially:

biti={2'b10,x<=000000};

The VHDL source assigns all 26 element positions of biti:

            biti := "10" & x"000000"; -- 2^(25)

The Verilog source should as well. The leftmost element a '1' the remaining elements all '0'.

The inferred latches aren't clear without line numbers but appear to come from the mismatched function call parameter length in the Verilog source.

The remaining warning is due to x_sign not being evaluated (read). It and it's assignment can be eliminated (in the VHDL source as well).

By definition there should be no warnings nor errors when the Verilog is compiled, there are none in the VHDL source.

When simulated the VHDL source approximates the output of the -2008 IEEE packaged float_pkg. That can be validated with a testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.float_pkg.all;

entity sqrt_tb is
end entity;

architecture fuu of sqrt_tb is
    signal x, y:    std_logic_vector(31 downto 0);
begin
DUT:
    entity work.sqrt
        port map (
            x => x,
            y => y
        );
THE_PROCESS:
    process
    begin
        wait for 0 ns;          -- ignores default value 
        for i in 14 to 35 loop
            report "x = " & integer'image(i);
            x <= to_stdlogicvector(to_float(real(i)));
            wait for 0 ns;
            report LF & HT & "X = " & to_string(to_float(x));
            wait for 1 ns;
            report LF & HT & "y = " & to_string(to_float(y)) &
                   LF & "expected  = " & to_string(sqrt(to_float(x))) &
                   LF & HT & "y = " & real'image(to_real(to_float(y))) &
            LF & "expected  = " & real'image(to_real(sqrt(to_float(x)))) & LF;
        end loop;
        wait for 0 ns;
        wait;
    end process;
end architecture;

Note the square root of 14 and 35 varies.

sqrt_tb.vhdl:163:13:@0ms:(report note): x = 14
sqrt_tb.vhdl:166:13:@0ms:(report note):
    X = 0:10000010:11000000000000000000000
sqrt_tb.vhdl:168:13:@1ns:(report note):
        y = 0:10000000:11011110111011101010001
expected  = 0:10000000:11011110111011101010000
        y = 3.7416574954986572
expected  = 3.741657257080078

sqrt_tb.vhdl:163:13:@21ns:(report note): x = 35
sqrt_tb.vhdl:166:13:@21ns:(report note):
    X = 0:10000100:00011000000000000000000
sqrt_tb.vhdl:168:13:@22ns:(report note):
        y = 0:10000001:01111010101000010000111
expected  = 0:10000001:01111010101000010000110
        y = 5.916079998016357
expected  = 5.916079521179199

There's a subtle algorithmic difference. The mantissa LSB shows up different in the result, it's a precision issue (floating point numbers are approximate).

-1
votes

This seems to be a bug in your compiler. You should be allowed to make an assignment to function name as the return value. But since you are using SystemVerilog, you can use the return statement instead.

function [63:0]bit2bit_sq(input [31:0]x);
  reg[63:0]y;
  for (int i =31; i > 0; i=i-1) begin
     y [2*i] = x[i]; 
     y [(2*i)+1] = 1'b0;
  end 
  return y;
endfunction