Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

timing requirement not met

Hello

I'm kind of new in the world of FPGA and puzzled with a timing warning message sent by quartus.

This fonction extract ratio info of an arbitrary PWM signal every period and send the ratio over a 14 bits bus to another function.

the code is as follow :

entity formfactor is
    Port (    PWM    : in STD_LOGIC;
                rst   : in STD_LOGIC;
                clk    : in STD_LOGIC;
                FF2    : out integer range 0 to 10020 );
end formfactor;
architecture behaviour of formfactor is
signal  buf_ton1, buf_ton2,buf_T1, buf_T2, compteur1, compteur2: integer range 0 to 12000;
type etats is (s0,s1,s2,s3);  --type of state machine.
signal s: etats; 
signal flag: std_logic_vector (1 downto 0);
type atats is (a0,a1,a2,a3);
signal a : atats;
begin    
    
DUREE:process (clk, rst)
    begin
    if rst = '0' then 
    compteur1 <= 0;
    compteur2 <= 0;    
    flag <= "00";
    elsif (clk'EVENT and clk ='1') then
        
       case s is
        
when s0 => 
compteur2 <= compteur2 + 1;
if (PWM ='1' AND compteur2 > (buf_ton2 + 10) ) then buf_T2 <= compteur2; 
    s <= s1;
        flag <= "10";
                
else s <= s0;
end if;             
when s1 =>
compteur1 <= compteur1 + 1; 
if(PWM = '0' AND compteur1 > 10 ) then buf_ton1 <= compteur1; 
    
    compteur2 <= 0;
    
    s <= s2 ; 
else s <= s1;    
end if; 
when s2 =>
compteur1 <= compteur1 + 1; 
if (PWM ='1' AND compteur1 > (buf_ton1 + 10)) then buf_T1 <= compteur1; 
                                                        s <= s3;
                                                        flag <= "01";
else s <= s2;
end if;
when s3 =>
compteur2 <= compteur2 + 1;
if (PWM ='0' AND compteur2 > 10 ) then     buf_ton2 <= compteur2; 
    compteur1 <= 0;
    
    s <= s0;
else s <= s3;
end if; 
end case;
end if;
end process DUREE;
DIVIDE: process (clk)
BEGIN
    
    if (clk'EVENT and clk ='1') then
    
    case a is
    
    when a0 =>
    if(flag = "10") then a <= a1;
    else a <= a0;
    end if;
    
    when a1 =>
    FF2 <= 100000000 /((buf_T1 * 10000) / buf_ton1);
    a <= a2;
    when a2 =>
    if(flag = "01") then a <= a3;
    else a <= a2;
    end if;
    
    when a3 =>
    FF2 <= 100000000 /((buf_T2 * 10000) / buf_ton2);
    a <= a0;
    
    end case;
        
    end if;
end process DIVIDE;    
end behaviour;

Clock is 100Mhz

Timequest gives me a negative slack of -127 in the worst case between bufTx / buf_tonx and FF2

ex : -127.307 formfactor:inst10|buf_T2[0] formfactor:inst10|FF2[0] inst1|altpll_component|auto_generated|pll1|clk[0]

The problem is obviously in my process DIVIDE but I can not manage to find it.

Can someone give me a hint ? It would be much appreciated.

Thanks

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

        when a3 =>
        FF2 <= 100000000 /((buf_T2 * 10000) / buf_ton2);
        a <= a0;

    It is ultimately saying that the logic can not run at the speed you would like it to. The line above starting with "FF2" is a bit much to expect to run at 100MHz. You will probably want to pipeline your math to make this a bit easier on the compiler to have your design meet timing.

    I might suggest keeping your * and / operations isolated by registers.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The division operation is *VERY* slow and complex to implement in actual logic.

    The usual solution is to avoid it.

    A common strategy is to have a table of reciprocals and replace division by multiplication by the reciprocal.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    at least simplify the massive term 100000000 /((buf_T1 * 10000) / buf_ton1) to:

    10000 *buf_ton1 / buf_T1 and remember not to call them twice but once otherwise the tool creates two instants of * & / as it may not be that kind.

    Incidentally, your figures helped me find out that:

    10000 = 8192+1024+512+256+16

    hence you can shift add if you wish to trade 1 mult for adders.