![]() |
|
|
|||||||
![]() |
VHDL - Synchronizer theory and question |
|
|
Thread Tools | Search this Thread |
|
|
#1 |
|
Hi experts,
Sorry for the cross posting, but I wanted to ensure a complete readership. It's more a design question than language specific. When I pass a signal between clock domains (clkfrom to clkto), I use two FF's in the clkto domain prior to using the signal in this domain. If there is a timing violation (setup or hold) at the first FF, then the O/P will become metastable. i.e. Unknown, and it will stay in this state for a time determind by a probability distribution. We therefore use a second FF before we use the signal. Hopefully, the O/P of the fist FF will be stable by the next clock edge. This is not guarenteed, and depends on the clock frequency, target technology etc. All we can say is that there is a probabilty of X% that it will always work. Therefore, first question : Is my understanding correct? If so, I have another question. If I am passing a signal from a fast clock domain (16MHz) to a slow clock domain (100Hz) at 0.18us, do I need to synchronize? e.g. As a simple example, I have a timer on a system bus. The cycle time register is in the fast domain. Ignoring reset's, (and assuming I gray code the counter) my code looks like p_fast : process(fastclk) if fastclk'event and fastclk='1' then if write_cycle='1' then r_cycle <= wr_data ; end if; end if ; end process ; p_slow : process(slowclk) if slowclk'event and slowclk='1' then r_cycle_eq_count <=cycle_eq_count ; // This is an interrupt which will be sync'ed into fast clock domain if r_cycle_eq_count='1' then r_count <= (others => '0') ; else r_count <= r_count + 1 ; endif ; end if ; end process ; assign cycle_eq_count = '1' when r_cycle=r_count else '0' ; Is there a problem with this code? If r_cycle changes around slowclk, there may be metastabity in r_cycle_count, but this should have settled within a 100Hz cycle? Any further suggestions/insights welcomed. Steven moogyd@yahoo.co.uk |
|
|
|
|
#2 |
|
Posts: n/a
|
There are two issues when changing clock domains with
multibit data. The first is data coherency and this would be addressed using Gray code. There are other methods when the destination clock is much slower than the source clock. My favourite is to create a sampling signal in the source clock domain just after the edge in the destination clock. Use this as a clock enable in the source clock domain to latch the data, which is then used directly at the next destination clock edge. The second issue is metastability, and at 100 Hz I would say this is not likely to become an issue. In the Gray code case only one bit at a time is changing and therefore unless your metastability window spans the source clock period the sampled data will be usable at the next edge of 100 Hz. The important issue here is not so much the two-stage synchronizer, but the single point of sampling. i.e. at the sampling clock edge only one flip-flop in the 100 Hz clock domain can sample each bit. This seems to be addressed in your slowclk process below. Of course this delays your interrupt by 10 milliseconds. wrote: > Hi experts, > > Sorry for the cross posting, but I wanted to ensure a complete > readership. It's more a design question than language specific. > > When I pass a signal between clock domains (clkfrom to clkto), I use > two FF's in the clkto domain prior to using the signal in this domain. > If there is a timing violation (setup or hold) at the first FF, then > the O/P will become metastable. i.e. Unknown, and it will stay in this > state for a time determind by a probability distribution. > We therefore use a second FF before we use the signal. Hopefully, the > O/P of the fist FF will be stable by the next clock edge. This is not > guarenteed, and depends on the clock frequency, target technology etc. > All we can say is that there is a probabilty of X% that it will always > work. > > Therefore, first question : Is my understanding correct? > > If so, I have another question. > > If I am passing a signal from a fast clock domain (16MHz) to a slow > clock domain (100Hz) at 0.18us, do I need to synchronize? > > e.g. As a simple example, I have a timer on a system bus. The cycle > time register is in the fast domain. > > Ignoring reset's, (and assuming I gray code the counter) my code looks > like > > p_fast : process(fastclk) > if fastclk'event and fastclk='1' then > if write_cycle='1' then > r_cycle <= wr_data ; > end if; > end if ; > end process ; > > p_slow : process(slowclk) > if slowclk'event and slowclk='1' then > r_cycle_eq_count <=cycle_eq_count ; // This is an interrupt which > will be sync'ed into fast clock domain > if r_cycle_eq_count='1' then > r_count <= (others => '0') ; > else > r_count <= r_count + 1 ; > endif ; > end if ; > end process ; > > assign cycle_eq_count = '1' when r_cycle=r_count else '0' ; > > Is there a problem with this code? > If r_cycle changes around slowclk, there may be metastabity in > r_cycle_count, but this should have settled within a 100Hz cycle? > > Any further suggestions/insights welcomed. > > Steven |
|
|
|
#3 |
|
Posts: n/a
|
wrote:
> When I pass a signal between clock domains (clkfrom to clkto), I use > two FF's in the clkto domain prior to using the signal in this domain. > If there is a timing violation (setup or hold) at the first FF, then > the O/P will become metastable. i.e. Unknown, and it will stay in this > state for a time determind by a probability distribution. The most likely result of a timing violation in FF1 is proper synchronization either on that edge or the next. The primary job of the flop is to eliminate races to the subsequent flops in the design by retiming the edges. The most common symptom of a logic race is an "impossible" state transition. The second flop is there to reduce the odds of synchronization failure from say once a year to maybe once every hundred years. That's cheap insurance. Without any synchronization, I would expect a race problem in much less than a year -- more likely in less than a millisecond. For a synchronizer example, search for "retime" in the reference design here: http://home.comcast.net/~mike_treseler/ > If I am passing a signal from a fast clock domain (16MHz) to a slow > clock domain (100Hz) at 0.18us, do I need to synchronize? Yes. The easiest way is to run the "slow" counter at 16MHz using clock enables. See the "clock enabled counters" source for an example. Or you could handshake the transaction with ready and ack signals, properly synchronized, of course. > e.g. As a simple example, I have a timer on a system bus. The cycle > time register is in the fast domain. > Is there a problem with this code? Yes. If you travel down this road you will eventually reinvent the uart or the fifo. -- Mike Treseler |
|
|
|
#4 |
|
Posts: n/a
|
The second flop is assumed to have more timing margin on its input than
other flop inputs driven through combinatorial logic. If adequate timing margin can be guaranteed to produce a desired probability of failure, it does not matter whether it is one flop with no preceding logic, or one or more flops, each with preceding logic. As an example, say an asynchronous input is registered only once, and then used to drive a load signal on a counter. Generally speaking, the timing margin from clock to setup, going through the load muxes to all the bits of the counter will be less than the timing margin to a single additional flop immediately downstream from the synchronizing flop. But, depending on routing, placement, and logic involved, there can actually be less margin on the single flop than on the multiple flops with preceding mux logic. Unless the timing is additionally constrained to give you that extra margin (in either case), there is no guaranteed improvement in probability of failure from inserting a second flop after the synchronizing flop (we call the second flop the meta[stable]-rejecting flop). The above only holds true for non-causal (i.e. clocked) inputs. It is not true for causal (clock or asyncrhonous) inputs. Never drive causal inputs from output of the first synchronizing flop. You should also constrain the synchronizing input register (the first one) so as not to be replicated due to high fanout (or any other reason). Such replication is almost never a problem if you have a single, second flop before fanning out into the rest of your logic (although in rare cases, the second flop gets replicated enough times to where it creates enough fanout on the first register to trigger replication!). Such replication is more common when the synchronizing flop drives your logic directly. Either way, the no-replicate constraint is highly recommended. You also don't want the synchronizing flop to be re-timed either. Andy Mike Treseler wrote: > wrote: > > > When I pass a signal between clock domains (clkfrom to clkto), I use > > two FF's in the clkto domain prior to using the signal in this domain. > > If there is a timing violation (setup or hold) at the first FF, then > > the O/P will become metastable. i.e. Unknown, and it will stay in this > > state for a time determind by a probability distribution. > > The most likely result of a timing violation in FF1 is proper > synchronization either on that edge or the next. The primary > job of the flop is to eliminate races to the subsequent flops > in the design by retiming the edges. The most common symptom of a logic > race is an "impossible" state transition. > > The second flop is there to reduce the odds > of synchronization failure from say once a year to maybe > once every hundred years. That's cheap insurance. > Without any synchronization, I would expect a race problem > in much less than a year -- more likely in less than a millisecond. > > For a synchronizer example, search for "retime" > in the reference design here: > http://home.comcast.net/~mike_treseler/ > > > If I am passing a signal from a fast clock domain (16MHz) to a slow > > clock domain (100Hz) at 0.18us, do I need to synchronize? > > Yes. > > The easiest way is to run the "slow" counter at 16MHz > using clock enables. See the "clock enabled counters" > source for an example. Or you could handshake the > transaction with ready and ack signals, properly > synchronized, of course. > > > e.g. As a simple example, I have a timer on a system bus. The cycle > > time register is in the fast domain. > > > Is there a problem with this code? > > Yes. > > If you travel down this road you will > eventually reinvent the uart or the fifo. > > -- Mike Treseler |
|
|
|
#5 |
|
Posts: n/a
|
Thanks for all the responses and clarifications.
The reason for the initial question is that I require very low power (both static and dynamic). Therefore: - Sampling the slow clock using the fast clock is not possible. I only want the fast clock to be running when a bus operation is required. I am using AMBPA APB, so this may be 2 clock cycles (when the PSEL is active) - I am trying to reduce gate-count (i.e. I'll try to avoid having the compare register in both clock domains) I am hoping that this problem has a solution. When I think about it too hard, my head hurts Thanks, Steven |
|
|
|
#6 |
|
Posts: n/a
|
Hello Mike,
Are you advicing that synchronizing the signal between two clock domains via two flip flops is OK? I have one clock which is running at 24MHz and the second clock running at 1MHz. John Mike Treseler wrote: > wrote: > > > When I pass a signal between clock domains (clkfrom to clkto), I use > > two FF's in the clkto domain prior to using the signal in this domain. > > If there is a timing violation (setup or hold) at the first FF, then > > the O/P will become metastable. i.e. Unknown, and it will stay in this > > state for a time determind by a probability distribution. > > The most likely result of a timing violation in FF1 is proper > synchronization either on that edge or the next. The primary > job of the flop is to eliminate races to the subsequent flops > in the design by retiming the edges. The most common symptom of a logic > race is an "impossible" state transition. > > The second flop is there to reduce the odds > of synchronization failure from say once a year to maybe > once every hundred years. That's cheap insurance. > Without any synchronization, I would expect a race problem > in much less than a year -- more likely in less than a millisecond. > > For a synchronizer example, search for "retime" > in the reference design here: > http://home.comcast.net/~mike_treseler/ > > > If I am passing a signal from a fast clock domain (16MHz) to a slow > > clock domain (100Hz) at 0.18us, do I need to synchronize? > > Yes. > > The easiest way is to run the "slow" counter at 16MHz > using clock enables. See the "clock enabled counters" > source for an example. Or you could handshake the > transaction with ready and ack signals, properly > synchronized, of course. > > > e.g. As a simple example, I have a timer on a system bus. The cycle > > time register is in the fast domain. > > > Is there a problem with this code? > > Yes. > > If you travel down this road you will > eventually reinvent the uart or the fifo. > > -- Mike Treseler |
|
|
|
#7 |
|
Posts: n/a
|
john wrote:
> Are you advicing that synchronizing the signal between two clock > domains via two flip flops is OK? I have one clock which is running at > 24MHz and the second clock running at 1MHz. I would advise running the module at 24 MHz and using the second clock as a plain input to be synchronized and and converted to a single cycle strobe. -- Mike Treseler |
|
|
|
#8 |
|
Posts: n/a
|
Hi Mike,
I am trying to write a 48 bit buffer in the FPGA at the rising edge of the USB clock and then trying to use the 1MHz clock to read the 48bit bit buffer and then serially outputing them. What I understood from ur advise that FPGA will run at 24MHz and the 1MHz clock will be input and pass through flip flops and at the output of the second flip flop will be used to read the 48bit buffer and serially output the data. Am I right? Please adivse some sample code > Regards John |
|