In VHDL, is it synthesizable to use variables other than i,j in FOR loops? - for-loop

I am a freshman to VHDL, and am learning it by myself.
As a practice, I am doing a data process (calculate spatial average data) to a 320*240 graphic data.
I am considering the way like this :
1. Create a 10*10 cluster of homogeneous simple elements, where each element calculates the average value of a single pixel.
2. Each time connect one portion of the graphic data to the 10*10 cluster, make calculation then change connection. And after 32*24 times of operation, the work is finished.
But I got synthesizing problem in step 2. In order to dynamically change connections, I have to use variables other than i,j in FOR statement. But it seems to be not synthesizable for this pattern of using FOR loop(the synthesizing time goes unlimited.).
Would anyone help me out of this?
The problematic code segment is as follows:
FSM1: process(clk) is
variable cnt1 : integer range 0 to 5 := 0;
variable cnt2 : integer range 0 to 32-1 := 0;
variable cnt3 : integer range 0 to 24-1 := 0;
variable BlockBaseX : integer range 0 to 310 := 0;
variable BlockBaseY : integer range 0 to 230 := 0;
variable varPRLLc_ave_indata : std_logic_vector(400*8-1 downto 0) :=(others=>'0');
begin
if rising_edge(clk) then
PRLLc_ave_indata <= varPRLLc_ave_indata;
if stateFSM2A = s3 then
case stateFSM1 is
when s1 =>
if do_InitCopy = '1' then
workGD <= baseGD;
end if;
stateFSM1 <= s2;
when s2 =>
if do_NumProc = '1' then
case cnt1 is
when 0 =>
BlockBaseX := cnt2*10; -- 10, 20, ..., 310
BlockBaseY := cnt3*10; -- 10, 20, ..., 230
for i in 0 to 9 loop
for j in 0 to 9 loop -- PRLLc_ave_indata (400*8-1 downto 0);
if i = 9 then
if j = 9 then
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j-1) & workGD(BlockBaseY+i-1, BlockBaseX+j) & workGD(BlockBaseY+i-1, BlockBaseX+j-1);
else
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j+1) & workGD(BlockBaseY+i-1, BlockBaseX+j) & workGD(BlockBaseY+i-1, BlockBaseX+j+1);
end if;
else
if j = 9 then
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j-1) & workGD(BlockBaseY+i+1, BlockBaseX+j) & workGD(BlockBaseY+i+1, BlockBaseX+j-1);
else
varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(BlockBaseY+i, BlockBaseX+j) & workGD(BlockBaseY+i, BlockBaseX+j+1) & workGD(BlockBaseY+i+1, BlockBaseX+j) & workGD(BlockBaseY+i+1, BlockBaseX+j+1);
end if;
end if;
end loop;
end loop;
-- If the above For loop is replaced with the following one(BlockBaseX,BlockBaseY are removed), the synthesis can be accomplished.
-- for i in 0 to 9 loop
-- for j in 0 to 9 loop -- PRLLc_ave_indata (400*8-1 downto 0);
-- if i = 9 then
-- if j = 9 then
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j-1) & workGD(i-1, j) & workGD(i-1, j-1);
-- else
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j+1) & workGD(i-1, j) & workGD(i-1, j+1);
-- end if;
-- else
-- if j = 9 then
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j-1) & workGD(i+1, j) & workGD(i+1, j-1);
-- else
-- varPRLLc_ave_indata((i*10+j)*32+31 downto (i*10+j)*32) := workGD(i, j) & workGD(i, j+1) & workGD(i+1, j) & workGD(i+1, j+1);
-- end if;
-- end if;
-- end loop;
-- end loop;
when 1 =>
when 2 =>
when 3 => -- got answer
when 4 =>
when others =>
end case;
if cnt1 < 5 then
cnt1 := cnt1 + 1;
else
cnt1 := 0;
if cnt2 < 32 then
cnt2 := cnt2 + 1;
else
cnt2 := 0;
if cnt3 < 24 then
cnt3 := cnt3 + 1;
else
cnt3 := 0;
stateFSM1 <= s3;
end if;
end if;
end if;
else
end if;
when s3 => -- after detecting a signal indicating OV7670 module has come to the requested point,
-- launch the pump out function - pump data from WorkGD to a stream
when others =>
end case;
else
stateFSM1 <= s1;
end if;
end if;
end process FSM1;

Related

Generating sine using cordic algorithm

I want to apologize for this + - popular question, but nowhere did I find a specific implementation on vhdl. I write the algorithm from scratch and I have a problem with math implementation. The output is invalid. nothing counts, but just shows 1 value. If someone knows what i need to do, how to fix it, would be very grateful for any help.
Math part
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity massive is
port (
clk : in std_logic;
reset : in std_logic;
sinus : out std_logic_vector (15 downto 0));
end massive;
architecture Behavioral of massive is
type my_type is array (0 to 16) of signed (15 downto 0);
signal x : my_type;
signal y : my_type;
signal z : my_type;
signal j : my_type := ("1010111111001000", "0110011111000101", "0011011011010100", "0001101111010101", "0000110111111000",
"0000011011111110", "0000001101111111", "0000000111000000", "0000000011100000", "0000000001110000",
"0000000000111000", "0000000000011100", "0000000000001110", "0000000000000111", "0000000000000100",
"0000000000000010", "0000000000000001");
begin
process(clk)
begin
x(0) <= "0000010100000110";
y(0) <= "0000000000000000";
z(0) <= "0000000000000000";
if rising_edge(clk) then
if reset <= '1' then
For n in 0 to 15 loop
if (z(n) >= 0) then
x(n+1) <= x(n) - (y(n)/2**n);
y(n+1) <= y(n) + (x(n)/2**n);
z(n+1) <= z(n) + j(n);
else
x(n+1) <= x(n) +(y(n)/2**n);
y(n+1) <= y(n) -(x(n)/2**n);
z(n+1) <= z(n) - j(n);
end if;
end loop;
sinus <= std_logic_vector(y(16));
end if;
end if;
end process;
end Behavioral;
Rotation part
entity step_control is
generic (
first : integer := 0;
second : integer := 1;
third : integer := 2;
fourth : integer := 3;
);
Port ( clk : in STD_LOGIC;
Angle : out STD_LOGIC_VECTOR (12 downto 0);
quarter_in : out STD_LOGIC_VECTOR (1 downto 0));
end step_control;
architecture Behavioral of step_control is
signal Ang : std_logic_vector (12 downto 0) := (others => '0');
signal state : unsigned (1 downto 0) := to_unsigned(first,2);
signal count_ang : std_logic_vector (11 downto 0) := (others => '0');
begin
process (clk)
begin
if (rising_edge(clk)) then
case(state) is
when to_unsigned(first,2) => if (count_ang >= 3999) then --00
state <= to_unsigned(second,2);
count_ang <= "000000010000";
quarter_in <= "01";
Ang <= Ang - 16;
else
state <= to_unsigned(first,2);
quarter_in <= "00";
Ang <= Ang + 16;
count_ang <= count_ang + 16;
end if;
when to_unsigned(second,2) => if (count_ang >= 3999) then --01
state <= to_unsigned(third,2);
count_ang <= "000000010000";
quarter_in <= "10";
Ang <= Ang + 16;
else
state <= to_unsigned(second,2);
quarter_in <= "01";
Ang <= Ang - 16;
count_ang <= count_ang + 16;
end if;
when to_unsigned(third,2) => if (count_ang >= 3999) then
state <= to_unsigned(fourth,2);
count_ang <= "000000010000";
quarter_in <= "11";
Ang <= Ang - 16;
else
state <= to_unsigned(third,2);
quarter_in <= "10";
Ang <= Ang + 16;
count_ang <= count_ang + 16;
end if;
when to_unsigned(fourth,2) => if (count_ang >= 3999) then
state <= to_unsigned(first,2);
count_ang <= "000000010000";
quarter_in <= "00";
Ang <= Ang + 16;
else
state <= to_unsigned(fourth,2);
quarter_in <= "11";
Ang <= Ang - 16;
count_ang <= count_ang + 16;
end if;
when others => count_ang <= (others => '0');
end case;
end if;
end process;
Angle <= Ang;
end Behavioral;
And testbench (but I do not know, I'm kind of all asking in the module. and my "empty" tesbench is obtained)
ENTITY testmass IS
END testmass;
ARCHITECTURE behavior OF testmass IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT massive
PORT(
clk : IN std_logic;
reset : IN std_logic;
sinus : OUT std_logic_vector(15 downto 0)
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '0';
--Outputs
signal sinus : std_logic_vector(15 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: massive PORT MAP (
clk => clk,
reset => reset,
sinus => sinus
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
Your question isn't a Minimal, Complete and Verifiable example, it's not verifiable:
Describe the problem. "It doesn't work" is not a problem statement. Tell us what the expected behavior should be. Tell us what the exact wording of the error message is, and which line of code is producing it. Put a brief summary of the problem in the title of your question.
The output is invalid. nothing counts, but just shows 1 value.
What's the one value? When someone attempts to duplicate your problem one thing we see is assertion warnings for each evaluation of z(n) in the process in entity massive:
if (z(n) >= 0) then
The issue is subtle as basic to VHDL signals.
You assign values to signals in the process and expect them to be immediately available. That does not occur. No signal is updated while any process has yet to have been resumed and subsequently suspended in the current simulation cycle.
For each simulation time in the projected output waveform (a queue) there is only one entry. Subsequent assignments (which don't occur here) would result in only the last value being queued.
More important is that the future value isn't available in the current simulation cycle.
x, y and z can be variables declared in the process instead:
architecture foo of massive is
-- not predefined before -2008:
function to_string (inp: signed) return string is
variable image_str: string (1 to inp'length);
alias input_str: signed (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
process (clk)
type my_type is array (0 to 16) of signed (15 downto 0);
variable x: my_type;
variable y: my_type;
variable z: my_type;
constant j: my_type := ("1010111111001000", "0110011111000101",
"0011011011010100", "0001101111010101",
"0000110111111000", "0000011011111110",
"0000001101111111", "0000000111000000",
"0000000011100000", "0000000001110000",
"0000000000111000", "0000000000011100",
"0000000000001110", "0000000000000111",
"0000000000000100", "0000000000000010",
"0000000000000001");
begin
x(0) := "0000010100000110";
y(0) := "0000000000000000";
z(0) := "0000000000000000";
if rising_edge(clk) then
if reset = '0' then -- reset not driven condition was <=
report "init values:" & LF & HT &
"x(0) = " & to_string(x(0)) & LF & HT &
"y(0) = " & to_string(y(0)) & LF & HT &
"z(0) = " & to_string(z(0));
for n in 0 to 15 loop
if z(n) >= 0 then
x(n + 1) := x(n) - y(n) / 2 ** n;
y(n + 1) := y(n) + x(n) / 2 ** n;
z(n + 1) := z(n) + j(n);
else
x(n + 1) := x(n) + y(n) / 2 ** n;
y(n + 1) := y(n) - x(n) / 2 ** n;
z(n + 1) := z(n) - j(n);
end if;
report "n = " & integer'image(n) & LF & HT &
"x(" & integer'image(n + 1) & ") = " &
to_string(x(n + 1)) & LF & HT &
"y(" & integer'image(n + 1) & ") = " &
to_string(y(n + 1)) & LF & HT &
"z(" & integer'image(n + 1) & ") = " &
to_string(z(n + 1));
end loop;
sinus <= std_logic_vector(y(16));
report "sinus = " & to_string(y(16));
end if;
end if;
end process;
end architecture foo;
The report statements are added to allow the values to be output to the simulation console. Without the passage of time between successive assignments to variables values of variables in waveform have no useful meaning. There are simulators that won't report variables in waveform dumps.
And the above architecture produces:
ghdl -a testmass.vhdl
ghdl -e testmass
ghdl -r testmass
testmass.vhdl:86:17:#5ns:(report note): init values:
x(0) = 0000010100000110
y(0) = 0000000000000000
z(0) = 0000000000000000
testmass.vhdl:100:21:#5ns:(report note): n = 0
x(1) = 0000010100000110
y(1) = 0000010100000110
z(1) = 1010111111001000
testmass.vhdl:100:21:#5ns:(report note): n = 1
x(2) = 0000011110001001
y(2) = 0000001010000011
z(2) = 0100100000000011
testmass.vhdl:100:21:#5ns:(report note): n = 2
x(3) = 0000011011101001
y(3) = 0000010001100101
z(3) = 0111111011010111
testmass.vhdl:100:21:#5ns:(report note): n = 3
x(4) = 0000011001011101
y(4) = 0000010101000010
z(4) = 1001101010101100
testmass.vhdl:100:21:#5ns:(report note): n = 4
x(5) = 0000011010110001
y(5) = 0000010011011101
z(5) = 1000110010110100
testmass.vhdl:100:21:#5ns:(report note): n = 5
x(6) = 0000011011010111
y(6) = 0000010010101000
z(6) = 1000010110110110
testmass.vhdl:100:21:#5ns:(report note): n = 6
x(7) = 0000011011101001
y(7) = 0000010010001101
z(7) = 1000001000110111
testmass.vhdl:100:21:#5ns:(report note): n = 7
x(8) = 0000011011110010
y(8) = 0000010010000000
z(8) = 1000000001110111
testmass.vhdl:100:21:#5ns:(report note): n = 8
x(9) = 0000011011110110
y(9) = 0000010001111010
z(9) = 0111111110010111
testmass.vhdl:100:21:#5ns:(report note): n = 9
x(10) = 0000011011110100
y(10) = 0000010001111101
z(10) = 1000000000000111
testmass.vhdl:100:21:#5ns:(report note): n = 10
x(11) = 0000011011110101
y(11) = 0000010001111100
z(11) = 0111111111001111
testmass.vhdl:100:21:#5ns:(report note): n = 11
x(12) = 0000011011110101
y(12) = 0000010001111100
z(12) = 0111111111101011
testmass.vhdl:100:21:#5ns:(report note): n = 12
x(13) = 0000011011110101
y(13) = 0000010001111100
z(13) = 0111111111111001
testmass.vhdl:100:21:#5ns:(report note): n = 13
x(14) = 0000011011110101
y(14) = 0000010001111100
z(14) = 1000000000000000
testmass.vhdl:100:21:#5ns:(report note): n = 14
x(15) = 0000011011110101
y(15) = 0000010001111100
z(15) = 0111111111111100
testmass.vhdl:100:21:#5ns:(report note): n = 15
x(16) = 0000011011110101
y(16) = 0000010001111100
z(16) = 0111111111111110
testmass.vhdl:109:17:#5ns:(report note): sinus = 0000010001111100
Where we see the values of your array elements are changing instead of propagating 'X's through addition (or subtraction when z(n) < 0), assigned in the previous loop iteration.
Also note the reset doesn't change value in the testbench and there is an erroneous evaluation for it's value using the relational operator "<=" in the original massive process.
j is not assigned other than an initial value and is shown as a constant in the above architecture.
I'm personally somewhat skeptical you can perform these 16 chained additions or subtractions along with selecting which operation in one 10 ns clock.

How to shift std_logic_vector?

I want shift std_logic_vector.
But this code is has an error:
architecture led_main of testing is
signal clk_cnt : std_logic_vector(64 DOWNTO 0) := (others => '0');
signal led_buf : std_logic_vector( 3 downto 0 ) := "0001";
begin
process(clk)
begin
if rising_edge(clk) then
clk_cnt <= clk_cnt + 1;
if clk_cnt >= 24999999 then
led_buf <= led_buf(0) & led_buf(3 downto 1);
end if;
end if;
end process;
ground <= '0';
end led_main;
I think "0001", "0010", "0100" ...
Your shifter is OK. Actually, it's a rotator.
But your counter is to big (65 bits) and it doesn't roll over or reset to zero in a proper time. Your current design waits for 25M cycles and then shifts in every cycle from 25M to 2**64.
More over, you are using a non standard IEEE package to perform arithmetic operations (addition) on std_logic_vector. Please use type unsigned from package numeric_std.
The needed number of bits for your counter can be obtained by a log2 function like this:
function log2ceil(arg : positive) return natural is
variable tmp : positive;
variable log : natural;
begin
if arg = 1 then return 0; end if;
tmp := 1;
log := 0;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
Source: https://github.com/VLSI-EDA/PoC/blob/master/src/common/utils.vhdl
Full code rewrite:
use IEEE.numeric_std.all;
architecture led_main of testing is
constant CNT_MAX : positive := 25000000;
signal clk_cnt : unsigned(log2ceil(CNT_MAX) - 1 downto 0) := (others => '0');
signal led_buf : std_logic_vector( 3 downto 0 ) := "0001";
begin
process(clk)
begin
if rising_edge(clk) then
clk_cnt <= clk_cnt + 1;
if clk_cnt = (CNT_MAX - 1) then
clk_cnt <= (others => '0');
led_buf <= led_buf(0) & led_buf(3 downto 1);
end if;
end if;
end process;
end led_main;
```

Need advice for my vhdl code

I am working on my college project a digital clock on altera board. the problem i am facing is my hours goes to 29 instead of 24! I am using integer type for my hours right digit ranging 0 to 9; i got if statement that when my hours left digit is 2 and hours right digit is 3 i want my second, minutes and hours 00:00:00.. But its not implementing why? Need some advice... Thanks
here is my code :
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 master is
port(
clk : in std_logic;
hrs_lft : out std_logic_vector(1 downto 0 );
hrs_rght : out std_logic_vector(3 downto 0 );
min_lft : out std_logic_vector(2 downto 0 );
min_rght : out std_logic_vector(3 downto 0 );
second_lft: out std_logic_vector(2 downto 0);
second_rght : out std_logic_vector( 3 downto 0)
);
end master;
architecture bhv of master is
signal second_lft_int : integer range 0 to 5;
signal second_rght_int : integer range 0 to 9;
signal min_lft_int : integer range 0 to 5;
signal min_rght_int : integer range 0 to 9;
signal hrs_lft_int : integer range 0 to 2;
signal hrs_rght_int : integer range 0 to 9;
begin
process(clk)
begin
if (rising_edge(clk)) then
second_rght_int <= second_rght_int + 1;
if second_rght_int = 9 then
second_lft_int <= second_lft_int + 1;
second_rght_int <= 0;
if second_lft_int = 5 then
second_lft_int <= 0;
min_rght_int <= min_rght_int + 1;
if min_rght_int = 9 then
min_lft_int <= min_lft_int + 1;
min_rght_int <= 0;
if min_rght_int = 5 then
hrs_rght_int <= hrs_rght_int + 1;
min_rght_int <= 0;
if hrs_rght_int = 9 then
hrs_lft_int <= hrs_lft_int + 1;
if (hrs_rght_int = 3 and hrs_lft_int = 2) then
hrs_lft_int <= 0;
hrs_rght_int <= 0;
min_lft_int <= 0;
min_rght_int <= 0;
second_rght_int <= 0;
second_lft_int <= 0;
end if ;
end if;
end if;
end if;
end if;
end if;
end if;
end process;
second_rght<= std_logic_vector(to_unsigned(second_rght_int,second_rght'length));
second_lft<=std_logic_vector(to_unsigned(second_lft_int,second_lft'length));
min_rght<= std_logic_vector(to_unsigned(min_rght_int,min_rght 'length));
min_lft <= std_logic_vector(to_unsigned(min_lft_int,min_lft'length));
hrs_rght<= std_logic_vector(to_unsigned(hrs_rght_int,hrs_rght 'length));
hrs_lft <= std_logic_vector(to_unsigned(hrs_lft_int,hrs_lft'length));
end bhv;
You process didn't look right, so I wrote it de novo:
process (clk)
begin
if rising_edge(clk) then
if second_rght_int = 9 then
second_rght_int <= 0;
if second_lft_int = 5 then
second_lft_int <= 0;
if min_rght_int = 9 then
min_rght_int <= 0;
if min_lft_int = 5 then
min_lft_int <= 0;
if (hrs_lft_int = 2 and hrs_rght_int = 4)
or hrs_rght_int = 9 then
hrs_rght_int <= 0;
if hrs_lft_int = 2 then
hrs_lft_int <= 0;
else
hrs_lft_int <= hrs_lft_int + 1;
end if;
else
hrs_rght_int <= hrs_rght_int + 1;
end if;
else
min_lft_int <= min_lft_int + 1;
end if;
else
min_rght_int <= min_rght_int + 1;
end if;
else
second_lft_int <= second_lft_int + 1;
end if;
else
second_rght_int <= second_rght_int + 1;
end if;
end if;
end process;
And that gives:
In VHDL "+" for integer is defined as an operation on a type integer and not a modular integer, you have to check for the boundary condition yourself.
You might also notice I set the clk rate to 1 ps in simulation. A bit excessive but I wanted to search for roll over events.
A testbench can consist of as little as a direct entity instantiation with a single port association for the clk. (The waveforms are from the Device Under Test).

My function does not return a value, and I do not understand why? VHDL

Part of code in VHDL. Workspace ISE.
My function does not return a value, and I do not understand why
Note that appears to me in ISE is "function 'con_integer14' does not always return a value."
The Function is:
function con_integer14 (vNumberSTD : std_logic_vector(14 downto 0)) return integer is
variable vCounter : integer range 0 to 16 := 0;
variable vNumberINT : integer range 0 to 16384 := 0;
begin
if (vCounter = 0) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif ((vCounter >= 1)or(vCounter < 14)) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif (vCounter = 14) then
if ((vNumberSTD(vCounter)) = '1') then
vNumberINT := (vNumberINT+(2**vCounter));
elsif ((vNumberSTD(vCounter)) = '0') then
vNumberINT := vNumberINT;
end if;
vCounter := (vCounter+1);
elsif (vCounter = 15) then
return vNumberINT;
vCounter := 0;
elsif (vCounter > 15) then
vNumberINT := 0;
vCounter := 0;
end if;
end function con_integer14;
Please help me, thank you :)
I'd go a step further and tell you your function never returns a value. I took the liberty of removing the superfluous parentheses and then took a look at the function's structure.
You're going to execute the first if statement and fail to return a value - there is no return statement in reach.
Add a test bench:
library ieee;
use ieee.std_logic_1164.all;
use work.foo.all;
entity fum is
end entity;
architecture fie of fum is
signal vNumberINT: integer range 0 to 16384;
signal vNumberSTD: std_logic_vector(14 downto 0) := "011001110111100";
begin
CALL:
process
begin
wait for 1 ns;
vNumberINT <= con_integer14(VNumberSTD);
wait for 1 ns;
wait;
end process;
end architecture;
Analyze it, elaborate it and run it:
ghdl -a something.vhdl
david_koontz#Macbook: ghdl -e fum
david_koontz#Macbook: ghdl -r fum
./fum:error: missing return in
function at something.vhdl:10
./fum:error: simulation failed
ghdl: compilation error
And we get it to tell us there's a missing return for the first if statement, that a call to it won't return a value.
To make a conversion routine that converts your std_logic_vector to integer you should use a loop statement with an iteration scheme based on the index range of the input vNumberSTD.
When the loop statement is done 'calculating' vNumberINT return VNumberINT.
Note that if you don't do anything specific about meta values for elements of vNumberSTD they will be treated as '0'.
And with some modifications:
library ieee;
use ieee.std_logic_1164.all;
package foo is
function con_integer14 (vNumberSTD: std_logic_vector(14 downto 0)) return integer;
function conv_slv_int (input: std_logic_vector) return natural;
end package;
package body foo is
function con_integer14 (vNumberSTD : std_logic_vector(14 downto 0)) return integer is
-- variable vCounter: integer range 0 to 16 := 0;
-- variable vNumberINT: integer range 0 to 16384 := 0;
variable vNumberINT: integer range 0 to 32767 := 0;
begin
-- if vCounter = 0 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter >= 1 or vCounter < 14 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter = 14 then
-- if vNumberSTD(vCounter) = '1' then
-- vNumberINT := vNumberINT + 2 ** vCounter;
-- elsif vNumberSTD(vCounter) = '0' then
-- vNumberINT := vNumberINT;
-- end if;
-- vCounter := vCounter + 1;
-- elsif vCounter = 15 then
-- return vNumberINT;
-- vCounter := 0;
-- elsif vCounter > 15 then
-- vNumberINT := 0;
-- vCounter := 0;
-- end if;
for i in vNumberSTD'range loop
report "vNumberSTD(" & integer'image(i) & ") = " & std_ulogic'image(vNumberSTD(i));
if vNumberSTD(i) = '1' then
vNumberINT := vNumberINT + 2 ** i;
report "vNumberINT = " & integer'image(vNumberINT);
end if;
end loop;
return vNumberINT;
end function con_integer14;
function conv_slv_int (input: std_logic_vector) return natural is
alias inp: std_logic_vector (input'LENGTH - 1 downto 0) is input;
variable int_equiv: natural range 0 to 2 ** input'LENGTH - 1 := 0;
begin
if Is_X(input) then -- announce meta values - interpreted as '0's
report "conv_slv_int input contains meta value";
end if;
for i in inp'RANGE loop
if To_bit(inp(i)) = '1' then -- convert 'H' to '1', 'L' to '0'
int_equiv := int_equiv + 2 ** i;
end if;
end loop;
return int_equiv;
end function;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use work.foo.all;
entity fum is
end entity;
architecture fie of fum is
signal vNumberINT: integer range 0 to 32767;
signal vNumberSTD: std_logic_vector(14 downto 0) := "HX1001110111100";
begin
CALL:
process
begin
wait for 1 ns;
vNumberINT <= con_integer14(VNumberSTD);
wait for 1 ns;
report "vNumberINT = " &integer'image(vNumberINT);
report "conv_slv_int returns " & integer'image(conv_slv_int(vNumberSTD));
wait;
end process;
end architecture;
Notice I corrected the range of vNumberINT, it can be based on the argument to function con_integer14.
You can remove the report statements in the function. I used them to illustrate the function loop.
I added a second function showing conversion of any length std_logic_vector that will fit in a natural range. It will generate an error when called (function local variables elaborated) if the length of the input won't fit in an integer.
The second function also detects meta value inputs and converts 'H' to '1' and 'L' to '0' for each element of the input.
The use of the alias inp for he input allows us to always deal with the input as natural range, caring about length instead of left and right bounds.
When running the new test bench:
something.vhdl:45:13:#1ns:(report note): vNumberSTD(14) = 'H'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(13) = 'X'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(12) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4096
something.vhdl:45:13:#1ns:(report note): vNumberSTD(11) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(10) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(9) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4608
something.vhdl:45:13:#1ns:(report note): vNumberSTD(8) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4864
something.vhdl:45:13:#1ns:(report note): vNumberSTD(7) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 4992
something.vhdl:45:13:#1ns:(report note): vNumberSTD(6) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(5) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5024
something.vhdl:45:13:#1ns:(report note): vNumberSTD(4) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5040
something.vhdl:45:13:#1ns:(report note): vNumberSTD(3) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5048
something.vhdl:45:13:#1ns:(report note): vNumberSTD(2) = '1'
something.vhdl:48:17:#1ns:(report note): vNumberINT = 5052
something.vhdl:45:13:#1ns:(report note): vNumberSTD(1) = '0'
something.vhdl:45:13:#1ns:(report note): vNumberSTD(0) = '0'
something.vhdl:87:9:#2ns:(report note): vNumberINT = 5052
something.vhdl:59:17:#2ns:(report note): conv_slv_int input contains meta value
something.vhdl:88:9:#2ns:(report note): conv_slv_int returns 21436
We see that you can pass std_logic_vector to both that only conv_slt_int will interpret correctly.
Save yourself some time and use the built-in functions. If you just use numeric_std, then you can do the following:
library IEEE ;
use IEEE.numeric_std.all ;
...
signal Y_int : integer ;
signal A_slv15 : std_logic_vector(14 downto 0) ;
...
Y_int <= to_integer( unsigned( A_slv15) ) ;
If you also include numeric_std_unsigned (warning this is VHDL-2008 and may not yet be supported by your tools - try it and report a bug if it does not work) -
library IEEE ;
use IEEE.numeric_std.all ;
use IEEE.numeric_std_unsigned.all ;
...
signal Y_int : integer ;
signal A_slv15 : std_logic_vector(14 downto 0) ;
...
Y_int <= to_integer( A_slv15) ;
Like what has already been mentioned, you did not cover all possible conditions. It's always good to have a default assignment, either by having an "else" clause, or have a default before the if-elsif statement:
function con_integer14 (...) return integer is
begin
vNumberINT := -1;
if (vCounter = 0) then ...
elsif ...
elsif ... then return vNumberINT;
end if;
return vNumberINT;
end function con_integer14;
or alternatively,
function con_integer14 (...) return integer is
begin
if (vCounter = 0) then ...
elsif ...
elsif ... then return vNumberINT;
else
return vNumberINT;
end if;
end function con_integer14;
I personally prefer the first option, because some tools still complain that not all paths are covered for the second option, though in fact all paths were covered. Anyway, this is just a matter of style.
It seems to me that you are only returning a value when vCounter=15:
elsif (vCounter = 15) then return vNumberINT; ...
and this condition is not always met by your testbench (perhaps never met as analysed by David).
-daniel

Infinite HDL synthesis

Whenver I try to synthesize my code, it is caught in an infinite loop i.e it is stuck at HDL SYNTHESIS. I have not used any loops. But problem persists.
----------------------------------------------------------------------------------
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 mat is
port(
start,clck,start4,add4,check4,delete3,start3,add3,final3,load,load3,load4,search3:in std_logic;
data1,data2,newitem:in std_logic_vector(0 to 8);
completeload4tocontroller,completeadd3,search3cmplt,completeload3tocontroller,
completeloadtocontroller,discerncomplete,complete4add,completedel3,step4comptocntrl:out bit;
data4,data6:out std_logic_vector(0 to 15));
end mat;
architecture Behavioral of mat is
type positiveelem is array (0 to 255) of std_logic_vector(0 to 18);
type negativeelem is array (0 to 255) of std_logic_vector(0 to 18);
signal poselem:positiveelem ;
signal negelem:negativeelem ;
signal pospointer:integer range 0 to 255:=0;
signal negpointer:integer range 0 to 255:=0;
signal jpst:integer range 0 to 255 := 0;
signal jnst:integer range 0 to 255 := 0;
signal jp1st:integer range 0 to 255 := 0;
signal jp2st:integer range 0 to 255 := 0;
signal jn4st:integer range 0 to 255 := 0;
signal jp4st:integer range 0 to 255 := 0;
signal j3pntr:integer range 0 to 255 := 0;
signal j3npntr:integer range 0 to 255 := 0;
signal j3ptr:integer range 0 to 255 := 0;
type list12 is array(0 to 65535) of integer range 0 to 31;
signal clist:list12;
signal limitcount:integer range 0 to 255 :=0;
signal flag1:std_logic :='0';
signal position:integer range 0 to 255;
begin
P1:process(load,load4,clck,load3,check4,start,add4,start4,start3,delete3,add3)
variable temp4:std_logic_vector(0 to 15);
variable temp5:std_logic_vector(0 to 15);
variable temp1:std_logic_vector(0 to 15);
variable tempp3:std_logic_vector(0 to 15);
begin
if(rising_edge(clck))then
if(load='1')then
poselem(pospointer) <= data1;
negelem(negpointer) <= data2;
pospointer <= pospointer + 1;
negpointer <= negpointer + 1;
limitcount <= limitcount + 1;
if(limitcount = 10)then
completeloadtocontroller <= '1';
end if;
elsif((load4 = '1') and (load ='0'))then
poselem(pospointer) <= newitem;
pospointer <= pospointer + 1;
completeload4tocontroller <= '1';
elsif((load3 = '1') and (load = '0'))then
negelem(negpointer) <= newitem;
negpointer <= negpointer + 1;
completeload3tocontroller <= '1';
elsif(start = '1')then
if((jpst <= pospointer) and (jnst <= negpointer))then
temp4 := poselem(jpst)(0 to 15) xor negelem(jnst)(0 to 15);
clist(conv_integer(temp4)) <= clist(conv_integer(temp4)) + 1;
if((jnst = (negpointer - 1)) and (jpst < (pospointer - 1)))then
jnst <= 0;
jpst <= jpst + 1;
elsif(jnst < (negpointer - 1) and (jpst < (pospointer - 1)))then
jnst <= jnst + 1;
elsif(jpst = (pospointer - 1) and (jnst < (negpointer - 1)))then
jnst <= jnst + 1;
elsif((jp1st = pospointer) and (jp2st = pospointer) and
(jpst = pospointer) and (jnst = negpointer))then
discerncomplete <= '1';
end if;
end if;
elsif(start4 = '1')then
if(add4 = '1')then
temp1 := newitem(0 to 15) xor negelem(jn4st)(0 to 15);
if(clist(conv_integer(temp1)) = 0)then
data4 <= temp1;
end if;
clist(conv_integer(temp1)) <= clist(conv_integer(temp1)) + 1;
if(jn4st < (negpointer - 1))then
jn4st <= jn4st + 1;
elsif((jp4st = pospointer - 1) and (jn4st = negpointer - 1))then
complete4add <= '1';
end if;
end if;
elsif(start3 = '1')then
if(delete3 = '1')then
if((poselem(position)(0 to 15) /= poselem(j3pntr))
and (poselem(position)(16 to 18) /= poselem(j3pntr)(16 to 18)))then
tempp3 := poselem(position)(0 to 15) xor poselem(j3pntr)(0 to 15);
if(clist(conv_integer(tempp3)) = 1)then
data6 <= tempp3;
end if;
if(clist(conv_integer(tempp3)) /= 0)then
clist(conv_integer(tempp3)) <= clist(conv_integer(tempp3)) - 1;
end if;
if(j3pntr < (pospointer - 1))then
j3pntr <= j3pntr + 1;
elsif((j3pntr = pospointer - 1) and (j3npntr = negpointer - 1))then
completedel3 <= '1';
poselem(position) <= "0000000000000000000";
end if;
end if;
elsif(search3 = '1')then
if((poselem(position)(16 to 18) /= newitem(16 to 18))
and (poselem(position)(0 to 15) = newitem(0 to 15)))then
flag1 <= '1';
end if;
if((position < pospointer) and (flag1 = '0'))then
position <= position + 1;
elsif(flag1 = '1')then
search3cmplt <= '1';
end if;
elsif(add3 = '1')then
tempp3 := newitem(0 to 15) xor poselem(j3ptr)(0 to 15);
if(clist(conv_integer(tempp3)) = 0)then
data4 <= tempp3;
end if;
clist(conv_integer(tempp3)) <= clist(conv_integer(tempp3)) + 1;
if(j3ptr < pospointer - 1 and (j3ptr = (position - 1)))then
j3ptr <= j3ptr + 2;
elsif(j3ptr = (pospointer - 1))then
completeadd3 <= '1';
else
j3ptr <= j3ptr + 1;
end if;
end if;
end if;
end if;
if(falling_edge(clck))then
if(start = '1')then
if((jp1st /= pospointer) and (jp2st /= pospointer) and (poselem(jp1st)(16 to 18) /= poselem(jp2st)(16 to 18))
and (poselem(jp1st)(0 to 15) /= poselem(jp2st)(0 to 15))) then
temp5 := poselem(jp1st)(0 to 15) xor poselem(jp2st)(0 to 15);
clist(conv_integer(temp5)) <= clist(conv_integer(temp5)) + 1;
end if;
if(jp1st < (pospointer - 1) and jp2st = (pospointer-1))then
jp1st <= jp1st + 1;
jp2st <= 0;
elsif(jp1st = (pospointer - 1) and jp2st < (pospointer-1))then
jp2st <= jp2st + 1;
elsif(jp1st < (pospointer - 1) and jp2st < (pospointer-1))then
jp2st <= jp2st + 1;
elsif((jp1st = pospointer) and (jp2st = pospointer) and (jpst = pospointer) and (jnst = negpointer))then
discerncomplete <= '1';
end if;
elsif(start4 = '1')then
if(add4 = '1')then
if((poselem(jp4st)(0 to 15) /= "0000000000000000"))then
if(poselem(jp4st)(0 to 15) /= newitem(0 to 15))
and (poselem(jp4st)(16 to 18) /= newitem(16 to 18)))then
temp1 := newitem(0 to 15) xor poselem(jp4st)(0 to 15);
if(clist(conv_integer(temp1)) = 0)then
data4 <= temp1;
end if;
clist(conv_integer(temp1)) <= clist(conv_integer(temp1)) + 1;
end if;
if(jp4st < (pospointer - 1))then
jp4st <= jp4st + 1;
elsif((jp4st = pospointer - 1) and (jn4st = negpointer - 1))then
complete4add <= '1';
end if;
end if;
elsif(start3 = '1')then
if(delete3 = '1')then
tempp3 := newitem(0 to 15) xor negelem(j3npntr)(0 to 15);
if(clist(conv_integer(tempp3)) = 1)then
data6 <= tempp3;
end if;
if(clist(conv_integer(tempp3)) = 0)then
clist(conv_integer(tempp3)) <= clist(conv_integer(tempp3)) - 1;
end if;
if(j3npntr < negpointer - 1 )then
j3npntr <= j3npntr + 1;
elsif((j3pntr = pospointer - 1) and (j3npntr = negpointer - 1))then
completedel3 <= '1';
poselem(position) <= "0000000000000000000";
end if;
end if;
end if;
end if;
end process P1;
end Behavioral;
My comments address some of these issues, but I thought I'd type them up as an answer to add a little more detail and clarification.
Synthesis software getting stuck at a certain step and locking up has little to nothing to do with any particular language structure you're using, and probably means the software is having trouble parsing your code. While I would call this a bug in the software, you can probably get around it by looking for syntax errors (using another compiler, like ModelSim or something, might also help, if you have access). For instance, you appear to have an if-loop you're not closing somewhere under if falling_edge(clck). You also have a missing ( on the lines:
if(poselem(jp4st)(0 to 15) /= newitem(0 to 15))
and (poselem(jp4st)(16 to 18) /= newitem(16 to 18)))then
And you're assigning data1, a 9-bit vector, to poselem(pospointer), a 19-bit vector (and other similar assignments). Check your port and signal definitions.

Resources