VHDL Looking for clock dropout on clocks of different speeds....

S

Steve Auch-Schwelk

Guest
I have a SoC which is being fed an external 125MHz clock. I am using the Zynq processor with internal clock speed of 100MHz as an independent source to see if there are any dropouts.

Here is the heavily redacted code, to just produce the problem I am seeing.

Basic premise is that the faster clock will always have updated it’s clock_count, by the time the slower clock checks to see if it has changed.. If it is the same, the faster clock has failed for some reason, and I want to record how may cycles it has failed for.

Clock_in is 125MHZ. Clock_100 is 100MHz.

The error_count_s is being incremented about .05% of the time, even though there is no failure or fallout of Clock_in.

I have independently verified that the counters are updating at the correct rate.

Is there some timing issue here I’m missing?

---------------------------------------------------
process(Clock_in,reset)
begin
if (reset=\'0\') then
clock_counter <= (others=>\'0\');
elsif rising_edge(Clock_in) then
clock_counter <= clock_counter + 1;
end if; -- rising edge clock_in
end process;
process(Clock_100,reset) --loss of clock detector, clocked from onboard processor clock
begin
if (rising_edge(Clock_100)) then
if (clock_counter = clock_counter_old) then -- clock_counter hasn\'t been updated since the last pulse
error_count_s <= error_count_s + 1;
CSO_down_out <= error_count_s; --count how long we\'ve been without 125MHz clock
end if;
clock_counter_old <= clock_counter;
end if; -- rising edge
end process;
 
On 9/29/22 12:47 AM, Steve Auch-Schwelk wrote:
I have a SoC which is being fed an external 125MHz clock. I am using the Zynq processor with internal clock speed of 100MHz as an independent source to see if there are any dropouts.

Here is the heavily redacted code, to just produce the problem I am seeing.

Basic premise is that the faster clock will always have updated it’s clock_count, by the time the slower clock checks to see if it has changed. If it is the same, the faster clock has failed for some reason, and I want to record how may cycles it has failed for.

Clock_in is 125MHZ. Clock_100 is 100MHz.

The error_count_s is being incremented about .05% of the time, even though there is no failure or fallout of Clock_in.

I have independently verified that the counters are updating at the correct rate.

Is there some timing issue here I’m missing?

---------------------------------------------------
process(Clock_in,reset)
begin
if (reset=\'0\') then
clock_counter <= (others=>\'0\');
elsif rising_edge(Clock_in) then
clock_counter <= clock_counter + 1;
end if; -- rising edge clock_in
end process;
process(Clock_100,reset) --loss of clock detector, clocked from onboard processor clock
begin
if (rising_edge(Clock_100)) then
if (clock_counter = clock_counter_old) then -- clock_counter hasn\'t been updated since the last pulse
error_count_s <= error_count_s + 1;
CSO_down_out <= error_count_s; --count how long we\'ve been without 125MHz clock
end if;
clock_counter_old <= clock_counter;
end if; -- rising edge
end process;

The problem is syncronization, and slight differences in propigation
time for each bit of the counter.

This can cause the faster counter, when sampled by the slower clock,
when it is counting from a value like 0111 to the value 1000 to see
some of the new bits and some of the old bits, allowing ANY value
between 0000 and 1111 to appear.

One simple solution is to change the counters to \"Gray Counters\" which
only change a single bit on each transisition, counting like:

000
001
010
011
111
110
100
101
100
000

And that sort of value won\'t get grabled crossing the clock domain.
 

Welcome to EDABoard.com

Sponsor

Back
Top