Problems with synchronization - 2

A

ALuPin

ALuPin said:
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é
 
R

Roger

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...
 
P

Pieter Hulshoff

ALuPin said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top