Error for if statement condition in adder/subtractor - vhdl

I am new to the VHDL language, so please bear with me and please help me out.
I have written code for a addition/subtraction unit which will operate on signed integer but at the "if else" part in the last, the compiler is giving an error.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(A,B : in std_logic_vector(3 downto 0);
SUM : out std_logic_vector(3 downto 0);
mode: in std_logic_vector(0 downto 0));
end adder;
architecture behave of adder is
component xorgate is
port( p,q: in std_logic_vector(3 downto 0);
r: out std_logic_vector(3 downto 0));
end component;
signal a1,b1,sum1,output1,mode1:integer;
signal tmp: std_logic_vector(3 downto 0);
variable output: std_logic_vector(3 downto 0);
begin
u1: xorgate port map (B, mode, output);
output1 <= to_integer(signed (output));
a1 <= to_integer(signed(A));
b1 <= to_integer(signed(B));
mode1 <= to_integer(signed(mode));
process(a1,output1,b1,tmp,mode1)
begin
if ( mode1 <= '1') then
sum1 <= a1 + output1 ;
else
sum1 <= a1 + b1;
end if;
tmp <= std_logic_vector(to_signed(sum1,4));
SUM <= tmp( 3 downto 0);
end process;
end behave;
XST Error Message:
ERROR: HDLCompiler:1731 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 31: found '0' definitions of operator "<=", cannot determine exact overloaded matching definition for "<="
ERROR: HDLCompiler:854 - "E:\XILINX PROGRAM\FULLADD\FULLADD.vhd" Line 11: Unit ignored due to previous errors.

Line 31: if ( mode1 <= '1') then
you meant: if ( mode1 = 1) then
Line 11: This just means that because of the previous error, the compiler 'gave up'.

The <= operator in mode1 <= '1' is less-than-or-equal compare of integer with '1', which have no definition, thus the found '0' definitions of operator "<=". Change '1' to simply the integer literal1`.
Other issues with the code are listed below.
The ´variable output: ...´ must be signal output: when output is used as actual for in port map for xorgate. In typical design you don't have variables in the declaration section, between begin and end, of an architecture.
Length of mode is only 1 std_logic (bit), but actual for mode in xorgate port map, which is q in xorgate, is 4 bits. You probably meant to make mode as 3 downto 0 in the port declaration of adder, since compare like mode1 <= 1 will be trivial true if mode is 1 bit.
The intermediate integer signals named *1 and other signal are actually not required if the process uses signed additions from numeric_std package like:
process(A, B, mode, output) is
begin
if signed(mode) <= 1 then
SUM <= std_logic_vector(signed(A) + signed(output));
else
SUM <= std_logic_vector(signed(A) + signed(B));
end if;
end process;
And this can even be reduced to the below, with only output as intermediate signal:
SUM <= std_logic_vector(signed(A) + signed(output)) when (signed(mode) <= 1)
else std_logic_vector(signed(A) + signed(B));
Finally, if mode is to be treaded like unsigned, then replace with unsigned(mode), since unsigned is also defined in the numeric_std package.

The puzzle is probably why the error message is about failure to find an overloaded operator
'1' has at least two definitions, first as a character literal, then as a bit literal. Neither of these have a <= operator comparing them with type Integer, and that's why the compiler gave up.
If you had used an integer literal 1 instead, the compiler could have found a <= operator easily... so if mode1 <= '1' then would work.
Alternatively, you could write your own <= operator accepting inputs of these two types and returning a boolean :
function "<=" (a : Integer; b : Bit) return Boolean is ...
While it would work, it would also deserve a slap on the wrist!

Related

Getting "test2.vhd(43): VHDL Compiler exiting" error with if-statement on commented out lines but not with the "sum2" lines

As the title says, I'm getting a compiler exiting error with the if-statement when I use the lines commented out with the "sum" value but not with the "sum" 2 value and I'm not sure why.
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.std_logic_unsigned.all;
entity test2 is port
(
a, b : IN unsigned( 3 DOWNTO 0 );
cin : IN unsigned;
sum : OUT unsigned( 4 DOWNTO 0 )
);
end test2;
architecture behavioral of test2 is
signal a_5, b_5, cin_5, sum2 : unsigned(4 downto 0) := (others => '0');
signal x, y : unsigned(4 downto 0) := (others => '0');
signal z : std_logic;
begin
a_5 <= ('0' & a);
b_5 <= ('0' & b);
cin_5 <= ('0' & '0' & '0' & '0' & cin);
sum <= a_5 + b_5 + cin_5;
sum2 <= a_5 + b_5 + cin_5;
process (sum2, b_5)
--process (sum, b_5)
begin
if (sum2 > b_5) then
--if (sum > b_5) then
z <= '1';
else
z <= '0';
end if;
end process;
end behavioral;
For some context:
I'm working on an adder that adds two 4bit numbers and eventually displays the decimal value on a 7seg display.
I want to take the "sum" value and check if it is greater than decimal value 9 and if so then it sets a flag to always have the 7seg display for the 10s value display a 1. (I only need to count up to decimal value 19). I can probably do this another method but I started doing it this way and got stuck here and I think this is something fundamental I am just not understanding.
sum is a port, which has the type "out". Ports out type "out" can't be read. If you want to read an output port, you must use the type "buffer". sum2 instead is a signal, which can always be read
(By the way you should only use numeric_std and not std_logic_unsigned, which is an old solution and not preferred anymore).

How to set branch in case statement from a constant? ERROR: choice must be locally static expression

Verilog allows the branches of a case statement to be defined as a constant in a different file. Example:
`define COND1 3'b001
`define COND2 3'b010
`define COND3 3'b100
module xyz(input wire [2:0] select, output reg value);
always #*
case(select)
`COND1: value = 1'b0;
`COND2: value = 1'b1;
`COND3: value = 1'b0;
default: value = 1'b0;
endmodule
How can I do the same in VHDL? I want to have my constants for the case defined in a package and to pull these constants into the current architecture and use the constants to define the branches for the case statement. Working example:
library ieee;
use ieee.std_logic_1164.all;
entity stuff is
port(
sel1: in std_logic_vector(2 downto 0);
val1: out std_logic
);
end entity;
architecture rtl of stuff is
constant COND1 : std_logic_vector(2 downto 0) := "001";
constant COND2 : std_logic_vector(2 downto 0) := "010";
constant COND3 : std_logic_vector(2 downto 0) := "100";
begin
process(sel1)
begin
case sel1 is
when COND1 => val1 <= '0';
when COND2 => val1 <= '1';
when COND3 => val1 <= '0';
when others => val1 <= '0';
end case;
end process;
end architecture;
Which works ok...
However, when I try it in my VHDL code I get a strange error:
..\simtools\ghdl\bin\ghdl.exe -a stuff2.vhdl
stuff2.vhdl:40:18: choice must be locally static expression
stuff2.vhdl:41:18: choice must be locally static expression
stuff2.vhdl:42:18: choice must be locally static expression
Here's the code that gives this error:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity stuff is
generic(
CW : integer := 3
);
port(
sel1 : in std_logic_vector(CW-1 downto 0);
val1 : out std_logic
);
end entity;
architecture rtl of stuff is
function n(n_value:integer; n_width:integer)
return std_logic_vector is
begin
return std_logic_vector(to_unsigned(n_value, n_width));
end function;
constant CMD1 : std_logic_vector(2 downto 0) := n(0, 3);
constant CMD2 : std_logic_vector(2 downto 0) := n(1, 3);
constant CMD3 : std_logic_vector(2 downto 0) := n(2, 3);
constant CMD4 : std_logic_vector(2 downto 0) := n(3, 3);
constant CMD5 : std_logic_vector(2 downto 0) := n(4, 3);
signal sel2 : std_logic_vector(2 downto 0);
begin
sel2 <= sel1(2 downto 0);
process(sel2)
begin
case sel2 is
when CMD1 => val1 <= '0';
when CMD2 => val1 <= '1';
when CMD3 => val1 <= '0';
when others => val1 <= '0';
end case;
end process;
end architecture;
Kevin Kruse's answer depends on -2008:
9.4.2 Locally static primaries
An expression is said to be locally static if and only if every operator in the expression denotes an implicitly defined operator or an operator defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE, and if every primary in the expression is a locally static primary, where a locally static primary is defined to be one of the following:
...
e) A function call whose function name denotes an implicitly defined operation or an operation defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE and whose actual parameters are each locally static expressions
which is not yet implemented as of ghdl-0.36. Otherwise Kevin's answer appears valid for fully -2008 compliant locally static primaries.
In earlier revisions the constants value expressions are not locally static due to the return value of functions n or to_unsigned.
See -2002 or earlier 7.4.2 Globally static primaries (9.4.3 - 2008) "i) A function call whose function name denotes a pure function and whose actual parameters are each globally static expressions" where every locally static expression is also globally static.
The -2008 change adding called functions in IEEE packages that are not allowed to have their function declarations nor functionality changed, allows them to be treated as locally static and is controlled by the copyright licensing terms for the package sources.
For non-compliant implementations of -2008 or earlier revisions of the standard it's possible to define the numeric value of CMD1 - 4 and convert sel(2 downto 0) to a locally static integer subtype value:
architecture rtl of stuff is
constant CMD1: natural range 0 to 7 := 0; -- "000"
constant CMD2: natural range 0 to 7 := 1; -- "001"
constant CMD3: natural range 0 to 7 := 2; -- "010"
constant CMD4: natural range 0 to 7 := 3; -- "011"
constant CMD5: natural range 0 to 7 := 4; -- "100"
signal sel2: natural range 0 to 7; -- locally static subtype
begin
sel2 <= to_integer(unsigned(sel1(2 downto 0)));
process (sel2)
begin
case sel2 is
when CMD1 => val1 <= '0';
when CMD2 => val1 <= '1';
when CMD3 => val1 <= '0';
when others => val1 <= '0';
end case;
end process;
end architecture;
But the question's first VHDL example most closely implements the Verilog snippet.
To enable the use of a globally static range of sel1 using a fixed slice for decoding requires the declaration for sel2 to provide a locally static subtype for the case expression:
architecture equiv_w_generic_sel1 of stuff is
constant COND1: std_logic_vector (2 downto 0) := "000";
constant COND2: std_logic_vector (2 downto 0) := "001";
constant COND3: std_logic_vector (2 downto 0) := "010";
signal sel2: std_logic_vector (2 downto 0);
begin
sel2 <= sel1(sel2'range); -- locally static subtype
process (sel2)
begin
case sel2 is
when COND1 => val1 <= '0';
when COND2 => val1 <= '1';
when COND3 => val1 <= '0';
when others => val1 <= '0';
end case;
end process;
end architecture;
where you're not redefining the problem to be harder by using non-locally static function calls and also don't require a use clause to provide visibility for package numeric_std declarations. Note the COND1, COND2 and COND3 constants have locally static value expressions as does the Verilog snippet.
Both of the above architectures analyze with or without ghdl's --std=08 being specified.
Note the command line shown for ghdl in the question does not specify the VHDL revision and ghdl defaults to the equivalent of --std=93c which provides relaxed compliance matching Modelsim's implementation of the -1993 revision of the standard.
Your use of the function n makes the value of the constants not locally static.
If you replace n(0, 3) with std_logic_vector(to_unsigned(0, 3)) it would work. Or, as you've already shown, replace it with "000".

Use of conv_integer in VHDL

I am in the process of trying to write some code that will simply just shift a 32 bit vector left or right, with a 5 bit input that will be used for the shift amount (shamt). The issue I am having is trying to convert an std_logic_vector to an integer. My code is this:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x : in std_logic_vector(31 downto 0);
shamt : in std_logic_vector( 4 downto 0);
y : out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
signal shift : integer;
signal temp : std_logic_vector(31 downto 0);
begin
shift <= conv_integer(unsigned(shamt));
temp <= x(shift downto 0);
y <= temp;
end beh;
The code is not complete I know, but to test some ideas I am trying to pass "00010" (2) into shamt, but shift comes out to be -2147483648. But I cannot figure out why it is doing this, nor can I find any resources online that shows anything different than what I am doing. I greatly appreciate any help.
-2147483648 (-2**31) is the default initial value for integers, being the leftmost, most negative value in its range. It suggests that the signal assignment to shift has not executed. Most likely because it is a continuous assignment and there hasn't been an event on shamt to cause it to update.
std_logic_arith is not an IEEE standard library. You should use to_integer() from ieee.numeric_std instead. It is also beneficial to keep numeric ports as unsigned or signed so that your intent is clear and to minimize type conversions. Also, you cannot directly assign the variable length slice of x to temp since their lengths do not match. You should use resize() (from numeric_std) to extend the length back to 32-bits or rethink your approach.
I fixed the obvious typo in the entity name, started the simulation (ModelSim) and forced the signal shamt to "00010". Then just after trying to run for 1 ps, ModelSim complains about:
Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 0 (-2147483648 downto 0 (null array)).
Time: 0 ps Iteration: 0 Process: /shiftlogical/line__16 File: shiftlogical.vhdl
Fatal error in Architecture beh at shiftlogical.vhdl line 16
That is because all your concurrent statements are executed in parallel. The new signal values are scheduled for the next delta cycle within the simulation. Thus, the line
temp <= x(shift downto 0);
is executed with the old value of shift which is the initial value of this signal. The initial value of an integer is -2**31 as also Kevin pointed out.
Of course you can initialize the signal shift, but the only value which will not result in an error will be 31 because in this asignment the signal on the left and the expression on the right must match in array (std_logic_vector) size. The signal shamt must be forced to "11111" as well, so that shift keeps 31.
You cannot easily fix this, because for a left shift you must add zeros at the right (LSB) and for a right shift zeros or the sign at the left (MSB).
#Martin Zabel what I had really tested there was to see if shift would hold an integer value which it did until I tried to pass it in for temp <= x(shift downto 0); What I realized was that the signal needed to really be a variable to work as intended and as follows my code consists of:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x: in std_logic_vector(31 downto 0);
shamt: in std_logic_vector(4 downto 0);
dir: in std_logic;
y: out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
begin
process(dir)
variable shift : integer;
begin
shift := conv_integer(unsigned(shamt));
if(dir = '0') then --Left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
elsif(dir = '1') then --Right shift
y(31-shift downto 0) <= x(31 downto shift);
y(31 downto 31-shift) <= (others => '0');
else --Always left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
end if;
end process;
end beh;

signal statement must use <= to assign value to signal

I've got this error in the expression "individuos(x):=cout" of the following code. What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos", the same will happen if i trie to build a sequential statement with the assert function. How do I fix this?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_TEXTIO.ALL;
use ieee.numeric_std.all;
--package genetica_type is
--type genetica is array(0 to 49) of unsigned(7 downto 0);
--type fitness is array(0 to 49) of unsigned (2 downto 0);
--end package genetica_type;
use work.genetica_type.all;
entity conexao is
Port (
clk : in bit;
cout: in unsigned (7 downto 0);
individuos: out genetica
);
end entity;
architecture Behavioral of conexao is
--type genetica is array (0 to 49) of std_logic_vector (7 downto 0);
--signal s_individuos : genetica;
--signal i: genetica;
begin
process (clk)
begin
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) := cout;
end loop;
end if ;
end process;
end Behavioral;
I've got this error in the expression "individuos(x):=cout" of the following code.
That is a syntax error. Use <= exactly as the compiler says.
What I'm trying to do is assign to each array of individuos a different random "cout" input sequentially. If I change the expression to "individuos <= cout", it'll asign the same "cout" to all "individuos"
That is exactly what you ask it to do :
If (clk 'event and clk = '1') then
for x in 0 to 49 loop
individuos(x) <= cout;
end loop;
end if ;
On every rising clock edge, loop 50x performing 50 assignments, each of the same data, to all 50 addresses.
What I think you want to do, is, on every clock, perform ONE assignment, and increment the address to point to the next location.
signal x : natural range 0 to individuos'high;
...
if rising_edge(clk) then
individuos(x) <= cout;
x <= x + 1 mod individuos'length;
end if;
This code has several other differences from yours:
It uses the simpler rising_edge(clk) function
It will still work when you change the size of the input array.
It still has a bug : if you change the array lower bound to something other than 0, it will fail... for example:
type genetica is array(3 to 49) of ...
Easy to catch this with an assert:
Assert individuos'low = 0 report "Array Individuos bound error" severity failure;
It also runs continuously. If you want to start and stop it, or reset the address counter, or stop when it reaches 50, that takes additional logic.

VHDL 4-bit AdderSubtractor error - expecting ";"

I feel like I'm making a very simple mistake here... I'm new to VHDL, trying to make a simple 4-bit ASU but I get one which I can't figure out.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
ENTITY asu is
PORT (Cin : IN std_logic;
X,Y : IN std_logic_vector(3 downto 0);
S : OUT std_logic_vector(3 downto 0);
Cout, Overflow : OUT std_logic);
End asu;
ARCHITECTURE Behaviour OF asu IS
SIGNAL Sum : STD_LOGIC_VECTOR(4 DOWNTO 0);
BEGIN
PROCESS (X,Y,Cin)
BEGIN
IF Cin = 1 THEN
Sum <= (0 & X) - (0 & Y);
S <= Sum(3 DOWNTO 0);
Cout <= Sum(4);
Overflow <= Sum(4)XOR X(3) XOR Y(3) ;
ELSE
Sum <= (0 & X) +(0 & Y) + Cin;
S <= Sum(3 DOWNTO 0);
Cout <= Sum(4);
Overflow <= Sum(4)XOR X(3) XOR Y(3) ;
end IF;
end PROCESS;
END behaviour;
I get the following errors:
Error (10327): VHDL error at asu.vhd(17): can't determine definition of operator ""="" -- found 0 possible definitions
You can't compare with 1 you have to compare with '1'
so you should write
IF Cin = '1' THEN
The expression in condition Cin = 1 requires a signature for an overloaded equality operator of [std_ulogic, integer return boolean] and there isn't one.
std_logic is a resolved std_ulogic which is an enumerated scalar type with possible values 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H' and '-'.
If you change that 1 to a '1' your analyzer will detect an "=" that will work. An equality operator between a value of a type and a value of the same type is predefined.
Also notice the four occurrences of concatenating zero with a std_logic vector (e.g. (0 & x)). These 0s need to be '0's as well for the same reason. There is no concatenation operator defined between an integer and a std_logic_vector.
The assignments to s, cout and overflow don't want to be in the process. sum is not in the process sensitivity list, and shouldn't be.
Deciding to add or subtract base on cin doesn't make any sense (to me).

Resources