clock synchronization and flip flops

J

john

Hello All,

I am need for some serious advice. I am trying to synchronize the
passing of the control signal "Reset_counter" between two clocks
namely "clk1x" and clk_b = clk_synch. The clk_b is equal to
"clk_divider (6) and generated by dividing the "clk1x" as you can see
in the following code.

The sequential machine is running on "clk1x" and it generates the
signal called "Reset_counter" to reset the 49 bit counter
"p2s_counter". This counter outputs 49 bit of serial data at the
rising edge of the slower clock "clk_synch". Because "clk_synch" is
slower than the "clk1x", so I tired to pass the signal "Reset_counter"
through atleast three flip flops as you can see in the code clocking
with the slower clock " clk_synch".

Then I used the resultant output signal " synch_reset_2" to Reset the
49 bit counter. The sequential state machine " ser_out_state" checks
running on "clk1x" for p2s counter to get equal to count 49. after the
counter reaches its count the state machine gets into a new state.
Since, "clk1x " is way faster than "clk_synch" thats why it will not
miss the p2s_counter signal.

I am using xess board and foundation code and have all sorts of
problems simulating the code. SO thats why i am testing the code using
Logic Analyzer.

My questions is

Am I synchronizing the clocks in the right way?

I will appreciate any advice!

John


combinatorial : process(err_r, addr_r, dIn, rand, begun, done,
rdPending, doAgain )
begin
case state_r is
when INIT =>
Reset_counter <= '1';
state_x <= Ser_buff_LOAD_1;

when Ser_buff_LOAD_1 =>
Reset_counter <= '1';
state_x <= Ser_buff_LOAD_2;

When Ser_buff_LOAD_2 =>
Reset_counter <='1';
state_x <= Ser_buff_LOAD_3;

When Ser_buff_LOAD_3 =>
Reset_counter <='1';
state_x <= Reset_state;

when Reset_state =>
Reset_counter <='1';
state_x<= Tag_state;

when Tag_state =>

Reset_counter <='1';
state_x <= ser_out_state;
----------------------------------------
when ser_out_state =>

Reset_counter <='1';

if ( p2s_counter /= "110001") then
Reset_counter <='0';
state_x <= ser_out_state;
else
Reset_counter <='1';
state_x <= Ser_buff_LOAD_1;
end if;
---------------------------------------
When EMPTY_PIPE =>

Reset_counter <='1';
if done = YES then
cke <= YES;
end if;

if rdPending = NO then
state_x <= STOP;
end if;
When others =>
end process;

------------------------------------
-- clk1x is the main clock generated by xess's program
update: process (clk1x)
begin
if clk1x'event and clk1x = '1' then
if rst = YES then -- main reset from xess's program
state_r <= INIT;
else
addr_r <= addr_x;
state_r <= state_x;
end if;
end if;
end process;
------------------------------------
clk_synch <= clk_b;
-------------------------------------
-- 49 bits, parallel to serial port conversion--
serial_count : process ( clk_synch)
begin
if rising_edge (clk_synch) then
if ( synch_reset_2 = '0') Then
p2s_counter <= p2s_counter + 1;
ser_out<=ser_buff ( to_integer ( p2s_counter ) );
else
p2s_counter <= ( others =>'0');
end if;
end if;
end process;

------------------------------------

Two_flip_flop_synch: process(clk_synch, Reset_counter)
variable synch_reset_a : std_logic;
variable synch_reset_b: std_logic;
begin
If (Reset_counter = '1') Then
synch_reset_a := '1';
synch_reset_b := '1';
elsif rising_edge (clk_synch) then
synch_reset_a :=synch_reset_b;
synch_reset_b:= '0';
end if;
synch_reset <= synch_reset_a ;
end process;
-----------------------------------
-- Third Synchronizing Flip Flop to sycnhronize the Reset_counter --

third_flip_flop_synch : process (clk_synch,Reset_counter )
variable synch_reset_c: std_logic;
variable synch_reset_d:std_logic;
Begin
if ( Reset_counter ='1') then
synch_reset_c:= '1';
synch_reset_d:='1';
elsif rising_edge (clk_synch) then
synch_reset_c:= synch_reset;
synch_reset_d:='0';
end if;
done_1 <= synch_reset_c;
synch_reset_2<= synch_reset_c;
end process;
----------------------------------
-- Dividing the 100MHz clk1x to 1MHz clk_synch--
div : process ( rst,clk1x)
begin
If ( rst = '1') Then
clk_divider <= "00000000000";
elsIf rising_edge (clk1x) then
clk_divider <= clk_divider + 1;
end if;
end process;
 
Joined
Mar 24, 2009
Messages
5
Reaction score
0
Hi John,
I think the 1st debugging step here is with the patch of code below:
I think the patch should prodice clk_synch as the output. You are using 'clk_divider' but apparently not using it to generate teh actual clock 'clk_synch'.

Since you mentioned you are using a logic analyzer, you should assign 'clk_synch' to a pin and check it on LA.

----------------------------------
-- Dividing the 100MHz clk1x to 1MHz clk_synch--
div : process ( rst,clk1x)
begin
If ( rst = '1') Then
clk_divider <= "00000000000";
elsIf rising_edge (clk1x) then
clk_divider <= clk_divider + 1;
end if;
end process;
---------------------------------
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
It sounds like you might have some size optimization turned on. That may be deleting your redundant registers and putting you back into a metastable condition. If you don't understand this search for "metastability" on the web.

What compiler are you using?

Also, clk_b is used but never defined in the logic. Where is the rest of the code?

John
 
K

KJ

I am using xess board and foundation code and have all sorts of
problems simulating the code. SO thats why i am testing the code using
Logic Analyzer.

You're attacking the problem backwards then. It is far easier and
more productive to debug in a simulator then with a logic analyzer.
With the simulator you have immediate access to every signal in the
design at any time...with the analyzer you do not.
My questions is

Am I synchronizing the clocks in the right way?

No. Unless you're doing a custom ASIC design, don't generate clocks
at all, timing between clock domains will be your doom. Have
everything run off of one clock signal. Rather than creating a
divided down clock from a high speed clock consider this approach

1. Create a counter that counts from 0 to some maximum count and then
goes back to 0. For example, if you want to create a lower speed
clock that is 1/50th of the original clock signal what you would do
instead is have a counter that runs from 0 to 49 and then resets back
to 0. You're not using this counter as a clock, it's just a counter.

2. Create a clock enable signal from the counter by decoding one of
the counter states like this "clock_enable <= '1' when (counter = 7)
else '0'; Here I've arbitrarily picked a count value of 7, unless you
have some specific phase relationship to maintain between the clocks
for some reason the exact count value can be anything. This clock
enable signal will fire for exactly one clock cycle and then sit
inactive for the other values of the counter (in the above example, it
would sit inactive for 49 clock cycles).

3. Wherever you would have liked to do this...
process(Generated_Clock)
if rising_edge(Generated_Clock) then
...Your logic here
end if;
end process;

Do this instead...
process(Clock)
if rising_edge(Clock) then
if (Clock_Enable = '1') then
...Your logic here
end if;
end if;
end process;

I will appreciate any advice!

The best advice is to try to avoid multiple clocks until you really
have an understanding of how to do it correctly. I haven't gone into
how to do that here simply because it doesn't appear that you've fully
mastered good synchronous design practice.
 combinatorial : process(err_r, addr_r, dIn, rand, begun, done,
rdPending, doAgain )

Don't use combinatorial process. They are sources of the following
types of design errors that are difficult to debug to but are
completely avoidable if you simply use only clocked processes and
concurrent signal assignments.

- Synthesis differs from simulation because synthesis tools do not
properly handle sensitivity lists per the LRM. If your sensitivity
list is missing a signal, you'll get burned.
- Latches are easy to create and if you do create one...again, you'll
get burned.

Kevin Jennings
 
J

john

Hi,

So , I will use the counter output as clock. I need a 1MHz clock to
serial output the data. Where will I get that clock?

Regards,
John
 
K

KJ

So , I will use the counter output as clock.

As the clock to what? An external device? Internal to the design?

If it is internal to the design, then you didn't get my post at all so
go back and re-read. If it is a signal to an external device, then it
is not a 'clock' from the perspective of your design since it is not
used *by your design* to sample anything.
I need a 1MHz clock to
serial output the data. Where will I get that clock?
This suggests to me that the '1MHz clock' is some output of your
design and that there is some other serial output data as well...those
are two separate outputs. But the '1 MHz clock' is not a clock to
your design at all, it is a clock input to *the external device*.

If that is what you're trying to do (I'm not sure, it's not at all
clear to me) then to generate this 1 MHz output signal from say a 50
MHz clock input you would construct the counter like I mentioned
previously to count from 0 to 49 (or 49 downto 0 if you'd like). Keep
in mind that any particular value of the count then essentially
defines something that happens at a 1 MHz rate. So....

process(Clock)
begin
if rising_edge(Clock) then
if (Count = 3) then
My_1MHz_Output <= '1';
elsif (Count = 28) then
My_1MHz_Output <= '0';
end if;
end if;
end process;

The signal 'My_1MHz_Output' then will be a 1 MHz output signal, you
wouldn't use it internally within your design, it is simply the output
signal that you're generating in order to interface to whatever device
is using this signal.

The value of '3' that I picked for switching the output to a '1' is
arbitrary, any value would work. The value of '28' was chosen because
people like to see 50% duty cycle clocks. If you want a different
duty cycle then change the 28 to something else.

Presumably your serial output data must have some specific timing
relationship to the 'clock' to meet some setup or hold time
requirement. Perhaps the external device samples on the data on the
rising edge so you would need to make sure that the data is stable
around that point (which from the above example would be around the
time when Count=3). Based on whatever your requirement is, you might
then decide that 70 ns is more than enough hold time and decide to
only allow the data to change when the count = 10 (7 ticks of the 100
MHz clock = 70 ns).

process(Clock)
begin
if rising_edge(Clock) then
if (Count = 10) then
Serial_Out_Data <= ...
end if;
end if;
end process;

That's the basic idea. You would probably want to define some
constants so that the numbers '3', '10' and '28' (or whatever) have
real definitions instead of appearing to be magic constants.

Kevin Jennings
 
K

KJ

then decide that 70 ns is more than enough hold time and decide to
only allow the data to change when the count = 10 (7 ticks of the 100
MHz clock = 70 ns).

Should've said 7 ticks of the 50 MHz clock...and said that maybe 140
ns is plenty of hold time

KJ
 
J

john

Hi,

I am not doing ASIC. I think , I got the idea. I will try your adviced
solution and we will see. I am trying to generate clock, data and tag
signals for a DAC. The DAC needs 49 bit of data at the clock of 1MHz.
The internal clock frequency is 100MHz. I think that the counter
solution might work.

Thanks
John
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
John,

That is a very good paper that you are referencing. I suggest you make sure you are strong in synchronous design before tackling the asynchronous design aspects. His technique of making synchronous modules is a good one. Make sure you can get one module through the entire process (design -> simulation -> synthesis -> programming) before you tackle multiple asynchronous modules.

John D
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top