Квадрат с плавающей точкой root в Верилоге - PullRequest
0 голосов
/ 18 апреля 2020

Вот мой код для квадрата root в формате с плавающей запятой в 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

Почему отображается следующая ошибка?

Ошибка (10833): ошибка SystemVerilog в fp_sqrt.v (8): аргумент «x», связанный с пустым выражением, должен иметь значение по умолчанию

this сообщение после завершения компиляции

10036 Verilog HDL или VHDL бродят по fp_sqrt.v (93): объекту "x_sign" присвоено значение, но он никогда не читается
⚠️ 10230 Предупреждение о назначении Verilog HDL в fp_sqrt.v (122): усеченное значение размером 32 для соответствия размеру цели (8)
⚠️ 10230 Предупреждение о назначении HDL Verilog в fp_sqrt.v (127): усеченное значение размером 32 для соответствия размеру цели (8 )
24 10242 Предупреждение объявления функции Verilog HDL на fp_seqrt.v (14): переменная «y» может иметь значение «Не важно», поскольку ей нельзя присвоить значение во всех возможных ...
⚠️ 10230 Предупреждение о назначении Verilog HDL в fp_sqrt.v (127): усеченное значение размером 65 для соответствия размеру цели (53)
❌ 10833 Ошибка SystemVerilog в fp_sqrt.v (7): аргумент «x» связан с пустым выражением n должно иметь значение по умолчанию
30 10230 Предупреждение о назначении HDL Verilog на fp_sqrt.v (142): усеченное значение с размером 64 для соответствия размеру цели (52)
⚠️ 10240 Предупреждение Verilog HDL всегда создавать на fp_sqrt.v (89): вывод защелки (ей) для переменной «i», которая хранит свое предыдущее значение в одном или нескольких путях ...
12153 Невозможно разработать иерархию пользователей верхнего уровня
❌ Quartus II 64- Анализ и синтез битов оказались безуспешными. 2 ошибки и 8 предупреждений

это код, который я конвертирую из этого оригинального кода VHDL Я пытаюсь понять, затем пытаюсь отредактировать код verilog. в то время как, когда я компилирую код ниже, который является реализацией VHDL 32-битного квадрата с плавающей запятой root. ошибки нет и функционируют хорошо. в то время как я преобразовываю в код verilog есть ошибка. пожалуйста, помогите мне.

  -- 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 ]

0 голосов
/ 18 апреля 2020

в этом примере у вас есть как минимум 2 ошибки. Я думаю, что вы не показывали все сообщения об ошибках, и то, что вы показали, является результатом предыдущих ошибок.

  1. вы не объявили i. скорее всего, ваша ошибка является результатом ее, и x[i], вероятно, вносит свой вклад в сообщение.

  2. кажется, что операторы начала / конца не в правильном месте.

Здесь я добавил отступы, чтобы показать, как компилятор интерпретирует ваш l oop:

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

Так что, скорее всего, begin должен быть сдвинут как В примере Дейва и end должны быть перемещены вверх. Иначе это не имеет смысла.

for (i =31; i > 0; i=i-1)
begin 
   y [2*i] = x[i];     
   y [(2*i)+1] = 1'b0; 
end
bit2bit_sq=y;
и, наконец, этот код не выглядит как квадратная root какуляция. Проверьте это: https://verilogcodes.blogspot.com/2017/11/a-verilog-function-for-finding-square-root.html
0 голосов
/ 21 апреля 2020

Номера строк предупреждений и ошибок Verilog не могут быть легко обнаружены без идентичного исходного файла, представленного здесь.

В контрольном изображении также отсутствует одно предупреждение (и изображения текста не должны предоставляется в вопросах).

Существует два класса ошибок / предупреждений. Это связано с объявлением функции и присваиванием biti в блоке always.

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

Путаница с размером векторного типа возвращаемого значения и размером векторного типа входных данных x происходит от непонимания семантики VHDL в исходном 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;

Подтип возвращаемого значения определяется выражением (y), которое возвращается. VHDL строго типизирован, и каждое объявление object определяет подтип , а также базовый тип. Подтип - это тип и ограничение.

Вызов функции для функции может передавать подтип (и здесь необъявленный подтип в объявлении параметра x происходит из фактического выражения в вызове функции:

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

Есть несколько вещей, которые известны о возвращаемом значении bit2bit_sq. Из его объявления меткой типа является std_logic_vector. Количество элементов в возвращаемом значении должно быть таким же, как a:

        variable a : STD_LOGIC_VECTOR (51 downto 0);

, поскольку логическому оператору or требуется соответствующий элемент между его левым и правым операндами.

Известен диапазон индекса переданного параметра biti:

        variable biti : STD_LOGIC_VECTOR (25 downto 0);

Связи между формалами (здесь объявлены параметры) и фактическими данными (переданное выражение, здесь biti) требуют соответствия элементов, а не идентичных диапазонов индексов.

Это вся информация, необходимая для исправления объявления функции Verilog:

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

Назначение Verilog для biti имеет недостаточное количество элементов (бит) a Первоначально ssigned:

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

Источник VHDL назначает все 26 позиций элементов biti:

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

Должен также источник Verilog. Крайний левый элемент a '1', остальные элементы все '0'.

Выводимые защелки не очищаются без номеров строк, но, похоже, происходят из-за несоответствующей длины параметра вызова функции в источнике Verilog.

Остальное предупреждение из-за того, что x_sign не оценивается (чтение). Его и его назначение можно исключить (также в источнике VHDL).

По определению не должно быть ни предупреждений, ни ошибок при компиляции Verilog, в источнике VHDL их нет.

При моделировании источник VHDL приближается к выходу пакета -2008 IEEE, упакованного float_pkg. Это можно проверить с помощью тестового стенда:

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;

Обратите внимание, что квадрат root из 14 и 35 варьируется.

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

Есть небольшая разница в алгоритмах c. В результате мантисса LSB выглядит иначе, это проблема точности (числа с плавающей запятой являются приблизительными).

0 голосов
/ 18 апреля 2020

Кажется, это ошибка в вашем компиляторе. Вам должно быть разрешено сделать присваивание имени функции в качестве возвращаемого значения. Но так как вы используете SystemVerilog, вы можете использовать вместо него оператор return.

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
...