Clogb2 () function generated by vivado cannot synthesize with limit loop error
I am trying to create an AXI_master peripheral with vivado. I used the axi peripheral generator in the vivado menu and modified the generated VHDL code.
In the vhdl code, there is a clogb2 function declared with the following code:
function clogb2 (bit_depth : integer) return integer is
variable depth : integer := bit_depth;
variable count : integer := 1;
begin
for clogb2 in 1 to bit_depth loop -- Works for up to 32 bit integers
if (bit_depth <= 2) then
count := 1;
else
if(depth <= 1) then
count := count;
else
depth := depth / 2;
count := count + 1;
end if;
end if;
end loop;
return(count);
end;
This works in simulation (GHDL) but fails with error:
[Synth 8-403] loop limit (65538) exceeded
I tried to increase the loop limit in vivado with the following tcl command:
set_param synth.elaboration.rodinMoreOptions "rt::set_parameter max_loop_limit <X>"
As explained here , but vivado is synthesized with infinite time and never ends. Do you know how to fix this problem?
source to share
You can also try another way. Although floating point is not supported in logic (although support is growing), it is allowed for internal computation, etc. (Xilinx and Altera / Intel at least).
Try the following:
use ieee.math_real.all;
function ceillog2(input : positive) return natural is
begin
return integer(ceil(log2(real(input))));
end function;
source to share
Finally I found a solution that works, rewriting the function with a larger case:
function clogb2 (bit_depth : integer) return integer is
begin
case bit_depth is
when 0 to 2 => return( 1);
when (2** 1)+1 to 2** 2 => return( 2);
when (2** 2)+1 to 2** 3 => return( 3);
when (2** 3)+1 to 2** 4 => return( 4);
when (2** 4)+1 to 2** 5 => return( 5);
when (2** 5)+1 to 2** 6 => return( 6);
when (2** 6)+1 to 2** 7 => return( 7);
when (2** 7)+1 to 2** 8 => return( 8);
when (2** 8)+1 to 2** 9 => return( 9);
when (2** 9)+1 to 2**10 => return(10);
when (2**10)+1 to 2**11 => return(11);
when (2**11)+1 to 2**12 => return(12);
when (2**12)+1 to 2**13 => return(13);
when (2**13)+1 to 2**14 => return(14);
when (2**14)+1 to 2**15 => return(15);
when (2**15)+1 to 2**16 => return(16);
when (2**16)+1 to 2**17 => return(17);
when (2**17)+1 to 2**18 => return(18);
when (2**18)+1 to 2**19 => return(19);
when (2**19)+1 to 2**20 => return(20);
when (2**20)+1 to 2**21 => return(21);
when (2**21)+1 to 2**22 => return(22);
when (2**22)+1 to 2**23 => return(23);
when (2**23)+1 to 2**24 => return(24);
when (2**24)+1 to 2**25 => return(25);
when (2**25)+1 to 2**26 => return(26);
when (2**26)+1 to 2**27 => return(27);
when (2**27)+1 to 2**28 => return(28);
when (2**28)+1 to 2**29 => return(29);
when (2**29)+1 to 2**30 => return(30);
when (2**30)+1 to (2**31)-1 => return(31);
when others => return(0);
end case;
end;
With this weird code structure that works in synthesis and simulation.
source to share
This recursive version synthesizes:
function clogb2 (bit_depth : integer) return integer is
begin
if bit_depth <= 1 then
return 0;
else
return clogb2(bit_depth / 2) + 1;
end if;
end function clogb2;
You can use it to measure other things like
entity counter is
generic (max_count : POSITIVE);
port (clock, reset : in std_logic;
Q : out std_logic_vector(clogb2(max_count) downto 0)
);
end;
or you can use it like combinational logic:
process (I)
begin
O <= clogb2(I);
end process;
BTW: you're better off using integer subtype for input:
function clogb2 (bit_depth : positive) return integer is
-- ^
-- |
source to share