Problems with synchronization - 2

A

ALuPin

Guest
ALuPin wrote:
Is the change from s_wait to s_state1 performed
without any problems ? IMO SETUP and HOLD violations can erase
which under circumstances can lead to an unscheduled change.

Mr Hulshoff wrote:
No, it is not performed without problems. The signal l_enable_generate_ack
needs to be synchronized to the 30 MHz domain before using it. Otherwise
you can get very unexpected behaviour in your eventual chip.

ALuPin wrote
What possiblities do I have to avoid that ?
Any synchronization method should consume little amount of time.

Mr Hulshoff wrote
Clock the signal twice on the 30 MHz signal, and use that signal instead.
You can also opt for clocking three times, and use the 2nd and 3rd FF to do
edge detection.
Hi Mr Hulshoff,

thank you for your answer.

What do you mean by edge detection ? Do mean that I could sample the Clk_30
with Clk_90 to find out the falling edge time area of Clk_30?

process(Clk_90)
begin
if rising_edge(Clk_90) then
l_sample1 <= Clk_30;
l_sample2 <= l_sample1;
l_sample3 <= l_sample2;
end if;
end process;
process(l_sample2, l_sample3)
begin
l_center30 <= '0';
if ((l_sample2='0') and (l_sample3='1')) then
l_center30 <= '1';
end if;
-- l_center30 could be used to assign a flag in the 90MHz domain.
-- This flag can then be used in the 30MHz domain ?
end process;

Rgds
André
 
ALuPin wrote:
What do you mean by edge detection ? Do mean that I could sample the
Clk_30 with Clk_90 to find out the falling edge time area of Clk_30?
No, I meant you could use the falling or rising edge of the synchronized
version of l_enable_generate_ack. Similar to what Roger wrote in his
example:


PROCESS
BEGIN

WAIT UNTIL clk_30 = '1';

-- synchronize l_enable_generate_ack to 30 MHz clock area
l_enable_generate_ack_meta   <= l_enable_generate_ack;
l_enable_generate_ack_clk30 <= l_enable_generate_ack_meta;
l_enable_generate_ack_clk30_d <= l_enable_generate_ack_clk30;

-- Use only the double clocked signal
IF l_enable_generate_ack_clk30 = '1 THEN
-- etc.
END IF;

-- Use positive edge
IF l_enable_generate_ack_clk30 = '1' AND
l_enable_generate_ack_clk30_d = '0' THEN
-- etc.
END IF;

-- Use negative edge
IF l_enable_generate_ack_clk30 = '0' AND
l_enable_generate_ack_clk30_d = '1' THEN
-- etc.
END IF;

-- synchronous resets of your signals
IF reset = '1' THEN
l_enable_generate_ack_meta   <= '0';
l_enable_generate_ack_clk30 <= '0';
l_enable_generate_ack_clk30_d <= '0';
END IF;

END PROCESS;


Regards,

Pieter Hulshoff
 
Heres what you wrote with my comments:

-- Generate_ack is synchronous to Clk_90
process(Reset, Clk_90)
begin
if Reset='1' then
l_enable_generate_ack <= '0';
elsif rising_edge(Clk_90) then

--this assignment is implied in a clocked process
l_enable_generate_ack <= l_enable_generate_ack;


if Generate_ack='1' then
l_enable_generate_ack <= '1';
end if;
if l_eop_sync='1' then
l_enable_generate_ack <= '0';
end if;
end if;
end process;


process(Reset, Clk_30)
begin
if Reset='1' then
l_state <= s_wait;
l_eop <= '0';
elsif rising_edge(Clk_30) then

--these assignments are implied in a clocked process
l_state <= l_state;
l_eop <= '0';


case l_state is


when s_wait =>
--you cannot use the Clk_90 signal l_enable_generate_ack
--directly due to metastability issues
if l_enable_generate_ack='1' then
l_state <= s_state1;
end if;
when s_state1 =>
if other_condition_30MHz_domain='1' then
l_state <= s_state2;
end if;
when s_state2 =>
l_state <= s_state3;
l_eop <= '1';
when s_state3 =>
l_state <= s_state4;
when s_state4 =>
l_state <= s_state5;
when s_state5 =>
l_state <= s_wait;
end if;
end process;

So the major issue is with the l_enable_generate_ack signal.
Since this signal is clocked by Clk_90, it may change at or
near a Clk_30 rising edge. When this happens, a setup or hold
violation occurs and the state variable l_state may become
corrupted. For instance, if the state variable is 2-bits, one
bit may change since its circuit sees l_enable_generate_ack
as a '1' while the other bit remains unchanged since its
circuit sees l_enable_generate_ack as a '0'. There is a ton
of literature on the web addressing this issue.

You need to synchronize the signal to Clk30 prior to use. This
is typically done using two flops as follows:

process(Reset, Clk_30)
begin
if Reset='1' then
l_enable_generate_ack_meta <= '0';
l_enable_generate_ack_clk30 <= '0';
elsif rising_edge(Clk_30) then
l_enable_generate_ack_meta <= l_enable_generate_ack;
l_enable_generate_ack_clk30 <= l_enable_generate_ack_meta;
end if;
end process;

l_enable_generate_ack_meta is an unstable signal and should only be
used to generate l_enable_generate_ack_clk30.

l_enable_generate_ack_clk30 is the synchronized version of
l_enable_generate_ack. Now all you have to do is change your
state machine to account for the 2 cycle shift of the
l_enable_generate_ack signal.

Good luck...
 

Welcome to EDABoard.com

Sponsor

Back
Top