- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hola Homie,
I believe this code will do what you want. Cheers
Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
----------------------------------->
Entity YourCount is
Generic( n: integer := 16);
Port(
clk : in std_logic ;
rst : in std_logic;
enable : in std_logic;
max_ticks : out std_logic;
Cnts_out : out Unsigned (N-1 downto 0)
);
End YourCount;
----------------------------------------->
Architecture Count of YourCount is
Begin
------------- CountBe quick ---------------------------
CountBeQuick : Process(clk,rst,enable)
Variable count : integer range 0 to ((2**N)-1); -- integer range 0 to 65,535
Begin
if(rst = '1') then
count := 0; -- clear count
max_ticks <= '0'; -- clear max ticks
elsif (clk'EVENT and clk ='1' and enable = '1') then
count := count + 1;
if (count = ((2**N)-1)) then
max_ticks <= '1'; -- max_ticks stays high till reset
end if;
end if;
if (enable'Event and enable ='0') then -- this transfers count value and clears count
Cnts_out <= TO_UNSIGNED(count,N); -- converts count to unsigned of length N
count := 0;
end if;
End Process CountBeQuick;
----------------------------------------------------------
End Count;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Logically red:your code will work in a simulator, but wont work on an FPGA because you're trying to use the enable signal as a clock, which is not allowed.
This is a much tidier version that wont give you any warnings about latches:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
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):= to_unsigned(0, N); --use to_unsigned function so that it works with the generic N
signal enable_r : std_logic; --enable register
begin
pCntr: process(clk,reset) --no need for enable in here
begin
if(reset = '1') then
r_reg <= (others => '0');
elsif rising_edge(clk) then
if enable = '1' then
r_reg <= r_reg + 1; --Increment - this rolls over back to 0
end if;
--Register enable so we can detect falling edge
enable_r <= enable;
if enable_r = '1' and enable = '0' then --falling edge of enable
cnts_out <= r_reg;
end if;
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
also - if you want the counter to reset after an enable burst:
if enable = '1' then
r_reg <= r_reg + 1; --Increment - this rolls over back to 0
else
r_reg <= to_unsigned(0, N); --reset when enable is low
end if;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tricky, as usual, thank you for helping wash off all the newb on my shirt.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
LogicallyRed and Tricky... thank you so much for your help...
Tricky: I want to start always at zero after I transfer the counts. I added the second comment to this code is this correct?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
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):= to_unsigned(0, N); --use to_unsigned function so that it works with the generic N
signal enable_r : std_logic; --enable register
begin
pCntr: process(clk,reset) --no need for enable in here
begin
if(reset = '1') then
r_reg <= (others => '0');
elsif rising_edge(clk) then
if enable = '1' then
r_reg <= r_reg + 1; --Increment - this rolls over back to 0
else
r_reg <= to_unsigned(0, N); --reset when enable is low
end if;
--Register enable so we can detect falling edge
enable_r <= enable;
if enable_r = '1' and enable = '0' then --falling edge of enable
cnts_out <= r_reg;
end if;
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Guys,
I have modified the code you provided in an effort to get my counter to count up, and to reset it before it starts again based on the Enable signal = '1'. One thing I didn't mention is that the counter will not reach its rollover point, so I have to reset it some how before I reuse it. I am not sure the changes are correct but all the stuff I added is in RED, and comments are in green Would this work?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
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):= to_unsigned(0, N); --use to_unsigned function so that it works with the generic N
signal q_reg: unsigned(N-1 downto 0):= to_unsigned(0,N);
signal enable_r : std_logic; --enable register
begin
pCntr: process(clk,reset) --no need for enable in here
Variable X: integer range 0 to ((2**N)-1); -- Will this work?
begin
if(reset = '1') then
r_reg <= (others => '0');
elsif rising_edge(clk) then
if enable = '1' then
r_reg <= X + 1; --Increment - this rolls over back to 0
end if;
end if;
-- I need to start counting from zero next time I come back into the counter
-- A signal controller is toggling the enable back High/low, but the r_reg
-- will hold the previous value unless it sees a reset coming in which I don't
-- available. I am trying to clear out the r_reg so that after is sent
-- How does this change detect the edge? If I am not mistaken (bear with
-- me I am new to VHDL) it seems to me enable_r stores the state in the
-- first rising edge, since everything executes sequentially, the second time
-- in the previous state will get over-written and the if() will not fire! What
-- is the explanation of this code so I understand why this works?
--Register enable so we can detect falling edge
enable_r <= enable;
-- This code may generate the same warning since it does not have
-- the else condition on it, unless I add this...
-- if ((enable_r = '1') and (enable = '0')) then --falling edge of enable
if(enable = '0') then
cnts_out <= std_logic_vector (r_reg); --Changed to this since unsigned is different type than cnts_out right!
X := 0; --Reset the counter
else
cnts_out <= std_logic_vector(q_reg) --Does this work?
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
have you connected the clock?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
VHDL is so complex!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Usually is a bad Idea to make the process sensitive to enable.
Just remove enable from the sensitivity list.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 :)

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page