Index overflow in VHDL std_logic_vector - vhdl

I have a doubt in following VHDL code regarding index overflow of len:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package mypack is
subtype small_int is integer range 0 to 3;
end mypack;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.mypack.all;
entity top is
port(
CLK : in std_logic;
rst : in std_logic;
myPtr : in small_int;
temp : in unsigned(1 downto 0);
myout : out std_logic_vector(3 downto 0));
end entity;
architecture rtl of top is
signal len : std_logic_vector(3 downto 0) := (others=>'0');
constant si : small_int := 1;
begin
myout <= len;
process(clk,rst) begin
if (RST='1') then
len <= "0000";
elsif rising_edge(CLK) then
len(myPtr - si) <= temp(0);
end if;
end process;
end architecture;
What should be correct behaviour when myPtr = 0:
Would len(3) <= temp(0); happen?
Or, would there be an index over flow situation? Which means, len(3) will always remain at 0.
Thanks in advance.

In simulation, an out of range index value will generate an error.
In hardware, and out of range index value result in undefined operation, so any or no update may occur.

Related

How to declare an array of arrays in the test bench of a VHDL code?

I have an array of arrays defined as the input to my entity. I used a package to define the array of arrays. In the test bench, I included that package and declared the component in the architecture but there is an error saying "formal port x does not exist in entity average. Please compare the definition of block average to its component declaration and its instantion to detect the mismatch."
Attaching the declarations below. Please help.
-- the code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
package vpkg is
type m_array is array(1 downto 0, 1 downto 0) of std_logic_vector(7 downto 0);
end package;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.vpkg.all;
entity average is
Port (x : in m_array;
clk : in std_logic;
y : out std_logic_vector(7 downto 0)
);
end average;
architecture avg_arch of average is
signal sum : std_logic_vector(8 downto 0) := (others => '0');
begin
process(x):
for I in 0 to 1 loop
for J in 0 to 1 loop
sum <= sum + ('0' + x(I,J));
end loop;
end loop;
end process;
y <= std_logic_vector(to_signed(to_integer(signed(sum) / 4),8));
end avg_arch;
--the test bench
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.vpkg.all;
entity tb_average is
-- Port ( );
end tb_average;
architecture tb_average_arch of tb_average is
component average
Port (x : in m_array;
clk : in std_logic;
y : out std_logic_vector(7 downto 0)
);
end component;
signal x : m_array;
signal clk : std_logic := '0';
signal y : std_logic_vector(7 downto 0);
begin
average_1 : average Port Map (x => x,clk => clk,y=>y);
input_proc : process
begin
wait for 100ns;
x(0,0) <= "00001001";
x(0,1) <= "00000110";
x(1,0) <= "00000011";
x(1,1) <= "00000001";
wait;
end process;
clk_proc : process
begin
wait for 100ns;
loop
clk <= '1';
wait for 10ns;
clk <= '0';
wait for 10ns;
end loop;
end process;
end tb_average_arch;

Implementing Overflow Checking in 4-bit Adder/Subtractor (VHDL)

I am rather new (3 weeks) to VHDL, and I am having a problem in my latest assignment, which involves implementing overflow checking in a simple 4-bit adder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity add_sub_4bit is
Port ( a : in STD_LOGIC_VECTOR(3 downto 0);
b : inout STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC );
--sum : inout STD_LOGIC_VECTOR(3 downto 0)
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal localsum : STD_LOGIC_VECTOR (3 downto 0);
begin
localsum <= a + b when sel = '1'
else
a - b;
process(a,b,localsum) begin
if a(3) = '0' AND b(3) = '0' AND localsum(3) = '1' then
localflow <= '1';
elsif a(3) = '1' AND b(3) = '1' AND localsum(3) = '0' then
localflow <='1';
else
localflow <='0';
end if;
end process;
end Behavioral;
Now, the test cases are as such:
A=5, B=-3, giving 0 to sel adds them, 1 subtracts.
A=6, B=2, working much the same.
Now, given that the numbers are signed, of course, they are two's complement numbers, so is the result. However, I can only detect overflow in a case of adding 6 (0110) and 2 (0010), giving out -8 (1000), which is obviously an overflow case in 4-bit. But, when doing 5 -(-3), the result is much the same, 1000, but since I have given numbers of two different signs, I cannot detect overflow using my method.
My teacher has suggested that we change the sign of B depending on the value of sel - I tried something like making b <= b+"1000" based on that but that didn't help, and I don't know of other ways, being very new to the language. What can I do to get a proper program? Thank you.
Firstly:
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Don't do that. Especially if you want the numbers to be signed. Normal to use is:
use IEEE.numeric_std.all;
After that, you should cast the std_logic_vector to the wanted data type, e.g. 'signed', for the correct arithmetic.
Secondly, don't use inout. VHDL is not so good with bidirectional assignments. Either use in or out.
So combining the above, you could do (n.b. not the best code):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit is
Port (
a : in STD_LOGIC_VECTOR(3 downto 0);
b : in STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(3 downto 0);
overflow : out std_logic
);
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal locala, localb, localsum : signed(4 downto 0); -- one bit more then input
signal sumout : std_logic_vector(4 downto 0);
begin
locala <= resize(signed(a), 5);
localb <= resize(signed(b), 5);
localsum <= locala + localb when sel = '1' else locala - localb;
-- overflow occurs when bit 3 is not equal to the sign bit(4)
localflow <= '1' when localsum(3) /= localsum(4) else '0';
-- convert outputs
sumout <= std_logic_vector(localsum);
--outputs
sum <= sumout(4)&sumout(2 downto 0);
overflow <= localflow;
end Behavioral;
You can test this using a testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit_tb is
end add_sub_4bit_tb;
architecture Behavioral of add_sub_4bit_tb is
signal sel : std_logic_vector(0 downto 0);
signal a, b, sum : std_logic_vector(3 downto 0);
begin
uut: entity work.add_sub_4bit
port map (a, b, sel(0), sum);
test: process
begin
for sel_o in 0 to 1 loop
sel <= std_logic_vector(to_signed(sel_o, 1));
for a_o in -8 to 7 loop
a <= std_logic_vector(to_signed(a_o, 4));
for b_o in -8 to 7 loop
b <= std_logic_vector(to_signed(b_o, 4));
wait for 1 ns;
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;

VHDL Counter Error (vcom-1576)

guys im trying to code a simple counter in VHDL but i always get this error:
Error: C:/Users/usrname/dir1/dir2/dir3/counter.vhd(22): near "rising_edge": (vcom-1576) expecting == or '+' or '-' or '&'.
Here is my Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
port (
EXT_RST : in std_logic;
EXT_CLK : in std_logic;
EXT_LED : out std_logic_vector(7 downto 0)
);
end counter;
architecture fast of counter is
signal count : std_logic_vector(7 downto 0);
begin
process(EXT_CLK, count)
begin
if (EXT_RST = '1') then
count <= "00000000";
elseif rising_edge(EXT_CLK) then
count <= count + '1';
end if;
end process;
EXT_LED <= count;
end fast;
Has anyone an idea why im getting this error?
Besides the elsif Lars Asplund suggested using in his comment use type conversions for `count:
count <= std_logic_vector(unsigned(count) + 1);
or use package numeric_std_unsigned (VHDL -2008 only) instead of numeric_std.
Notice the 1 instead of '1' and type conversions. Those aren't needed with numeric_std_unsigned which has a "+" adding operator function with this signature:
[STD_ULOGIC_VECTOR,STD_ULOGIC return STD_ULOGIC_VECTOR]
Using package numeric_std you can also make count an unsigned instead of std_logic_vector and convert for the LED assignment -
EXT_LED <= std_logic_vector(count);
Also, count doesn't need to be in the process sensitivity list:
process(EXT_CLK)
There are no assignments in the process where the value of count is used except on the clock edge.
Modifying your code with the first suggestion and indenting (which helps show the sensitivity list doesn't need count:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter is
port (
EXT_RST : in std_logic;
EXT_CLK : in std_logic;
EXT_LED : out std_logic_vector(7 downto 0)
);
end counter;
architecture fast of counter is
signal count : std_logic_vector(7 downto 0);
begin
process(EXT_CLK)
begin
if (EXT_RST = '1') then
count <= "00000000";
elsif rising_edge(EXT_CLK) then
count <= std_logic_vector(unsigned(count) + 1);
end if;
end process;
EXT_LED <= count;
end fast;
This analyzes, elaborates and will simulate.
This prompts the question of how EXT_RST and EXT_CLK are derived should you actually synthesize your design. If they are from buttons (particularly the clock), debounce could be necessary even with membrane switches which can age and later bounce.

how to check for any carry generated while adding std_logic_vector using operator overloading?

I am trying to add two std_logic_vectors using the notation given below:-
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 adder is
port( a:in std_logic_vector(31 downto 0);
b:in std_logic_vector(31 downto 0);
o:out std_logic_vector(31 downto 0));
end adder;
architecture Behavioral of adder is
begin
o<=a+b;
end Behavioral;
One possibility is to generate the result with carry, and then split that afterwards, like:
architecture Behavioral of adder is
signal c_o : std_logic_vector(o'length downto 0); -- Result with carry
signal c : std_logic; -- Carry only
begin
c_o <= ('0' & a) + b; -- Result with carry; extended with '0' to keep carry
o <= c_o(o'range); -- Result without carry
c <= c_o(c_o'left); -- Carry only
end Behavioral;
You can do this. The carry is not saved, but it's being reported that there was an overflow.
function "+" (Add1: std_logic_vector; Add2: std_logic_vector) return std_logic_vector is
variable big_sum: bit_vector(Add1'LENGTH downto 0);
begin
big_sum = Add1 + Add2;
assert big_sum(Add1'LENGTH) = 0
report "overflow"
severity warning;
return big_sum(Add1'LENGTH-1 downto 0);
Of course you'll need to define a new package and also include that package in your already existing file.
o<=std_logic_vector(unsigned(a)+unsigned(b))
Although I suggest you use unsigned/signed on your ports (and have a clock cycle of latency).
If you want the carry
o_with_carry <= std_logic_vector('0'&unsigned(a)+unsigned(b));
o_carry <= o_with_carry(o_with_carry'high);
o <= o_with_carry(o'range);

Counting down from an input value in VHDL

I'm trying to assign the value of input aa to the signal t in the code below. It compiles successfully, but there is a warning:
WARNING[9]: C:/Modeltech_5.7f/examples/hassan1.vhd(14): (vcom-1013) Initial value of "t" depends on value of signal "aa".
Here is the code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all ;
use ieee.numeric_std.all;
entity counter is
port(clk :in std_logic;
reset : in std_logic;
aa: in std_logic_vector(3 downto 0);
check : out std_logic_vector(3 downto 0));
end counter;
architecture imp of counter is
signal i:std_logic_vector(3 downto 0):="0000";
signal t:std_logic_vector(3 downto 0):=aa;
begin
process(clk)
begin
if rising_edge(clk) and (t>0) then
t<=t-1;
i<=i+1;
end if;
end process;
check<=i;
end imp;
What should I be doing in order to decrement the input 'aa' in the process? The program is meant to decrement the value at input aa to 0.
It looks like you are trying to implement a down-counter with a load input. In such a counter, when load_enable = '1' you should register the load input value (aa in your case) into an internal signal. When load_enable = '0', you would decrement this count value. Here is a code example that does that:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity down_counter is
port (
clock: in std_logic;
reset: in std_logic;
load_enable: in std_logic;
load_data: in std_logic_vector(3 downto 0);
output: out std_logic_vector(3 downto 0)
);
end;
architecture rtl of down_counter is
signal count: std_logic_vector(3 downto 0);
begin
process (clock, reset) begin
if reset then
count <= (others => '0');
elsif rising_edge(clock) then
if load_enable then
count <= load_data;
else
count <= count - 1;
end if;
end if;
end process;
output <= count;
end;
For the record, the code above can be improved, but I didn't want to throw too much stuff at once. It is probably a good idea to use an integer instead of std_logic_vector for your count signal. Also you should check if the count proceeds as you expected, since the example uses the numeric_std_unsigned package. I'd recommend that you change it to numeric_std once you understand the code completely.

Resources