Very often is necessary to detect edges of signals in designs. It can be helpful during developing communication interfaces, filters, sequential events. It seems that writing this module is easy, but as always designer should be careful. He has to remember, that his VHDL code will be synthesized to hardware, so he should keep in mind what structure will be created and how tools will understand his intentions.
Many times, I saw people trying to detect rising edge by using rising_edge function. This is very poor and not proper approach. Compiler seeing rising_edge clause, treats signal in this function as a clock and thinks that was intention of a designer. This signal would be connected to clk input of the register, but probably this is not what designer really wanted to do. This hardware would bring many problems with clock domains, asynchronous signals etc. In effect, it is very likely that design would stop working one day.
Beginners in FPGA should try to use only one clock in a design. All registers should be clocked by the same clock. This simple rule will save their time, because it will protect designs against many timing issues.
Therefore, signal of which edge you want to detect, also should be synchronized by a global clock. Think, how can you detect the edge? What hardware do you have to build to be sure that it will work every time? Fig. 1 presents one of the methods for detecting rising edge.
Code which creates the depicted above hardware :
library ieee; use ieee.std_logic_1164.all; entity EdgeDetector is port ( clk :in std_logic; d :in std_logic; edge :out std_logic ); end EdgeDetector; architecture EdgeDetector_rtl of EdgeDetector is signal reg1 :std_logic; signal reg2 :std_logic; begin reg: process(clk) begin if rising_edge(clk) then reg1 <= d; reg2 <= reg1; end if; end process; edge <= reg1 and (not reg2); end EdgeDetector_rtl;
Input signal goes through registers. The first one synchronizes the signal (if it is already done, you don’t have to do that again) and the second is for detecting the edge. If the input signal changes to high, every register will delay it by one clock. This means that for one period, signal at output of the first register will be high, but at the same time, output of the second register will be still low. Hardware will give high signal only for one cycle. Then the second register will be updated to high, so output will return to low state.
* For detecting falling edge of the signal, structure is very similar to presented above.
If the input signal comes from external world, other clock domain or is asynchronous, before detecting edge, it must be synchronized. It should go through synchronization registers and then through registers for detecting edge. This must be done to avoid metastability. If you are not sure of source of the signal, add at least one or two (two are recommended by Altera) at the input of the detector.
Truly speaking, best practice is to always synchronize every signal which comes to FPGA. You should send it through registers, before using inside a chip.
*** *** ***
All source codes used in that post you can find on gitlab.com.
*** *** ***