externally triggered time counter in verilog - Page 1
Forum section: electronics / general

author: fabioacosta
author_rank: Newbie
timestamp: November 03, 2014, 04:15:14 am
content: Hi I'm new to the fpga world, just got a Xilinx Spartan 3E and started playing around with it in verilog with ISE design tools.My frustration came when I try to use 2 external triggers to activate counters. My goal is to make a program that when given 3 posedges of a push button in a range of 5 seconds turns on a led. If the 5 seconds go and there haven't been 3 events from the push, resets and restart the process.I tried to code this and the concept was something like thisAlways@(posedge push)**if first push then flag=1**Always @(posedge clock)** if flag==1 then start counter**check function for pushes and time resetThis had the issue that I had to change registers on both blocks so I've been told to put both processes in one block. The problem with it is that I don't see a way to make the push posedge work since the clock is always faster.Is there a way for me to activate a clock counter after another posedge event and make it synthesizable. I know for a fact this is a possible implementation using a counter that controls another one via reset or enable and I would just make it through schematic if it wasn't for the absurdly large counter that is needed with a 50Mhz clock.Please help me with this and I'll be eternally grateful.

author: jahonen
author_rank: Super Contributor
timestamp: November 03, 2014, 11:04:40 am
content: You'll need to synchronize the push signal to your clock so that they have guaranteed (or almost, excluding metastability probability) timing relationship. Then generate "edge flag" for the push signal. I suck at verilog so in VHDL something likeCode:signal push : std_logic;signal push_rise : std_logic;...push_sync: process(clk, reset)variable sreg : std_logic_vector(2 downto 0); -- adjust length for desired metastability protectionbeginif reset = '1' thensreg := (others => '0');push <= '0';elsif rising_edge(clk) thenpush <= sreg(sreg'left);sreg := sreg(sreg'left-1 downto 0) & push_in; -- push_in is the unsynchronized signalend if;end process;push_edgedet: process(clk, reset)variable prev : std_logic;if reset = '1' thenprev := '0';push_rise <= '0';elsif rising_edge(clk) thenpush_rise <= '0';if prev /= push and push = '1' thenpush_rise <= '1';end if;prev := push;end if;end process;Now the push_rise is the signal which goes to '1' for one clock period whenever a rising edge is detected, so you can read it safely in your synchronized counter. I guess that it comes from some push-button so it is left an exercise to the reader to implement a debounce for that signal.Regards,Janne

author: langwadt
author_rank: Super Contributor
timestamp: November 06, 2014, 12:09:41 am
content: Quote from: fabioacosta on November 03, 2014, 04:15:14 amunless you have very specific needs or want to make life difficult run everything synchronous on asingle clocki.e. sample the button input on the clock edges, detect the change from low to high use thatto control state machine that counts down from 5 seconds, once it sees the first "pushed"

author: hamster_nz
author_rank: Super Contributor
timestamp: November 06, 2014, 08:46:14 pm
content: Depending on exactly what you want there is many different ways to skin the cat. Here's how I would do it (in a gibberish pseudo code)Code:on the posedge of the external clock// Detect when you need to respond to the button pressif btn_debounced_last = '0' and btn_debounced = '1' and led = '0' thenif counter = 0 then// Start the counter for five secondscounter = clock_freq * 5 - 2;elsif press2 = 0 then// Flag that we have seen a second presspress2 = '1';else// We've seen the third press!// Turn on the LED and set up a five second timeoutled = '1';counter = clock_freq * 5 - 1;end if;elseif counter != 0 thencounter = counter -1;else// Reset statepress2 = '0';led = '0';end if;end if;btn_debounced_last = btn_debounced;It's not perfect, and doesn't show how to debounce the button input, but logic looks OK to me at first glance.