Forum Discussion
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 [email protected] 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
Honored Contributor
Proof of what I am saying, this code:
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 :)if(enable='1') then r_reg <= r_reg + 1; else r_reg <=(others => '0'); end if; - Altera_Forum
Honored 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
Honored 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
Honored Contributor
Usually is a bad Idea to make the process sensitive to enable.
Just remove enable from the sensitivity list. - Altera_Forum
Honored 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 fineuse 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
Honored Contributor
VHDL is so complex!!
- Altera_Forum
Honored Contributor
Yes...I have connected everything. i think the way i am going to approach this problem will be the dumb way. I will let the counter run and use a d-ff to latch only the last value so the fifo only gets the largest count.
I don't know how to make counter that resets itself on an enable trigger and only provides the last count... thanks for your help though - Altera_Forum
Honored Contributor
have you connected the clock?
- Altera_Forum
Honored Contributor
I tried it, and even the simulator and hardware predict the same... I gets zeros out... not counts at all. I don't know how to do this... It can't be that difficult.
- Altera_Forum
Honored Contributor
I suggest you try the code I posted, without the enable = '0' reset condition.
For the bit you dont understand, you have to remember that what you are trying to do is describe hardware, not write code. For what I posted, the enable_r signal will always be what enable was 1 clock cycle ago. This way you can check to see if enable has changed since the last clock cycle. The "if" statement I put in detects a falling edge on the enable signal. This is the only way to detect falling/rising edges in logic (clocks are a special case). With the variable you added, you never actually set the value of X to anything other than 0, so r_reg will always be 1.