Non-static loop limit exceeded in Xilinx - vhdl

I have this code in VHDL:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.NUMERIC_STD.all;
entity Div is
Port ( Ain : in STD_LOGIC_VECTOR (6 downto 0);
Bin : in STD_LOGIC_VECTOR (6 downto 0);
Q : out STD_LOGIC_VECTOR (6 downto 0);
R : out STD_LOGIC_VECTOR (6 downto 0)
Rez : out std_logic_vector(13 downto 0));
end Div;
architecture Behavioral of Div is
begin
Proc1 : process (Ain, Bin) is
variable cnt : std_logic_vector(6 downto 0);
variable Atemp : std_logic_vector(6 downto 0);
begin
if (Ain < Bin) then
cnt := "0000000";
Atemp := Ain;
elsif (Ain = Bin) then
cnt := "0000001";
Atemp := (others => '0');
elsif (Ain > Bin) then
cnt := "0000001";
Atemp := (Ain - Bin);
while (Atemp >= Bin) loop
Atemp := (Atemp - Bin);
cnt := cnt + "0000001";
end loop;
end if;
Q <= cnt;
R <= Atemp;
Rez <= "0000000" & cnt;
end process Proc1;
end Behavioral;
and when I synt in Xilinx, I have this error message
Non-static loop limit exceeded
at that while loop.

When VHDL is synthesised, the synth tool needs to unwrap your loop to create a circuit. Because it has no idea what the Atemp or Bin are, other than they are 7 bit integers, it has to assume that Atemp and Bin could be static forever, and hence the loop never unrolls.
The problem with your code is that you used a while loop. Your HDL needs to describe a circuit, and a while loop generally doesn't. Instead of using a while loop, consider using a clock in your process and incrementing the counter by 1 on each clock. Circuits have no knowledge of time without a clock.

Related

Unexpected function output when function parameter is negated

I have a priority encoding function that returns a vector containing a 1 at the position where the first 1 is found in the input vector. The function works as expected, unless I try to negate the input vector. Here's an example that demonstrates the unexpected behavior:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
entity tb IS
end tb;
architecture run of tb is
constant N : natural := 5;
function get_first_one_in_vec (vec_in: std_logic_vector) return std_logic_vector is
variable ret: std_logic_vector(vec_in'high downto vec_in'low);
begin
ret := (others => '0');
for i in vec_in'low to vec_in'high loop
if vec_in(i)='1' then
ret(i) := '1';
exit;
end if;
end loop;
return ret;
end get_first_one_in_vec;
signal a : std_logic_vector(N-1 downto 0);
signal abar : std_logic_vector(N-1 downto 0);
signal first_a : std_logic_vector(N-1 downto 0);
signal first_nota : std_logic_vector(N-1 downto 0);
signal first_abar : std_logic_vector(N-1 downto 0);
begin
process
begin
a <= "10100";
wait for 10 ns;
a <= "01011";
wait for 10 ns;
wait;
end process;
abar <= not(a);
first_a <= get_first_one_in_vec(a);
first_nota <= get_first_one_in_vec(not(a));
first_abar <= get_first_one_in_vec(abar);
end run;
To my understanding, first_nota should be the same as first_abar. However, my simulator (ModelSim - Intel FPGA Starter Edition 10.5b, rev. 2016.10) thinks otherwise, as you can see here:
What am I missing here?
This works OK:
function get_first_one_in_vec (vec_in: std_logic_vector) return std_logic_vector is
variable ret: std_logic_vector(vec_in'length downto 1);
variable inp: std_logic_vector(vec_in'length downto 1) := vec_in;
begin
ret := (others => '0');
for i in inp'right to inp'left loop
if inp(i)='1' then
ret(i) := '1';
exit;
end if;
end loop;
return ret;
end get_first_one_in_vec;
https://www.edaplayground.com/x/3zP_
Why does yours not work? Well, when you call your function with the not operator* as part of the expression:
first_nota <= get_first_one_in_vec(not a);
the numbering of the input to the function is changed to 1 to by the not operator. Why? Here is the code for the not operator and you can see why:
-------------------------------------------------------------------
-- not
-------------------------------------------------------------------
FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector IS
-- pragma built_in SYN_NOT
-- pragma subpgm_id 204
--synopsys synthesis_off
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X');
--synopsys synthesis_on
BEGIN
--synopsys synthesis_off
FOR i IN result'RANGE LOOP
result(i) := not_table( lv(i) );
END LOOP;
RETURN result;
--synopsys synthesis_on
END;
---------------------------------------------------------------------
Anyway, this breaks your code (which starts scanning from the other end of the word).
One way of making function agnostic to the ordering of the numbering of its input is to normalise the inputs like this:
variable inp: std_logic_vector(vec_in'length downto 1) := vec_in;
Once you have done this, you're in control. So, instead of loops from 'high downto 'low, we can be more explicit and loop from 'right to 'left:
for i in inp'right to inp'left loop
not is an operator not a function. You don't need the brackets.

Count "01" sequences in input signal

My goal is to count the number of "01" sequences in iaI array.
I tried following code but it does not work as I assumed.
entity prob35 is
port (
iaI : in std_logic_vector (11 downto 0);
oaO : out std_logic_vector (2 downto 0)
);
end prob35;
architecture Behavioral of prob35 is
signal counter : integer := 0;
begin
process(iaI)
begin
for i in 1 to 11 loop
if (iaI(i-1)='1' and iaI(i)='0') then
counter<=counter+1;
end if;
end loop;
oaO<=conv_std_logic_vector(counter,oaO'length);
end process;
end Behavioral;
There is significant difference between signals and variables in vhdl. While the variable takes the value of assignment immediately, signal in sequential code (like process) are used to create flip-flops, which inherently do not immediately take the value of their assignment. You should use variable to achieve desired functionality here.
entity prob35 is
port (
iaI : in std_logic_vector (11 downto 0);
oaO : out std_logic_vector (2 downto 0)
);
end prob35;
architecture Behavioral of prob35 is
begin
process(iaI)
variable counter : unsigned(2 downto 0) := "000";
begin
counter := "000";
for i in 1 to 11 loop
if (iaI(i-1)='1' and iaI(i)='0') then
counter := counter + 1;
end if;
end loop;
oaO <= std_logic_vector(counter);
end process;
end Behavioral;

VHDL code to find square root of number?

Is there is any in built function or any library that can be included in the design to find square root of a number?
Restoring square root algorithm is easy to implement on fpga, wikipedia has an example.
FPGA vendors should have cores available, it hides inside the general purpose CORDIC core on Xilinx. They also have square root cores for floating points, if that's what you need.
For non-synthesizable (simulation/test-bench only) operation, square root for real can be done with:
y := math_real.sqrt(x)
For synthesizable operation, see answer from Jonathan Drolet.
This one worked for me.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_unsigned.ALL;
entity squart is port(
clock : in std_logic;
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(3 downto 0)); end squart;
architecture behaviour of squart is
signal part_done : std_logic := '0';
signal part_count : integer := 3;
signal result : std_logic_vector(4 downto 0) := "00000";
signal partialq : std_logic_vector(5 downto 0) := "000000";
begin
part_done_1: process(clock, data_in, part_done)
begin
if(clock'event and clock='1')then
if(part_done='0')then
if(part_count>=0)then
partialq(1 downto 0) <= data_in((part_count*2)+ 1 downto part_count*2);
part_done <= '1'; else
data_out <= result(3 downto 0);
end if;
part_count <= part_count - 1;
elsif(part_done='1')then
if((result(3 downto 0) & "01") <= partialq)then
result <= result(3 downto 0) & '1';
partialq(5 downto 2) <= partialq(3 downto 0) - (result(1 downto 0)&"01");
else
result <= result(3 downto 0) & '0';
partialq(5 downto 2) <= partialq(3 downto 0);
end if;
part_done <= '0';
end if;
end if;
end process;
end behaviour;
Check this one:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity SQRT is
Generic ( b : natural range 4 to 32 := 16 );
Port ( value : in STD_LOGIC_VECTOR (15 downto 0);
result : out STD_LOGIC_VECTOR (7 downto 0));
end SQRT;
architecture Behave of SQRT is
begin
process (value)
variable vop : unsigned(b-1 downto 0);
variable vres : unsigned(b-1 downto 0);
variable vone : unsigned(b-1 downto 0);
begin
vone := to_unsigned(2**(b-2),b);
vop := unsigned(value);
vres := (others=>'0');
while (vone /= 0) loop
if (vop >= vres+vone) then
vop := vop - (vres+vone);
vres := vres/2 + vone;
else
vres := vres/2;
end if;
vone := vone/4;
end loop;
result <= std_logic_vector(vres(result'range));
end process;
end;

VHDL code runs but timing diagram shows nothing

I am trying to implement a cache memory 16 * 37 in VHDL in DesignWorks 5. The code is given below.
The code runs but when i change values from IO panel or even simulate anyway, the timing diagram shows nothing and basically the code is not running for some reason. Any suggestions would be really helpful.
Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity Cache is
port(cs, r, clr : in std_logic;
data : in std_logic_vector(31 downto 0);
addr : in std_logic_vector(7 downto 0);
cline : out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v : out std_logic);
end Cache;
architecture behav of Cache is
type RAM is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process is
variable M : RAM;
variable locn : natural;
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(addr);
if r = '1' then
temp_val := M(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
M(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
end if;
end if;
if clr ='1' then
locn := 0;
while(locn<16) loop
M(locn) := X"000000000" + "0";
locn:=locn+1;
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
wait on cs;
end process;
end behav;
This line:
M(locn) := X"000000000" + "0";
appears incorrect.
M is your ram array type with an element length of 37. A 36 bit zero added to zero is still 36 bits (it doesn't look like you reached this statement, it would be a run time error).
To make a length 37 vector of '0' values use `(others => '0').
You can also use a for loop for the ram clear, you need to not use an index of 16, it's out of range, which tells us you didn't reach the clear either.
I think you ought to show us your stimulus otherwise your problems can't be reproduced.
Your missing data and addr as sensitivity elements (and ya, you case cs surrounds, but you want to build a hardware model here).
Switch to a sensitivity list (cs, data, addr).
locn is an unconstrained natural and should have a range matching the array type ram (0 to 15). Notice your while loop reaches 16. Really, use a for loop (shown below). The reason for constraining locn is to prevent a bound error when accessing ram(locn).
Note for converting addr to a natural (locn) you need to AND mask addr with a length four run of '1's to prevent a range error for normal ram operations.
The package numeric_std is an affectation, it's easier than passing a couple of command line options to ghdl (ieee=synopsys -fexplict) during analysis and elaboration.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cache is
port (
cs, r, clr: in std_logic;
data: in std_logic_vector(31 downto 0);
addr: in std_logic_vector(7 downto 0);
cline: out std_logic_vector(31 downto 0);
ctag: out std_logic_vector(3 downto 0);
v: out std_logic
);
end entity;
architecture behav of cache is
type ram is array (0 to 15) of std_logic_vector(36 downto 0);
begin
process (cs, data, addr)
variable m : ram;
variable locn : natural range (ram'range);
variable temp_val : std_logic_vector(36 downto 0);
variable cline_val : std_logic_vector(31 downto 0);
variable ctag_val : std_logic_vector(3 downto 0);
variable v_val : std_logic;
begin
if cs = '1' then
locn := to_integer(unsigned(addr and x"0F"));
if r = '1' then
temp_val := m(locn);
cline_val := temp_val(31 downto 0);
ctag_val := temp_val(35 downto 32);
v_val := temp_val(36);
else
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
m(locn) := temp_val;
v_val := 'Z';
ctag_val:= "ZZZZ";
cline_val:= (others => 'Z');
end if;
end if;
if clr ='1' then
for i in ram'range loop
m(i) := (others => '0');
end loop;
end if;
cline <= cline_val;
ctag <= ctag_val;
v <= v_val;
end process;
end architecture;
This code analyzes and elaborates, you could have an error somewhere I didn't mention, and bound (range) errors show up at run time in assignments (expressions can not care).
And one final bit:
temp_val(31 downto 0) := data;
temp_val(35 downto 32) := addr(3 downto 0);
temp_val(36) := '1';
can be expressed:
temp_val:= '1' & addr(3 downto 0) & data;
As well as:
locn := to_integer(addr);
expressed as:
locn := to_integer(addr(3 downto 0));
You can also create an AND mask with a length defined algorithmically from the ram'range should you set the ram size with a generic.
And without seeing your stimulus there are several places that could cause run time errors. Check your console output.

What's wrong with this signal assignment?

When I compile with Xilinx 9.1i, It tells me:
"Line 91. Type of Tens is incompatible with type of tensOut."
"Line 92. Type of Ones is incompatible with type of onesOut."
But both are std_logic_vector (7 downto 0)
Here's the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity BNG is
Port ( Clk : in STD_LOGIC;
E : in STD_LOGIC;
BNRand : in STD_LOGIC_VECTOR (6 downto 0);
Letter : out STD_LOGIC_VECTOR (7 downto 0);
Tens : out STD_LOGIC_VECTOR (7 downto 0);
Ones : out STD_LOGIC_VECTOR (7 downto 0));
end BNG;
architecture Behavioral of BNG is
type states is (neutral, gen);
signal current_state, next_state : states;
begin
state_register: process(Clk)
begin
if rising_edge(Clk) then
current_state <= next_state;
end if;
end process;
next_logic: process(current_state)
begin
case current_state is
when neutral => if E = '1' then next_state <= gen; else next_state <= neutral; end if;
when gen => next_state <= neutral;
end case;
end process next_logic;
logic: process(current_state)
variable letterOut, tensOut, onesOut : std_logic_vector (7 downto 0);
variable tens, ones : integer range 0 to 9;
variable input : integer;
constant B : std_logic_vector (7 downto 0) := "01000010";
constant I : std_logic_vector (7 downto 0) := "01001001";
constant N : std_logic_vector (7 downto 0) := "01001110";
constant G : std_logic_vector (7 downto 0) := "01000111";
constant O : std_logic_vector (7 downto 0) := "01001111";
constant zero : std_logic_vector (7 downto 0) := "00110000";
begin
if current_state = gen then
input := conv_integer( unsigned(BNRand) );
tens := input / 10;
ones := input mod 10;
if (input > 0) and (input < 16) then
letterOut := B;
elsif (input > 15) and (input < 31) then
letterOut := I;
elsif (input > 30) and (input < 46) then
letterOut := N;
elsif (input > 45) and (input < 61) then
letterOut := G;
elsif (input > 60) and (input < 76) then
letterOut := O;
end if;
tensOut := zero + std_logic_vector( conv_unsigned(tens, 8) );
onesOut := zero + std_logic_vector( conv_unsigned(ones, 8) );
end if;
Letter <= letterOut;
Tens <= tensOut;
Ones <= onesOut;
end process logic;
end Behavioral;
In VHDL the identifiers are not case sensitive. The identifiers Tens and Ones are declared as port, while identifiers tens and ones are declared as variables in the process. The assign with Tens <= tensOut; and Ones <= onesOut; inside the process thus sees the variables tens and ones, and not the ports.
A useful coding style is to name variables with a ending _v, thus getting tens_v and ones_v, which also helps to remember the kind of assign as <= for signals and := for variables.

Resources