Forum Discussion

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

VHDL Counter

I am new to VHDL, and I am trying to create a counter that will count up from 0 to X when a signal called enable will be true.

I get errors like Latches are generated for incomplete case or if statements. I don't know how to code it.

A signal called enable will drop low and before it goes low the counter is incrementing. What I want ideally is to use this counter and get the counts at the point where enable goes low.

A second counter picks up the ball (same counter instantiated twice) in the mean time I want to the counts of the first count to be zero before I use it.

The error I get is this

Found 16-bit latch for signal <cnts_out>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.

I don't know what to put on the else statement of this process...

can someone help please write a counter:

1. Count up

2. transfer the counts only when enable goes low

3. next time it is used it should start from zero up!

Help

rjrodrig@yahoo.com

pOut: process(enable,r_reg)

begin

if(enable ='0') then -- If the enable drops low then transfer the counts

cnts_out<= std_logic_vector(r_reg); --Typecast into bus vector

--temp <= std_logic_vector(r_reg); -- Keep the last counts

--else

-- cnts_out <= temp;

end if;

end process;


--Entry port 
entity Counter is
     generic(N: integer :=16);                   --Scale it to 20bits counter
    port ( clk         : in  STD_LOGIC;
           enable        : in     STD_LOGIC;        --Enable this counter
              reset        : in  STD_LOGIC;
              max_ticks    : out std_logic;
              cnts_out     : out  STD_LOGIC_VECTOR (N-1 downto 0));
end Counter;
architecture Behavioral of Counter is
signal r_reg: unsigned(N-1 downto 0):=x"0000";
begin
    
    pCntr: process(clk,reset,enable)                        --Counter process
        begin
            if(reset = '1') then
                r_reg <= (others => '0');
            elsif (clk'event and clk='1' and enable ='1') then          
                    r_reg <= r_reg + 1;                        --Increment 
            end if;
    end process;
    
    --Output logic
    --Only transfer the last count when enable goes low!   
 pOut: process(enable,r_reg)
    begin
        if(enable ='0') then                                    -- If the enable drops low then transfer the counts
            cnts_out<= std_logic_vector(r_reg);            --Typecast into bus vector
        end if;
    end process;
--Set an overflow Flag in due case we reach the maximum counts
    max_ticks <= '1' when r_reg = (2**N-1) else '0';    --Overflow counter indicator    
end Behavioral;

16 Replies

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

    I figured out a work around I just created a simple counter. I created a separate unit which provide a reset signal so I can reset the counters. I also made sure the counter counts only when enable is true.

    This works fine

    
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
    --Entry port 
    entity Counter is
         generic(N: integer :=16);                   --Scale it to 20 bits counter
        port ( clk         : in  STD_LOGIC;
               enable        : in     STD_LOGIC;        --Enable this counter
                  reset        : in  STD_LOGIC;
                  max_ticks    : out STD_LOGIC;
                  cnts_out     : out  STD_LOGIC_VECTOR (N-1 downto 0));
    end Counter;
    architecture Behavioral of Counter is
    signal r_reg: std_logic_vector (N-1 downto 0) := (others =>'0');
    BEGIN
    PCntr: process(clk,reset,enable) 
        begin
            if(reset='1') then
                r_reg <= (others => '0');
            elsif(rising_edge(clk)) then
                if(enable='1') then
                    r_reg <= r_reg + 1;
                else
                    r_reg <=(others => '0');
                end if;
            end if;
    end process PCntr;
        
    --Output logic
    max_ticks <= '1' when r_reg = (2**N-1) else '0';    --Overflow counter indicator     
    cnts_out <= r_reg;
    end Behavioral;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Usually is a bad Idea to make the process sensitive to enable.

    Just remove enable from the sensitivity list.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I know I am posting in an Altera Website... I am using Xilinx ISE... It complains if it is not in the sensitivity list. Also, as I understand it, the reason why you put it in the sensitivity list is so that the "event" when any of the signals within the process(*) changes state, the process block will execute.

    So I would think if the enable happens to change, as it is in my case of a random signal, I need to be able to start and stop my counter. If I don't put it there, there is a chance my counter will neither stop or start its counting process. So I don't completely agree with your statement, but I have been proven wrong other times.

    I am not very experienced VHDL writer. I only do glue logic with CPLDS...
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I know I am posting in an Altera Website... I am using Xilinx ISE... It complains if it is not in the sensitivity list. Also, as I understand it, the reason why you put it in the sensitivity list is so that the "event" when any of the signals within the process(*) changes state, the process block will execute.

    So I would think if the enable happens to change, as it is in my case of a random signal, I need to be able to start and stop my counter. If I don't put it there, there is a chance my counter will neither stop or start its counting process. So I don't completely agree with your statement, but I have been proven wrong other times.

    I am not very experienced VHDL writer. I only do glue logic with CPLDS...

    --- Quote End ---

    If it is complaining, it is a bug with ISE. Nothing will happen unless there is a clock event, so having the process execute when enable changes is pointless. You only care about the state of the enable signal when there is an event on "clk".

    Adding extra signals to sensitivity lists reduces the performance of your code inside a simulator as it makes the simulator evaluate the process unneccesarily.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Proof of what I am saying, this code:

    
      if(enable='1') then
          r_reg <= r_reg + 1;
      else
          r_reg <=(others => '0');
      end if;
    
    Will only get executed at posedge clk NO MATTER what.

    And that means: adding "enable" to the sensitivity list will only confuse your code (for both humans and compilers).

    Besides that, when enable changes, surely there will be a clk posedge shortly after that (after all clk is a PERIODIC signal), and at that point your code WILL get evaluated (have no fear).

    Besides that I also know ISE tools and I know what I'm saying here :)