I designed and tested my VHDL code. I used ISIM (xilinx simulator) to test the code. ISIM was buggy so i switched to modelsim SE 10c.
when i run modelsim through xilinx ise i get following error in modelsim
Fatal: (vsim-3421) Value -14 is out of range -7 to 7.
my related VHDL code is
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
signal img_int : integer range -7 to 7 ;
signal add1 : integer range -7 to 7 ;
signal add2 : integer range -7 to 7 ;
process (clk)
begin
if rising_edge(clk) then
add1 <= to_integer( signed(e(0)) ) + to_integer( signed(e(1)) ) +
to_integer( signed(e(2)) ) + to_integer( signed(e(3)) );
add2 <= to_integer( signed(e(4)) ) + to_integer( signed(e(5)) ) +
to_integer( signed(e(6)) ) + to_integer( signed(e(7)) );
end if;
end process;
img_int <= add1 + add2;
the problem line is
img_int <= add1 + add2;
Can any tell why modelsim is giving this error?
Because the minimum possible value of 'add1' is -7. The same for 'add2'.
Adding 'add1' with 'add2' gives you a minimum value of -14.
That value (-14) can not be held in your 'img_int' signal.
You can extend the range of 'img_int' to e.g. integer range -14 to 14 or truncate the result.
Anyway: Try to use the 'signed' and 'unsigned' types of the liberary 'ieee.numeric_std' i.s.o. the type 'integer'.
Related
Using Ada 2018 (increment of 2012), within a loop structure, I need to calculate the Nth root of Integers.
In my package combinations.ads specification declaration (using GNAT GPS), I have
type Real is digits 6;
In package body combinations.adb, I have a procedure build, where before the begin, I instantiate Ada’s Generic_Elementary_Functions(Float), with
package Fermat_math is new
Ada.Numerics.Generic_Elementary_Functions(Real) ;
use Fermat_math
Later, in output section, I try:
-- -------------- buggy, fix
-- combo_sum_root := Fermat_math.Exp (Log (Integer(combo_sum_root) / n); — n is integer type
combo_sum_root := Real(combo_sum) ** (1/n) ;
-- -------------
put(" and sum's root is ");
put(combo_sum_root'image ); — -- gives all roots as 1.00000E+00
I had it working a few weeks back, with roots = 3.878… etc., but I lost that in careless version control.
Actual Code here:
— combinations.ads specification ------------------------------------------
with gearbox;
use gearbox;
with Ada.Float_Text_IO ; use Ada.Float_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics; use Ada.Numerics;
with Ada.Numerics.Elementary_Functions;
use Ada.Numerics.Elementary_Functions;
package combinations is
type combo_action is (add_element,clear, show, show_sum, Build);
type Real is digits 6 ;
combo_sum_root : Real ;
i,n,b, combos_cnt
,combo_sum : integer ;
procedure get_parms ;
Procedure build (b,n,r:integer) ;
end combinations;
-- combinations.adb BODY ---------------------------------------
with Text_IO ; use Text_IO;
with Ada.Text_IO ; use Ada.Text_IO;
with Ada.INteger_Text_IO ; use Ada.Integer_Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.UNbounded;
with gearbox ; use gearbox;
with Ada.Numerics.Generic_Elementary_Functions ;
package body combinations is
group, Intersection_count,r : Integer ;
done, get_value : boolean := false ;
CR: constant Character := Character'Val (13) ;
type gear_arrays is array(positive range <>) of integer;
-- ------------------------------------------------------------
procedure get_parms is
begin
...
end get_parms ;
-- --------------------------------------------------
procedure build (b,n,r: Integer) is
-- --------------------------------------------------
cnt, e_cnt, value : integer :=0 ;
launch, pause : character ;
run_again : String := " " ;
show_group : Unbounded_string ;
all_done, combo_done : boolean := false ;
combo_sum_root : Real ;
progress_string : Unbounded_String ;
gears:gear_array (1..r) ;
-- with Ada.Numerics.Generic_Elementary_Functions ; — in specification .ads file
package Fermat_math is new
Ada.Numerics.Generic_Elementary_Functions(Real) ;
use Fermat_math ;
begin
...
...
put("Selecting "); -- put(tot_combos, width=>1);
put(" Possible Combinations,"); New_line;
While Not all_done loop -- for all/x combiNatioNs
...
end loop;
-- ------------------------
combo_sum := 0;
for e in 1..r loop -- select r value, element of grou & size of combiatios
value := fermats(gears(e).position,1);
...
put ("Combination sum is "); put (combo_sum, width => 1);
…..
-- -------------- buggy, fix
-- combo_sum_root := Fermat_math.Exp (Log (Integer(combo_sum_root) / n);
combo_sum_root := Real(combo_sum) ** (1/n) ;
-- -------------
put(" and sum's root is ");
put(combo_sum_root'image ); -- gives all roots as 1.00000E+00
end loop;
group := group + 1; --
end if; -- is New group and shift
end loop; -- Not all doNe
eNd build;
begin -- package
Null;
end combinations;
The critical issue in your example is that "n is integer type." When you try to create a rational exponent, your expression 1/n evaluates to an Integer with value zero. The package Generic_Elementary_Functions requires that "Exponentiation by a zero exponent yields the value one."
The solution is to use the type Real when creating your exponent: 1.0 / Real(N). Expanding on #Jim Rogers' example, the code below also illustrates calculating the power via the logarithm:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure Nth_Root is
type Real is digits 6;
package Real_Functions is new Ada.Numerics.Generic_Elementary_Functions
(Real);
use Real_Functions;
N : constant Natural := 2;
Power : constant Real := 1.0 / Real(N);
Base : constant Real := 2.0;
begin
Put_Line ("√2:" & Real'Image (Sqrt (Base)));
Put_Line ("√2:" & Real'Image (Base**Power));
Put_Line ("√2:" & Real'Image (Exp (Power * Log (Base))));
end Nth_Root;
Console:
√2: 1.41421E+00
√2: 1.41421E+00
√2: 1.41421E+00
The "**" operator in Ada.Numerics.Generic_Elementary_Functions provides you with the ability to find the Nth root of a floating point number.
The following example compares use of the sqrt function and the "**" operator.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure Main is
type Real is digits 6;
package Real_Functions is new Ada.Numerics.Generic_Elementary_Functions(Real);
use Real_Functions;
base : Real := 2.0;
Power : Real := 1.0 / 2.0;
begin
Put_Line("sqrt of 2.0 is: " & Real'Image(sqrt(base)) & " and " &
Real'Image(base**Power));
end Main;
The result of this example is:
sqrt of 2.0 is: 1.41421E+00 and 1.41421E+00
The exponent for the "**" operator is simply the inverse of N.
Edit: Adding the manipulations to calculate an integer root of a number.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Numerics.Generic_Elementary_Functions;
procedure integer_roots is
function int_root (Num : Positive; Exponent : Positive) return Natural is
type Real is digits 6;
package real_functions is new Ada.Numerics.Generic_Elementary_Functions
(Real);
use real_functions;
Real_Num : Real := Real (Num);
Real_Exponent : Real := 1.0 / Real (Exponent);
Real_Result : Real := Real_Num**Real_Exponent;
begin
return Natural (Real'Truncation (Real_Result));
end int_root;
Num : Positive;
Exponent : Positive;
begin
Put ("Enter the base number: ");
Get (Num);
Skip_Line;
Put ("Enter the root: ");
Get (Exponent);
Put_Line
("The" & Exponent'Image & "th root of" & Num'Image & " is" &
Natural'Image (int_root (Num, Exponent)));
end integer_roots;
The function int_root shown above calculates the floating point root then converts the truncated result to the subtype Natural.
A sample execution of this program is:
Enter the base number: 10000
Enter the root: 20
The 20th root of 10000 is 1
I am currently doing a project in ModelSim, and Im having some trouble with the compilation. All I want to is change the value of my pin from 0 to 1, but when I compile it says that there os a error.
tool directives are not supported before VHDL 2008. I dont know why this is happening, once that my professor disponiblized a example file and I did exactly like he did. The full code is below.
-- João Vítor Abrantes - 19/0031085
-- UnB - Engenharia Elétrica
--
-- - Experimento 2 -
-- Somador Completo
-- Entity
entity testbench is end;
-- Library
library ieee;
use ieee.std_logic_1164.all;
use std.textio.all;
architecture tb_sum of testbench is
-- Component
component tb_sum1
port(
W : in std_logic; --A
X : in std_logic; --B
Y : in std_logic; --Cin
Z : out std_logic; --S
Z1 : out std_logic --Cout
);
end component;
signal i_1 : std_logic;
signal i_2 : std_logic;
signal i_3 : std_logic;
Begin
S1 : tb_sum1 port map ( W => i_1 , Y => i_2 , X => i_3 , Z => open);
Cout1 : tb_sum1 port map ( W => i_1 , Y => i_2 , X => i_3 , Z1 => open);
estimulo: process
begin
wait for 5 ns; i_1 <= `1`, -- This is the part that he says the error is
wait for 5 ns;
wait for 5 ns;
wait for 5 ns;
wait for 5 ns;
wait for 5 ns;
wait for 5 ns;
wait;
end process estimulo;
end tb_sum;
you should use ' instead of ` and also need to use ; instead of ,
your code:
wait for 5 ns; i_1 <= `1`,
replace with:
wait for 5 ns; i_1 <= '1';
I searched for tool directives VHDL, and I get this:
Tool directives are arbitrary words preceded by a backtick character `.
I believe ' or " should be used here.
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
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.
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.