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).
Related
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).
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;
I am very new to VHDL coding and I have been trying to debug my code for a 32-bit adder/subtractor. The N-bit adder/subtractor is composed multiple 1-bit adder/subtractor using a generate statement. I have been testing it for 6-bit inputs using simulation. The waveform is constantly incorrect and I have tried changing just about everything. Maybe, it is a problem with the delays and the generate statement not cycling through correctly. (I am just beginning to learn how to code in vhdl.)
My 1-bit adder/subtractor
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity addsub_1bit is
Port ( in_0 : in STD_LOGIC;
in_1 : in STD_LOGIC;
cin : in STD_LOGIC;
AddOrSub : in STD_LOGIC;
sum_sub : out STD_LOGIC;
cout_bout : out STD_LOGIC);
end addsub_1bit;
architecture data_flow_addsub_1bit of addsub_1bit is
begin
sum_sub <= (in_1 and (not in_0) and (not cin)) or ((not in_1) and in_0 and (not cin)) or ((not in_1) and (not in_0) and cin) or (in_1 and in_0 and cin) after 19 ns;
cout_bout <= (in_1 and in_0 and (not AddOrSub)) or ((not in_1)and in_1 and cin) or ((not in_1)and cin and AddOrSub) or (in_0 and cin) or (in_1 and cin and AddOrSub) after 19 ns;
end data_flow_addsub_1bit;
The N-bit adder/subtractor:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY adder_sub32 is
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC;
sub : IN STD_LOGIC;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END adder_sub32 ;
ARCHITECTURE adder_sub32_arch OF adder_sub32 IS
signal tmp : std_logic_vector (BW downto 0);
BEGIN
tmp(0) <= cin;
gen: for i IN 0 TO BW-1 GENERATE
as1: entity work.addsub_1bit
PORT MAP(
in_0 => a_32(i),
in_1 => b_32(i),
cin => tmp(i),
AddOrSub => sub,
sum_sub => sum_32(i),
cout_bout => tmp(i+1));
end GENERATE;
ov <= tmp(BW) after 95 ns;
END ARCHITECTURE;
My testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY adder_sub32_TB_SHan_53967364 IS
END adder_sub32_TB_SHan_53967364;
ARCHITECTURE behavior OF adder_sub32_TB_SHan_53967364 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT adder_sub32 IS
GENERIC (BW : INTEGER :=32);
PORT ( a_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
b_32 : IN STD_LOGIC_VECTOR (BW -1 downto 0);
cin : IN STD_LOGIC ;
sub : IN STD_LOGIC ;
sum_32 : out STD_LOGIC_VECTOR (BW -1 downto 0);
cout : INOUT STD_LOGIC ;
ov : OUT STD_LOGIC ); -- ov stands for overflow
END COMPONENT;
signal a : std_logic_vector(5 downto 0); --:= (others => '0');
signal b : std_logic_vector(5 downto 0); --:= (others => '0');
signal cin : std_logic;
signal sub : std_logic;
signal cout : std_logic;
signal sum_32 : std_logic_vector(5 downto 0);
signal ov : std_logic;
BEGIN
test1: adder_sub32
GENERIC MAP (6)
PORT MAP (a_32 => a,b_32 => b,cin => cin,sub => sub,sum_32 => sum_32,cout => cout,ov => ov);
sub <= '0';
cin <= '0';
a <= "101010";
b <= "110101";
END;
The waveform I got:
The final sum is correct ("101010" + "110101" = "011111") in this case, but not in all cases.
EDIT2: Let's take a closer look, why the carry is not rippling as expected in your addition. The bits 0 (LSB) to 5 of the operands together, request that the carry-in is propagated from bit 0 to the carry-in of bit 6. Bits 6 of the operands generate a carry, which is carry-out of the adder. As the cin of bit 0 is '0', all intermediate carry-ins will be '0' too, but it should ripple through the carry-chain.
Now lets, take a look at the one-bit adder. You are adding two numbers, so that, AddOrSub is '0'. With this, the equation of cout_bout can be simplified to:
cout_bout <= (in_1 and in_0) or (in_0 and cin);
This equation is definitly wrong, because the carry-in is not propagated when in_1 = '1' and in_0 = '0'. Thus, some of the intermediate carries will be computed to '0' just after 19 ns without waiting for the rippling carry. The corresponding sum bit will be valid after 38 ns as shown in your waveform. The final value of the sum is not affected because this shortcuted carry is identical to the expected rippling carry. Please consider here, that all the 1-bit adder (generated by the generate statement) work concurrently.
To fix the equation, I recommend to write a testbench for the 1-bit adder. This testbench would have to check all possible 16 input combinations of in_0, in_1, cin, and AddOrSub.
Another testcase would be to add the above two operands with an cin of '1'.
(End of EDIT2.)
The ov is correct too in this case, but not in all cases.
EDIT: You mixed up the overflow ov with the carry-out cout. The overflow flag indicates an overflow in the signed number space. For the addition, the overflow flag is '1' if and only if:
the addition of two positive numbers results in a negative sum, or
the addition of two negative numbers results in a positive sum.
For subtraction it is the other way round.
Because this is a homework question, I will not solve it completely. But I will give a you a testcase where your current logic fails: if you add 1 ("000001") plus -1 ("111111"), then the sum must be zero, the overflow '0' and the carry-out '1'. (End of Edit.)
The cout is 'U' because you haven't connected it in adder_sub32. The carry-out is the top-most bit in your carry-chain, and thus:
cout <= tmp(BW);
And you should fix the direction of cout in adder_sub32. The carry-out is just an output of this component. So declare it as out instead of inout.
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!
I have a problem with VHDL, I want to rotate the signal Checked1 and save it in itself:
Checked1<=to_stdlogicvector(to_bitvector(Checked1) ROR 1);
and I get all zeros, instead of 0100->0010
I know I can't use the same signal, but I have to change Checked1 in a loop.
How can i used it?
The whole code is here:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_arith.ALL;
use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Stall_control is
Port ( EP : in STD_LOGIC_VECTOR (7 downto 0);
SP : in STD_LOGIC_VECTOR (7 downto 0);
Comp : in STD_LOGIC_VECTOR (7 downto 0);
Position : out STD_LOGIC_VECTOR (7 downto 0));
end Stall_control;
architecture Behavioral of Stall_control is
type state is (LOOP_STATE, END_STATE);
signal FSM_state: state;
signal Check: STD_LOGIC_VECTOR (7 downto 0);
signal Checked: STD_LOGIC_VECTOR (7 downto 0);
signal Checked1: STD_LOGIC_VECTOR (7 downto 0):="00000000";
signal flag: STD_LOGIC:='0';
begin
Checked<= EP;
process(EP, SP, Comp, Check, CheckED, CheckED1, FLAG)
begin
Position<= "11111111";
case FSM_state is
when LOOP_STATE=>
if((Checked AND Comp)="00000000") OR ((Checked1 AND Comp)="00000000") then
Checked1<=to_stdlogicvector(to_bitvector(Checked1) ROR 1);
--Checked<=Checked1;
--Checked1(7 downto 0)<=Checked1(0)&Checked1(7 downto 1);
flag<='0';
if(CheckED1/= SP) then
FSM_state<=LOOP_STATE;
else
FSM_state<=END_STATE;
end if;
else
flag<='1';
FSM_state<=END_STATE;
end if;
when END_STATE=>
if flag='1' then
Position<= Checked1;
else
--Position<= Checked1;
Position<= "11111111";
end if;
end case;
end process;
end Behavioral;
You are never assigning anything but all '0's to checked1.
case fsm_state is
when loop_state =>
if (checked and comp) = "00000000" or
(checked1 and comp) = "00000000" then
checked1 <= to_stdlogicvector(to_bitvector(checked1) ror 1);
flag<='0';
if checked /= sp then
fsm_state<=loop_state;
else
fsm_state<=end_state;
end if;
else
flag<='1';
fsm_state<=end_state;
end if;
checked1 has a default value of (others => '0') (all zeros) and is only rotated by 1. Of course it's going to be all zeros.
-- The ror operator returns a value that is L rotated right by R index positions. That is, if R is 0 or if L is a null array, the return
value is L. Otherwise, a basic rotate operation replaces L with a
value that is the result of a concatenation whose right argument is
the leftmost (L'Length - 1) elements of L and whose left argument is
L(L'Right). If R is positive, this basic rotate operation is repeated
R times to form the result. If R is negative, then the return value is
the value of the expression L rol -R.
It sounds like you want a different default value for checked1.
You don't need the ROR operator, you can use concatenation:
checked1 <= checked1(0) & checked1 (7 downto 1);
(Because your ROR operator R value is a constant and within the length of checked1).
And none of these now commented out packages are needed in your context clause:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;
-- use ieee.numeric_std.all;
-- use ieee.std_logic_unsigned.all;
Not a one of the three, and there can be potential conflicts from the combination.
And the way the process sensitivity list is populated, you've created an oscillation, any signal assigned in the process that is also in the sensitivity list will cause the process to resume the next simulation cycle. Put a '1' somewhere in the default value for checked1 and rotating it will cause an event (a change of value) on checkd1 causing the process to be invoked successively.