在 VHDL 中计算向量的模
Calculate the module of a vector, in VHDL
如何计算向量的模数?
由于向量不是 VHDL 中的预定义类型,因此对我来说没有实现向量模的函数是有意义的。如果有这样的我还没有找到它。
这基本上是求一个数的平方根的问题,因为模块可以定义为:
sqrt(a^2+b^2+...+n^2)
实现向量所有成员平方的总和不是一个挑战,所以我认为最必要的部分是有一个函数来计算一个数的平方根。
据我所知,还没有任何官方包实现这个功能。如何实现计算向量模的函数?
或者,如果您愿意,如何实现平方根?
这是一种可能的解决方案。我会给你3个代码。
-第一个提供用于向量的类型定义。它并不重要,但需要它才能正常工作。
-第二个是定义函数的包。对其进行了注释,以便您可以轻松地将其适应任何类型的矢量。它可能可以升级,使其使用一些参数自行适应,这样工作正常。
-第三个是一个测试平台来尝试一下。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package tipos is
constant bandas : positive := 4;
type vector32 is array (0 to bandas-1) of signed (31 downto 0);
end package tipos;
注意使用矢量定义正确调用库。在我的例子中,它被编译用于 ModelSim 模拟
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work; use work.tipos.all;
package propios is
--function declaration.
function module (a : vector32; bands: natural) return unsigned;
end propios; --end of package.
package body propios is --start of package body
--definition of function
--based on: https://en.m.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
function module (a : vector32; bands: natural) return unsigned is --To adapt it to a diferent number of bits in the input vector:
--substitute the 71 for the needed number. Number of bits in each element of the vector *2 + power of two that can represent the maximum
--number of bands, or fields. In this case, 32bit numbers, maximum number of bands, 256, so 2^8. 32*2+8=72.
variable sum : unsigned(71 downto 0):= (others => '0');
variable b : unsigned(71 downto 0):=(0=>'0', 70 => '1', others => '0');
variable a_unsig: unsigned(31 downto 0):=(others =>'0');--for this vector use the same length as the input vector, 32bit in my case.
variable result: unsigned (71 downto 0):= (others => '0');
begin
for i in 0 to bands-1 loop--Sum of all the elements squared
a_unsig:=unsigned(a(i));
sum:=sum + (a_unsig * a_unsig);
end loop;
--Square root of sum
while b>sum loop--Do any needed changes here. You only have to change the 71's
b:='0'&'0'& b(71 downto 2);
end loop;
while (b/=0) loop
if (sum>=result+b) then
sum:=sum - (result + b);
result:=('0'& result(71 downto 1))+b;
else
result:='0'& result(71 downto 1);
end if;
b:='0' & '0' & b(71 downto 2);
end loop;
return result(35 downto 0);--sqrt(2^72)=2^36. Use half of the bits you put in place of 71
end module;
end propios; --end of the package body
这是测试台。再次注意正确调用包
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.propios.all;
use work.tipos.all;
ENTITY test IS
END test;
Architecture simple of test is
signal a:vector32;
signal c: unsigned(35 downto 0);
signal b: natural:= 4;
begin
a(0)<="00000000110010011010011100000000";
a(1)<="00000000110010011010011100000000";
a(2)<="00000000110010011010011100000000";
a(3)<="00000000110010011010011100000000";
process
begin
wait for 200ps;
c<= module (a , b);
wait;
end process;
end simple;
如何计算向量的模数?
由于向量不是 VHDL 中的预定义类型,因此对我来说没有实现向量模的函数是有意义的。如果有这样的我还没有找到它。
这基本上是求一个数的平方根的问题,因为模块可以定义为:
sqrt(a^2+b^2+...+n^2)
实现向量所有成员平方的总和不是一个挑战,所以我认为最必要的部分是有一个函数来计算一个数的平方根。
据我所知,还没有任何官方包实现这个功能。如何实现计算向量模的函数?
或者,如果您愿意,如何实现平方根?
这是一种可能的解决方案。我会给你3个代码。
-第一个提供用于向量的类型定义。它并不重要,但需要它才能正常工作。
-第二个是定义函数的包。对其进行了注释,以便您可以轻松地将其适应任何类型的矢量。它可能可以升级,使其使用一些参数自行适应,这样工作正常。
-第三个是一个测试平台来尝试一下。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package tipos is
constant bandas : positive := 4;
type vector32 is array (0 to bandas-1) of signed (31 downto 0);
end package tipos;
注意使用矢量定义正确调用库。在我的例子中,它被编译用于 ModelSim 模拟
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work; use work.tipos.all;
package propios is
--function declaration.
function module (a : vector32; bands: natural) return unsigned;
end propios; --end of package.
package body propios is --start of package body
--definition of function
--based on: https://en.m.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
function module (a : vector32; bands: natural) return unsigned is --To adapt it to a diferent number of bits in the input vector:
--substitute the 71 for the needed number. Number of bits in each element of the vector *2 + power of two that can represent the maximum
--number of bands, or fields. In this case, 32bit numbers, maximum number of bands, 256, so 2^8. 32*2+8=72.
variable sum : unsigned(71 downto 0):= (others => '0');
variable b : unsigned(71 downto 0):=(0=>'0', 70 => '1', others => '0');
variable a_unsig: unsigned(31 downto 0):=(others =>'0');--for this vector use the same length as the input vector, 32bit in my case.
variable result: unsigned (71 downto 0):= (others => '0');
begin
for i in 0 to bands-1 loop--Sum of all the elements squared
a_unsig:=unsigned(a(i));
sum:=sum + (a_unsig * a_unsig);
end loop;
--Square root of sum
while b>sum loop--Do any needed changes here. You only have to change the 71's
b:='0'&'0'& b(71 downto 2);
end loop;
while (b/=0) loop
if (sum>=result+b) then
sum:=sum - (result + b);
result:=('0'& result(71 downto 1))+b;
else
result:='0'& result(71 downto 1);
end if;
b:='0' & '0' & b(71 downto 2);
end loop;
return result(35 downto 0);--sqrt(2^72)=2^36. Use half of the bits you put in place of 71
end module;
end propios; --end of the package body
这是测试台。再次注意正确调用包
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.propios.all;
use work.tipos.all;
ENTITY test IS
END test;
Architecture simple of test is
signal a:vector32;
signal c: unsigned(35 downto 0);
signal b: natural:= 4;
begin
a(0)<="00000000110010011010011100000000";
a(1)<="00000000110010011010011100000000";
a(2)<="00000000110010011010011100000000";
a(3)<="00000000110010011010011100000000";
process
begin
wait for 200ps;
c<= module (a , b);
wait;
end process;
end simple;