# VHDL internal timer not consistent time

I'm having inconsistent times on my timer, can be anywhere from 300ms - 4 seconds, what could be causing this?

The code logic looks good to me but the oscope shows different times almost everytime I run it. Here's how I set up the code for the timer. I'm using an arduino as a clock at about 256Hz. The timer should go off at 4 seconds not any sooner like it is.

library ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;

constant C_2SEC_TC : integer := 1023;
signal tmr_cnt  : std_logic_vector(11 downto 0) := (others => '0');
signal tc_2sec  : std_logic;

begin
-- counter for internal timer
second_cntr_proc: process(CLK)
begin
if (rising_edge(CLK)) then
tmr_cnt <= tmr_cnt + 1;
if (tc_2sec='1') then
tmr_cnt <= (others => '0');
end if;
end if;
end process second_cntr_proc;

tc_2sec <= '1' when tmr_cnt = C_2SEC_TC else '0';


I initialize a pin high and when tc_2sec goes high I set that pin low. The high time of that pin isn't always the same.

• (1) What FPGA pin is the Arduino sending the "clock" into? Is it just a regular FPGA pin? Or is it actually an FPGA clock pin with a dedicated clock network? (2) Why are you involving in this at all instead of just using the FPGA's oscillator? (3) If you are inputting things onto an actual FPGA clocking pin, does the FPGA even support a clock as slow as 256Hz? (4) If you are inputting things onto a regular FPGA pin, are you at least synchronizing it to the FPGA's clock domain first? – DKNguyen Aug 26 '19 at 19:22
• (5) Why does it seem like your FPGA doesn't have an oscillator? You have not shown us all your code. What is CLK exactly? Is it the Arduino signal? If so, then what is your FPGA's REAL clock? You cannot use rising_edge() blindly. It is ONLY for REAL clocks that run the entire FPGA that connect to a dedicated clock network. Not for something trivial like a signal being produced by an Arduino. – DKNguyen Aug 26 '19 at 19:25
• @DKNguyen (1) I'm connecting this to a general I/O pin on board my atf1502 asv CPLD. Its not connected to the clock pin because im using it on a Dev board that uses a 2MHz clk, the problem with that is this chip only has 32 macro cells, my std_logic_vector would have to be much higher for 4 seconds and it will not fit with 32 macro cells. (2) To my knowledge there is no oscillator inside this chip. (3) Using an I/O pin. (4) Not sure what this means, I'm new to VHDL. (5) Yes, clk is an input pin, signal is coming from the arduino digital signal that goes high and low. I though rising_edge was – Sean Kerr Aug 26 '19 at 20:33
• @DKNguyen okay to use on any digital signal – Sean Kerr Aug 26 '19 at 20:33
• What you're doing looks fine at first glance and a clock input can be any frequency below the FPGA's specified maximum. So, next, how sure are you that your Arduino's clock into the FPGA is noise-free and at the right frequency? – TonyM Aug 26 '19 at 20:57

You should know that the kind of initialization you are using for tmr_cnt may not be synthesizable. If you don't explicitly reset this counter it could power up with an unknown value. If that value happens to be greater than C_2SEC_TC then your 12-bit counter will have to count up until it rolls over and reaches 1023 before tc_2sec will go low.

If the problem is occurring on the first pulse after power up then I would suspect this kind of problem. You will need to add a reset signal to your design and use it to clear the counter. It would be helpful if you included a link to the manufacturer's datasheet for your CPLD.

• Not sure about other FPGAs but Xilinx and Altera FPGA docs say all initial values are synthesisable in their FPGAs for years now. This is to avoid the overhead of global resets in FPGA designs. – Mitu Raj Aug 27 '19 at 6:10
• @MituRaj Agreed, but the OP says they are using a CPLD from Microchip and didn't provide a link to the datasheet. I'm not familiar with those particular devices. – Elliot Alderson Aug 27 '19 at 14:20
• @elliotalderson Didnt I initialize it to 0 with the statement := (others => '0')? Sorry the data sheet can be found here. ww1.microchip.com/downloads/en/DeviceDoc/doc1615.pdf – Sean Kerr Aug 27 '19 at 17:35
• @MituRaj, VHDL designs should use resets, and never initial values, to keep those designs portable. RAM-based FPGAs allow initial values whereas flash-based FPGAs/CPLDs and ASICs don't. Initial value designs won't work in the latter. That's why vendor IP, for example, uses resets. It's better practice and little overhead, with nearly all FPGAs/CPLDs I've seen supporting asynchronous resets in hardware and using little routing to employ them. Ensure the asynchronous reset is synchronously negated and they're fine. – TonyM Aug 27 '19 at 18:38
• @TonyM Good to know. I was not aware of that since I only work with FPGAs, nearly all of which are SRAM. When does VHDL reset code stopped being interpreted as a reset? (i.e. After you have the signal sensitivity list, but not under a rising_edge(), what types of VHDL lines will cause the synthesizer to no longer interpret it as a reset and therefore no longer use the reset hardware. Is it just anything that is not a direct signal assignment? (i.e. such as IF statements, etc)? – DKNguyen Aug 27 '19 at 22:46

SOLVED: Updated the proc as follows appeared to fix my issue



   library ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;

constant C_2SEC_TC : integer := 1023;
signal tmr_cnt  : std_logic_vector(11 downto 0);
signal tc_2sec  : std_logic : = '0';

begin
-- counter for internal timer
second_cntr_proc: process(CLK)
begin
if (RST = '0') then
tmr_cnt  <= (others => '0');
elsif (clk'event and clk = '1') then
tmr_cnt <= tmr_cnt + 1;
if (tc_2sec='1') then
tmr_cnt <= (others => '0');
end if;
end if;
end process second_cntr_proc;

tc_2sec <= '1' when tmr_cnt = C_2SEC_TC else '0';

• It looks like changing the initialization fixed the issue. So it seems like it was the initial value vs reset that pointed out by Elliot and TonyM was the problem which would make sense since you are working off a Flash/EEPROM device and not an FPGA which runs from SRAM. You really should use rising_edge() though and not (clk'event and clk = '1'). That is the old way and is obsolete. – DKNguyen Aug 27 '19 at 22:41