VHDL Synthesis Error - math

I'm trying to write some simple math functions in VHDL but I keep getting the error
found '0' definitions of operator "+", cannot determine exact overload matching definition for "+" and I also get the same error about the division.
Here is the relevant code:
signal delay_1 : integer range 0 to 127;
-- signal delay_2 : integer range 0 to 127;
-- signal delay_3 : integer range 0 to 127;
-- signal delay_4 : integer range 0 to 127;
signal us_clock : std_logic;
signal ds_squareroot : integer range 0 to 100;
signal ds_squared : integer range 0 to 5000;
if(i_reset = '1') then
delay_1 <= 0;
delay_2 <= 0;
delay_3 <= 0;
delay_4 <= 0;
ds_squared <= 0;
ds_squareroot <= 0;
elsif(rising_edge(i_clock)) then
-- Delay 1 calculations
ds_squared <= (i_distance*i_distance + (speaker_distance)*(speaker_distance));
for n in 0 to 20 loop
ds_squareroot <= ((50 + ds_squared/ds_squareroot)/2);
end loop;
delay_1 <= (ds_squareroot - i_distance)/ speed_sound;
And here are the libraries that I'm calling.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;
Any advice as to why this is not compiling would be very helpful.

The error was that i_distance was a std_logic_vector and speaker_distance was an integer. Obviously this did not synthesize because of the difference in types here. I solved it with this simple expression
distance <= conv_integer(i_distance);
This made both integers, which allowed the design to synthesize. Thanks for the help.

Related

Is it possible to declare a port as unknown sized 2d matrix in VHDL?

I need to process input ports without knowing their sizes. Here is my code below. Because I am beginner at vhdl, I am confused about this language.
I am trying to compose the code on an online playground with Aldec Riviera Pro 2020.04 simulator.
library IEEE;
use IEEE.numeric_std.all;
PACKAGE vsd is
TYPE array_2d is array(natural<>,natural<>) of INTEGER;
END PACKAGE;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.vsd.all;
entity my_conv is
port(
in_signal : in array_2d;
conv_signal : in array_2d;
result : out array_2d
);
end my_conv;
architecture arc of my_conv is
function conv_fn (conv_m, conv_n,indis_m, indis_n : natural) return INTEGER is
variable sum : INTEGER := 0;
begin
for i in conv_m-1 downto 0 loop
for j in conv_n-1 downto 0 loop
sum := sum + in_signal(i,j) * conv_signal(indis_m-i,indis_n-j);
end loop;
end loop;
return sum;
end conv_fn;
VARIABLE var_conv_m, var_conv_n, var_in_m, var_in_n : INTEGER;
VARIABLE temp_result : array_2d;
BEGIN
var_conv_m := conv_signal'length(1);
var_conv_n := conv_signal'length / var_conv_m;
for i in var_conv_m-1 downto 0 loop
for j in var_conv_n-1 downto 0 loop
temp_result(i,j) := conv_fn(var_conv_m,var_conv_n,i,j);
end loop;
end loop;
result := temp_result;
END arc;

assign data(i) into std_logic_vector(0 downto 0) in vhdl

I have the following problem:
My code has this constant value
constant source_vector : std_logic_vector(7 downto 0) := "1011000";
This value needs to be fed into a signal of type std_logic_vector, bit by bit. The problem is that the destination vector has a size defined in a constant. For the test, I am using size 1.
constant k : integer := 1;
dest_vector : in std_logic_vector(k-1 downto 0);
When I try to assign the first bit:
dest_vector <= std_logic_vector(to_unsigned(source_vector(0), k));
I got this error:
ERROR: [VRFC 10-925] indexed name is not a natural
I have tried several things, but no luck. Perhaps I am missing something... Any advice here?
Answer from user1155120 Jul 16 '17 at 19:47
Use dest_vector <= source_vector(0 downto 0); which uses a slice name or dest_vector(0) <= source_vector(0); which uses indexed names for both target and right hand side. There's also dest_vector <= "" & source_vector(0); which derives the type of the concatenation result from context while concatenating a null array to a value of the element type. See IEEE Std 1076-2008 8.4 Indexed names, 8.5 Slice names, 9.2.5 Adding operators ("&") and 12.5 The context of overload resolution (which "&").

VHDL directly comparing vectors

I was wondering if its possible to directly compare 2 vectors with eachother instead of just looking at them bit by bit.
For example:
entity Comparator is
port(a,b in: std_logic_vector (2 downto 0);
out1, out2 out: std_logic);
end Comparator;
architecture behavioural of Comparator1 is
begin
if a = b then
out1 <= '1'
else if /= then
out2 <= '1'
end if;
end behaviour;
Is this possible?
The answer is yes, you can compare two array types of the same type and subtype indication directly.
However your example code isn't valid.
The result of the expression a=b is boolean. You convert that to std_logic by assigning out1 and out2. An if statement in this context has to be in a process statement. Also you don't need two outputs:
architecture foo of Comparator1 is
begin
UNLABELED:
process (a,b)
begin
if a = b then
out1 <= '1';
else
out1 <= '0';
end if;
end process;
end architecture;
Alternative a concurrent signal assignment statement, a conditional signal assignment that has an equivalent process to that above:
architecture fum of Comparator1 is
begin
UNLABELED:
out1 <= '1' when a = b else '0';
end architecture;
You can also use to_integer(unsigned(a)) and threat them as integers.
For example:
IF(to_integer(unsigned(a)) < to_integer(unsigned(b))) THEN

VHDL Bit Vector Operators

I'm having a lot of trouble getting some simple math done in VHDL. I'm terrible at this language so if my syntax is stupid or something, I have an excuse :P. I'm trying to implement a very simple random number generator that calculates a pseudo-random number by this formula:
seed = (seed*1103515245) + 12345
How I'm trying to do it:
Signalss here
signal seed: std_logic_vector(31 downto 0) := x"2B4C96B9";
signal multiply: std_logic_vector(31 downto 0) := x"41C64E6D";
signal add: std_logic_vector(31 downto 0) := x"00003039";
signal temp1: std_logic_vector(63 downto 0);
signal temp2: std_logic_vector(31 downto 0);
Computation here (done in a state in a state machine)
temp2 <= seed;
temp1 <= std_logic_vector((unsigned(temp2)*unsigned(multiply)));
seed <= std_logic_vector(unsigned(temp1(31 downto 0)) + unsigned(add));
temp2 always ends up being undefined. Additionally, seed ends up being undefined as well. I've tried it several different ways but all of them were wrong mostly because of the vector sizes and order or operations. I feel like I'm doing it right at the moment based on what I've found through semi-extensive Googling but I just can't figure it out.
The best thing I can think of right now is to do each step of the calculation in its own state in a state machine. Can anyone see what I'm doing wrong here?
VHDL is different from other languages in that signal assign by <= does not take effect for read until after a delta delay, thus if you do:
temp2 <= seed;
temp1 <= std_logic_vector((unsigned(temp2)*unsigned(multiply)));
seed <= std_logic_vector(unsigned(temp1(31 downto 0)) + unsigned(add));
then the temp2 not actually updated for read in the expression used to assign temp1 until a delta delay has passed.
Depending on the details about your design, you can consider declaring the intermediate variables as variables:
variable temp1: std_logic_vector(63 downto 0);
variable temp2: std_logic_vector(31 downto 0);
and then assign like:
temp2 := seed;
temp1 := std_logic_vector((unsigned(temp2)*unsigned(multiply)));
seed <= std_logic_vector(unsigned(temp1(31 downto 0)) + unsigned(add));
In this case the intermediate variables temp1 and temp2 will have the result ready for read right after the assign, and the seed will have the value after a delta delay, assuming that you will not do the next iteration until next cycle.
It will clarify the intention in the code if constants are declared as such, doing:
constant MULTIPLY : std_logic_vector(31 downto 0) := x"41C64E6D";
constant ADD : std_logic_vector(31 downto 0) := x"00003039";
A comment on you calculation, then the VHDL design truncates the result of the multiplication, thus doing:
seed = (seed*1103515245) mod (2**32) + 12345

Is overflow defined for VHDL numeric_std signed/unsigned

If I have an unsigned(MAX downto 0) containing the value 2**MAX - 1, do the VHDL (87|93|200X) standards define what happens when I increment it by one? (Or, similarly, when I decrement it by one from zero?)
Short answer:
There is no overflow handling, the overflow carry is simply lost. Thus the result is simply the integer result of your operation modulo 2^MAX.
Longer answer:
The numeric_std package is a standard package but it is not is the Core the VHDL standards (87,93,200X).
For reference : numeric_std.vhd
The + operator in the end calls the ADD_UNSIGNED (L, R : unsigned; C : std_logic) function (with C = '0'). Note that any integer/natural operand is first converted into an unsigned.
The function's definition is:
function ADD_UNSIGNED (L, R : unsigned; C : std_logic) return unsigned is
constant L_left : integer := L'length-1;
alias XL : unsigned(L_left downto 0) is L;
alias XR : unsigned(L_left downto 0) is R;
variable RESULT : unsigned(L_left downto 0);
variable CBIT : std_logic := C;
begin
for i in 0 to L_left loop
RESULT(i) := CBIT xor XL(i) xor XR(i);
CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i));
end loop;
return RESULT;
end ADD_UNSIGNED;
As you can see an "overflow" occurs if CBIT='1' (carry bit) for i = L_left. The result bit RESULT(i) is calculated normally and the last carry bot value is ignored.
I've had the problem with wanting an unsigned to overflow/underflow as in C or in Verilog and here is what I came up with (result and delta are unsigned):
result <= unsigned(std_logic_vector(resize(('1' & result) - delta, result'length))); -- proper underflow
result <= unsigned(std_logic_vector(resize(('0' & result) + delta, result'length))); -- proper overflow
For overflow '0' & result makes an unsigned which is 1 bit larger to be able to correctly accommodate the value of the addition. The MSB is then removed by the resize command which yields the correct overflow value. Same for underflow.
For a value of MAX equal to 7 adding 1 to 2**7 - 1 (127) will result in the value 2**7 (128).
The maximum unsigned value is determined by the length of an unsigned array type:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity foo is
end entity;
architecture faa of foo is
constant MAX: natural := 7;
signal somename: unsigned (MAX downto 0) := (others => '1');
begin
UNLABELED:
process
begin
report "somename'length = " & integer'image(somename'length);
report "somename maximum value = " &integer'image(to_integer(somename));
wait;
end process;
end architecture;
The aggregate (others => '1') represents a '1' in each element of somename which is an unsigned array type and represents the maximum binary value possible.
This gives:
foo.vhdl:15:9:#0ms:(report note): somename'length = 8
foo.vhdl:16:9:#0ms:(report note): somename maximum value = 255
The length is 8 and the numerical value range representable by the unsigned array type is from 0 to 2**8 - 1 (255), the maximum possible value is greater than 2**7 (128) and there is no overflow.
This was noticed in a newer question VHDL modulo 2^32 addition. In the context of your accepted answer it assumes you meant length instead of the leftmost value.
The decrement from zero case does result in a value of 2**8 - 1 (255) (MAX = 7). An underflow or an overflow depending on your math religion.
Hat tip to Jonathan Drolet for pointing this out in the linked newer question.

Resources