Forum Discussion

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

How to apply time constraints to counter?

Please give me a link for "How to apply time constraint to counter"

Can not find any good explanation.

If counter consist of two or several parts

should i use multicycle for all elements (then 2^32 not acceptable in TimeQuest) or

should i use false_path and

Should I constraint only the the most changing bit or

not.

The counter of 64 bit can be as 4bit and 60 bit, or 4 parts by 16bits, or 2 parts by 32 bits or else.

9 Replies

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

    --- Quote Start ---

    Please give me a link for "How to apply time constraint to counter"

    Can not find any good explanation.

    If counter consist of two or several parts

    should i use multicycle for all elements (then 2^32 not acceptable in TimeQuest) or

    should i use false_path and

    Should I constraint only the the most changing bit or

    not.

    The counter of 64 bit can be as 4bit and 60 bit, or 4 parts by 16bits, or 2 parts by 32 bits or else.

    --- Quote End ---

    Normally we define clock and the tool takes care of internal paths. As regard multicycling a counter you can't do that if you are say incrementing every clock cycle. Though only bit0 changes every clock and other bits change every 2,4,8,... etc clocks but still the counter value (adder result must be ready to be read at every clock and no delay is tolerated. Think of it as one single result that is read every clock, rather than independent multibits.

    If it was independent bits then yes you can apply multicycle and provided you control the phase of sampling edge.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Normally we define clock and the tool takes care of internal paths. As regard multicycling a counter you can't do that if you are say incrementing every clock cycle. Though only bit0 changes every clock and other bits change every 2,4,8,... etc clocks but still the counter value (adder result must be ready to be read at every clock and no delay is tolerated. Think of it as one single result that is read every clock, rather than independent multibits.

    If it was independent bits then yes you can apply multicycle and provided you control the phase of sampling edge.

    --- Quote End ---

    agree.... his right...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    okay. if counter consist only one part so you don't need any special time constraints. -< Okay

    if you counter consist of two (for one direction) or three (for both direction) parts you can apply multicycle constraints to middle part to relax Fitter efforts.

    So if I create first( and last) part as only 1bit, i'll apply multicycle setup=2 and hold=1 to another(middle) part? <- Yes or No?

    I asked cause I see difference for Fmax in TimeQuest reports.

    Actually I create more than one counter and for each i must apply its own constraints. but as functional it looks like only one.

    You have only one(two) part(s) small in size that runs every cycle, the reminder can be great as long as your satisfied with TimeQuest results.

    Will it bring any problems if big part runs on the same clock as small but with clock-enable or even with sync_load?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    okay. if counter consist only one part so you don't need any special time constraints. -< Okay

    if you counter consist of two (for one direction) or three (for both direction) parts you can apply multicycle constraints to middle part to relax Fitter efforts.

    So if I create first( and last) part as only 1bit, i'll apply multicycle setup=2 and hold=1 to another(middle) part? <- Yes or No?

    I asked cause I see difference for Fmax in TimeQuest reports.

    Actually I create more than one counter and for each i must apply its own constraints. but as functional it looks like only one.

    You have only one(two) part(s) small in size that runs every cycle, the reminder can be great as long as your satisfied with TimeQuest results.

    Will it bring any problems if big part runs on the same clock as small but with clock-enable or even with sync_load?

    --- Quote End ---

    Not sure about parts but the principle is that if you count every clock there is no multicycle. if you count every n clocks (e.g. through enable) then you can apply n multicycles on setup and n-1 on hold
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank a lot of for clarification.

    Yes, one logical counter splitted to several parts. And then i want to use clock-enable as predicted signal that should be computed one clock cycle before it wiil be used and so it shoud be delayed.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This sounds exactly like a little experiment we ran.

    I managed to create a 128 bit down counter that gave an FMax of 450 Mhz in Timequest (using a stratix 4, all pins virtual). To make it an upcounter you can simply invert the output.

    It is split into 16x 8 bit down counters. Each counter outputs an "is_0" signal that is generated when counter = 1 and it is enabled. The enable of the next counter simply ANDs all the 0s together.

    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity cnt8 is
        port (
            clk         : in  std_logic;
            clk_en      : in  std_logic;
            
            load        : in  std_logic;
            load_val    : in  unsigned(7 downto 0);
            
            is_0        : out std_logic
        );
        
    end entity cnt8;
    architecture rtl of cnt8 is
        signal cnt      : unsigned(7 downto 0);
    begin
        cnt_proc : process(clk)
        begin
            if rising_edge(clk) then
                if load = '1' then
                    cnt         <= load_val;            
                    
                    if load_val = 0 then
                        is_0        <= '1';
                    else
                        is_0        <= '0';
                    end if;
                    
                elsif clk_en = '1' then
                    cnt         <= cnt - 1;
                    
                    if cnt = 1 then
                        is_0    <= '1';
                    else    
                        is_0    <= '0';
                    end if;
                end if;
               
            end if;
        end process;
    end architecture rtl;
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    use ieee.std_logic_misc.all;
    entity counter_challenge is
        port (
            clk         : in  std_logic;
            
            load_val    : in  unsigned(127 downto 0);
            load        : in  std_logic;
            
            done        : out std_logic
        );
    end entity counter_challenge;
    architecture rtl of counter_challenge is
        signal cnt          : unsigned(127 downto 0);
            
        signal load_r       : std_logic;
        signal load_val_r   : unsigned(127 downto 0);
        
        signal is_0_array   : std_logic_vector(0 to 15);
    begin
        cnt_proc : process(clk)        
        begin
            if rising_edge(clk) then
            
                load_r      <= load;
                load_val_r  <= load_val;
            
                if and_reduce( is_0_array ) = '1' and load = '0' then
                    done    <= '1';
                else
                    done    <= '0';
                end if;
            end if;
        end process;
        
        counter_gen : for i in 0 to 15 generate
            
            signal count_en         : std_logic;
        begin
        
            process(is_0_array)
                variable cnt_en_high    : std_logic;
                variable cnt_en_low     : std_logic;
            begin
                cnt_en_high      := '0';
                cnt_en_low       := '1';
            
                for j in 0 to i-1 loop
                    cnt_en_low  := cnt_en_low and is_0_array(j);
                end loop;
                
                for j in i to 15 loop
                    cnt_en_high := cnt_en_high or not is_0_array(j);
                end loop;
                
                count_en        <= cnt_en_low and cnt_en_high;
            end process;
        
            
            
            cnt8_inst : entity work.cnt8
            port map (
                clk         => clk,
                clk_en      => count_en,
                
                load        => load_r,
                load_val    => load_val_r( (i+1)*8 -1 downto i*8 ),
                
                is_0        => is_0_array(i)
            );
       
        end generate counter_gen;
        
        
    end architecture rtl;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This sounds exactly like a little experiment we ran.

    I managed to create a 128 bit down counter that gave an FMax of 450 Mhz in Timequest (using a stratix 4, all pins virtual). To make it an upcounter you can simply invert the output.

    It is split into 16x 8 bit down counters. Each counter outputs an "is_0" signal that is generated when counter = 1 and it is enabled. The enable of the next counter simply ANDs all the 0s together.

    --- Quote End ---

    I assume by parts you mean cascading counters. For example we can have a counter 0 ~ 999 either directly as one counter or cascaded into three 0~9 counters:

    
    if(rising_edge(clk))then
      if count1 /= 9
         count1 <= count1 + 1;
      else
        count1 <= (others => '0');
        if count2 /= 9 then
          count2 <= count2 + 1;
        else
          count2 <= (others => '0');
          if count3 /= 9 then
            count3 <= count3 + 1;
          else
            count3 <= (others => '0');
          end if;
        end if;
       end if;
    end if;
    

    in the case of single counter 0~999 it is enabled every clock.

    In the case of three counters only count1 need update every clock but count2 every 10 clocks and count3 every 100 clocks so I assume these two counters can be multicycled 10 or 100

    However to read final count value the phase of reading must be looked after carefully to account for multicycle delay.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I want provide a little bit different for clock enable it can be precomputed when counter near all ones or near all zeroes but if I compute it before to such condition and delay for one cycle

    I post nearly the same recently when replying in carry-sum problem
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I want to compute clock enable signal for increment counter when it's value 2**n-3 then register it on the same edge as counter outputs and provide final value as output of register which run on falling edge