Calculate the module of a vector, in VHDL - vhdl

How can I calculate the module of a vector?
As a vector is not a pre-defined type in VHDL it makes sense to me that there is no function implementing the modue of a vector. If there is such I have not found it.
This is basically a problem of obtaining the square root of a number, as the module can be defined as:
sqrt(a^2+b^2+...+n^2)
Implementing the sum of all the members of the vector squared is not a challenge so I think the most necessary part is having a function to calculate the square root of a number.
As far as I'm concerned there isn't any official package implementing this function. How to implement a function to calculate the module of a vector?
Or if you prefer it, how to implement a square root?

This is one possible solution. I will provide you 3 codes.
-The first one provides the type definition used for the vector. Its not important but it is needed to make it work.
-The second one is the package in which the function is defined. It is commented so that you can easily adapt it to any kind of vector. It can probably be upgraded to make it adapt by itself using some parameters by this works fine.
-The third one is a testbench to try it out.
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;
Be aware of calling properly the library with the vector definition. In my case it was compiled to work for the ModelSim simulation
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
And here is the testbench. Again take care of calling the packages properly
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;

Related

VHDL 10^x LUT With-Select

I have to write a VHDL code that calculates the 10^x function for integer values of x between zero and nine (including zero and nine). Entity should have one 4-bit unsigned integer (std_logic_vector) type input and one 32-bit unsigned integer (std_logic_vector) type output. 32 bit width is enough for 10^9. I have to use the LUT (Look-up table) logic for the solution. For this, I should use the signal assignment and with-select structure in the architecture block without using the process at all. By using with-select, I will have determined with a fixed assignment what the output (LUT) will be for each value of x.
Error when i start synthesizing:
width mismatch in assignment; target has 32 bits, source has 1 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity main is
Port (
input : in std_logic_vector(3 downto 0);
output: out std_logic_vector(31 downto 0)
);
end main;
architecture Behavioral of main is
begin
with input select
output <= "00000000000000000000000000000001" when "0000", --10^0
"00000000000000000000000000001010" when "0001", --10^1
"00000000000000000000000001100100" when "0010", --10^2
"00000000000000000000001111101000" when "0011", --10^3
"00000000000000000010011100010000" when "0100", --10^4
"00000000000000011000011010100000" when "0101", --10^5
"00000000000011110100001001000000" when "0110", --10^6
"00000000100110001001011010000000" when "0111", --10^7
"00000101111101011110000100000000" when "1000", --10^8
"00111011100110101100101000000000" when "1001", --10^9
"0" when others;
end Behavioral;
You understood what the problem was, so this answer is just to show you how to avoid the external computation of your ten 32-bits constants (with VHDL 2008), thanks to the ieee.numeric_std_unsigned package and a constant array of 32-bits vectors, computed by a function:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity main is
...
end main;
architecture Behavioral of main is
type w32_array is array(0 to 15) of std_ulogic_vector(31 downto 0);
function powers_of_ten return w32_array is
variable res: w32_array := (others => (others => '0'));
begin
for i in 0 to 9 loop
res(i) := to_stdulogicvector(10**i, 32);
end loop;
return res;
end function powers_of_ten;
constant pw10: w32_array := powers_of_ten;
begin
output <= pw10(to_integer(input));
end architecture Behavioral;
Note: and yes, it should be synthesisable, because it is the synthesizer that computes the constants during synthesis, not the synthesized hardware.

Adding two vectors of 5 bit numbers in vhdl

I am new to vhdl, I am trying to add 2 vectors of 5 bit unsigned numbers.In the following code the signal firstsum gives proper output in waveform but the vector sum does not show any output, I am using quartus ii. What is the error in this code?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
package UVEC is
subtype UINT5 is std_logic_vector (4 downto 0);
type UVEC5 is array (2 downto 0) of UINT5;
subtype UINT6 is std_logic_vector (5 downto 0);
type UVEC6 is array (2 downto 0) of UINT6;
end UVEC;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
use work.UVEC.all;
entity FP_Vecsum1 is
port(
a,b : in UVEC5;
sum : out UVEC6;
firstsum : out UINT6
);
end FP_Vecsum1;
architecture FP_Vecsum1_MX of FP_Vecsum1 is
begin
firstsum <= std_logic_vector(('0'&unsigned(a(0)))+('0'&unsigned(b(0))));
sum(0) <= std_logic_vector(('0'&unsigned(a(0)))+('0'&unsigned(b(0))));
sum(1) <= std_logic_vector(('0'&unsigned(a(1)))+('0'&unsigned(b(1))));
sum(2) <= std_logic_vector(('0'&unsigned(a(2)))+('0'&unsigned(b(2))));
end FP_Vecsum1_MX;
welcome to the VHDL world.
I also haven't found anything wrong with your code, but you can try the following, maybe this will help:
first, try to cast the signals to unsigned in the beginning of your architecture, before doing the math:
a_us(0) <= unsigned(a(0));
a_us(1) <= unsigned(a(1));
a_us(2) <= unsigned(a(2));
this is quite convenient: if your ports to the outside world are neutral vectors, the math inside your component is either signed or unsigned. do the conversion once, and you're free.
second, instead of manually doing the sign extension, now that you have determined your vectors as unsigned, you can use resize function to automatically set the summed vectors to the result length:
sum(0) <= std_logic_vector(resize(a_us(0),sum(0)'length) + resize(b_us(0),sum(0)'length));
you can also do a little trick by adding a zero with a relevant vector width:
sum(0) <= std_logic_vector( to_unsigned(0,sum(0)'length) + a_us(0) + b_us(0) );
it might look a little longer, but in my opinion it's a more robust code.
hope this helps,
ilan.

Generic Multiplexer warning

I created a generic multiplexer( on number of inputs and bits per input) in VHDL. I tested it and it works correctly but I get a width mismatch warning:
Width mismatch. < output > has a width of 8 bits but assigned expression is 64-bit wide.
This is the code of my generic MUX. Can anyone explain me why I get this warning? WHat's wrong with my code? My professor wants me to implement this without the use of process. Thanks
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.package_log.all;
use IEEE.NUMERIC_STD.ALL;
entity mux_generic is
generic(N : natural :=8;
M : natural := 8);
-- N: number of inputs
-- M: bit per input/output
Port ( input : in STD_LOGIC_VECTOR (N*M-1 downto 0);
sel: in STD_LOGIC_VECTOR (log2ceil(N)-1 downto 0);
output : out STD_LOGIC_VECTOR (M-1 downto 0));
end mux_generic;
architecture DataFlow of mux_generic is
begin
output <= input(M*(to_integer(unsigned(sel))+1) - 1 downto M*(to_integer(unsigned(sel))));
end DataFlow;
The function log2ceil is defined in this way:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package package_log is
function log2ceil( n : natural) return natural;
end package_log;
package body package_log is
function log2ceil (N : natural) return natural is
variable i, j : natural;
begin
i := 0;
j := 1;
while (j < N) loop
i := i+1;
j := 2*j;
end loop;
return i;
end function log2ceil;
end package_log;
Please update to the lastest ISE version 14.7, if you haven't done so far. Then enable the new parser for your Spartan-3E FPGA:
Right click on Synthesize -> Process Properties.
Change property display level to "Advanced".
For property "Other XST Command Line Options" enter -use_new_parser yes.
Now the warning goes away. A new warning appears, just noting, that the new parser is not the default one. But, I didn't experienced a problem with this yet.
By the way, your multiplexer description is not yet efficient. Take at look at my other post, for different implementations and their effects on resource usage and timing analysis.

Write code that flip the nth bit

As the title say I need to write a vhdl code that take as input a 32 bit vector and a 6 bit vector. I need to output another 32 bit vector which is equal the input 32 bit vector but the nth bit of it is flipped. n= the number of the 6 bit vector. Here is my code but is incorrect.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity flipMSB is
Port ( Anotf : in STD_LOGIC_VECTOR (31 downto 0);
count : in STD_LOGIC_VECTOR (5 downto 0);
Af : out STD_LOGIC_VECTOR (31 downto 0));
end flipMSB;
architecture bhv of flipMSB is
signal sig: STD_LOGIC_VECTOR(31 downto 0);
signal n : integer;
begin
n<=CONV_INTEGER(count);
sig<=Anotf;
sig(n)<=not sig(n);
Af<=sig;
end bhv;
First, a 6 bit number goes up to 64, you only need 5 bits for your count signal!
Second:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
std_logic_arith and numeric_std have conflicting types. Since std_logic_arith and std_logic_unsigned are not part of the VHDL standard (and IEEE, despite the library name), I suggest you only use numeric_std. If you use VHDL-2008, you can use numeric_std_unsigned. You will need to replace n <= conv_integer(count) with n <= to_integer(unsigned(count))
Finally,
sig<=Anotf;
sig(n)<=not sig(n);
will have two output driver for the bit n, which is bad. If you put that logic into a process, it would be fine since the first assignation to sig(n) would be overridden (instead of driven twice):
process(Anotf, count)
variable n : natural;
begin
Af <= Anotf;
n := to_integer(unsigned(count));
Af(n) <= not Anotf(n);
end process;
Think of it this way, if two processes drive the same signal, this result in two drivers (and conflict!). A statement outside a process is implicitly in its own process. Also, in a process only the last statement assigning a signal will have an effect.

VHDL: issues with adding and subtracting

What issues could I run into with this code? I was thinking that there could be an issue if the result from the addition is bigger than what 15 bits can represent (32767), or if I get a negative number in the subtraction.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity test is
port( input: in std_logic_vector(14 downto 0);
sel : out boolean;
output: out std_logic_vector(14 downto 0));
end test;
architecture test of test is
constant first : integer := 1050;
constant second : integer := 33611;
begin
output <= input - first;
output <= input + second;
sel <= input < first;
end test;
The primary issue you have is that the design intent is not communicated so it is impossible to distinguish correct from incorrect results - in that sense, whatever it does must be right!
I differ from David's opinion in one respect : where he says "std_logic_vector is an unsigned representation" I suggest that std_logic_vector is neither signed nor unsigned; it is just a bag of bits. If it happens to follow unsigned rules, that's an accident of the set of libraries you have included.
Instead, I would delete the non-standard libraries:
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
and use exclusively the standard libraries:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Then - if the input and output ports are meant to represent unsigned numbers, the best thing to do is say so...
port( input : in unsigned(14 downto 0);
sel : out boolean;
output : out unsigned(14 downto 0));
(If you are not allowed to change the port types, you can use unsigned signals internally, and type convert between them and the ports.)
Now as regards the expressions, they may overflow (and in the case of "second" obviously will!).
In simulation, these overflows OUGHT to be reported as arithmetic errors. (Note : at least one simulator runs with overflow checks off as the default setting! Just dumb...)
As the designer, you decide what the correct semantics for overflows are:
They represent bugs. Simulate with overflow checks enabled, detect and fix the bugs.
They are permitted, and e.g. negative numbers represent large positive numbers. Express this in the code, e.g. as output <= (input - first) mod 2**output'length; Now anyone reading the code understands that overflow is allowed, and simply wraps.
Overflow should saturate to the positive or negative limit. Signal this by writing output <= saturate(input - first); I'll leave writing the Saturate function as an exercise...
The adding operators "+" and "-" are performed bit wise - std_logic_vector is an array type with a base element type of std_ulogic which represents 'bits' as a multi level value system that includes meta values. Their result is bounded by the longer of the two operands. (They don't overflow).
See the source for package std_logic_unsigned:
function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
-- pragma label_applies_to plus
constant length: INTEGER := maximum(L'length, R'length);
variable result : STD_LOGIC_VECTOR (length-1 downto 0);
begin
result := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus
return std_logic_vector(result);
end;
Which uses the unsigned add from std_logic_arith:
function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is
-- pragma label_applies_to plus
-- synopsys subpgm_id 236
constant length: INTEGER := max(L'length, R'length);
begin
return unsigned_plus(CONV_UNSIGNED(L, length),
CONV_UNSIGNED(R, length)); -- pragma label plus
end;
An this uses unsigned_plus also found in std_logic_arith:
function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is
variable carry: STD_ULOGIC;
variable BV, sum: UNSIGNED (A'left downto 0);
-- pragma map_to_operator ADD_UNS_OP
-- pragma type_function LEFT_UNSIGNED_ARG
-- pragma return_port_name Z
begin
if (A(A'left) = 'X' or B(B'left) = 'X') then
sum := (others => 'X');
return(sum);
end if;
carry := '0';
BV := B;
for i in 0 to A'left loop
sum(i) := A(i) xor BV(i) xor carry;
carry := (A(i) and BV(i)) or
(A(i) and carry) or
(carry and BV(i));
end loop;
return sum;
end;
std_logic_vector is an unsigned representation, there is no concept of negative numbers, it's a bag of bits. If you want to signify signed operations you should be using package numeric_std, and either type convert or use operands for your relational and adding operators that are type signed.
That being said you'll get the same answers using std_logic_vector with Synopsys's std_logic_unsigned package or unsigned with the IEEE numeric_std package.
(And your last two use clauses aren't needed by the code you show).
And the reason you don't need a use clause making packages numeric_std or std_logic_arith visible is because you aren't using signed or unsigned types and package std_logic_unsigned has it's own use clause for std_logic_arith and otherwise has declarations for everything you're using in your design specification ("+", "-" and "<").

Resources