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

  • Follow


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;
0
Reply ISO 1/24/2011 8:32:01 PM

On Jan 24, 3:32=A0pm, Trygve Laugst=F8l <tryg...@inamo.no> wrote:
> 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:
>
> =A0 =A0 =A0trigger_xfer: process(reset, clk, clk_200kHz, output_trigger)
> =A0 =A0 =A0begin
> =A0 =A0 =A0 =A0 =A0trigger <=3D '0';
> =A0 =A0 =A0 =A0 =A0if reset =3D '1' then
> =A0 =A0 =A0 =A0 =A0 =A0 =A0trigger <=3D '0';
> =A0 =A0 =A0 =A0 =A0elsif clk'event and clk =3D '1' and output_trigger =3D=
 '1' then
> =A0 =A0 =A0 =A0 =A0 =A0 =A0trigger <=3D '1';
> =A0 =A0 =A0 =A0 =A0elsif clk_200kHz'event and clk_200kHz =3D '0' then
> =A0 =A0 =A0 =A0 =A0 =A0 =A0trigger <=3D '0';
> =A0 =A0 =A0 =A0 =A0end if;
> =A0 =A0 =A0end process;
>
> =A0 =A0 =A0main: process(...)
> =A0 =A0 =A0 =A0 =A0if reset
> =A0 =A0 =A0 =A0 =A0 =A0 =A0...
> =A0 =A0 =A0 =A0 =A0elsif clk_200kHz'event and clk_200kHz =3D '1' then
> =A0 =A0 =A0 =A0 =A0 =A0 =A0...
> =A0 =A0 =A0 =A0 =A0end if;
> =A0 =A0 =A0end 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
0
Reply Gabor 1/24/2011 8:41:01 PM


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

On 1/24/11 9:41 PM, Gabor wrote:
> On Jan 24, 3:32 pm, Trygve Laugst�l<tryg...@inamo.no>  wrote:
>> 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.

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

--
Trygve
0
Reply ISO 1/24/2011 8:47:26 PM

Trygve Laugstøl wrote:

> 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?

> 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;
> 

-- 
Paul Uiterlinden
www.aimvalley.nl
e-mail addres: remove the not.
0
Reply Paul 1/24/2011 9:30:11 PM

On 1/24/11 10:30 PM, Paul Uiterlinden wrote:
> Trygve Laugstøl wrote:
>
>> 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?

No, it fails with the error message in the subject.

--
Trygve
0
Reply UTF 1/24/2011 9:53:24 PM

On Jan 24, 3:47 pm, Trygve Laugst=F8l <tryg...@inamo.no> wrote:
> [Note that I'm quite a newbie to VHDL]
>
> On 1/24/11 9:41 PM, Gabor wrote:
>
>
>
> > On Jan 24, 3:32 pm, Trygve Laugst=F8l<tryg...@inamo.no>  wrote:
> >> 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). Wh=
at
> >> 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<=3D '0';
> >>           if reset =3D '1' then
> >>               trigger<=3D '0';
> >>           elsif clk'event and clk =3D '1' and output_trigger =3D '1' t=
hen
> >>               trigger<=3D '1';
> >>           elsif clk_200kHz'event and clk_200kHz =3D '0' then
> >>               trigger<=3D '0';
> >>           end if;
> >>       end process;
>
> >>       main: process(...)
> >>           if reset
> >>               ...
> >>           elsif clk_200kHz'event and clk_200kHz =3D '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.
>
> 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).
>
> --
> Trygve

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 =3D '1') then
	  TT_D			<=3D '0';
	  TT_DD			<=3D '0';
    elsif (rising_edge(SysClk)) then
	  TT_D			<=3D TT_B2;
	  TT_DD			<=3D 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
0
Reply rickman 1/24/2011 10:00:00 PM

5 Replies
348 Views

(page loaded in 0.039 seconds)


Reply: