Forum Discussion
Altera_Forum
Honored Contributor
16 years agoVHDL 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
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; - Altera_Forum
Honored Contributor
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; - Altera_Forum
Honored Contributor
Tricky, as usual, thank you for helping wash off all the newb on my shirt.
- Altera_Forum
Honored Contributor
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; - Altera_Forum
Honored Contributor
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; - Altera_Forum
Honored Contributor
Hola Homie,
I believe this code will do what you want. CheersLibrary 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;