Forum Discussion
Altera_Forum
Honored Contributor
18 years agoUsing CPLD/FPGA as a Timer
Hi.
I am interested to implement a timer that can count up to hours, in my FPGA/CPLD. The main purpose of the timer is to issue a pulse after a certain fixed duration, eg. every 2 hours. Normally I would use a counter to do this, if the period is not that long. But for the counter that can count up to hours, it needs too many LEs, since I am using a 5-MHz input clock. Is the any better way to do this, without using too many LEs? I would like to keep the 5-MHz clock if possible. Any idea is much appreciated. Thanks! Regards, CW4 Replies
- Altera_Forum
Honored Contributor
how about pre-scaling at the output? say with few ripple-counter ICs and a D-flipflop to square the waveform duty cycle to 50%
sure, a bit of a solder job but it may be easier than tinkering with the 5Mhz especially if you are using pre-fab board with all-SMD parts... ~B - Altera_Forum
Honored Contributor
Thanks Frank.
I guess without using a much slower clock, there is no way I can greatly reduce the amount of LEs used. Regards, CW - Altera_Forum
Honored Contributor
Hello,
I just was aware, that the said MAX_COUNT overflows the integer range, thus my example is incorrect. Changing the count value to unsigned with full length, the LE consumption increases to 54. Sorry for the confusion. Frank
P.S.: Rounding MAX_COUNT to x"860000000", the LE consumption decreases to 41-- Modified Quartus II VHDL Template -- Binary Counter library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity timer is generic ( MAX_COUNT : unsigned(35 downto 0) := x"861C467FF" ); port ( clk : in std_logic; reset : in std_logic; enable : in std_logic; q : out std_logic ); end entity; architecture rtl of timer is begin process (clk) variable cnt : unsigned(35 downto 0); begin if (rising_edge(clk)) then if reset = '1' then -- Reset the counter cnt := (others => '0'); q <= '0'; elsif enable = '1' then -- Increment the counter if counting is enabled if cnt < MAX_COUNT then cnt := cnt + 1; q <= '0'; else cnt := (others => '0'); q <= '1'; end if; end if; end if; end process; end rtl; - Altera_Forum
Honored Contributor
Hello,
basically, the simple fact that the system needs (2*3600*5e6) states can't be bypassed. ceil(log2((2*3600*5e6)-1)) = 36 gives the number of bits for a binary counter, which is always the minimal state representation, I think. Using a modified vhdl binary counter template with a MAX II CPLD, I got an overall LE consumption of 46. The 10 additional LE's are a tribute to the particular MAX_COUNT, a 2**N value would allow a simple ripple-carry counter. Best regards and Happy New Year! Frank-- Modified Quartus II VHDL Template -- Binary Counter library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity timer is generic ( MIN_COUNT : natural := 0; MAX_COUNT : natural := (5e6*3600*2)-1 ); port ( clk : in std_logic; reset : in std_logic; enable : in std_logic; q : out std_logic ); end entity; architecture rtl of timer is begin process (clk) variable cnt : integer range MIN_COUNT to MAX_COUNT; begin if (rising_edge(clk)) then if reset = '1' then -- Reset the counter cnt := MIN_COUNT; q <= '0'; elsif enable = '1' then -- Increment the counter if counting is enabled if cnt < MAX_COUNT then cnt := cnt + 1; q <= '0'; else cnt:=MIN_COUNT; q <= '1'; end if; end if; end if; end process; end rtl;