statement is not synthesizable since it does not hold its value underNOT(clock-edge) condition

T

Trygve Laugstøl

Hello!

I'm trying to get the following snippet to work and I'm 1) wondering
what's wrong and 2) wondering if I'm going about this the right way.

I have two clocks, one CPU clock (at 48MHz) and a LCD clock (200kHz)
which control the CPU and the output to the LCD (obviously enough). What
I want to happen is that the CPU will set trigger on the leading edge of
the CPU clock and clear it on the falling edge of the LCD clock (which
should ensure that it has been picked up by the 'main' process).

The error message I'm getting is "statement is not synthesizable since
it does not hold its value under NOT(clock-edge) condition".

The code:

trigger_xfer: process(reset, clk, clk_200kHz, output_trigger)
begin
trigger <= '0';
if reset = '1' then
trigger <= '0';
elsif clk'event and clk = '1' and output_trigger = '1' then
trigger <= '1';
elsif clk_200kHz'event and clk_200kHz = '0' then
trigger <= '0';
end if;
end process;

main: process(...)
if reset
...
elsif clk_200kHz'event and clk_200kHz = '1' then
...
end if;
end process;
 
G

Gabor

Hello!

I'm trying to get the following snippet to work and I'm 1) wondering
what's wrong and 2) wondering if I'm going about this the right way.

I have two clocks, one CPU clock (at 48MHz) and a LCD clock (200kHz)
which control the CPU and the output to the LCD (obviously enough). What
I want to happen is that the CPU will set trigger on the leading edge of
the CPU clock and clear it on the falling edge of the LCD clock (which
should ensure that it has been picked up by the 'main' process).

The error message I'm getting is "statement is not synthesizable since
it does not hold its value under NOT(clock-edge) condition".

The code:

     trigger_xfer: process(reset, clk, clk_200kHz, output_trigger)
     begin
         trigger <= '0';
         if reset = '1' then
             trigger <= '0';
         elsif clk'event and clk = '1' and output_trigger = '1' then
             trigger <= '1';
         elsif clk_200kHz'event and clk_200kHz = '0' then
             trigger <= '0';
         end if;
     end process;

     main: process(...)
         if reset
             ...
         elsif clk_200kHz'event and clk_200kHz = '1' then
             ...
         end if;
     end process;

First, I know of no FPGA that has dual-clocked flip-flops available in
the internal
fabric. So it's no wonder that the code is not synthesizable.

Second, 200 KHz is really slow, so you should probably just sample it
with the
48 MHz CPU clock and use the sampled signal with another flip-flop
delay
to detect edges instead of trying to create a dual-clocked process.

Third. It's not clear to me that you are taking care of
synchronization properly
here. If the intent is for a single event on the CPU clock to create
an output
that can be sampled at the falling edge of the 200 KHz clock, then I
don't
see how you will ensure any minimum setup time unless the event was
already somehow synchronous to the 200 KHz clock.

-- Gabor
 
T

Trygve Laugstøl

[Note that I'm quite a newbie to VHDL]

First, I know of no FPGA that has dual-clocked flip-flops available in
the internal
fabric. So it's no wonder that the code is not synthesizable.

Hm, I though this should synthesize a S/R+reset flip flop but I guess
because of the 'event it will become clocks instead.
Second, 200 KHz is really slow, so you should probably just sample it
with the
48 MHz CPU clock and use the sampled signal with another flip-flop
delay
to detect edges instead of trying to create a dual-clocked process.

How would that work? It is generated from the 48MHz clock already just
on the outside of the entity.
Third. It's not clear to me that you are taking care of
synchronization properly
here. If the intent is for a single event on the CPU clock to create
an output
that can be sampled at the falling edge of the 200 KHz clock, then I
don't
see how you will ensure any minimum setup time unless the event was
already somehow synchronous to the 200 KHz clock.

Hm, I'm not really seeing the problem but that's probably because of my
lack of understanding. Could you elaborate or show/point me some code
that does what I want to do? I've been trying to read up on links from
searches like "clock synchronization" and "clock domains" but haven't
found something that really applies to my case (and makes sense to me).
 
P

Paul Uiterlinden

Trygve said:
Hello!

I'm trying to get the following snippet to work and I'm 1) wondering
what's wrong

The first assignment to "trigger" (right after the "begin") cannot be right.

What you have described here is something like: "reset trigger on any event
on signals reset, clk, clk_200kHz and output_trigger, unless there is a
rising edge on clk while output_trigger is '1'. In the latter case, set
trigger."

If you leave out the first assignment, things perhaps start looking what you
want. If it will be synthesisable, I don't know (I don't do synthesis).

Have you simulated this code at all?
 
R

rickman

[Note that I'm quite a newbie to VHDL]

First, I know of no FPGA that has dual-clocked flip-flops available in
the internal
fabric. So it's no wonder that the code is not synthesizable.

Hm, I though this should synthesize a S/R+reset flip flop but I guess
because of the 'event it will become clocks instead.
Second, 200 KHz is really slow, so you should probably just sample it
with the
48 MHz CPU clock and use the sampled signal with another flip-flop
delay
to detect edges instead of trying to create a dual-clocked process.

How would that work? It is generated from the 48MHz clock already just
on the outside of the entity.
Third. It's not clear to me that you are taking care of
synchronization properly
here. If the intent is for a single event on the CPU clock to create
an output
that can be sampled at the falling edge of the 200 KHz clock, then I
don't
see how you will ensure any minimum setup time unless the event was
already somehow synchronous to the 200 KHz clock.

Hm, I'm not really seeing the problem but that's probably because of my
lack of understanding. Could you elaborate or show/point me some code
that does what I want to do? I've been trying to read up on links from
searches like "clock synchronization" and "clock domains" but haven't
found something that really applies to my case (and makes sense to me).

Here is how I do it. I cut this from a program and ripped out all the
other code to just highlight the edge detection. Replace TT_B2 with
your LCD clock and add your code where indicated. The function
NegEdge() just ANDs TT_DD with not TT_D to make it clear what the IF
statement is doing. There will be a delay of one to two clock cycles
from the edge of your slow clock before the code in the IF statement
is executed, but with your app, I expect this doesn't matter.

CTPData: process (SysClk, SysRst) begin
if (SysRst = '1') then
TT_D <= '0';
TT_DD <= '0';
elsif (rising_edge(SysClk)) then
TT_D <= TT_B2;
TT_DD <= TT_D;
-- RD output interface
if (NegEdge(TT_D, TT_DD)) then -- falling edge of TT data strobe
-- This is where you put your LCD code
end if; -- NegEdge(TT
end if; -- elsif (rising_edge(SysClk
end process CTPData;

This approach solves a lot of problems. It gets rid of communication
issues between clock domains and the two FFs handle metastability
issues, which you can still have even though the two frequencies are
locked, the phase is likely not. If you really want to be sure of
dealing with meta stability, combine the two delay FFs and register
that. With only one LUT, 20 ns will be lots of settling time.

Rick
 

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

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top