Tales From The Helpdesk
Tales From The Helpdesk
The Problem
Quite often your code needs to react to a change on some control signal. That can be an external input,
something saying that another part of the circuit has done it's job and that we can continue. All sort of
scenarios exist that call for a signal generate by one part of a system to be detected by another part or a
different system.
A little while ago, we received a question from an engineer who was engaged in the task of condensing
an old system implemented on a board into a single FPGA. He was having trouble with clocks in his
FPGA implementation, and a small investigation showed us the problem. The system board consisted
of a processor and various peripherals (all separate ICs,) communicating using a tristate bus and all
manner of asynchronous control strobes. He had found some HDL IP to implement the peripherals in
the FPGA, but alas the IP used all the same tristates, latches and strobes.
Why is it a problem?
All this asynchronous stuff is fine and dandy if you're still in 1980, but not so good if you want to use
an FPGA. Why? Well, every time I use code like this to detect an edge on a strobe:
if rising_edge(strobe) then
Or this
always @(posedge strobe)
Then the FPGA tools think "Aha! A clock!" and act accordingly. They route the signal in question
through a clock buffer, and if you have a few of these edge-detect fragments you pretty soon run out of
clock buffers. Then your tools start using general routing for clocks and your nice, dependable, lowskew clocks go completely out of the window.
propagated the new value, or perhaps got confused for a while and not settled to any real output value
("metastability"). If the input signal changes within the "metastability window" the output could take a
long (theoretically infinite) time to settle to a stable value. That time could well be longer than one
clock cycle, so we add another flip-flop just in case. It's vanishingly unlikely for the second flip-flop to
get hit by metastability. Now read on...
Synchronization is conventionally done with a two-stage shift-register that is clocked by the target
domain's clock. That's great, our input is now synchronous to the sysclk. We need to detect a change,
and we can do that by extending the shift-register a little and comparing the values of different bits:
The first stage of the shifter takes the hit of timing errors, and we compare the next two stages (C1 and
C2) to see whether we have a rise or a fall on the input signal. We output two signals that indicate a
rise or a fall; each will be high for one sysclk cycle. The compare logic is trivially simple.
Conclusion
Don't do asynchronous edge detection, ever. This circuit is a nice edge detector that gives you
synchronous notification of edges on your input signal. There's no excuse for not doing this; it's a tiny
circuit in just five lines of Verilog. A bit more in VHDL, obviously...
Remember: Keep It Synchronous, Stupid.
Copyright 2009 by Doulos Ltd. All rights reserved. All information is provided as is without warranty of any kind.